利用“抽象分支”做增量式大规模软件改造_第1页
利用“抽象分支”做增量式大规模软件改造_第2页
利用“抽象分支”做增量式大规模软件改造_第3页
利用“抽象分支”做增量式大规模软件改造_第4页
利用“抽象分支”做增量式大规模软件改造_第5页
已阅读5页,还剩1页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

第第页利用“抽象分支”做增量式大规模软件改造利用“抽象分支”做增量式大规模软件改造

发表于:2023-02-27来源:不祥:乔梁点击数:标签:持续交付

利用“抽象分支”做增量式大规模软件改造!很多开发团队通常严重依赖于版本控制系统的分支功能。分布式版本控制系统让分支操作更加方便。然而,在《持续交付》一书中描述的很多非常规言论中,就有一条是:“使用分支,你就无法做持续集成”。

很多(开发)团队通常严重依赖于版本控制系统的分支功能。分布式版本控制系统让分支操作更加方便。然而,在《持续交付》一书中描述的很多非常规言论中,就有一条是:"使用分支,你就无法做持续集成'。根据定义,如果你有代码在某个分支上,那就没有集成。有一种很常见的情况,会让人很自然地想到利用版本控制工具的分支功能:那就是"对应用程序进行大规模改造时'。然而,还有一种替代这种真实分支的做法,技术上叫做"抽象分支(BranchbyAbstraction)'。

抽象分支:在主干上进行以增量方式对软件进行大规模改造的一种模式。

PaulHammant在2023年就提到过用这种方式把ORmapping的方案从Hibernate切换到iBatis(详见这里)。同样,我曾经工作的一款商业产品(持续集成与敏捷发布管理平台Go)则从iBatis改到了Hibernate,这已经是两年前做的事情了。我们也把产品的UI层慢慢地从"使用Velocity和JsTemplate'转移到了"JRubyonRails'上。

这两种变化都是慢慢地增量式地完成的,在改变的同时,也做新功能的开发,但这并不妨碍我们每天向Mercurail的版本库主干上提交数次代码,甚至在切换过程中做了数次正式发布。我们是如何做到的呢?

从iBatis迁移到Hibernate

团队决定从iBatis迁移到Hibernate,有两个原因:第一,我们可以更高效地使用ORM,因为我们对产品(数据库)的结构有绝对控制权,这样就不用写太多的定制(SQL);第二,它有二级缓存,对(性能)有帮助。

当然,我们并没想一次性把整个代码库都迁移到Hibernate上。我们的策略是:当开始增加新功能时,如果需要增加新的方法去访问数据库的话,就使用Hibernate来完成,当必要时,才将原有对iBatis的调用迁移过来。

对持久层逻辑的更新相对来说比较直接,因为产品Go的代码库使用标准的分层结构,控制器层使用服务层,而服务层使用仓库层(repositories)。因为所有需要访问数据库的代码都利用repositorypattern封装在仓库层中,所以每次将一个仓库从iBatis改成Hibernate,增量式地完成修改是一件比较容易的事情。服务层根本不知道底下的持久层框架是什么。

我的同事PavanK.S.说:"抽象分支有一个严格要求,那是纪律性,即:开发人员不能再以任何借口添加原有模式的代码。也就是说,作为第一原则,不要再增加iBatis查询(尽管这么做可能更快更省事儿),必须用Hibernate来做。这是确保你进度的唯一方法。一种强制手段是在持续集成构建时只要发现新增了iBatis查询,就令持续集成构建失败。并且,只能不断减少这个阀值,绝不能增加。'

从Velocity和JsTemplate转向JRubyonRails

产品GO还从"以(Java)为基础的UI软件栈'转向"JRubyonRails'的软件栈。这也有两个原因:一是新的框架更容易写(测试),二是它会加速UI的开发。当然,这个变更也是增量式完成的。当在应用程序中创建新的页面时,我们会使用JRubyonRails,一旦做好以后,就让应用程序的其它部分指向这个新页面。

当需要对某个旧页面进行大量变更时,我们就把它迁移到JRubyonRails上。一旦做好,就把应用程序中所有指向这个页面的URI都更改为这个新的页面。此时,要把对应的旧页面删除。所以,当Go的界面大部分都是JRubyonRails的实现时,仍旧有一些页面是原有JAVA版的实现。

然而,只看页面的话,根本不会觉察,因为它们的样式是统一的,但从URI是能够看出来的。所有使用/go/tab前缀的URI都会跳转到旧的Velocity页面上。其它页面会跳转到JRubyonRails页面上,当然它也同样会使用原有界面所用的(java)服务层。

抽象分支究竟如何操作呢?

抽象分支通过如下几个步骤进行大规模增量式修改:

在你想改变的那部分代码之上创建一个抽象层。

对其余部分的代码进行重构,使其使用这个抽象层使用其之下的代码提供的功能。

在新的实现代码里实现一些新的类,让其上的抽象层根据需要,选择性的导向旧代码或新增的类上。

剔除原有的旧实现。

清理,并重复前两步,如果需要,可同时交付你的软件。

一旦旧实现完全被代替后,如果你愿意,可以移除那个抽象层。

老马(MartinFowler)指出,这些步骤也可以变化一下。"在最简单的情况下,你可以创建一个抽象层,然后重构,让所有的代码都调用它,然后再新写一个实现,最后切换一下就行了。但是,还可以将它分开做。比如,不创建整个抽象层,而只是创建将要修改的功能的一个子集,迁移这部分代码,然后再做下一部分(此时新旧代码共存)。'

在上面iBatis/Hibernate的例子中,抽象层就是指那个仓库层,它隐藏了持久层框架使用的细节。在JRubyonRails的例子中,抽象层是ServletEngine,通过URI的匹配,它可以决定是将Request分发到JRubyonRails框架,还是标准的JavaServlets上。

尽管Go这个项目相对比较小,开发人员不到十个,而且到现在也仅有五年的时间,但是,这些原则完全可以应用于各种大小的项目上。即使在大型且分布式的团队项目里,也可以成功地使用这种模式。

不可否认的是,抽象分支在开发过程上增加了开销,而且当你的代码库结构性很差时,开销会更多一些。为了能够以这种方式做增量式变更,你必须仔细思考,一点儿一点儿地慢慢向前走。但是,在很多情况下,这种额外的工作量是值得的,越是大的重构,就越应该考虑使用这种抽象分支。

抽象分支的关键收益是你的代码在整个结构调整的过程中都能够正常工作,能够做到持续交付。也就是说,你的发布计划与架构上的调整完全解耦,因此,在任何时间点你都可以停止重构工作,做优先级更高的事情,比如发布一个你刚刚想到的非常好的功能特性。

对于抽象分支来说,需要定义一个终止策略,这一点非常重要。当你能够做到"不完

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

最新文档

评论

0/150

提交评论