从一无所知,到否认它的存在;从接受它不可避免,到开始极力抗拒;最终,走向一种务实的中间立场。这大概是许多工程师在面对技术债务时都会经历的一条典型路径。
技术债务是软件开发中绕不开的问题。人们很容易想直接跳到结论:如何消除技术债务,以及如何避免技术债务。但如果跳过中间的认知过程,就很难真正理解最终立场的意义。所以,不妨从你还不知道“技术债务”这个概念的时候讲起。

什么是技术债务:从无知到第一次遇见它
一旦开始专业地编写软件,那种对技术债务一无所知的幸福阶段,通常不会持续太久。有些人入职几个月后就会意识到它的存在,有些人则可能要过几年才真正注意到它。等到你积累了足够多的经验,可以被称为资深程序员时,你大概率已经对技术债务非常熟悉,甚至能够坦然接受它。
我花了整整一年半,才第一次真正遇到它——尽管当时我还不知道该如何称呼它。
它以一团乱麻般的代码形式出现,让人完全摸不着头脑。当时我还是大三学生,接到一份短期合同,任务是改进我所在大学一位教授正在开发的数据挖掘软件。那段代码由一位数学家编写,他完成软件的第一个版本后就离开了项目。教授他们估计,这项改进工作只需要几周时间。
我一头扎了进去。
然而,没有文档,没有测试,命名也让人完全摸不着头脑。我尝试修改一些地方,但代码并没有按预期运行,而是不断出错。最后,我放弃了,也离开了这个项目。
当时我以为,一定是自己缺乏基本的工程能力,所以才看不懂这段代码。但事实并非如此。教授后来告诉我,我已经是他们雇来的第三个无法对这段代码进行合理修改的人。最终,他们不得不从头重写整个程序。
真正扼杀这个项目的,正是技术债务:糟糕的编码方式,以及几乎完全缺失的软件工程实践。
技术债务为什么会被否认
产品经理:“我们在这个页面上加个按钮吧。用户点击以后,可以直接和客服聊天。这需要多久?”
开发人员:“嗯……大概两周。”
产品经理:“两周?聊天功能不是已经有了吗?这不就是加个按钮吗?到底什么地方需要两周?”
开发人员:“呃……其实这个改动没那么简单。我们现在的代码并没有为修改这些界面元素,或者直接打开聊天流程做好准备……”
产品经理:“你知道吗?我不相信。你只有四天时间。否则……”
开发人员:(叹气……开始想办法绕过现有限制……)
当你是一名开发人员,而你的上级从未真正接触过软件开发时,就很容易发生一些奇怪又令人无奈的事情。更糟的是,他们可能有过一点基础开发经验,却从未真正理解过技术债务。
在我职业生涯早期,我和团队成员曾多次试图解释我现在称为“技术债务”的东西。那时我们还不知道这是一个专业术语。我们只知道:代码库里有些功能很难实现,代码显然没有为这些变更做好准备,花时间改进架构才是更明智的选择,而我们也确实需要更多时间才能把事情做好。
但我们从来没有得到足够的时间。相反,我们还被指责进度慢、能力不足。
他们会说,团队里的“明星开发者”才是榜样,因为他完成所有工作的速度都比我们快得多。是的,我认识这个人,也认识他的代码。他会引入一些令人匪夷所思的临时方案,然后巧妙地把自己从后续工作中摘出去。他会说,主要功能已经实现了,剩下的交给别人完成就好。
但所谓“完成剩下的部分”,从来都不是一件容易的事。很多时候,这意味着要重写他之前留下的代码,因为那些代码需要大量修补,而且写得混乱、脆弱、毫无逻辑。
在一家对技术债务视而不见的公司工作,通常意味着糟糕的工程环境。管理层是否理解或关心技术债务,反而不是最关键的问题。真正的问题在于,他们奖励的是权宜之计、短期方案,以及那些善于提出临时方案的人。
而那些想把事情做得更扎实、希望考虑维护性和长期演进的人,往往得不到重视。他们甚至可能被指责拖慢团队进度、不关注真正重要的事情,或者活在自己的工程师世界里。
在这样的环境里工作,压力很大。你仍然可以做出好东西,但可能不得不“偷偷”做很多改进,或者在正常工作时间之外完成这些改进,以免被指责速度不够快。
另一方面,优秀的工程师往往会离开这样的环境,去那些理解并接受技术债务的公司和团队。
接受技术债务:它确实存在
一家公司的工程文化越成熟,就越能意识到技术债务的存在。我花了很多年才真正明白这一点。
我职业生涯中第一次认真理解技术债务,是在某海外大型科技公司的通信产品团队。那是我第一次看到一个团队真正系统地思考技术债务:他们会梳理不同类型的债务,也会讨论如何偿还这些债务。也正是在那里,我终于对技术债务有了足够清晰的认识,能够准确地描述它,并向他人解释它。
技术债务,是软件开发过程中产生的额外成本。随着代码量增加、系统复杂度提高,技术债务也会随之出现。
对于全新的代码库和全新的项目而言,这种额外成本几乎为零。但代码越复杂,在保持原有功能正常运行的前提下进行修改,所需的工作量就越大。
那些拼凑而成、缺乏自动化测试和文档的代码库,修改起来会非常耗时,也会积累大量技术债务。相反,如果开发人员定期投入时间提升代码的可维护性,那么代码库中的技术债务就会更少,修改成本也会更低。
提升可维护性,包括提升代码可读性、可测试性、自动化程度,以及完善相关工具链。
“技术债务”这个词,非常准确地描述了修改代码时产生的额外成本。债务意味着它会随着时间推移而累积。
在现实生活中,如果你欠了钱,可以选择不同的还款方式。你可以先只付利息,等贷款到期时再偿还本金;也可以一边付利息,一边还本金;还可以一次性还清所有贷款。如果你拖得太久,利息就会增加,还可能产生各种额外费用。在极端情况下,债务甚至会累积到让你破产的地步。
技术债务在很多方面都与此类似。
如果运用得当,债务可以加速发展;如果运用不当,维护成本就会变得非常高。所谓“被技术债务拖垮”,也是真实存在的:当删除并重写代码库的成本,低于继续维护或修复现有代码库的成本时,这种情况就已经发生了。
如何减少技术债务:先控制增长
一旦你接受了技术债务是任何复杂代码库都不可避免的事实,就会开始思考另一个问题:我们如何才能把技术债务降到最低?
技术债务虽然不可避免,但如果遵循一些关于代码可维护性和可修改性的最佳实践,它的累积速度就会大大降低。这些实践包括:编写可读性强的代码、补充测试、进行代码审查、持续集成与持续交付、编写文档,以及做出合理的架构决策。
假设你很幸运,参与开发的是一个技术债务很少、并且已经遵循了许多最佳实践的代码库。为了防止技术债务不断增长,你必须努力保持这种状态。
这时,要尤其警惕“破窗效应”。
破窗效应:技术债务如何悄然滋生
我见过许多原本不错的代码库逐渐积累技术债务,而这些债务最初都很小。
它们往往来自某个人的一次疏忽,或者一次未经充分代码审查的变更。这些问题一开始通常很容易修复。但如果这些小债务不断累积,却始终没人处理,问题就会开始恶化。
代码库很容易陷入“破窗效应”的陷阱:例外逐渐变成常态。人们会想:“既然这里已经这样写了,那我也照着这个模式来吧。”于是,原有技术债务形成了一种模式,并开始在整个代码库中蔓延。
一般来说,如果你能找到简单方法清理技术债务,那就去做。只要改动足够小、足够快,并且能让代码比之前更好,这样的清理就值得进行。
技术债务治理:从哪里开始?
当然,更常见的情况是:你并没有那么幸运,手上的代码库并不是技术债务极少的理想状态。
假设你正在维护的代码库经常出现各种问题,你应该如何开始治理这些技术债务?
对于小规模技术债务,最好的方式是边做边修复。遵循“营地原则”:离开时代码要比你来时更干净。就像离开营地时,应该把营地清理得比来时更整洁一样。
对于规模较大的技术债务,则需要先清点债务,量化它的影响,以及消除这些债务所需的工作量。
当债务规模很大时,你不可能一次性全部解决。如果不收集与大型技术债务相关的数据,就很难做出正确决策。面对需要数周甚至数月才能修复的问题,团队必须进行优先级排序:这项工作与那些能直接影响业务的工作相比,究竟处在什么位置?
这也是为什么研发团队在治理技术债务时,需要把需求、缺陷、代码变更、测试、发布和知识沉淀放在同一套流程中审视。像 PingCode 这样的智能化研发管理工具,可以帮助团队把目标、需求、开发、测试、发布与 Wiki 知识沉淀串联起来,让技术债务不再只是零散的口头讨论,而是能被记录、跟踪、评估和持续治理的研发管理问题。
是的,代码中确实存在重复。但如果要把这些代码迁移到共享库,会带来什么影响?成本又是多少?
对于经常被使用的代码库来说,收益可能很大。相反,对于即将弃用的代码库来说,这可能意味着投入巨大、回报却很有限。
构建速度很慢?如果构建流程被频繁运行,并且由许多人共同使用,那么影响可能非常大。它甚至可能大到值得组建专门团队,花几个月时间来提升构建速度——这类情况在一些海外大型互联网公司中确实存在。
测试不稳定?影响可能很大,但希望修复工作量不要太高。样板代码冗长?影响可能较小,但仍需要一定工作。某个命名只是你个人不喜欢?影响可能不大,但修改起来反而可能耗费不少精力。
所有这些判断,都取决于你所在的具体环境。
用明确影响争取技术债务治理资源
要提出那些能够产生明确影响的项目,并投入专项精力解决技术债务。
有些技术债务非常值得优先处理,因为它们的影响显而易见。例如,假设团队在生产环境中发布了大量缺陷,而你们又没有自动化测试或持续集成机制。那么,通过减少缺陷、降低人工测试需求所带来的收益,就足以说明这项投入的重要性。
再比如,团队提出要开发一个可靠性达到 99.9% 的新系统,而现有系统可靠性只有 98%。如果这个改进每年可能节省数百万美元,那么你就成功论证了这个项目的商业价值。
可靠性提升、成本节约、更快的开发周期和更少的缺陷,是我见过的、最常被用来争取高层支持大型技术债务治理或系统迁移项目的几个理由。
将技术债务治理与高影响力项目结合起来
遗憾的是,大多数时候,很难单独为一个技术债务治理项目找到足够有力的立项理由。
为什么?因为团队通常都会优先选择最有影响力的项目,也就是那些能创造最大商业价值的项目。而商业价值往往体现在收入增长、用户指标改善等方面。
这些项目通常目标宏大,关注度高。为了交付这些项目,团队往往又必须改动那些技术债务最重的系统。而修改高技术债务系统,本来就意味着开发速度会显著下降。
既然团队已经需要对一个技术债务沉重的系统进行多次修改,为什么不顺势多花一点时间,先降低一部分债务呢?
那些既能创造业务价值、又能同时削减技术债务的团队,往往掌握了一个不太公开的秘诀:他们很少会事先单独申请“清理技术债务”的许可。相反,他们会把技术债务治理工作打包进高价值项目中,然后一起推进。
开发人员:“我们会发布这个每年能带来 500 万美元额外收入的功能,同时也会引入集成测试。”
项目经理:“我们可以不做集成测试,直接发布吗?”
开发人员:“当然可以。但那样的话,开发时间可能会更长,而且我们可能会因此损失一部分收入。我们发现,最近几次功能发布后都出现了不少 bug,需要更多人工测试,也需要发布更多修复版本。如果引入自动化集成测试,我们反而可以更快完成。我们的估算是:加上集成测试需要 4 个月,不做集成测试则可能需要 6 个月。”
为什么要把这些事情捆绑在一起?
因为这样才能确保它们真正完成。
那些只减少技术债务、却没有直接业务价值的项目,通常很容易被降低优先级。而高影响力项目,则几乎不会轻易被忽视。如果你希望大型技术债务治理方案真正落地,就应该把它和高影响力项目结合起来。
技术债务管理:务实的折中方案
技术债务真的可能“太少”吗?
当你偿还了足够多的技术债务后,你会发现,答案是肯定的。技术债务过少,本质上就是一种过早优化。它会在关键时刻拖慢团队和公司的脚步。
以初创公司为例。在公司早期,速度和快速迭代往往是生存和成功的关键。你会优先追求简洁优雅的 API 和完善的数据模型,还是会把所有东西先塞进一个任何开发者都能快速修改的非结构化 JSON 文件中?
我曾经工作过的一些后来获得成功的初创公司,在早期都选择了承担更多技术债务。
某海外出行平台就是这样一个例子。我刚加入时,公司早期积累的技术债务仍然经常被提起,一些代码库中也还能看到当年短期决策留下的痕迹。
但这些技术债务最终确实发挥了作用。它们让公司能够在最关键的阶段——寻找并抓住产品与市场契合点时——快速发展。之后,公司又投入大量资源,逐步清理这些技术债务。
技术债务在早期项目中往往是必要的:比如开发一次性原型、最小可行产品,或者验证初创公司的商业模式时。技术债务可以通过后期投入时间和工程资源来偿还,就像许多快速成长的公司后来所做的那样。
如果一家快速发展的后期初创公司,从未在内部偿还早期技术债务,那就值得警惕。类似地,如果一个拥有成熟产品的团队完全不关注技术债务,也没有进行必要投入来控制债务,那同样可能意味着问题正在积累。
务实的工程师并不会把技术债务视为绝对的坏事。他们会把它看作速度与质量之间的一种权衡,是复杂系统中天然存在的一部分。
他们会把技术债务放到项目目标中去评估,而不是试图偿还超过实际需要的部分。他们也会持续跟踪技术债务,在债务过高之前及时介入并加以控制——必要时,还会用更有创造力的方式来解决问题。
所以,你的项目应该保留多少技术债务?你又打算如何减少,甚至在某些阶段有意识地增加这些技术债务?
文章包含AI辅助创作:技术债务是什么?如何治理技术债务并找到务实的中间立场,发布者:su,转载请注明出处:https://worktile.com/kb/p/3972139
微信扫一扫
支付宝扫一扫