设计|代码和设计是如何一步步腐化的


地址:
cnblogs.com/xybaby/p/13173047.html
设计|代码和设计是如何一步步腐化的
本文插图

经历了几个从商业角度来看或成功或失败的项目 , 都会发现代码、设计都会慢慢地、在不经意间腐化 。
而且有一个项目开始的时候 , 架构是经过精心设计的 , 也有较为严格的代码规范 , 并且通过静态代码检查来尽量保证代码的质量 , 连code review都有一个可供参考的checklist 。
但半年一年之后 , 还是会发现 , 很多代码都已经臃肿走样 , 到处都是复制粘贴 , 动辄好几千行代码的模块 , 能 work、但不 right的代码 。
getting it work is easygetting it right is hard
不禁想问问代码和设计是如何一步步腐化的?
代码如何开始腐烂 其实大家都听说过 clean code , 但不一定真正意识到其重要性 , 且知道并不等同于做到 , 而时间更是一把杀猪刀 , 让程序员秃了 , 让代码烂了 。
一个新项目开始的时候 , 大家都是满怀壮志 , 期待灵活可复用的架构 , 期待成功的产品 。
与此同时 , 敏捷开发告诉我们不要过度设计 , 当然 , 本身也是很难预料到以后需求变化的方向 , 于是应该等到第一次变化的时候才去考虑如何重构以应对这一类型的变化 。 但问题很可能就会出现在这里 。

也就是说 , 也许哪一天 , 当我们需要加一个新功能的时候 , 会发现原来的设计和代码不是很方便增加这个新功能 。
当然 , 我们不应该过多苛责之前的设计 , 因为以前没有预料到这个新功能 , 也就没有在这个地方引入抽象 。
【设计|代码和设计是如何一步步腐化的】这个时候有两种解决办法:

  • 第一种是重构术 , 就是加功能之前先了解、重构已有的代码 , 比如调整一下类的基础体系、抽象出基类、或者引入一个间接层以隔离变化 。
  • 另一种则是修补术 , 在现有的函数中加一个 if-else(或者 switch case)、在现有的类中加几个特殊字段 。
这两种方法都能解决问题 , 修补术治标 , 重构术治本 , 但显然 , 治标来得更快 , 治本对程序员的要求更高 。
什么时候程序员会选择修补术而不是重构术呢?
也许这个程序员看过 clean code、refactor , 精通设计模式和面向对象 , 也非常希望维护一份漂亮的代码 。 但我们知道 , 重构是需要时间的 , 而且还可能引入bug 。
也许重构耗费的时间就超过了用修补术 workaround 的时间 , 就短期来说 , 修补术的性价比是更高的 。
那么长远来说呢 , 也许重构术的性价比更高?可是只顾眼前、及时行乐是人的本能 , 走捷径、偷懒是无时不存在的诱惑 。

当然 , 也许有追求的程序员会抵制这种诱惑 , 但是社会心理学告诉我们 , 在压力、干扰面前我们很难理智思考 , 自控力也会失效 。
时间、进度压力就是垂悬在程序员头上的达摩克利斯之剑 , 这压力可能让人失眠、让人头秃 , 写点垃圾代码似乎也无可厚非 。
况且 , 重构还可能引入bug , 重构的前提是要有完备的测试机制 , 单元测试、功能测试、集成测试一个都不能少 。
可是 , 理想很丰满 , 现实很骨感 , 单元测试覆盖率往往不足 , 而且还可能依靠手动回归测试 。
把代码重构好了可能压根没人知道 , 没人来感谢你、给你点个赞 , 但万一重构出了bug呢 , 大家都会收到事故报告 , 说不定还会影响KPI?不求有功但求无过 , Leader、经理是否认可重构的价值 , 也很大程度影响组员对于重构的积极性 。
当然 , 增加新功能的也许是一个新手 , 新手加入团队后 , 一般就是从维护某个模块 , 实现一些小需求入手 。

新手有可能水平本身就不行 , 而且业务逻辑和代码都是陌生的 , 如果缺乏完善的文档以及足够的掌握 , 新手是万万不敢重构的 , 修补术是最自然的选择 , 复制、粘贴、稍微修改一下、build、run , 成功啦!又实现了一个需求!你知道 , 新人是急于证明自己的 , 快速的实现一个又一个需求是证明自己的最佳办法 。


推荐阅读