如果你想要使技术债务的概念真正生动起来,就要有一些数字支持。
当Ward Cunningham提出技术债务时,他需要一种方法来讨论在项目早期做出的决策,这些决策会在工程师们继续开发时开始困扰他们。他当时在一家做金融软件的公司工作,所以需要一个财务隐喻。为了尽快推出产品,他们在早期做出的技术决策可能不再适用,除非修正这些决策,否则团队的工作效率就会受到影响,发布新功能的速度也会变慢。
这个比喻已经流行开来,几乎无需解释。很多成功的公司都是利用技术债务起家的,只是后来还清了债务。例如,Facebook 最初是用 PHP 编写的。最初的实现对其当时的需求来说是可行的,但随着功能、复杂性和规模的增加,他们需要偿还 PHP 的巨额债务。值得注意的是,技术债务并不一定意味着你最初的选择是错误的。最初用 PHP 编写网站并不是一个错误的决定—这并不是一个后来受到糟糕代码影响的案例。PHP是一种不错的语言,但公司逐渐发展超越了它。
事实上,阻碍人们从过时的框架或库中升级的并不是技术问题。与这个比喻一样,主要障碍是资金问题。我见过很多升级因为需要安装、转换代码和测试升级效果而搁置多年。与此同时,未修补的安全漏洞可能会让你的系统变得脆弱,而你无法获得的新功能可能会让你的应用程序在市场上处于不利地位。不过,总有一天,这个账单将会到期。
显然,技术债务不仅仅是语言和工具的更新。它可以是为了获得即时利益而做出的善意编码决策。越早解决技术债务越好。但要解决这些债务,你需要进一步深入研究技术债务,并准确量化你的工程团队承担了多少债务。
维护时间成本
开发人员喜欢解决问题,但这种热爱并不总是延伸到寻找错误和替换过时的技术上。不过,有些人则会乐于代码重构,创造出完美干净的代码。不管你的个人感受如何,管理层才是决定下一个迭代的任务和项目的关键。而管理层的想法与普通开发人员不同。
开发人员可能追求极致优雅的代码,但管理者(以及他们之上的高层管理人员)是为业务服务的,而业务通常关注的是利润和亏损。要还清技术债务,首先需要从成本和收益的角度来考虑,以适应当今的数据驱动和基于项目的开发周期。
技术债务的经济影响是真实存在的。Stripe在2018年进行了一项研究,试图衡量技术债务和其他“糟糕代码”效应的影响。他们发现,开发人员平均在技术债务上花费了13.5小时,而在“糟糕代码”的处理上会花费近4个小时。如果将开发人员每小时的工资乘以这个数字,那么技术债务的成本就相当可观了。
源自 The Developer Coefficient
Chelsea Troy曾撰文指出,“技术债务 ”一词并不准确,并提出了 “维护成本 ”作为替代。过时的技术和为了效率而做出的牺牲都会产生质量上的影响;也就是说,它们在某些时候会让人感觉不好。但团队花在非功能代码上的时间有多少?这是一个可以制定预算的指标。
正如Software Engineering Stack Engineering网站上的某位网友所说:”质量差的代码往往由于复杂性而需要更长的时间来维护,而且通常错误数量也很高。因此,低质量最终会严重影响管理者的价值”。大多数公司都已经使用了某种问题跟踪系统,因此想要提出自己理由的开发人员可以利用这一系统。这只需要在跟踪问题单、估算故事点和证明维护技术债务所花费的时间方面遵守纪律。至于是否将所有债务汇总到一个大型任务中,这取决于组织的需求;更重要的是与跟踪与技术债务相关的具体行动。
这些可以适用于那些你已知的维护成本和现存债务。要确定特定债务领域的影响,需要查看代码。Andy Dent在Stack Overflow上建议跟踪哪些代码片段进行了最多的提交。他写道:“进行这样的数据挖掘,还可以识别代码维护时间的聚类,并将其与跟踪系统中的缺陷修复情况进行比较”。
不过,你也可以直接问你的团队。Stack Overflow的工程总监Roberta Arcoverde表示:“这可能听起来很天真,但这背后有实际的数据和科学依据,解释了为什么这通常与其他更复杂的技术一样有效:如果团队认识到某件事情很重要,他们可能最近花了一些时间在上面—这就是为什么它是最重要的—或者代码太糟糕了,以至于他们能够迅速记住它。”
当然,这些只是为修复和维护债务而编写代码的成本。另一个重要指标是你没有编写的代码。
机会成本
如果开发人员将近一半的时间都花在了技术债务和糟糕的代码上,这就意味着他们无法向客户交付新功能。对于近来痴迷于开发速度的软件行业来说,这是一件大事。开发新功能的速度越快,就越能满足客户的需求,对产品的附加值也就越高。反之,如果发布功能和修复推向市场所需的时间越长,就越会落后于竞争对手。
开发速度主要集中在软件开发生命周期(SDLC)的 DevOps 方面: CI/CD、代码审查、构建流程等等。在这方面,DORA 指标 是一个很好的指南。但是,任何技术债务都会影响到编写代码所需的时间,尤其是当你为了避免处理拖累你的技术债务,而编写了增加代码路径—圈复杂度的解决方法。这种复杂性本身就会成为你可能需要在某个时候解决的一笔债务。
复杂性与开发人员的工作效率之间绝对存在联系。随着代码变得越来越难以维护,新功能的发布也需要更长的时间。代码库中需要修改的地方越多,所需的时间就越长。这就是DRY 和KISS等激励性缩写词受到追捧的原因:其他人需要阅读这些代码,所以他们越容易阅读就越好。越容易阅读,就越容易修改。
有时,技术债务来自于过时或基于旧版本软件的善意技术决策。更新这些决策可能需要更大规模的重写,而不是简单的重构。在他的回答中,Michael Meadows 指列举了一些可能需要进行重写的情况,包括:
- 相关软件已被淘汰或即将被淘汰,或者有更好的替代品可用。
- 无法完全自动化部署。
- 测试耗时过长、无法自动化或无法覆盖重要功能。
虽然 DORA 指标可以提供帮助,但你也可以将当前的开发速度与努力冲刺的最佳故事点进行比较,这通常在软件生命周期的开始阶段。Doug Knesek 写道,这可以被视为对技术债务所支付的利息。随着债务的增加,支付利息的负担也会越来越重,最后可能会超过本金。在软件组织中,随着技术债务的增长,用于偿还这些利息的时间和精力也会增加。整体开发速度越慢,交付给客户的新功能就越少。
当然,技术债务的成本并不仅仅体现在代码上。它们还会影响到编写代码的人员。
人力成本
软件公司(现在几乎每家公司都是软件公司)一直在激烈争夺顶尖技术人才。寻找和入职一名新员工的成本可能高达六到九个月的薪水。难怪这么多公司都在关注开发人员的经验:招聘一名新开发人员的成本很高。技术债务会影响专业技术人员在工作中的每一步,从他们坐在新键盘前的那一刻起就开始了。
入职培训是员工在公司体验的第一步,也是最重要的一步。让一名新员工尽快适应工作需要一到两个月左右的时间。糟糕的入职体验会让开发人员对公司产生反感;20% 的开发人员会在入职 45 天内离职。因此,顺利的入职体验意味着软件工程师是否能愉快地工作。
开发人员适应所需的时间取决于你现有的文档和流程,以及代码库的复杂性和可读性。缺乏流程文档本身就是一种债务。你知道在某些时候你会需要它,但为了快速上手,你跳过了它。任何新员工都必须四处打听,占用高级工程人员的时间来帮助他们熟悉。
一旦开发人员上岗并准备好提交代码,他们可能会发现自己对堆积如山的混乱代码感到沮丧。我听说过一些朋友被特立独行的编码方法搞得晕头转向,这些方法使得代码难以解析,比如将所有参数连接到一个变量中并将其传递给某个函数。这就变得令人沮丧和士气低落,因为你要不断地花时间去弄明白这段代码到底是怎么回事。
显然,技术债务不仅仅是需要重构以符合最佳实践的代码—过时或低效的工具和依赖关系也会让开发人员感到绝望。试想一下,你正在编写针对较旧版本的Java代码,却发现一个令人困惑的解决方法。“我以为 Y 版本已经解决了这个问题?“是的,但我们还在使用 X 版本。升级还没有得到批准”。
当你没有使用最适合工作的工具时,你的技能可能会退化。在开发人员去留原因调查中,我们发现 35-40%(根据地区而异)的人表示,他们正在寻找新工作来使用新技术,另外 35-40%的人提到了成长机会。
所有这些因素都会导致离职。如果你的公司人员流失频繁,或在第一年内失去员工,那么这就是一个机会,看看技术债务是否是问题所在。确保进行离职面谈,并跟踪他们提供给你的所有数据。如果这些债务让你失去了优秀的员工,那就有理由在下一个迭代中优先考虑它们。
计算你的债务
技术债务是一种比喻,因为它将工程问题转化为商业语言。如果你想还清这些债务,那么你就需要用商业语言来说明这一点。成本是多少?有什么坏处或好处?任何商业决策,总是要权衡利弊。
与金融债务类似,未偿还的技术债务会随着时间的推移不断困扰你,你将花费越来越多的时间来解决其带来的影响。糟糕的代码导致更糟糕的代码,利息会累积到本金上。你总有一天需要偿还债务,但如果你现在能更好地处理这些债务,你就能有更多的喘息空间来编写令你自豪的业务逻辑代码。