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