首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >让技术债务的偿付规模,与价值交付成比例!否则根本不要提它!

让技术债务的偿付规模,与价值交付成比例!否则根本不要提它!

作者头像
用户10377957
发布2026-06-17 21:17:39
发布2026-06-17 21:17:39
170
举报
1 引言

本文从一个提问出发,探讨有效减少技术债务的指南,以及如何培养一种心态来欢迎消除技术债务的短期收益。

这个问题就是:

『我想为团队偿还技术债务提出更好的理由。有哪些经过验证的方法可以做到这一点?』

事实上,这个问题 已经被研究了很多年。

在交付功能和偿还累积的技术债务之间找到合适平衡点的紧张关系,和软件工程本身一样古老。

关于如何最好地减少技术债务,没有统一的答案。

对于零技术债务是否是一个值得追求的目标,意见也存在分歧。

但确实存在一些适用于大多数团队的方法。

在本文中,我们涵盖:

  • 偿还技术债务以立即加快速度 经验较少的工程技术管理者通常认为,专注于功能而忽略技术债务是加快速度的方法。我也曾同意这个观点,但现在并不这么认为。
  • 利用技术债务提升生产力 三个例子,说明处理技术债务如何让工程团队立即行动得更快。
  • 将技术债务与价值交付联系起来 当合理处理技术债务时,它能带来商业价值。
  • 让技术债务的影响可视化 仪表板是可视化技术债务影响的有效方法。
  • 在考虑生产力时要考虑节省的时间 减少技术债务通常会改善每个人的编码、代码审查和部署。
  • 利用技术债务的偿还,进入心流状态 这是一个反直觉的观察:通过进行小的、非功能性的改进,你会对新的代码库更有信心,并能开始更快地行动。
  • 大型重构需要强有力的支持 没有技术管理层的支持,大规模重构很可能会失败。

2 立即偿还技术债务,以加快开发速度

什么是技术债务?

我将技术债务定义为代码库中影响程序员的任何问题,这些问题使得必要的变更变得更加困难。

作为一名程序员,我想修复这些问题,因为它们拖慢了我的速度。

但作为一名管理者,我必须确保团队向利益相关者交付价值。

在我的职业生涯中,我在这些角色之间来回转换,在两个方向上都犯了错误。

但我也学到了很多关于如何正确平衡的知识。

减少技术债务在更快的构建中立即获得回报

2010 年,我担任 Atalasoft(一家 .NET 开发工具公司)的开发主管。

我痴迷于交付,把所有时间都花在担心交付路线图中的功能上。

随着时间的推移,我们在这方面有所改进,这体现在我们的收入增长中,最终促成了收购。

我们处在一个竞争激烈的市场,机会多于我们能够处理的数量。

我们不到十名开发人员,但我们是自筹资金的,所以必须保持盈利,不能提前招聘。

被收购后,风险变得更高了。我们有两年的时间来交付一个雄心勃勃的路线图,其中有一个取决于交付的盈利奖金。

如果我们不交付,我们很可能会被归类为失败的收购。

我们的新所有者刚刚经历了一次这样的失败,导致了裁员和办公室关闭。

我的心态是,花在技术债务上的任何时间都意味着我们无法交付路线图。

我们不能通过浪费时间清理旧问题来冒险错过截止日期,必须在技术债务和路线图交付之间做出选择。回想起来,我认识到这是错误的。我学到,忽略技术债务的心态伤害了我的团队。

在一次离职面试中,一位离职的工程师提到技术债务促成了他们离开的决定,之后我开始在一对一谈话中询问人们对此的感受。

他们的回答显示了他们对我的沮丧。

那时,我已经当了十五年的开发人员,在有很多债务的代码库中工作过,所以我知道那是什么感觉。

但现在,我是一名偶尔贡献代码的管理者,已经忘记了每天被代码库阻碍是什么感觉。

对我的团队来说,我是问题的一部分。他们一直试图告诉我这一点,但我没有理解。

他们离职的同事在离职面试中无所顾忌,终于让我明白了,帮助我理解了问题的深度,以及它正在拖慢每个人的速度。

我学到了一个重要的教训:技术债务的成本每天都由你的团队承担,通过忽略它,你冒着损害士气和增加流失率的风险。

即使你有充分的理由在不解决技术债务的情况下继续前进,作为一个有同理心的管理者,你至少需要做点什么。什么都不做——就像我那样——不是一个好的选择。

所以我们开始做出改变。最大的问题是我们的构建系统和安装程序,因为它们影响每个开发人员和每个产品。

这是一堆杂乱的遗留代码,需要不断维护,但它不是很大,我批准了一个用现代工具重写它的计划。

这是一个小实验,但在更快的 CI 构建和更容易修改的代码库方面立即得到回报。

最重要的是,我看到它没有偏离我们的路线图,所以我们采取了其他小的举措。

这教会了我关于处理技术债务的另一个教训。我曾认为它可能会在长期内得到回报。

可能。这种信念使得在我必须实现短期目标时很难为其辩护。

但相反,发生了其他事情:

我们偿还了技术债务并立即提高了生产力!

我们有了一个反馈循环更快的构建,认知负担更少,当开发人员不得不添加内容(这种情况经常发生)时,不会让他们感到沮丧。

更新是用更少的代码完成的,并且不会破坏东西。

这是技术债务减少立即提高开发者生产力的一个例子。

在 Trello 学习过度重写的代价

Trello 得到下一个教训,我在那里从事 iOS 应用的工作。

当我 2014 年加入时,代码库已经三年了。它有可以理解的技术债务,因为他们需要快速行动,从 0 增长到 600 万注册用户。

在其上工作的开发人员是创始工程师,正如『实用工程师』在『作为创始工程师茁壮成长』中所描述的那样,在寻找产品市场契合度。

我们最大的技术债务问题是一些框架,这些框架让构建简单应用很快,但随着应用变得更复杂,它们拖累了我们。

我们自己的选择受到 AppleiOS 更新速度的影响。iOS 7 更新完全改变了 iOS 设计语言及其网络 API。

后来,iOS 8 引入了演示控制器,让开发人员在新视图显示时对动画有更多控制。

不幸的是,iOS 8 的变化破坏了我们的导航代码并导致崩溃。

这些问题累积起来,开始让我们的代码显得过时。

Apple 决定在 Apple Store 的实体 iPhone 上展示 Trello 时,我们的代码变得更加复杂。

为了在商店中展示,我们需要一个无需账户或网络就能工作的构建版本,因此为了演示目的在其中嵌入了一个模拟后端。

我们不想维护单独的代码库,所以有很多随机的演示模式逻辑片段,保留了很多年。

Trello,我每天都编码,所有这些都在我面前。幸运的是,我们是一个三名开发人员的小团队,所以我的直接经理也每天都在编码,对问题有同理心。

我们边做边重构,但有时做得太过火了。

为了处理 iOS 8 的演示控制器问题,我们在应用内部开发了一个新的屏幕导航范式,并重写了所有导航来使用它。

这种方法与我在 Atalasoft 的做法完全相反,在那里我忽略了所有技术债务。

不幸的是,早期重写的方法被证明是过度了。回想起来,我们本可以只修复崩溃的地方,然后继续使用我们已有的代码。

相反,我们花了几个月时间设计和实现一种新的、非标准的编写导航代码的方式,但忘记了一个重要的教训,这个教训是我们的一位创始人 Joel Spolsky 在 2000 年的『你永远不应该做的事情』中指出的:

『我们是程序员。程序员在内心深处是建筑师,当他们到达一个地方时,第一件事就是推平这个地方,建造宏伟的东西。我们对渐进式改造不感兴趣:修补、改进、种植花坛。

程序员总是想扔掉代码重新开始有一个微妙的原因。原因是他们认为旧代码是一团糟。这里有一个有趣的观察:他们可能是错的。他们认为旧代码是一团糟的原因是因为编程的一个基本、核心的法则:

阅读代码比编写代码更难。』

Trello 工程团队中,我们都非常熟悉这篇文章,经常互相引用,但它仍然有时会咬到我们。

重写一个系统而不是修复它的冲动很强烈,我们无法抗拒!

我们应该处理那些导致代码崩溃的几个复杂导航案例,而不是全面重写。

让技术债务的偿付规模与价值交付成比例。

这是我在这个项目上学到的最大教训。

我见过处理技术债务的两个极端:

  • 作为管理者,我过度抵制花时间处理技术债务
  • 作为工程师,我每天面对它的问题,没有足够抵制偿还它的冲动

这两个极端构成了处理技术债务的基本紧张关系。像往常一样,需要有一个平衡,但找到它并不那么容易。

这些天我用来偿还技术债务的启发式方法是:通过减少特定的技术债务,我能否*立即*提高开发者生产力并交付商业价值?

如果不能,那么我就不偿还它。

当债务大到现在不可能交付价值,或者价值是隐形的以至于没有人看到它时,我会做其他事情。让我分解一下我的启发式方法...

3 利用技术债务提高生产力

我尝试通过在前进过程中进行小的清理提交来定期偿还少量技术债务。

在 1999 年读了 Kent Beck 的『极限编程解释』后,我开始更有意识地这样做,这本书向我介绍了自动化单元测试和持续集成。

然后,当我读了 Martin Fowler 的『重构』时,我开始看到如何通过非常小的、保持行为的改变(由单元测试检查)来随时间改进代码库。

在这两本书以及其他书籍中,作者们都强调技术债务是不可避免的,遏制它的主要方法是不断地通过单元测试和机械重构来修复它。

我同意这一点。

单元测试、重构和持续集成在我编写的软件类型中无处不在,这些软件是 B2B SaaS 生产力应用。

即使在我的同事中,持续进行小的改进也很常见。

这不需要很长时间,而且通常有快速的成功,比如让代码更易读,或者使用单元测试来展示代码应该如何工作。

即使在前端代码中,TrelloiOS 采用了模型-视图-视图模型(MVVM),所以我们可以测试视图逻辑。

我们得到了即时的生产力好处,能够重复运行视图代码,而不需要通过几个屏幕操作运行中的应用程序来检查我们的更改是否有效。

问题是当债务很大时,怎么办?这就是我挣扎的地方。

我在 Atalasoft 的问题不是小的改进;而是那些我必须权衡当前好处(如交付路线图功能)与不确定未来好处的大改进。

但我意识到了一些事情。

即使是大型的举措,你也可以立即获得生产力好处。

如果你做得对,你会更快、更高质量地交付功能工作。

事实上,我认为那些不能立即带来开发者生产力收益的技术债务提案是可疑的。

Atalasoft 重写构建和安装程序带来了即时的生产力提升。

我们有一堆问题和新增需求,但重写花了一个开发人员大约一个月的时间。

当它完成时,许多问题就消失了,因为新系统基于一个框架,许多问题无法发生,这意味着我们可以关闭一堆报告的错误。

新系统是可单元测试的,所以在开发期间,我们不需要构建和安装整个系统来测试我们的新更改。

我们后来得到了更多好处,但即时的好处证明了它的合理性。

Trello,向代码库添加单元测试帮助我更快地完成了一个项目。

当我 2014 年加入时,我们正要开始i18n 项目,我为 iOS 应用承担了这个项目。

一部分是编写对 i18n 安全字符串插值(将变量或表达式插入字符串)和复数化(根据数字调整单词为复数形式,使短语语法正确)的支持——当时在 iOS 中只是部分支持。

它本质上是标准的字符串操作,但在 2014 年我们的 iOS 应用没有单元测试。

没有单元测试,如果我想运行代码,我需要运行应用程序,然后点-点-点直到到达特定的字符串。

我必须为我生成的每种类型的字符串都这样做。但有了单元测试,我可以列出所有例子及其预期结果,并在不到一秒的时间内运行测试。

所以,我向团队提议将单元测试添加到我们的构建和 CI 中。

没有人反对单元测试,但这不是一个优先事项。大部分代码是 UI 或网络代码,单元测试更难写。但我编写的代码是高度可测试的,事实上,没有测试更难写。

所以,我将单元测试项目添加到我们的工作区并编写了字符串代码。有了单元测试项目后,其他开发人员为他们的工作添加了测试。

我在那里又待了六年,随着时间的推移看到了测试的好处,特别是在像我们的同步引擎这样的复杂代码中。但这不是我这么做的原因:我添加单元测试是为了立即加快速度。

同样在 Trello,为设计系统创建抽象层让我们更有生产力。

最终,我们创建了一个设计系统,有减少的字体、颜色和其他设计属性集合以及使用它们的特定规则。

之前,在整个应用的视图控制器中看到硬编码值很常见,因为每个屏幕都实现了该屏幕的设计师规范,这并不总是一致的。

我们本可以将这些行更新为新的批准值,但这是为设计系统本身创建抽象的完美时机。

这样做让编写匹配设计的代码更快,当设计系统中的默认值改变时,它会反映到各处。

这三个例子也遵循我用来找到技术债务正确平衡的另一个启发式方法:将其与价值交付联系起来。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2025-11-18,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 持续交付2.0 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 2 立即偿还技术债务,以加快开发速度
    • 减少技术债务在更快的构建中立即获得回报
    • 在 Trello 学习过度重写的代价
  • 3 利用技术债务提高生产力
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档