技术债务的类别
技术债务是软件开发中用于比喻短期决定促使长期成本增加的现象,其中成本的增加类似于随时间增长的应计利息。更确切地说,团队当前为某个决定付出的工作越多,后期就越可能需要更高的工作量来纠正这个决定。
这一术语在软件行业内获得了不少的关注,但技术债务不是百害无一利的,它有时也能快速解决产品上市的问题。这个概念最早是由 Ward Cunningham 提出的:
有两个重要的点需要注意。首先,技术债务往往是软件交付过程中很有帮助的权宜之计。没有任何产品时完美的,无数软件项目都曾过于沉迷“打磨”短期内完全够用的代码而就此消失。第二点则是,在长期可支持性面前,这些权宜之计可能会需要重新考量。
不过,我们还需要对“技术债务”这一词有明确定义才能避免引起混淆。Kruchten、Nord 及 Ozkaya 在他们的《管理技术债务》一书中,对技术债务的概念及相应管理方法做了很好的概述,这是他们给出的定义:
这种定义深得我们喜爱,因为它更侧重于技术债务的影响,而非是其在金融债务方面的比喻,后者仅仅涵盖了部分问题所在。正如《实践中的持续架构》所言:
感兴趣的读者可以参阅注 2 中的《管理技术债务》,以获取关于该主题的更多内容。也可以在《管理技术债务》、《技术债务》,《技术债务和利息的实证模型》的参考文献部分,以及 雷曼法,找到更多关于技术债务的实证研究。
什么是技术债务?
依据 Kruchten、Nord 及 Ozkaya 的定义,技术债务可以分为以下三大类。
此外,技术债务可以是无意为之,也可以是特意为之。许多业界人士认为潜在的缺陷是技术债务的一部分,而架构决策则几乎永远是在两个相互冲突的 QAR 之间权衡,因此后者是属于“有意为之”的分类。
技术债务一词的不足
每个术语都有不足,“技术债务”也不例外。
相比之下,软件团队的限制较少。自动或手动的架构、设计,以及代码审查之类都可以防止技术债务意外发生。但在复杂的系统中,审计无法找到的很多错误只会在运行的系统中出现。错误预算或许能让团队在解决缺陷之前不再新增更多功能,但它的前提条件是要能识别出错误,而技术债务就像是水下冰山,大部分都是看不见的。
但是在多数情况下,开发团队可以随便“发布”任何包含有意为之的技术债务,而不会有人要他们为自己不可持续的决定负责。事实上,如果他们在面向项目的资金模型组织中工作,那么他们要做的就是把项目发布到生产中去,让 IT 运维去头疼因此产生的问题,成功让自己甩锅。
架构决策和技术债务
正如我们在前一篇文章中所述,软件架构是 QAR 驱动的决策,而这些决策可能对技术债务有积极或消极的影响,如图一所示。决策发生的时间决定了团队架构设计所要采取的方式。在项目之初,通常也是在确切定义 QAR 之前,便做出多数的架构决定,可能会导致前期架构不易发展,且随着对 QAR 更准确的定义,也需要大规模重构。与之相反,如果在敏捷架构中的每个阶段,逐步做出架构决策,可以更好地适应 QAR 的变化。
几乎所有的架构决策都是至少两个 QAR 之间的权衡。如安全性与可用性之间的抉择,无论怎么选都有可能增加技术债务,无论是优先考虑可用性但使系统更加脆弱,还是优先安全性但牺牲系统可用性。说到底,随着用户数量的增加,或者需要调整 QAR 的优先级才能让技术债务更可控,将来的某天我们总要面对这些问题。其他例子还有可扩展性和可修改性、可扩展性和上市时间。
这些决定通常被描述为“满足”,也就是“足够好”。虽然你还可以做得更好,但你选择在结果足够好时就停下来。正如《实践中的持续架构》中所言,“架构决策可以增加或削减技术债务”【注 5】。然而,具体增加或削减了多少,这是很难用财务甚至技术术语来量化的。
除非团队成员非常幸运或者知识极其渊博,否则无论是通过什么方法,他们所做的部分技术决策可能都需要根据反馈回路所带来的信息(见图一)在未来进行调整甚至彻底重做。对现有的架构决策进行调整或重做会产生额外工作量,并与其他积压的任务相竞争,后者常被期望能向利益相关者提供有用功能而被认为拥有更高优先级。因此,调整或重做架构决策相关的工作可能会被推迟,从而进一步增加系统的“技术债务”。
质量属性、架构决策、技术债务与反馈循环
每当团队做出决策时,都要做好所有这个决策相关工作在未来都可能要返工的准备。因此,团队需要将决策视作是需要在相当短的时间内验证或需要的假设,以确保所作的工作在未来的某一时刻不会被删除。
因为所有工作至少在验证之前,都有可能产生额外的返工工作量,所以,团队可以尝试以下几点:
了解并接收决策对技术债务的影响有助于团队更好地做出决策。但由于其很难通过财务术语量化,技术债务对评估决策成本没有帮助,且很难被用作是评估至少两个 QAR 之间权衡的精确评估工具。
让我们再回到安全性与可用性的例子。要想在短时间内部署一个 MVP,我们很难估算最小可用架构(MVA)在优先可用性而非安全性时所带来的财务影响。更好的方案是做出一系列最小化决策后,随着时间的推移,借助经验对其进行测试和发展。这些决策应当搭配一套最小架构实践加以补充,以帮助团队在发展产品的同时保持架构的可行性。
当然,架构工作中最重要的一部分就是沟通,即使我们无法将与决策相关的技术债务数量进行准确量化,还是可以利用这一比喻可以帮助团队沟通决策的长期影响。
延迟维护:或许是更合适的用词?
技术债务在工程界有另一个说法:延迟维护。延迟维护是设计优秀的大桥断裂、设计优秀的大楼坍塌、设计优秀的飞机从空中坠落的原因。在物理学中,熵的增加是有代价的,而如果无法领先熵的增长将会产生灾难性后果。
分析物理学延迟维护成本的优势在于,我们能更清晰地看到维护被推迟时,成本是如何快速累加的:如果底层钢板没什么问题,那么密封图层就足够了。而一旦钢板开始锈蚀,在重新喷漆之前就必须先清理干净旧涂层和铁锈。如果钢板已经出现裂痕,那么就还需要加固,裂痕过于严重甚至还可能需要更换全部的结构。
对于软件来说,事情远没这么简单。错误不易被检查发现,再加上组件之间交互导致返工可能影响到全部代码库。即使是“简单”的组件替换也会非常困难,因为新组件可能有副作用,或者需要不同的参数数据,而调用它的代码可能无法访问这些数据。如果变动的是如调整算法等更深层次代码,那么成本将会是指数级地增加。
但就如“维护”一词也是有限制的。“维护”通常是指对磨损部件的简单维护,但软件不会随着使用而磨损。软件的变化可能由外部事件引起,如操作系统或框架的变化、供应商倒闭,或者基础设施软件的新版本,以及更具破坏性的,由客户行为、商业运作或组织战略变化等造成的影响。
每一种用词都有其局限性,有时我们必须抛弃这些术语,才能找到更好的模型来帮助我们做出决策。
结论
多数团队并不认为目前的决策在未来可能会被撤销或返工,但现实中事情总会发生变化,而我们需要不同的方式以面对这些变化。虽然团队无法预测未来,但他们可以通过实验,在变更所带来的影响变得无法接收之前检测出这种可能性。
技术债务是对未来变更工作量已知的一个例子,常发生于团队决定推迟必须要完成的工作量。债务一词意味着,处理这类变化所需的成本将会随着时间的推移呈指数上升,与复利类似。但矛盾的是,正如我们在本文中所述,技术债务很难用财务术语进行量化,这也限制了它在决策评估成本模型中的作用。
虽然技术债务有助于向利益相关者传达团队决策的技术影响,但更合适的方法是通过质量属性要求重塑讨论,让利益相关者将其看作是软件系统必备的能力,而非是需要完成的工作量。
最后,感谢 Thomas Betts、Murat Erder、John Klein、Philippe Kruchten 以及 Eoin Woods 为本文的初版审阅。
尾注
原文链接 :top="4989">相关阅读:
中台是企业架构的又一次实践吗?
企业级业务架构设计:方法论与实践学习笔记二
阿里是如何使用分布式架构的?阿里内部学习手册分享
Github 限时开源!Alibaba 最新版亿级高并发系统架构