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