来源:     作者:     发布时间:2021-07-31     次浏览

许多团队都背负着技术债务,但很少有人能够真正设计出摆脱它的计划。为了更好地理解如何摆脱债务,我们首先要正确理解什么是技术债务。

技术债务是由于团队为了短期项目利益而做出错误的技术决策造成的。例如,为了更快地将产品推向市场,团队可能不会像面对一段棘手的代码那样编写深入的自动化测试。或者他们可能决定基于一个很快就会过时的框架来构建一个项目,而不是为该框架的升级、支持更好的版本付费。不管做出什么决定,关键是要意识到真正的技术债务是团队为了获得短期利益而故意做出会导致长期债务的决定。

这意味着我们通常归咎于“技术债务”的许多事情实际上根本不是债务。例如,随着系统年龄的增长,团队将无法始终保持最佳编码实践。在这种情况下,位点是正常的,而不是债务。或者,团队自愿做出的技术决策在后续实施中被证明是错误的,这不是技术债务。无论哪种情况,团队都不会为了获得短期利益而故意做出糟糕的长期决策。这种差异很重要,因为只有当我们就技术债务的构成达成一致时,我们才能就如何减少技术债务做出最佳决策。

考虑我们无意中引入代码库的债务的影响也很重要。但是,由于这种债务不是故意承担的,我们无法提前计划如何解决。在这些情况下,当我们发现债务时,我们必须优先考虑并解决它……就像团队在遇到新错误时所做的那样。

我们经常将技术债务与金融债务进行比较。但这是一个等价的类比吗?例如,如果我们不首先确定何时以及如何还款,银行真的愿意借给我们吗?可能不是。既然我们真的不能不先描述如何偿还债务就借到金融资本,我们就不应该这样对待技术资本。

这个财务比喻确实非常有效,所以我们将更充分地讨论它。

就像金融债务一样,在谈到技术债务时,我们需要确定两件事:如何以及何时偿还债务。

我们以前面提到的放弃自动化测试为例。如果我们的团队自愿决定放弃为棘手的代码段编写自动化测试,以便尽快将功能投入生产,那么我们需要确定如何纠正该债务。在这种情况下,我们只需要明确表示我们将在未来某个时候回到这段代码并添加测试。然而,仅仅说“我们稍后会添加测试”并不能合理地解决问题。为了帮助利益相关者真正了解我们的决策将如何影响产生的技术债务,我们需要尽最大努力准确解释稍后添加自动化测试的影响。例如,我们应该指定要添加测试的代码片段。我们还需要明确的是,在创建代码段时,向现有代码段添加自动测试总是比直接添加测试更困难和成本更高。最后一点很重要,因为它明确指出,如果我们将工作推迟到以后,我们实际上会比现在直接完成它花费更多的钱。换句话说,... 债务产生利息。

在讨论了报销方式后,团队及其利益相关者可能会意识到,这个问题比他们在编写代码时是否应该编写自动化测试更为复杂。事实上,他们可能会发现,在两个极端之间,他们确实有多种更适合整个项目的选择。例如,他们可能认为使用“圈复杂度”等指标来识别新功能最复杂的部分是有意义的,并立即添加测试以覆盖这些方面,同时推迟较简单的部分。或者,他们可能决定可以立即添加更简单但价值较低的自动化测试类型,如单元测试,但更困难的自动化测试,如自动化用户验收测试,可以推迟到未来的冲刺。无论哪种方式,

除了指定如何偿还债务外,我们还想指定何时偿还债务。一般来说,还款越早越好。为此,最好在债务发生时安排还款,以便更好地传达债务承诺的影响。例如,如果您的团队遵循冲刺计划,您可以选择将工作安排到下一个冲刺,或者最坏的情况是不超过几个未来的冲刺。

通常,团队有最好的愿望,即在债务来临时还清债务,但他们似乎从来没有时间这样做。当你需要消除债务时,在你的日历上写下最后期限并坚持下去。

我们金融比喻的最后一部分是弄清楚如果我们选择违约会发生什么。在金融方面,如果我从不偿还汽车贷款,银行就会把我的车开走。还应明确技术债务违约的后果。

让我们继续自动化测试的例子。如果团队决定不偿还其技术债务,基于现有未经测试的功能构建新功能只会使其变得越来越困难和成本高昂。在生产环境中,我们可能会看到更多的错误报告,这意味着客户可能对我们的产品质量有不好的印象。我们对市场变化的快速反应能力也会减弱,因为我们的大部分产品要么难以快速修改,要么风险太大而无法快速修改。

以上所有要点都需要向利益相关者明确,以帮助我们避免技术债务违约的诱惑。

到目前为止,我们所有的讨论都集中在计划的技术债务上,这是团队作为正常项目的一部分有意招致的。如果我们不讨论计划外的技术债务,我们就会被遗弃,因为它们也困扰着许多项目:比特衰减。

如前所述,比特衰减不是我们故意引起的。我们无法决定如何以及何时提前还款。从这个意义上说,它不同于正常的技术债务。然而,虽然我们不确切知道我们的项目中会出现怎样的位衰减,但这并不意味着我们不能为它做计划。

正如我们计划偿还已知技术债务时所做的那样,我们也可以在我们的项目计划中添加一个缓冲区来处理每个 sprint 中的位衰减。虽然当时我们可能不知道填充这个缓冲区的具体任务,但是在那里有这样一个缓冲区,给了我们一个特殊的空间来处理那些计划外的问题,比如 bug,必须立即处理的小规模重构,或者小规模的重构。 - 规模系统维护,我们称之为代码库的自然老化和衰减。

但是,如果在几个小时的开发时间内无法解决更大的问题呢?可能还有更多系统性问题困扰着我们,比如基础设施故障或架构老化无法满足业务需求。因为这些问题太大,不容易解决,我们可以利用这个缓冲区来确认和研究这些问题,以便在以后的项目中给予应有的重视。例如,在基础设施发生故障的情况下,也许我们可以确定基础设施中最常发生故障的部分,以便我们可以将故事添加到待办事项列表中以替换这些部分。然后,我们将优先考虑正常开发并相应地安排这些故事。或者,对于老化的架构,我们可以花一些时间来确定我们可以动态地对架构做出哪些最有价值的更改,然后将这些更改分解为可以在未来 sprint 中分段处理的故事。无论问题是什么,有时间确定它并制定计划意味着它可以像任何其他技术问题一样得到解决。

既然我们对产生技术债务的影响有了更好的理解,那么我们如何才能真正保证技术债务的偿还呢?为了对此有所了解,我们将财务比喻扩展到另一个方向……预算。

我们中的许多人每隔几周就会发一份固定工资。这个工资是年薪的一部分,全年平均分配。例如,如果我们一年赚 52000 美元,我们可能每两周赚 2000 美元……也就是说,一年 26 次。不过,虽然按照规定,我们每次都能拿到2000美元,但我们不太可能把它全部保留在我们的活期账户中。相反,我们更有可能只保留一部分在经常账户中,其余用于长期投资或偿还债务。例如,我们最初节省了 2000 美元,预算细目实际上可能如下所示:

500美元用于长期投资,例如退休账户,200美元用于短期债务,例如信用卡,300美元用于长期债务,例如抵押贷款或汽车贷款,250美元用于直接扣除,地方税或国家税,剩余的 750 美元用于活期账户

现在,虽然没有人对这种安排特别兴奋,但几乎没有人怀疑。在某种程度上,这几乎是公认的规范。既然这样的安排被广泛接受,为什么不把它扩展到我们的项目计划中呢?想象一下,我们正在计划基于故事点的冲刺,并且我们已经为该冲刺分配了 50 个故事点。虽然我们希望把50点全部用在新的开发上,但其实最合理的方式是安排一些点数来偿还技术债。例如,对于原来的50分,我们可以决定安排:10分技术债偿还,5分不间断代码库维护,例如bug修复或处理位衰减,35分用于新开发

查看我们的点预算,我们可以看到它与我们之前描述的财务预算有一些明显的相似之处。虽然我们每个 sprint 有 50 个积分,但并不是所有的积分都用于新的开发。更准确地说,我们必须用其中的 10 个积分来偿还我们故意产生的技术债务,就像我们用部分工资来偿还长期和短期债务一样。另外,我们用5分来持续维护代码库,就像我们用每份工资的一部分交税来帮助维护我们社区的正常运作一样。剩下的点是我们自己的,可以根据我们的意愿用于任何新的开发。就像剩余的钱存入往来账户一样,我们可以根据自己的意愿自由支配。

通过制定预算,我们可以确保我们的项目仍在向前推进,不会让它在技术债务的重压下崩溃。

当然,就像个人预算一样,这种预算也会有偏差。例如,如果我们比预期更快地偿还技术债务,我们将有一些剩余的故事点可用于新功能的开发。同样,如果我们发现自己背负了大量的技术债务,我们可能需要放慢新功能的开发速度,直到技术债务的数量回到更可控的水平。

用金融债的类比来考虑技术债,我们可以更理智的判断什么时候会发生技术债,有利于项目的改进。随着项目的进展,我们也可以更好地规划试图偿还债务的影响。

此外,通过在日常工作中规划我们的日常预算,我们可以更好地了解我们的债务什么时候是可控的,什么时候会让我们负担过重。


在线客服

关闭

客户服务热线

在线客服
网站地图