由一个系统重构引发的思考


前一段时间在做某系统的重构,之所以要做这个重构,是因为之前该业务逻辑混乱,维护性差,近期暴露的bad case较多,需要进行整体优化。避免引发更大的问题。
那为什么作为这个系统最重要功能的代码之前会如此混乱不堪呢?这是有深远的历史背景的。

当时的状况 & 背景

一、多人维护没有规范

从git commit历史上看,涉及该功能的逻辑从2016年底上线以来,几乎所有接手过该系统的同学都修改维护过这块逻辑,截止到重构之前一共有10多位同学。大家不断的在最初代码的基础上逐渐新增各种业务逻辑,代码逐渐变的臃肿起来。

二、过分兼容老逻辑

代码中很多地方有兼容老逻辑的逻辑在里面,新老逻辑混杂交织在一起,进一步给可维护造成困难。举个具体的例子,自从该系统收敛操作入口以来,双写老表的操作就长期存在,因为有其他的核心业务场景在使用,所以相当长的一段时间没有下掉,一直到上个月该场景的相关服务才迁移完成。

三、与国际化逻辑耦合严重

该系统不仅提供国内的服务,还提供国际化的服务,而国内和国际化的逻辑渐行渐远,但是在代码中还是只维护了一套,通过各种条件判断来走到不同的逻辑里,进一步加大的维护的困难。

四、历次漏洞改造带来的问题

最后是历次漏洞的修复带来的问题。如之前所说,系统相对来说比较久远,每次修bug都是缝缝补补,但这次重大的逻辑重构也引起了一系列问题,在此不赘述。

综上所述,加之分析代码,我总结原因主要有如下几点,

  1. 对于代码遵循“最小化改动”的原则,对于逻辑变更大的代码块缺乏合理、简洁的设计和实现;
  2. 可能是时间紧、任务重,一些代码的抽象程度很低,代码充斥着许多hard code和copy & paste的痕迹;
  3. 对异常情况的处理缺乏,有些异常的情况没捕获并做一些比如回滚之类的确保一致性的操作;
  4. 对代码的CR不够严谨,且测试case没有覆盖到所有的等价类;

因为上述的问题,随着代码量的上涨(最为夸张的是其中一个简单核心逻辑的代码,在本次重构之前竟然长期保持着接近500行代码),没有人能直接说清楚该逻辑的具体细节是什么,每次出现bad case都需要从头过一遍代码来排查问题,这其实是很可怕的。作为负责该系统的研发同学,对于该系统最核心的逻辑代码都不是很清晰,这是有很大的问题的。

其实这些代码层面的问题之前就有计划修改,但是因为线上没有暴露出bad case,所以大家误认为这件事优先级不高。而最近频频暴露出的bad case,使得重构这件事已经刻不容缓。经过重构,基本解决了上述存在的问题。

思考

这件事引起我的很多思考,总结了一下,主要有以下几点:

扫描二维码关注公众号,回复: 16752955 查看本文章
  1. 对于一个项目,应该有一个规范,写在README中,尽可能保证多人写出来的代码不会成为“千手观音”。
  2. 对于一些老逻辑,该推动业务方修改的就应该推动其修改,不能为了兼容而兼容,这样最终会使代码变得难以维护。
  3. 有时候适当的保持一定的代码冗余是有必要的。其实我感觉这就和数据库范式遵循的原则是类似的,并不是范式越高越好。就以刚才说的国内和国际化的逻辑为例,在这次重构中我将其完全拆出来了。固然,国内和国际化的逻辑是有相似部分的,完全拆出来会有一定的代码冗余,但是,我觉着这是利大于弊的。毕竟相互之间的逻辑不再耦合在一起,也就不会相互影响。在对各自的逻辑进行修改的时候,也就会更加专注,同时少一些条件判断。这样也就不会出现类似“对国内逻辑的修改影响到国际化”这种的事情。
  4. 带着一种对代码遵循”最小化改动“的思想去写代码,是有很大的问题的。因为它会把你自己的思维局限在现有代码的框架中,而缺乏了你自己的想法和设计,这就很容易引起一些bug,也压抑了自己的创造力。所以我个人的想法是,对于代码逻辑的改动,首先一定要很清楚之前的逻辑是什么、有什么问题,其次是我这次要解决什么问题、怎么解决(这里要抛开对现有的实现方式兼容的思想,思考自己是否有更合理的实现),最后是要进行折中,究竟是否要按照自己的新逻辑来重构,会不会有问题,可不可行,改造成本大不大等等。毕竟,任何一个项目要想保证质量完成,就得在需求、资源和时间三个因素间找到平衡。而一旦在需要对代码进行重构的时候,一定要坚决果断的重构。
  5. 异常处理非常重要!这方面我自己也有类似的问题,总是热衷于那些happy pass,而忽视那些exception。这是绝对不可取的。写出能运行的代码很容易,但是能写出在各种异常case下都不crash的代码确实是需要一定的能力和积累。
  6. 对代码的CR很重要,CR本身的目的就是发现问题,如果什么问题都发现不了,或者只能发现很表层的问题,那我觉着这种CR是没有什么意义的,仅仅是个形式,而我们要避免把它当成一种形式,要能真正发现问题。但是也要提醒一下:for reviewer,开发者不是冤大头。评审的目的不是证明谁是更优秀的程序员而是查找缺陷,并确保代码是简单和可维护的;for coder,它不是个人的事情,不要感情用事。别人说的不是,是代码中的缺陷或不足,而不是你。意识到你和你的代码是捆绑在一起是正常的事情。如果你为自己的工作感到自豪,那是一个很好的迹象,说明你是一个关心作品的人。有适当的自我、足够信任和捍卫自己的观点,但又不至于盲目拒绝对方的好建议和意见。人非圣贤,孰能无过。评审者作为第二双眼,可以指出你可能忽略的事情。问题与具体建议一样有价值。

注:本文写于2019年,原文发布于某公司内网,现脱敏后发布于此。

猜你喜欢

转载自blog.csdn.net/gongchenyu/article/details/122501670
今日推荐