重写?重构?

今天看到Gu Lu的Blog《知乎回答:入职后发现项目组代码异常混乱,是去是留?》中谈重写还是重构的问题,说的很好, 读了很有些感触。重写与重构的抉择问题存在于很多公司,尤其是创业企业。下面说说自己的意见:

先说结论:如果是功能单一的某模块,重写问题不大,而复杂系统在绝大多数情况下,都不赞同推翻重写。

原因如下:

  1. 复杂系统的推翻重写需要投入的开发资源很大,周期很长才能见到效果。对企业来说这是一种孤注一掷的赌博,风险很高。
  2. 而且重写期间,旧有系统得不到根本改进,公司要冒着长时间内业务需要的技术支持无法得到改善的风险。
  3. 还有,看到过的推翻重写的复杂系统,很多没什么好结果。不少重写出来的东西同样百病缠身,甚至还不如原有系统。

做出重写或重构的决定很容易,但真正让一个系统能有提高,真正让一个团队能更进一步,需要的是一些更深层次的改变。

 

  1. 重构应该贯穿代码开发的始终
    好的代码是改出来的,代码需要不停的重构, 重构应该贯穿代码开发的整个阶段。很多人能在创业初期迅速开发出能工作的系统,但他们把这期间的遗留的问题称为技术债务,总希望能抽出专门的时间来解决它。这种事自己也做过,但现在不赞同专门抽时间重构,而是认为重构应该贯穿开发的始终。这之间的差别貌似很小,其实是开发方法上的本质差别。
  2. 自动测试
    当面对的是一个很庞大复杂的系统, 很难在短期内通过简单的阅读代码就彻底读懂它。这时你的一些改动如果没有测试去做检查,那弄不好就会造成系统的一些很严重的问题。 这个问题在代码缺乏良好的风格,缺乏良好的架构情况下会更突出。但如果手工测试的话,过程会很漫长,会造成整个系统迭代速度极其缓慢。而且手工测试本身也是有不低的错误率的。 复杂系统的重构必须要有自动化测试做保障。单元测试的技术已经很成熟,而seleniumappium等测试工具的出现则为为浏览器,app等终端产品UI的自动测试提供了很好的手段。robot framework等测试框架的出现,则为搭建自己的测试系统提供了很好的支持。而云技术发展,则为搭建可自动缩放的测试系统提供了很好的基础。 当几百个测试用例可以在半个小时就全部跑完的时候,重构的迭代速度会大大加快,而且会是有质量保障的速度。
  3. 可测试性
    代码的可测试性大家谈的不多,很多编程名著里见不到他的踪影。代码的可测性可能在开发简单系统,比如单机软件时还不那么重要。但在开发复杂的系统时,当你需要重构它的时候,可测试性的重要性怎么强调都不为过。 当你重构出现问题时,可测试性好的代码应该能让你迅速发现问题,定位问题。可测性不好的系统,自动测试的意义会大打折扣。至于什么是可测性,大家可参看同济大学的朱少民老师写的一个非常好的ppt:谈软件可测试性,这里就不重复了。可测试性不只是有利于在开发阶段调试代码,在生产环境中,可测试性好的系统也有助于迅速发现定位问题,减少问题造成的损失。
  4. 其他
    1. 持续集成
      有了持续集成,你就可以从打包,到测试,到生产环境部署都可以全自动化完成。 一旦发现问题可以立刻自动回滚。
    2. 在线生产环境监测
      应该建立一套生产环境监测系统,并不断完善,一旦发现问题立刻发出警报, 甚至能自动做一些自动应急修复错误。

 

做好上面几点,重构就可以放心大胆的进行。否则重构也是很冒风险的,这也是为什么很多公司都有些大家都不敢动的老代码的原因。

说到底让团队能做好重构工作,是要在团队里建立一种开发文化:

  1. 产品快速构建,小步快速迭代
  2. 重视测试,重视软件工程

===========================================

曾经做过很成功的一次重构,在半年后旧有代码已经很少,几乎90%以上都是新代码,系统性能和稳定性都大幅提高。有可能从半年后的视角,会觉得这是一次重写,但这其实都是每天一点点重构带来的。整个重构的过程系统不断稳步提升,整个改变平滑顺利。除了重构代码的工作,还做了不少别的:

  1. 当时重构工作开始的第一天,就安排专人开发自动测试系统
  2. 后来又开发了生产环境的监控系统
  3. 给系统增加了不少专用的监测接口
  4. 当时业务人员遇到问题常常直接捅到开发这边来,后来给系统增加了一个接口,能迅速帮助业务人员定位是使用错误还是系统错误,如果是使用错误是具体什么错误。增加这个接口后,从业务那边过来的技术支持压力一下少了很多。这也算是增加了整个系统的可测试性。
  5. Gulu文章中提到的幽灵替补,灰度发布的方法都用到了

也有些方面没做好:

  1. 当时的持续集成一直想做,但因为各种原因一直没做起来,真正持续集成是在现在的公司才做到
  2. 当时的自动测试系统只能做基于Web API的测试,UI自动测试做了尝试,一直没真正做起来。这也是到了现在公司才真正知道怎么做。
  3. 柔性服务的思想很好,当时没想到,希望以后能试试。