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