数值风云

软件工程当中的一个难题——技术债的管理

为什么会产生技术债

通常来说,研发人员开发代码的时候,都是先理清需求动机、做好设计,实现上则是先调通功能,再做重构。不少成熟的项目,如果功能实现不够成熟和稳定,是不会贸然发布的。

抛开需求动机和设计不谈,实现上需要三天调通的工作,如果有五天到七天的工期,有技术债管理的动力,那么大部分开发者是能够尝试做一些重构和抽象的。我相信相当部分开发者有追求写好代码的动力。反之,如果只给三天,甚至早上的需求晚上就要上线,且不说需求是否合理不会分析,实现不经设计就是实现本身,也只会停留在调通的阶段。甚至由于必要工期的缩短,通过损害其他功能非热点路径的方式先搞定当前的需求。典型的,比如代码开洞和过度暴露底层细节。这样就产生了技术债,技术债指的是为了加速软件开发,在应该采用最佳方案时进行妥协,以未来风险交换了短期的软件开发速度的方案

实际上,我并不反对糊代码调通功能,这其实是大部分软件开发的必经之路。先写对,再写好。但是削减了开发工期,这些开发人员心中明知未来会踩坑的阴暗的角落,就会越积越多,直到某一天爆炸。

技术债之所以难以衡量:一方面是其延后生效的特性。也就是说,对于当前的开发任务来说,这实际上是最经济的方案。确实也有技术债虽然丑陋,但是运行十余年也没出现什么问题,也没有修改需求的例子。由于未来需求是很难预测的,提前判断技术债是否会造成实际影响的几乎不可能;另一方面,在于其难以衡量。虽然目前业界能够衡量代码风格、测试覆盖率和圈复杂度等等指标,但是这些并不是技术债的充分条件,甚至不是必要条件。比如追求测试覆盖率 100% 就很没意义。很多时候,认识到某个实现是技术债,是后面那个接到变更需求的人碰到一坨屎山才能发现的。

而依赖人的判断来认定技术债,就会引入很复杂的管理问题。试图通过合作的进化式的互惠策略来达成群体最佳结果,也很容易因为人员流动(换岗、离职)之频繁,使得当前刻意行为带来的长期好处不高而破灭。更重要的是,中高层乃至基层管理人员,往往意识不到技术债的存在或者无法估计出债务规模。

从而导致在一个典型的科层制组织环境下,所有人没有任何动力思考和解决技术债务问题,并且对于开发任务本身,采取造成(海量)技术债务的方案是最优解。这样的环境下,软件质量快速腐化以至于无法迭代,OOM / Panic / DATA RACE 频出,也就不奇怪了

技术债之所以难还:主要原因是软件框架不够抽象,模块间耦合关联性高。单个孤立软件(或独立功能模块)的技术债容易还,实在不济就是重写。难的是系统性、结构型、spec 级别的债务。上层依赖一大堆,上去难下去更难,无损迁移难上加难。

如何面对技术债

技术债不可能杜绝,我们能做的是正视技术债、评估技术债、管理技术债:搞清楚现在技术债有多少,评估需要花费多少人力时间来解决。重构和模块化以减低新人上手的门槛并提高开发效率,应当作为工作立项的一部分。

要考虑需求是否要变更以及代码的生命周期来看是否构成技术债。对于许多高风险的实验性的(可能是见光死的)项目,这种代码生存周期太短,只要最小成本的做到可用就可以了,算不上债而是当垃圾丢掉了。需求频繁迭代而且要维护很长时间的代码,就需要经常性的拿出来评估重构,这是一定要争取时间出来还债的。不然就会因为公司对技术团队的不满,有一天整个团队被取代。发生组织架构的大调整,接手的人从头开始设计重构了。

这是一个软件工程的整体问题,整个研发部门都要考量起来,决策层和分管领导也应当要关注。


本文整理自推文及其相关讨论(已授权):https://twitter.com/tison1096/status/1521758171928223744