技术债到底是什么

「技术债」这个词在团队里经常被用滥:有人用它指代一切写得难看的代码,有人一提它就皱眉头。它真正的含义更具体——为了赶进度而主动接受的一个次优折中,代价是未来某个时刻要付出更多的成本去修正。

一笔技术债通常长这样:为了赶上发布,先在主流程里塞一个临时分支;为了尽快出原型,跳过了那层抽象;为了不阻塞别人,先不补对应的测试。每一个决定在当时都有道理,但它们会一起把系统变得越来越难改。

技术债本身不是罪过,真正伤人的是不被记账、也不被偿还的那一部分。
本文核心知识点
  • 债务本质今天抄的近路,会变成明天要付的利息。
  • 显性与隐性写进 ADR 的是显性债,没人记得的是隐性债,隐性债更危险。
  • 偿还节奏不要攒一笔大钱,而是每个迭代都还一点。
  • 安全网没有测试兜底的重构,等于一边跑一边拆炸弹。
  • 决策视角借钱可以划算,关键是利息是否扛得住。
技术债示意:微微倾斜、带发光裂纹的半透明蓝色积木高塔,旁边悬浮一把发光扳手与一束修理聚光灯,周围漂浮扁平三角形警示图形,蓝色扁平插画
每一笔临时妥协都像一道裂纹:平时看不见,承重时最先开裂。

技术债是怎么累积起来的

技术债很少来自一次失控,更多是无数个看似合理的小让步叠加的结果。单独看每一条都没错,放在一起就压弯了系统。

  • 赶进度绕过抽象:先复制一段能用的代码,回头再抽,回头往往没来。
  • 测试一再推迟:功能要紧,测试下个版本补,下个版本又被新需求占满。
  • 命名与边界随手写:函数越写越长,模块之间谁都能改谁。
  • 技术栈长期冻结:依赖几年不升级,安全补丁和新特性都用不上。

判断一个系统债多不多,不看代码漂不漂亮,看它的修改成本:改一个小需求要不要动五六个文件?回归测试要不要点半天?新人独立上手要多久?这些数字恶化的速度,就是利息上涨的速度。

先分类:不是所有债都急着还

「还技术债」如果不分类,就会变成大家凭好恶挑活:有人想换掉看着不顺眼的旧模块,却对每天都要碰的混乱分支视而不见。更靠谱的做法是先把债分类,再按利息高低排序。

债务类型典型来源偿还优先级拖着不还的后果
架构债分层混乱、依赖方向反向高每次改动都牵一发动全身
测试债长期不补关键路径测试高不敢重构,回归全靠手点
代码债超长函数、重复逻辑、坏味道中理解成本上升,缺陷变多
依赖债框架与库版本长期陈旧中安全补丁和新能力用不上
文档债关键设计决策没记录低后人反复踩同一个坑

排序的原则不是「最讨厌哪个先还哪个」,而是利息最高、最拖慢交付的先还。一处每天都要被需求触碰的混乱分支,远比一个没人动的旧模块紧急。

建一本看得见的技术债台账

技术债要被管理,前提是它被看见。一次站会上口头抱怨十句,不如一条写下来、有人负责、有状态的台账。台账不需要复杂,关键是每条债都能被追溯。

# 技术债台账(轻量示例,按注释理解每条字段)
- id: DEBT-0017          # 唯一编号,方便在评审里引用
  位置: order/service.py: checkout()
  类型: 架构债           # 架构债/测试债/代码债/依赖债/文档债
  成因: 促销期间临时塞了 if 分支,事后未拆
  影响: 新增支付方式要改三处,已经错过两次需求
  负责人: 老郑
  偿还计划: 下个迭代抽掉分支,并入统一的策略对象
  状态: 已排期           # 已排期/进行中/已偿还/已豁免

每个迭代评审时,花十分钟过一遍台账里高优先级的条目就够了:谁在还、还到哪一步、有没有新冒出来的债。台账的价值不是存档,而是让债务从集体的模糊焦虑,变成一条条具体可执行的任务。

把还债排进日常迭代

把技术债攒到一个专门的「重构迭代」往往落空——因为业务永远比还债紧急,那个迭代总被新需求挤掉。更可持续的做法,是让还债成为每个迭代的固定比例。

  • 每个迭代预留一到两个还债任务,和业务需求一起排优先级。
  • 还债和它相关的新功能放在同一批里做,顺手就把利息付了。
  • 谁在新功能里又加了一笔债,就由谁优先来还。
  • 不允许只加功能、从不偿还,哪怕每次只还一小块。

把还债和业务价值绑在一起,它就不再是「技术自嗨」:这次重构之所以值得做,是因为它能让下周那个需求少改三个文件、少跑半天回归。这样还债自然成为交付的一部分,而不是和业务争抢的对手。