5

接手历史悠久的老项目,干or跑?

 3 years ago
source link: https://zacharyfan.com/archives/1478.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

接手历史悠久的老项目,干or跑?

这里是Z哥的个人公众号

每周五11:45 按时送达

当然了,也会时不时加个餐~

我的第「199」篇原创敬上

大家好,我是Z哥。

这是我的第199篇原创,离200篇还有一步之遥。为了庆祝这重要时刻,我也在琢磨着要不要在第200篇的时候搞个什么小活动。还没想好,等下周再看吧。

不过不管怎样,你也应该为Z哥的坚持点个赞吧,哈哈。所以,看完文章后不要忘了划到文末点赞哦~

好了,回到正题。

很多人吐槽老项目是怎么怎么垃圾。这的确是一个很大的问题。根据 IEEE Spectrum 之前发布的一份报告数据:

自 2010 年以来,全世界IT 产品和服务支出约为 35 万亿美元,其中约四分之三用于运营和维护现有的 IT 系统。另外,至少有 2.5 万亿美元用于尝试替换旧的 IT 系统,而且其中约有 7200 亿美元被浪费在失败的替换工作上。

——https://spectrum.ieee.org/computing/it/inside-hidden-world-legacy-it-systems

因此,面对不堪的、充满历史味道的老项目对程序员群体来说会是一个常态。

不过我们可以做些什么呢?难道是要么硬着头皮去填别人挖的坑,要么跑路么?

如果你不跑路的话,最常见的应对方式无非是「重写」或者「重构」。

01  重写

一般来说,越是年轻的程序员越是最喜欢重写。除了年轻气盛的原因外,主要是因为完全摆脱了老代码的技术债和束缚,可以尽情地施展自己的才华。

但是对于老系统的重写,如果没有高层的支持、业务部门的配合,靠谱的开发团队,这事大概率很难能按预期完成。

而且选择「重写」方案不仅仅是重新写一套代码这么简单,系统切换也是一个头疼的事情,在复杂一些的项目里,它的难度并不亚于重写一套代码。

而且一旦选择「重写」,意味着在一段时间内要么老系统并行开发,要么会攒一堆需求,业务方能不能持续支持「重写」也会面临很大的挑战。

就算这些问题都能搞定。「重写」还可能造成的一个结果是:在过了几个月后,重写后的系统又成了别人眼中的“破烂不堪的老系统”。这是最讽刺的……

如果在重写过程中,由于任何原因牺牲了对质量的要求,这个讽刺很容易成为现实。

因此,很多公司之所以不支持重写,理由是:

又不是不能用。

这么看来他们并不是迂腐,也是一种理性的选择,也是没错的。

02  重构

相对地,年纪越大的程序员可能更倾向于重构。毕竟他们有更多的机会见过、经历过那些惨痛的重写事件。当然更主要的原因是,他们掌握了更多应对“垃圾代码”的方式方法,认为通过小范围的代码重构也能化腐朽为神奇,提升项目质量。

的确没错,但这是有一个前提的。就是垃圾代码的产生速度要低于重构的速度。可是对大部分中小公司来说,开发团队可能不具备这样的条件。因为技术好的程序员要么走向了管理岗位,要么身上的重担太多,没太多时间来做重构。再加上技术差的程序员继续复制粘贴,挖更多的坑。通过重构来改善老项目,可能永远在“重构的路上”。

而且,如果项目的技术复杂度大于业务复杂度,那么配合重构的测试成本就很高了。

除了这两种常见的方式外,还有其它的方式也能应对这些老系统。它们的的风险和收益在下图里已经很好地呈现出来了。

a1478_1.png

其实Z哥认为,这些方式我们都可以用,但是要沿着正确的思路来。(绞杀是什么?往下看)

首先从业务角度来考虑到底是选择哪种方案。

  • 从业务敏捷视角来看,能不能让响应力变得更快?
  • 从运营效率视角来看,如何通过系统改造,提升业务运营的效率?
  • 从客户洞见视角来看,如何让系统更好地发现客户洞见,进而更好地理解客户需求和演进产品?

其次是从系统本身来考量,比如,我们想通过改造获得多大的弹性?

最后,根据整体上对业务帮助的价值大小来选择哪一种方式。如果对业务的帮助巨大,完全值得投入大量资源去重写,那么就不要畏畏缩缩的小范围重构。如果对业务帮助很小,那么也就别想着重写了,老老实实在小范围内修修补补就好了。

当你拿捏不准方案的时候,选择按模块替换会是一个不错的办法,相当于通过每一次换一个零部件,把整个机器上的零部件全部翻新一遍,以此完成重写的效果。Martin Fowler 称之为「绞杀法」。

「绞杀法」的最佳实践是DDD+微服务,因为它们可以提供更好的「隔离性」「自治性」,更有利于「替换」的进行。

当确定好改造的方案后,还需要制定度量指标,在实施改造的过程中持续关注这些指标的变化。最好能够通过可视化工具将这些信息共享出来,这样的好处有两点,

  • 一是能够让团队了解改造进展和成果,确保改造朝着正确的方向走;
  • 二是能够让相关的干系人(领导、业务部门)也能了解到工作的进展情况,提高对预期的确定性,以持续获得他们的支持。

关于具体重构方法我就不说了,可以翻看我之前的一篇文章《好的重构方法才能摆脱“屎山”》。

关于重写可以来聊几句,之前我们没聊过。我的建议是遵守以下几个原则。

  1. 系统具备演进的能力。
  2. 凭借度量指标来把握演进的方向。
  3. 小步快速迭代。

01  系统具备演进的能力

既然是重写系统,那么一定要为可见的未来做一些预留,方便后续的演进。毕竟能够决定重写的系统自然是比较核心的系统,不管在技术上还是在业务上都会持续发生变化,注重系统的演进能力就是在降低未来项目复杂度增长的幅度。

具体的方法可以概括为3个词:抽象、分类(分层)、解耦。

02  凭借度量指标来把握演进的方向

前面也提到了度量指标的价值。这里继续强调一下它的重要性。

如果说在重写时期,度量指标是衡量重写工作完成好坏的尺子,那么在重写后它就是指引未来系统演进的明灯。

不管系统后续要做什么升级改造,对自身了解的越清楚,做出的决定和选择自然越合理。而度量指标起到的就是这个效果。

一个缺少度量指标的系统,随着业务逻辑的不断堆砌,很容易自由生长过了头。

03  小步快速迭代

近些年随着CI/CD的普及,小步快跑式的敏捷开发被越来越多人提到,并且开始运用。

它的好处是显而易见的,对项目的可控性更高,容错性更强。

如果你不知道“小步”该多“小”?你就按发布出了问题能不能快速回滚作为标准去考虑就好了。能快速回滚的迭代节奏就是“小步”。

其实重写系统完之后还有一个头疼的事情要解决,就是数据迁移。业界常用的方案有四种,我先大致列一下主要思路,后续再发文展开聊聊。

01  双写

  1. 新库配置为旧库的从库,从旧库同步数据。
  2. 数据写入的时候,不仅要写入旧库,也要写入新库。
  3. 数据校验。
  4. 两边数据完全同步后,灰度切流量。

由于有双写的存在,所以在切换的过程中出现任何的问题,都可以将读写流量随时切换到旧库去,安全感极强。

02  异步双写+对账

这个方案其实是双写的变种,将同步写入变成了异步写入。也因此需要一个对账机制,确保最终一致性的达成。

一般这个异步的机制要么通过 MQ ,要么通过数据库的 binlog 进行。

03  直接用新库,数据惰性迁移

这个方案中间需要架设一个缓存层,用来存放数据的key。过程是这样的:

  1. 先访问新库,如果有数据则直接进入步骤 3 ,如无数据进入步骤 2 。
  2. 访问旧库,找到相应的数据 Insert 到新库,再进入步骤 3 。
  3. 进行业务逻辑的操作……

随着时间的推移,数据慢慢会从旧库同步到新库。剩下还未同步的数据使用同步工具做一次全量同步。

原则上,以上的每一个方案在实际切流量之前都要对数据做核对,确保两边的数据一致。

最后迁移完后可以通过流量回放工具(如阿里的 jvm-sandbox-repeater )或者全链路压测工具来验证新版本的系统是否能运行地符合预期。

好了,总结一下。

这篇呢Z哥和你分享了应对老项目的思路,总的有5种:

我建议根据业务敏捷、运营效率、客户洞见、系统本身的韧性和弹性来考虑选择哪一种。

接下来专门对重写展开细说了一下,建议遵守三个原则:

  1. 系统具备演进的能力。
  2. 凭借度量指标来把握演进的方向。
  3. 小步快速迭代。

最后分享了3个常用的新老数据迁移方案。

  1. 异步双写+对账
  2. 直接用新库,数据惰性迁移

如果你有兴趣进一步了解的话,推荐两本关于重构和重写不错的书给你,《重构-改善既有代码的设计》,《重构与模式》 。可以等有购书满减活动等时候入手。

在我看来,不管是重构还是重写,本质是让数据流转地更通畅。需要在过程中不断审视这一点。


原创文章,转载请注明本文链接: https://zacharyfan.com/archives/1478.html

关于作者:张帆(Zachary,个人微信号:Zachary-ZF)。坚持用心打磨每一篇高质量原创。欢迎扫描二维码~

微信公众号

定期发表原创内容:架构设计丨分布式系统丨产品丨运营丨一些思考。

如果你是初级程序员,想提升但不知道如何下手。又或者做程序员多年,陷入了一些瓶颈想拓宽一下视野。欢迎关注我的公众号「跨界架构师」,回复「技术」,送你一份我长期收集和整理的思维导图。

如果你是运营,面对不断变化的市场束手无策。又或者想了解主流的运营策略,以丰富自己的“仓库”。欢迎关注我的公众号「跨界架构师」,回复「运营」,送你一份我长期收集和整理的思维导图。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK