Skip to content

技术债务治理

技术债是被滥用最多的概念之一。任何看着不顺眼的旧代码都被叫做"技术债",于是"还债"变成了"我想重写"的借口,重写完发现新代码也很快变成下一轮债。治理技术债的前提,是先想清楚什么是债、什么不是,哪些债值得还、哪些债该让它继续存在。把这件事想明白,才不会陷入"无止境重构却没产出业务价值"的循环。

什么是技术债,什么不是

技术债是为了短期收益而有意做出的、会在未来产生额外成本的工程取舍。关键词是"取舍"——它有当时的理由,也有未来的代价。

text
不是技术债:
  - 只是代码写得丑,但没有影响任何东西
  - 旧技术栈但运行稳定、没人改
  - 你不喜欢但工作正常的实现

是技术债:
  - 为了赶上线跳过了抽象,现在每加个功能都要改十处
  - 没有测试,每次改动都提心吊胆
  - 共享数据库直连,导致无法独立部署

不是所有旧代码都是债。一个运行良好、没人需要改的老模块,哪怕风格过时,也不是债——它是已经还清的旧账。别为了"看着不顺眼"就去动它。

债的分类

债不是铁板一块,类型不同,处理方式完全不同:

维度类型特征
来源有意债当时权衡过的,有记录
无意债当时不懂事留下的,没记录
可承受性可承受债偶尔难受,但不阻碍业务
不可承受债每次改动都拖慢团队,频繁出 bug
性质设计债架构耦合、抽象缺失
测试债没测试、测试不稳定
文档债没人知道为什么这么写
依赖债老旧、有漏洞、不再维护的依赖

有意债要保留当时的记录("为什么这么做"),未来还债时不会误判。无意债最危险——团队不知道它的存在,每次踩坑都像第一次发现。

识别与记录:让隐性债显性化

治理的第一步是让债被看见。隐性债是最有害的,它存在于某个老员工的脑子里,人一走就失传。

text
做法:
  - 遇到坑时,立刻在代码里留 TODO / 注释,说明问题和影响
  - 用 issue 跟踪,打上 tech-debt 标签
  - 标注"影响什么"(每次改动多花 X 小时 / 偶发故障 / 阻碍某个功能)

记录的重点不是"这里很烂",而是"它造成了什么具体成本"。没有具体成本的"烂代码"不构成债,不值得投入。

偿还策略:不是所有债都要还

这是治理中最关键的判断。债像金融债务一样,有的该尽快还,有的可以一直背着:

债的特征策略
频繁出事、每次改动都拖慢专项偿还,优先级高
偶尔难受但能绕过维持,记录下来,等机会顺手改
有安全漏洞的依赖债立刻还,不能拖
没人再碰的老模块别还,让它自然淘汰

两种主流偿还节奏:

  • Opportunistically(顺手还):在改动某块代码时,把路过的相关债务一起清理。"童子军法则"——离开时比来时更干净。适合小规模、可承受债。
  • 专项偿还:对阻碍业务的不可承受债,立项集中投入。适合大债,但要明确目标和完成标准。

重写整个系统几乎从来不是好策略。重写的成本和风险巨大,而且重写过程中老系统还在出业务价值,团队往往陷入"新老并行、两头都维护不动"的泥潭。绝大多数债,应当通过渐进式重构逐步偿还

防止新增:还的同时别再欠

只还旧债不防新债,等于一边倒水一边漏水。防止新增比偿还更重要:

text
机制:
  - Code Review 时识别新增的债,要求留 TODO 和 issue
  - 有意债要记录"为什么、什么时候还"
  - 关键模块加架构约束(依赖方向、分层规则),CI 校验
  - 给新人讲清楚架构约定,避免无意债

有意债不是问题,没有记录的有意债才是问题。今天的取舍,要写得让三个月后的自己看得懂。

与业务沟通

技术债治理最大的障碍,是业务方听不懂"我们要花两个月还技术债"。换个说法:

text
错误沟通:
  "我们要停下来重构,还技术债"
  → 业务:然后呢?不交付功能了?

正确沟通:
  "现在每次加功能都要多花 3 天绕过这段代码,
   重构后能降到半天。两个月内省回来的工时,
   够我们多交付 X 个功能。"

把债翻译成业务能理解的语言:速度、稳定性、风险。还债的正当性来自它对未来交付速度的提升,而不是"代码该干净"这种审美诉求。

务实的检查清单

  • 你说的"技术债"是否真的造成了具体成本,还是只是看着不顺眼?
  • 有意债是否留下了当时的记录,未来不会误判?
  • 债是否被显性跟踪(issue / 标签),而不是存在于某人脑子里?
  • 是否区分了"该专项还的大债"和"该顺手还的小债"?
  • 是否在防新增(Review、架构约束),而不只是还旧的?
  • 与业务沟通时,是否把债翻译成了交付速度和风险,而不是技术审美?

为复用而记录,为理解而整理。