忘记技术债务(读书笔记)
重新审视一个看似不言自明的术语
2026年1月30日 Uwe Friedrichsen
14分钟阅读
忘记技术债务
首先澄清:我并不认为我们应该真的忘记技术债务。此外,这也不是第n篇讨论"债务"是否是一个恰当隐喻的文章。我对这个隐喻并没有强烈的看法。我的观点是,我在最近的一次讨论中意识到,最终问题不在于技术债务,而在于其他事情,我想分享这个想法。
因此,也许像这样的标题会更精确:"不仅仅是关于技术债务,而是关于许多其他至少与技术债务一样具有有害影响的事情,而且技术债务既是原因也是结果,这使得事情变得更加复杂"。然而,虽然仍然没有完全抓住要点,但这将是一个糟糕的标题,可能会引起更多的困惑而不是澄清。因此,我决定采用简单的、标题党式的标题,并提前道歉。
因此,为这个标题党式的标题道歉!
既然已经道歉了,让我们开始吧……
衡量技术债务
最近,一位客户找到我,需要衡量技术债务。他们希望评估整个系统景观中的技术债务,以便更准确地指导他们的软件现代化工作。听起来合理吗?是的,确实如此。如果我们花钱进行软件现代化,让我们首先投资在最痛苦的地方,即现代化回报最高的地方。
由于他们的系统景观由多种技术和编程语言组成,因此不清楚简单地购买工具是否是一个选项。能够覆盖几十年软件技术和编程语言的工具(这是存在几十年的所有公司的常态)很少见——而且如果它们存在并且能够做你想要的事情,它们往往非常昂贵。
因此,他们问我是否可以开发一些有用的技术债务指标,这些指标可以相对容易地进行调查,理想情况下是自动化的(并并行检查是否存在价格合理的适当工具来进行调查)。
于是我开始工作……
技术债务到底是什么?
在思考潜在指标时,我想到了技术债务的具体迹象。因为基本上软件开发中的每个人都在谈论它,所以必须有包含明确迹象的列表,我可以从中推导出一些有用的指标。至少我是这么认为的。我进行了网络研究,查看了几个定义和文章——但没有发现任何对我的任务有帮助的内容。
所有这些文章都以或多或少的抽象方式定义了这个术语。它们通常还描述了技术债务的一些驱动因素以及如何减少它的一些一般想法。但它们没有给我一个具体的债务迹象列表,我可以从中推导出一些指标。
我觉得这有点奇怪,因为无论你往哪里看,你都能看到人们在谈论技术债务。因此,人们会期望有一个明确的技术债务迹象目录,就像设计模式目录一样。然而,至少我没有找到任何这样的目录。感觉技术债务主要被用作一种通用的行动号召("我们需要减少技术债务")或一个无可辩驳的术语来贬低某些东西("这个程序充满了技术债务")。
或者也许我找错了地方。无论哪种方式,研究并没有真正帮助,因为它没有带来任何对我的任务有帮助的东西。因此,我决定从第一性原理重新开始。
我们想要实现什么?
从头开始时,我开始问这个问题:"通过减少技术债务,我们想要实现什么?"
如果我们思考这个问题,我们很快就会意识到技术债务是关于认知负荷的。技术债务增加了软件工程师的认知负荷。一个系统包含的技术债务越多,代码就越难理解,工程师在尝试实现更改或添加新内容时必须在脑海中记住的不同的概念、黑客手段等就越多。换句话说:增加了认知负荷。
然而,认知负荷并不是终点。减少工程师的认知负荷本身并不是目的。如果我们思考为什么减少认知负荷是可取的,我们最终会得到两个主要目标,我们通过减少认知负荷来支持这些目标:
- 在开发时,我们希望将实现给定需求所需的努力保持在尽可能小的范围内。
- 在运行时,我们希望最大限度地减少由于软件中的错误导致的问题和故障数量。
如果我们增加系统的技术债务,它会增加在其上工作的开发者的认知负荷,这反过来会对我们的主要目标产生有害影响:
- 实现努力蔓延——实现新需求所需的努力增加。
- 运行时稳定性恶化——无意中引入的、滑入生产环境的错误数量增加,导致生产环境中出现更多问题和故障。
这创建了一种依赖关系图,看起来像:
技术债务 -> 认知负荷 -> 实现努力蔓延/运行时稳定性恶化
箭头的意思是"驱动"。
从相反方向看
到目前为止,我们发现了一个从技术债务到软件系统中减少技术债务的想法背后的实际目标的因果联系。但是相反的方向呢?如果我们从损害两个主要目标开始并朝另一个方向看,我们会得到什么样的图?我们会得到相同的简单图,在认知负荷处有一个"中转站"吗?还是结果图看起来不同?
这就是事情开始变得有趣的地方。
如果我们查看实现努力蔓延的驱动因素,我们立即会看到一堆驱动因素,例如:
- 编写糟糕的需求
- 糟糕的开发平台支持
- 会议狂热(在许多公司中非常普遍)
- 开发人员被分配到不同的项目,需要频繁的上下文切换
- 在实施已经进行时频繁更改需求
- 由于缺乏有效性,系统中塞满了不需要和不想要的需求(例如,有关更多详细信息,请参阅我的"忘记效率"博客文章)
- 过于复杂的架构拖慢开发速度
- 过于复杂的流程拖慢开发速度
- 过于僵化的合规要求,过度限制开发人员
- 缺乏对开发人员的培训和教育
- 微观管理的经理,阻止任何流程
- 等等
当然还有增加的认知负荷。
如果我们查看运行时稳定性恶化,我们会看到类似的模式,例如,我们会看到这样的驱动因素:
- 运维部门人员不足
- 过时的平台和基础设施软件版本
- 未经培训的管理员,并不真正了解他们的平台系统
- 糟糕的监控,让容易检测到的错误漏掉
- 过于复杂、不连贯的技术栈,多年来不断增长
- 手动部署和管理流程
- 过于僵化的合规要求,过度限制运维
- 等等
当然还有由于增加的认知负荷而导致的软件错误数量增加。
我们意识到,我们并没有一条从损害两个主要目标到认知负荷的简单线。相反,我们看到一种完整的驱动因素树正在出现,认知负荷只是它的叶子之一。
如果我们深入一层并查看认知负荷的驱动因素,我们立即意识到树进一步扩展。软件工程师的认知负荷可以通过多种方式增加,而不仅仅是通过技术债务。
仅举几个例子:
- 浪费的业务需求,即用户最终不需要或不想要的需求,增加了工程师的认知负荷。他们还需要了解实现这些需求的代码,并围绕它进行编程。看看研究表明,非价值需求,即不创造业务价值(空闲性能)甚至破坏业务价值(价值减少性能)的需求,在普通公司中占所有需求的80%-90%,并且看看这些需求一旦实施通常永远不会从代码中删除的事实,我们可以得出结论,浪费的需求是比技术债务更大的认知负荷驱动因素。
- 认知负荷的另一个大驱动因素——或者更准确地说:认知能力降低的驱动因素——是压力。压力在我们的大脑中触发战斗或逃跑模式。在这种模式下,我们的心理处理能力受到严重限制。因此,如果在压力下执行,相同的任务将由于处理能力降低而导致高得多的认知负荷,而不是在没有压力的情况下执行——导致实现它需要更多时间以及更高的错误可能性。由于大多数公司培养了一种紧迫感与稀缺性相结合的氛围,导致持续的高压力和压力水平,因此降低(不仅是)软件工程师的压力水平可能对实际目标产生比减少技术债务高得多的积极影响。
- 过于复杂的规则和法规,例如来自流程、企业架构、合规性或类似的规则,迫使工程师在尝试工作时在脑海中记住大量的做与不做,增加了认知负荷。
- DevOps 出错,以各种形式表现出来,如 NoOps、缺乏平台团队或功能失调的平台团队,迫使开发人员考虑基础设施组件及其复杂性,阻止他们专注于软件开发。同样,增加了认知负荷。
等等。同样,我们看到从"认知负荷"分支中出现了一整棵驱动因素树。如果不为认知负荷的驱动因素兄弟或认知负荷的驱动因素兄弟重复这个练习,很明显我们最终会得到一整棵驱动因素树,而不是一条单线,而技术债务只是其中一片叶子。
因此,如果我们想要减少实现努力蔓延和运行时稳定性恶化,仅关注技术债务是不够的。技术债务只是拼图的一部分(或者更确切地说:树的叶子)。即使我们确保我们的系统完全没有技术债务,我们仍然可能处于实现非常缓慢且运行时稳定性很差的状态,这是由于其他驱动因素造成的。
进一步深入
在意识到这一点之后,我问自己是什么驱动了技术债务,即我想进一步深入树中。在这里,我也意识到了一些有趣的事情。驱动因素基本上分为两类。
第一类基本上是导致实现努力蔓延的相同驱动因素。这些驱动因素具有即时和延迟的影响。即时影响是实现努力蔓延。延迟影响是由于对解决方案及其质量的关注下降而导致的技术债务增加。此外,许多这些驱动因素还增加了软件工程师的认知负荷,这也降低了他们对解决方案及其质量的关注,同样导致技术债务增加。
作为副作用,我们意识到我们漂亮的树开始演变成一个相当复杂的依赖关系图,其中包含许多循环和相互依赖。我们还看到,许多额外的驱动因素也影响技术债务,这加强了先前的观察,即仅管理技术债务是不够的。减少技术债务对于减少实现努力蔓延和运行时稳定性恶化这一总体目标来说是不够的。此外,如果我们不能成功地控制其他驱动因素,我们将无法降低技术债务。
技术债务的第二类驱动因素与开发人员超负荷及其负面后果有关,例如:
- 极其紧迫的截止日期迫使开发人员妥协质量
- 过度拥挤的开发增量迫使开发人员妥协质量
- 缺乏时间在开发团队成员之间记录或共享相关信息(通常是由于过于紧迫的截止日期或过度拥挤的开发增量)
- 等等
通常,技术债务的驱动因素被简化为这一类。虽然这些驱动因素是强大的驱动因素(在负面意义上),但重要的是要意识到,这些绝不是驱动技术债务的唯一驱动因素。
为什么我们要限制我们的认知?
看到这幅图后,我问自己的问题是:为什么我们在软件工程社区中经常将讨论限制在技术债务上?我的意思是,很明显,仅仅尝试减少技术债务不会改善情况。它对实际目标(即实现努力蔓延和运行时稳定性恶化)只有非常有限的影响。如果我们不控制讨论的其他驱动因素,技术债务将比我们能够减少它的速度更快地积累。此外,为什么我们在讨论技术债务的驱动因素时如此关注开发人员超负荷,而忽略所有其他驱动因素?
我觉得这些问题令人困惑,我认为找到一个好的答案将有助于我们显著提高我们工作的影响力。不幸的是,我没有找到一个完美的答案,因为这是一个复杂的问题。
但我可以提供一个(希望是)有根据的猜测。我认为我们经常在软件工程社区中将讨论限制在技术债务上,因为它是立即对我们产生负面影响而没有任何间接因素的东西,因此我们立即认识到它。
许多其他驱动因素位于我们的直接感知之外。我们可能会感觉到它们可能以某种方式对我们产生负面影响,但这并不是我们经历的直接痛苦。
此外,我们可能会认为那些其他驱动因素位于我们的影响范围之外,因此专注于技术债务,因为我们知道如何用自己的双手降低它。对于大多数其他驱动因素,情况并非如此简单。它们是由其他方引起的,我们无法对它们应该如何工作发表意见。因此,我认为我们倾向于专注于技术债务,因为这是我们立即经历的,也是我们可以立即补救的——如果我们有时间这样做的话。
关于为什么我们经常只关注开发人员超负荷作为技术债务的驱动因素,可能也是如此。这是我们每天都在遭受的。对我们大多数人来说,这是一种极其普遍的负面经历。因此,开发人员超负荷经常被视为技术债务的主要驱动因素,我们无意中错过了也驱动技术债务的所有其他驱动因素——只是因为它们不那么存在。
同样,我不确定这个解释尝试是否真的抓住了要点。但即使没有,我认为其中有很多真理。至少,它更好地理解了为什么我们经常如此专注于技术债务而错过了画面的其余部分。
现在怎么办?
问题是:我们要用这个洞察做什么?
我们已经看到,仅关注技术债务是不够的。它只是关于认知负荷的许多驱动因素之一,而认知负荷又只是关于实现努力蔓延和运行时稳定性恶化的许多驱动因素之一。此外,仅与技术债务作斗争是不够的,因为许多其他驱动因素比我们能够降低它的速度更快地推动技术债务上升。
我的个人建议是,我们仍然需要谈论技术债务。我们需要明确它对IT之外的人最重要的事情产生有害影响:实现工作和生产稳定性。
但我们也需要拓宽视野。我们需要明确还有什么影响实现工作和运行时稳定性。我们需要更全面地讨论改善情况需要什么。我们需要提高对某些类型的决策和习惯产生反效果的认识。
我知道这比仅仅讨论技术债务要困难得多,也复杂得多。然而,如果我们真的想要改善我们的情况,恐怕我们需要走这条路并拓宽讨论——包括开始与IT之外的人进行深思熟虑的讨论。
我希望我给了你一些思考的想法。如果你应该有额外的想法可能有助于我们改善我们的情况(或者至少让那些经常在不了解其决策后果的情况下决定我们命运的IT之外的人更容易理解),请不要犹豫与我们的社区分享它们。事情只会变得更好……
-
即使希望大多数错误在QA期间被检测到(无论是与开发一起进行还是作为一个单独的阶段),一些错误也会未被检测地滑入生产环境。而且,由于过多的认知负荷而在开发时引入的错误越多,进入生产环境的错误就越多。
-
关于AI和经常做出的承诺,即它将通过接管软件开发来解决所有这些问题的旁注:仅仅添加AI而不改变其他任何东西不会解决问题。仅仅添加AI辅助或AI驱动的编码而不解决现有问题只会强化问题,这与我们希望通过AI实现的目标相反。
#标签 #技术债务 #软件开发 #认知负荷 #系统架构 #软件工程 #代码质量