无论债务是怎样累积起来的,你都必须偿还。
本文最初发布于 Kyle Brown 的个人博客,经原作者授权由 InfoQ 中文站翻译并分享。
让我们面对现实吧,2020 年是奇怪的一年。其中有一个奇怪的小现象,自 2012 年以来,美国的个人储蓄率首次出现增长(而且是以惊人的速度增长),而不是保持基本稳定[1]。虽然这其中大部分都与流行病有关,但这也许可以在一定程度上表明,消费者已经开始意识到,你不能一直借钱而不偿还你所欠下的债务。我希望企业能够意识到,同样的原则也适用于技术债务,就像适用于金融债务一样。这个类比可能会让一些人觉得不太舒服,但这实际上是一个非常著名的思想,它最早是由 Ward Cunningham 在 15 年前提出[2],并由 Joshua Kerievsky 在 2005 年进一步发展[3]。
简单地说,当开发团队为了完成其他活动而放弃重要的软件开发活动时,就会产生技术债务。通常,他们的想法是,他们会“回过头去”完成这项活动,但意图往往不会转化为活动。这类活动可能非常简单,如编写文档,但也可能是更棘手的活动,比如修改一段代码,让它更容易理解和维护,或者是更新因为代码变化而过时的设计文档。
我最近在处理几个客户的问题,我感觉自己就像一个消费者债务顾问,在和一对背负着巨额抵押贷款的夫妇谈话,他们的信用卡余额在不断增加,而且他们的孩子即将出生。在每一种情况下,我们都快要被技术债务压垮了,我们必须找到一些方法来减少债务,同时继续开发新功能并继续前进。我提出了一套实践方法,步骤和信贷顾问给他们客户的建议类似。让我们看看这些步骤,看看如何把他们应用于许多项目都面临的技术债务状况。
第一步:评估你的处境,弄清楚你欠了多少
这一步最关键。一旦团队决定必须偿还他们的技术债务(这不是一个容易的决定——而且必须与业务一起做出),他们就必须弄清楚他们实际上欠了多少债务。我发现,最好的方法是进行自上而下的设计和代码审查。
首先看看你的设计文档。它是最新的吗?它是否准确地描述了设计中最重要的点?然后,你可能想首先审查下代码的哪些部分给你带来了最大的麻烦——哪些部分最难修改?哪些地方出错率最高?那些部分对你的业务来说最重要?找出这些问题的答案,可以帮助你对你需要做的事情进行排序,找出方法改善你的处境。
系统中并不是只有代码和文档会导致技术债务。另一个需要考虑的关键因素是运营债务——例如,你是否运行在数据库或应用程序服务器等平台软件构成的后台上?你的运营团队是否在手动执行应该自动化完成的任务,既浪费时间又浪费钱?你是否有适当的监控,以便在问题导致站点宕机之前发现问题,或者你是否把时间浪费在了事后分析上?
通常,最好是请一个外部专家来帮助你评估项目状态。引入一名外部人员让你可以获得一份纯粹是基于解决方案技术优越性的评估,而不受办公室政治或个人对某些代码的情感所影响。
最终的评估需要描述需要更改的内容,按照优先级进行排序,并提出代码更改建议,以及列出的每个更改的估算成本。一旦你掌握了这些事实,你就可以开始与业务所有者协商你要偿还哪些债务以及以什么顺序偿还。
第二步:停止引入新债务
虽然上一步是整个计划中最重要的一步,但第二步通常会导致与业务最针锋相对的讨论。其中最难的部分是学会组织文化变革,这样你就不会让积累的债务超过合理的服务能力。就拿我们的金融债务来说,这也是一件非常困难的事情——改变你的消费习惯,只买你需要的东西,而不是用信用卡购买你想要的东西,这是一件非常困难的事情。
为了修复发现的问题,你必须花时间来实现修复,这意味着你在纠正问题时会搁置新的开发。关于这一点,没有什么完美的方法,无论你采取什么方法,你都需要与业务协商如何平衡技术债务偿还和新功能开发。下面是一些我们认为有效的策略。
在用户故事中包含债务偿还活动。如果前面的步骤已经形成了一组按大小分类并排好序的活动,那么你可以与业务合作,确保在每个开发周期中都包含其中一部分活动。比较难的是平衡债务偿还活动和涉及同一代码区域的新功能开发。例如,如果你正在开发一个电子商务网站,并且你发现大多数问题都是发生在结帐时,你可能想要把涉及这一部分的新功能开发推迟到你偿还该部分的技术债务时(例如,重构代码或更新文档)。在这种情况下,在更改的过程中添加新的促销活动或更改产品页面将是合理的选择。
采用贝塔测试。如果你构建的基础设施可以支撑两个网站(一个是主网站,另一个是“测试”网站),那么你可以在重构主代码流的同时继续在测试网站上开发新功能。这样做的好处是不会减慢任何新功能开发的速度,但代价是,当对测试站点的更改必须重新集成到主站点时,集成难度会增加。
第三步:选择债务偿还策略
在这种情况下,我们可以和信用卡债务偿还策略做个对比,考虑两种不同的确定债务偿还优先级的方法。第一种可能的策略是“最高利率优先”。在信贷领域,这种策略是先偿还利率最高的信用卡,因为这类信用卡支付的利息最高。在技术领域,这意味着你可以首先考虑承担影响最大的任务。如果你解决了这些问题,通常就可以为其他更改扫清障碍,并且可能在性能、可维护性等方面获得最大的回报。
另一种可能的策略是“最低余额优先”策略。用信用卡的术语来说,这意味着先还清余额最低的信用卡——事情很快就完成了,这会让你立即获得一种成就感。对于技术债务,一个类似的策略是首先处理最小的修复,如果你必须说服业务或管理人员偿还技术债务,或者如果你所在的公司非常注重结果导向,只有快速取得进展才能为更大的工作争取到资金支持,这会特别有用。
第四步:按计划行事!
这里的关键是,让偿还债务成为你长期活动的一部分。这不是一次性交易;对于“重构”[4]这类术语,人们不再像几年前它开始流行时那样抱有幻想,因为他们希望最好是可以从长期投资中获得短期结果。你总是会招致新的债务;关键是确保你能在合理的时间内偿还,而不是让它越积越多。
第五步:跟踪和评估进展
最后,你需要能够报告你在债务偿还活动中取得的进展。采集一些指标,用于向管理和业务证明,花费在这些活动中的时间是值得的,这点特别重要。例如,很多时候你需要重构代码来提高性能,这时,手上有正确的统计数据来显示用户体验的改进是很重要的。同样,当你在改进一个简单的代码库时,添加新特性的速度是另一个向业务证明价值的重要指标。
遵循这些步骤并不能解决技术债务相关的所有问题,但它们至少可以让你系统性地确定需要做什么,可以为开发过程带来什么价值,以及变更在多大程度上解决了问题。如果你坚持这样做,那么这应该可以使你的开发工件更容易维护,并且应该可以减少你的开发压力。
参考资料
[1] https://fred.stlouisfed.org/series/PSAVERT
[2] Ward Cunningham,The Wycash Portfolio Management System,ACM SIGPLAN OOPS Messenger,April 1993
[3] Joshua Kerievsky,“Refactoring to Patterns”,Addison-Wesley,2005
[4] Martin Fowler,“Refactoring, Improving the Design of Existing Code”,Addison-Wesley,1999
查看英文原文:Paying Back Technical Debt
评论 2 条评论