Google Measures and Manages Tech Debt
Google 如何衡量和管理 Tech Debt
技术债(Technical Debt)困扰着开发团队几十年,但仍然难以解释。每个人对技术债都有自己的定义。如果你问三个人技术债是什么,你可能会得到三个不同的答案。
最近,Google 大规模地面临着这一挑战——在内部调查中,很大一部分工程师反映他们被“不必要的复杂性和技术债”所阻碍。在一篇题为“Defining, Measuring, and Managing Technical Debt”的论文中,Google 的工程师 Ciera Jaspan 和 Collin Green 系统地理解了这个概念,该概念减缓了即使是最有才华的工程团队的速度。
他们试图回答以下问题:如何衡量如此无形的东西?一旦你识别出它,如何在不停止新开发的情况下管理它?
这项研究很重要,因为技术债经常被归咎于生产力问题,但很少被精确地定义或衡量。Google 的工作提供了任何工程组织都可以采用的具体策略。
因此,让我们深入了解并了解更多关于他们的方法。
Kestra: 停止用胶带粘合你的工作流程 (Sponsored)
还在缝合 Python 脚本、cron 任务和废弃的 DAG 吗? 没问题 - 直到凌晨 2 点的页面。
Kestra 带来秩序。 开源编排将分散的作业变成一个版本控制的、可观察的管道。
- ✅ 事件驱动和计划运行
- ✅ 存储在 Git 中的声明式 YAML
- ✅ 数百个插件——数据库、API、AWS、Azure、GCP…_
它是如何运作的: Stripe webhook → 用 Postgres 丰富 → 加载到 Snowflake → 提醒 Slack。
一个 YAML 文件。 一次提交。
1. 技术债的定义
“技术债”一词起源于 Ward Cunningham 在 1992 年,他使用金融债务的比喻来解释软件开发中的权衡。正如他所解释的那样,“首次发布代码就像欠债。只要及时通过重写来偿还,少量的债务可以加速开发。”
Google 没有强加自上而下的定义,而是采用了一种经验方法来定义技术债。他们询问工程师遇到的技术债类型以及哪些缓解措施适合修复此债务。
以下是 Google 研究中的十个类别,附带简要说明:
- 🔄 需要迁移或正在迁移——这可能与以前的设计决策有关,这些决策在出现问题之前运行良好,例如与不再维护的第三方服务集成。当我们必须重建系统以使其稳定和最新时,就会出现这种债务。
- 📄 糟糕或缺失的文档——重要的文档(例如系统如何工作或 API 用法)很难找到或不存在。缺乏关于当前行为或继承代码的清晰文档意味着开发人员浪费时间试图理解系统。
- 🧪 不充分的测试——测试覆盖率或质量不足。例如,关键区域没有自动化测试或使用糟糕的测试数据,导致构建脆弱、测试结果不稳定以及频繁回滚发布。
- 🪲 代码质量差——代码(或整体架构)设计不佳——可能是匆忙发布、作为原型而 hack,或者从未重构。结果是混乱或低效的代码,难以维护或扩展。
- 👻 死代码——旧代码、功能或整个项目仍然存在于代码库中,尽管已被取代或弃用。这种未使用的代码膨胀会使开发人员感到困惑,并可能导致意想不到的副作用。有一些开源工具可以帮助你删除死代码,但这样做需要时间。在大型代码库中删除死代码时要小心,因为你可能会搞砸一些东西。
- 🕸️ 代码退化——代码库的质量或一致性随着时间的推移_逐渐衰退_。系统的某些部分相对于当前标准或最佳实践而言已过时,通常是由于在“维护模式”下过长而没有清理。
- 🤷♂️ 知识差距——团队缺乏系统某些领域所需的专业知识。当最初的作者离开时,团队必须进行试验才能理解孤立的代码,这会减慢开发速度。
- 🔗 有问题的依赖项——项目所依赖的外部组件或库不稳定、变化迅速或经常破坏你的构建(导致回滚)。该债务依赖于不提供稳定基础的依赖项。
- ❌ 迁移失败——过去的迁移执行不力或不完整,导致某事物的_两个共存版本_现在都需要维护。这使每次更改的工作量加倍,并造成对哪条路径是“正确的”路径的困惑。另一种情况是,当团队期望在迁移后实现特定承诺,但随后发现情况并非如此时。
- 🐢 过时的发布流程——构建、发布或部署流程(包括生产中的监控)已过时或过于手动。例如,发布新代码需要繁琐的步骤,或者无法充分发现问题,从而拖累了生产力。
这些类别从代码级别的问题到文档、基础设施和团队相关的债务不等。它们共同构成了 Google 对各种形式的技术债的工作定义。并非每个团队都会同等地经历所有十个类别——债务通常反映了上下文。
例如,一家新兴的创业公司可能几乎没有死代码或代码腐烂(一切都是新的),但可能遭受测试或发布自动化不足的困扰。但是,大型企业或单体代码库可能会在正在进行的迁移和过时的组件方面遇到困难。
2. 衡量技术债
Google 通过一项 季度工程调查 来衡量技术债,该调查涵盖约 三分之一的工程师(大约有三分之一的人做出回应)。他们专门询问工程师哪些技术债类别阻碍了他们的工作,而不仅仅是存在哪些债务,而是 哪些债务正在积极地减慢他们的速度。
这种区分至关重要,因为它承认 并非所有技术债都需要立即关注。有时,技术债存在但不会显着影响生产力。
调查回复帮助 Google 识别在特定类型的技术债中挣扎的团队。例如,从事机器学习系统的工程师面临的技术债挑战与构建后端服务的工程师不同。这允许根据工具链或组织区域进行有针对性的干预。
但是,基于调查的衡量标准有其局限性:
- 每个季度只有大约 10% 的工程师做出回应,对于较小的团队来说,置信区间可能会很宽
- 调查是滞后指标——只有当债务严重到足以阻碍开发人员时才会出现
- 如果没有客观指标,可能会对主观报告持怀疑态度
为了解决这些限制,Google 研究人员尝试开发基于工程日志数据的指标,这些指标可以用作技术债形成的早期指标。他们专注于 三种债务类型(代码退化、团队缺乏专业知识以及需要迁移),并 探索了 117 个潜在指标,例如:
- 📝 代码中“TODO”的数量,作为代码退化的指标
- 👻 过去团队成员编写的代码比例,作为专业知识差距的标志
- 🔄 错误报告中与迁移相关的术语的频率
结果令人失望。没有指标可以预测工程师报告的技术债——线性回归模型解释了不到 1% 的调查回复差异。即使是复杂的随机森林模型也实现了高精度(>80%),但召回率较差(10-25%),这意味着他们可以识别一些负债累累的领域,但错过了许多其他领域。
这一发现突出表明了为什么技术债如此难以客观衡量:它不仅仅关乎系统的当前状态,还关乎该状态与工程师想要的理想状态之间的关系。
例如,只有在 Python 3 作为首选替代方案存在的世界中,Python 2 代码才代表技术债——代码本身不会改变,但上下文会改变。
这种洞察力解释了为什么自动化指标难以发挥作用:许多形式的债务都依赖于上下文并且具有前瞻性(我们_应该_做什么?)而不是纯粹关于当前代码。
技术债(作者:Manu Cornet)
3. 管理技术债
定义和衡量技术债对于研究至关重要,但真正的目标是 减少 它。Google 成立了一个内部 技术债联盟——一个由工程师和领导者组成的跨职能小组——以推动公司范围内的改进。
该小组采取了全面的方法,解决了流程、教育和工具问题。一些关键举措包括:
- 🗂️ 技术债管理框架。他们建立了一个框架,以便团队可以始终如一地列出他们的技术债、判断其影响、分配所有者并跟踪修复。现在,债务工作是有计划地进行的,而不是随机进行的。
- 🪜 技术债成熟度模型。该联盟开发了一个成熟度模型(附带自我评估),以评估团队系统地管理其债务的程度。
该模型定义了四个成熟度级别:
- 🔥 反应级别——处于此级别的团队没有管理技术债的真正流程。他们可能会偶尔通过有针对性的努力(例如“修复”)来处理债务,但只有在问题严重到足以阻碍工作时才会做出回应。他们通常会解决熟悉的问题,但缺乏识别或跟踪债务的系统方法。非技术领导者可能根本不了解技术债,直到出现严重问题。
- 📊 主动级别——在此级别,你的团队认识到技术债需要系统的关注。他们理解“如果你无法衡量它,你就无法改进它”,并主动跟踪与应用程序、开发工作流程和发布流程相关的指标。你已经意识到在有效管理技术债之前,你需要一份技术债清单。
- 🎯 战略级别——此处的关键改进是拥有专门的拥护者来负责技术债管理。这些拥护者识别并解决根本原因,而不仅仅是症状。他们已经创建了一个全面的技术债问题清单,并且知道如何优先处理最紧迫的问题,并分配人员来处理特定项目。技术债讨论发生在计划期间,而不仅仅是在出现问题时。
- ✅ 结构级别——这是黄金标准。技术债考虑因素直接包含在你的开发工作流程和流程中。技术和非技术团队成员都将债务修复视为工作的常规部分,并在 sprint 中定期分配专门的时间。该方法在各个团队之间标准化,从而创建组织一致性。
团队可以评估他们的立场,并获得有关达到下一级别的实践的指导。
- 🎓 教育和宣传——该联盟组织培训以传播最佳实践。他们举办了关于管理技术债的课堂会议和自助课程。他们设立了内部论坛和一个讲座系列(有内部和外部演讲者),以保持对话的进行。这有助于创建一个共享文化,让工程师和经理了解技术债以及如何处理它,而不是将其作为一种模糊的概念。
- 🛠️ 工具和指标——他们构建了工具来发现潜在的债务领域——例如,突出显示测试覆盖率低、缺少文档或严重弃用的依赖项的模块的仪表板。虽然之前的研究表明此类指标无法独立完美地识别债务,但这些工具仍然有用。目的是帮助怀疑自己存在问题的团队跟踪他们改进的进度。换句话说,如果一个团队知道他们没有正确的测试,那么覆盖率工具可以显示他们在每次修复工作后是否朝着正确的方向前进。
这些努力得到了领导的支持,甚至激励了改变以鼓励解决债务问题(例如,认可和奖励代码健康方面的改进,而不仅仅是功能交付)。
多年来,Google 对技术债的关注得到了回报。他们看到报告技术债或过于复杂的代码“中度”或“极大地”阻碍了他们工作的工程师百分比 大幅下降。
大多数 Google 员工现在表示,技术债仅_“轻微”或“根本没有”_阻碍他们。这是自调查开始以来的五年中观察到的任何生产力因素中 最显着的积极转变。
4. 正确的平衡
重要的是要注意,在 Google 或任何实际的工程组织中,零技术债不是目标。作者解释说,计划中的技术债对于实际项目很有价值。
Google 的季度调查还询问工程师:
- 他们的团队最近在多大程度上故意产生了技术债
- 这在多大程度上是正确的决定
- 减少现有债务的投资有多少
- 他们的债务管理流程运作得如何
这些问题认识到,技术债就像金融债务一样,可以被战略性地使用。正如抵押贷款允许你在节省全部购买价格之前拥有房屋一样,战略性技术债可以帮助团队在业务环境需要时更快地发布功能。
关键的区别,来自 Martin Fowler 的技术债象限模型,在于:
- **有意的、谨慎的债务:**在清楚了解后果的情况下有意识地承担
- **无意的、鲁莽的债务:**通过不良实践或缺乏意识而积累
Google 发现强大的团队不会试图完全避免技术债。他们在有帮助时接受它,并按照计划偿还它。
技术债象限(来源:[Martin Fowler 博客](https://newsletter.techworld-with-milan.com/p/<http:/Technical Debt Quadrant>))
5. 实践经验
并非每个组织都拥有 Google 的资源或规模,但这些见解中的许多见解都具有广泛的适用性。工程领导者、CTO 和高级工程师可以借鉴这些想法,以更好地平衡快速交付和可持续的代码质量。
以下是一些可以在你的环境中考虑的实用经验和清单。
未管理的技术债的迹象
如果你没有积极地管理技术债,它往往会以揭示性的方式表现出来。
留意你的团队日常工作中的这些危险信号:
- 🔥 频繁的救火和脆弱的代码。你经常处于“在它坏了之后修复它”的模式。生产事故、热修复、回滚或不稳定的测试很常见,这表明底层设计或质量问题从未完全解决(测试或代码质量中债务的经典症状)。
- 🐢 尽管努力,交付速度仍然很慢。新功能或更改所需的时间比应有的时间长,因为开发人员正在与现有代码作斗争。也许每次更改都需要触摸十几个模块或绕过过时的约束。当努力与产出不成比例时,技术债可能是不可见的阻力。
- 🙈 避免某些代码区域。该团队有一些他们害怕使用的代码库部分——可能是一个无人理解的旧子系统(知识债务)或多年前的混乱的 hack 集合。如果开发人员说“如果我们更改 X,我不知道会发生什么”,这是未管理债务的强烈信号。
- 🤯 入职很痛苦。新工程师需要很长时间才能提高生产力。一个常见的罪魁祸首是糟糕的文档和复杂的设置过程。如果文档已过时或不存在,并且了解系统的唯一方法是部落知识,那么你的技术债(在文档、发布流程等方面)会破坏团队的成长。目标是让工程师在第一周开始交付项目。
- 🛠️ 许多手动流程。工程工作流程有很多“粘合”工作——例如,手动运行部署步骤、手动处理数据迁移或持续修补依赖项问题。这通常表明自动化和工具方面的债务(例如,过时的发布管道或缺少适当的迁移工具)。
ℹ️ 技术债公式:技术债 =(修复成本/开发成本)* 100%(理想情况下应小于 5%。)
构建正确的技术债管理文化
解决技术债不是一次性的 sprint;而是一种持续的纪律。以下是一些帮助你的团队 主动管理债务 的实践:
- 📋 承认并清点债务。首先,使技术债成为对话中可见的一部分。鼓励工程师在计划讨论或回顾中提及债务问题。在特殊的 Jira 面板、wiki 或“技术债桶”中保留 已知债务项目列表。列出每个债务项目,使其成为一个简单、可跟踪的任务。
- 📆 确定优先级并分配时间用于债务。像对待功能工作一样对待最严重的技术债——按影响确定优先级。并非所有债务都是平等的:有些债务可能相对无害,可以暂时承担,而另一些债务(例如,没有测试的关键模块)则构成高风险和“利息”。一旦你确定了高优先级的债务,分配时间 来解决它们。这可能意味着安排每个 sprint 的一部分用于重构/清理,或定期“修复周”,专门用于减少债务。
- 🎯 产生新债务时要慎重。有时,承担技术债是实现截止日期或快速测试市场的正确选择,如果在有意识的情况下这样做。关键是要慎重:当你决定实施快速而肮脏的解决方案时,记录假设(例如,带有所有者和日期的
// TODO
注释或债务登记簿中的条目),理想情况下设置触发器或时间表以重新审视它。在健康的文化中,工程师不应该害怕承认“我们在这里走捷径”,但他们应该有一个稍后解决它的计划。 - 🏆 投资于流程和“拥护者”。考虑将技术债管理的明确 所有权分配给团队。Google 发现,采用_“战略”_方法的团队会指定拥护者来推动债务讨论和预防措施。这可以是轮换角色或技术主管职责的一部分。还将债务考虑因素嵌入到现有流程中——例如,在代码审查或设计审查中添加一个步骤,询问“这是否会引入任何新债务或清理现有债务?” 随着时间的推移,这些实践会将债务控制规范化为工作流程的一部分(类似于 Google 的_结构性_成熟度级别)。
- 📊 主动跟踪技术债。工具可以通过量化代码健康的某些方面来提供帮助——用于代码气味的 linters、测试覆盖率报告、依赖项新鲜度等。利用这些优势:它们可以跟踪进度(我们是否在改进?),并捕获回归。
- 🎓 启用持续教育。确保团队理解_为什么_技术债很重要——不是抽象地,而是它如何直接影响你交付的能力。分享过去由债务引起的事件的故事。鼓励高级工程师指导初级工程师编写干净、可维护的代码(以避免在不知不觉中增加新债务)。
最后,作为领导者,设定基调,即 技术债是一个战略问题,而不是我们犯的错误。每个软件系统都会有一些债务;这通常是快速交付的另一面。在使用 Agile 方法(例如 Scrum)时,这一点尤为重要。
目标不是消除债务(这无论如何都是不可能的),而是 有意识地管理它,在有商业意义时承担债务,并在它破坏你团队的速度和交付潜力之前定期偿还它。
Google 发现,一旦团队管理技术债,开发人员就会构建更多,并减少浪费在修复损坏的测试或混乱代码上的时间。平衡速度和质量的团队胜过那些匆忙然后放慢速度的团队,修复不断增加的技术债。
识别技术债,衡量其对人们的影响,并不断减少它,以便你的 团队可以顺利扩展。
➡️ 了解更多关于如何处理技术债的信息:
Tech World With Milan NewsletterHow To Deal With Technical DebtIn this issue, we are going to talk about the following…Read more2 years ago · 43 likes · 1 comment · Dr Milan Milanović ➡️ 或者如何处理遗留项目中的技术债:
Tech World With Milan NewsletterHow to deal with Technical Debt in legacy projects We have all been working on an existing project with many issues. Team members are more or less aware of these issues, which are, to some extent, apparent problems in the development flow. The umbrella term for all of these issues is Technical Debt…Read more8 months ago · 58 likes · 5 comments · Dr Milan Milanović
6. 结论
Google 的研究 为各种规模的工程组织提供了几个宝贵的教训:
- 技术债有多种形式,团队应该开发一个共享的词汇表来有效地讨论它。
- 衡量技术债仍然具有挑战性。调查并不完美,但比试图仅仅依赖代码指标提供更多的洞察力。
- 系统化的债务管理方法会产生结果,Google 通过其框架在生产力方面取得了显着改善。
- 目标不是零技术债,而是作为工程战略的一部分的 deliberate 债务管理。
虽然技术债的具体类别可能因组织而异,但定义、衡量和积极管理技术债可以使任何开发团队受益。
最成功的组织不会将技术债视为工程问题——他们认识到这是一个需要精心管理的战略问题。
🚀更快地获得 .NET 工程师职位
购买 我的 Ultimate .NET Bundle 2025——500 多页,包含现代 C#、架构和面试准备,来自 20 年的实际经验。
💥 首发价格:99 美元(原价 129 美元)——5 月 11 日结束
里面有什么:
- ✅ .NET 生态系统指南——了解整个堆栈(31 页)
- ✅ 为什么选择 C#——深入了解功能、工具和市场价值(60 多页)
- ✅ 现代 C# v6–13 概述——简单解释 50 多个关键功能(51 页)
- ✅ C# 中的设计模式——学习在生产中使用的模式(53 页)
- ✅ 200 多个面试问答——从初级到高级职位(122 页)
- ✅ 2025 .NET 路线图——结构化的、资源支持的学习(38 页)
- ✅ 身份验证大师班——以正确的方式保护应用程序(86 页)
🔥 𝗘𝘅𝗰𝗹𝘂𝘀𝗶𝘃𝗲 𝗯𝗼𝗻𝘂𝘀𝗲𝘀(价值 99 美元):
- 🎁 ASP.NET Core 最佳实践——可用于生产的指南(27 页)
- 🎁 中间件深度解析——掌握 ASP.NET 管道(23 页)
- 🎁 2025 C# 速查表——你的快速编码参考(73 页)
👉**立即获取 Bundle** → 5 月 11 日之前只需 99 美元。
使用代码:9FF67。
(一次性付款。终身访问权限。更新免费。)
感谢阅读 Tech World With Milan Newsletter! 免费订阅以接收新帖子并支持我的工作。