负债清单每季度更新一次,三年下来条目只增不减,没人删。到第六次更新时,这份清单已经没人当真了——它变成了一份"我们知道有问题"的存档,而不是一份待办。短期清单只做记录就够了,因为一个季度内条目本来就会被还掉;跨年台账的第一属性是它能减。一份只能增的台账,写的人是免责者,读的人是看客。
1. 条目只增不减的三个机制
| 机制 | 现场表现 | 长期台账里为什么必然发生 |
|---|---|---|
| 没人有权关单 | 状态字段只有"登记"和"已修" | 关单权默认跟着提出者,而提出者多半已换岗 |
| 关单需要证据 | 想关的人拿不出"已经不影响任何事"的证明 | 证据成本高于登记成本,理性选择是不动 |
| 条目本身是免责工具 | 出事时第一句话是"这条我早登记了" | 保留条目比关闭条目更安全,于是谁都不关 |
三条的共同点:登记的成本是五分钟,关闭的成本是一次调查。台账的激励结构天然偏向只增。
台账条目最小的字段集,缺任何一项都会让它在一年后变成无法处理的文本:
id: DEBT-0312
title: order-service 里三套并存的折扣计算入口
introduced: 2023-04 // 引入时间,不是登记时间
reason: 大促前为兼容老客户端临时加的旁路,未走完统一入口
affected: 下单链路、对账导出 // 影响面,要能被验证
current_cost: 每次改折扣规则要改三处并人工比对
close_condition: 旧客户端占比归零,且导出改用统一入口
owner: 当前维护该模块的人 // 跟着模块走,不跟着人走
owner 跟着模块走是这套字段里最关键的一条约定。写成人的名字,条目就会随着人走;写成模块,条目跟着代码走,才能被下一个人接手。
三个机制里,第三个最隐蔽。免责工具的作用是让登记者在事后有话说,因此它的读者往往不是执行者而是审计者——一份为审计者写的清单,天然不关心条目是否还成立。要改变它,只能改变关单的成本结构:把"证明它已经不重要"变成一次可以做完的检索,而不是一次需要多人会签的调查。
三条机制指向的是同一件事:台账需要的不只是记录格式,还需要一个有权关单的角色。没有这个角色,任何格式上的改进最后都会退化成一份更整齐的清单。
2. 可关闭条目的判据
关单不是"觉得没事了",而是三条判据之一成立并且能被指出来:
| 判据 | 需要的证据 | 谁来判 | 常见误判 |
|---|---|---|---|
| 问题已随重构消失 | 当前代码里找不到该结构 | 模块 owner + 一次代码检索 | 把"没人提"当成"已经改掉" |
| 影响面已归零 | 引用点、调用方、数据下游都为零 | 检索结果或调用统计 | 只看主仓,漏掉脚本与报表 |
| 代价已超过收益 | 现在修的成本大于未来一年预期损失 | owner 与主管共同确认 | 用"以后可能有用"当理由 |
三条都不成立的条目,应当降级为"已冻结",而不是继续挂在待办里。判据的顺序也重要:先查"问题是否还存在",再查影响面,最后才谈代价。顺序颠倒会把最容易验证的一条放到最后,于是整个关单流程卡在主观判断上。凡是要靠"觉得"才能通过的判据,实际执行中都会被无限推迟。
关单动作要落成一条可复核的记录,模板本身就构成证据:
// 关单申请(DEBT-0312)
判据: 影响面已归零
证据: 全仓检索 + 报表下游配置核对,旧客户端占比连续两个版本为 0
保留: 引入原因与当时的替代方案,写入模块 README
不复盘: 本条不进入季度回顾议题
3. 三年期台账该记什么、不该记什么
| 记 | 理由 |
|---|---|
| 引入原因 | 一年后唯一还能解释"为什么写成这样"的信息 |
| 影响面 | 决定它现在值多少钱 |
| 当前代价 | 用可复述的句子写,不写感受 |
| 关闭条件 | 缺它条目就永远不会关 |
| 不记 | 理由 |
|---|---|
| 形容词("很乱""历史遗留") | 无法验证,也无法关闭 |
| 重构设想 | 会随技术栈变化而过期 |
| 责任归因 | 三年后归因对象已经不在团队里 |
| 感受性优先级 | 与代价字段重复且不可比 |
同一份台账里还要把两类条目分开:还在还利息的(每次改动都要额外付代价)与已经不动了的(放在那里但没人碰,代价实际上是零)。混在一起看,会让"条目总数"这个数完全失去意义。
形容词还有一个麻烦:它会传染。一条写"这块代码很乱"的条目,会被下一个人抄成"这块代码一直很乱",三年后没人能说清乱在哪里。可复述的句子则相反——"改折扣规则要改三处"在两年后依然能被验证,也依然能被关闭。
4. 代际传递与定期重估
提出的人走了,条目还在。这是跨年台账与短期清单最大的不同:短期清单的内容和记忆在同一个团队里,跨年台账要处理的是记忆已经丢失的条目。因此台账的维护动作不是"定期检查",而是"定期重估":
| 动作 | 做什么 | 结果 |
|---|---|---|
| 定期检查 | 看条目是否还在、是否有新进展 | 条目数量不变 |
| 定期重估 | 用当前代码重新判断三条判据 | 会删掉条目 |
重估的议程可以很短,但必须产出删除动作:
// 季度重估(每条 3 分钟)
1. 打开 close_condition,看它是否已成立
2. 不成立的条目: current_cost 是否已经变成"没人再碰"
3. 没人再碰的条目 → 状态改为"已冻结"
4. 冻结超过四个季度的条目 → 一次性清零,并明确不复盘
陈年旧账适合一次性清零:用一个明确的决定把一批冻结条目同时关闭,并写明"这批不再进入回顾议题"。理由很简单——逐条重估一堆已经无人在意的条目,成本高于它可能省下的收益;而留着它们,会让台账的可信度继续下降。清零要留下宣告,避免下一任 owner 从代码里再把它"登记"一遍:
// 清零宣告
范围: 2022-2023 年登记且状态为"已冻结"的全部条目
处置: 关闭,不进入回顾,不要求补证据
后续: 同类问题若再次出现,按新条目重新登记并重新定价
新 owner 接手一个模块时,与债务有关的第一个动作不该是读完台账,而是把台账里属于该模块的条目重估一遍。三年以上的台账里通常有相当比例的条目已经失效,先读完反而会建立起错误的优先级。
台账与管理层可见性的关系是单向的:不可见,就永远是技术团队自己的事。定期把条目净变化与关闭率放进同一份汇报里,比把条目总数报上去有用得多。
汇报口径上有一个容易犯的错:把条目总数当进展指标上报。总数只增不减时,这个数字每年都在恶化,但它并不描述团队处境是否改善。更合适的是两个数:本季关闭了几条、条目平均存续多久。前者说明台账在流动,后者说明历史包袱在变薄。
5. 排错与边界
5.1 排错
| 现象 | 机制 | 处理 |
|---|---|---|
| 条目在增长但没人读 | 条目不可执行,只有描述 | 补 current_cost 与 close_condition 两列 |
| 关单申请常被驳回 | 判据缺证据,变成表态 | 关单必须附检索结果或调用统计 |
| 重估会开成追责会 | 条目里写了责任归因 | 删除归因字段,只谈影响面与代价 |
| 债务数字每年上涨 | 只统计新增,不统计关闭 | 度量条目净变化与关闭率 |
| 条目三年未动却被当成"高风险" | 冻结状态没和活跃状态分开 | 增设"已冻结"状态与到期清零 |
排错里最值得记的一条是关单被驳回。如果一份台账里大多数关单申请都被驳回,问题几乎一定不在申请者,而在判据不可验证:把"代价已超过收益"当成常用理由,会让关单变成一场立场之争。可行的做法是把该判据从台账流程里摘出去,留到最后、且只在双方都同意时才使用。
5.2 边界
| 场景 | 结论 |
|---|---|
| 团队成立不足一年 | 正式台账是负担,用迭代待办即可 |
| 条目少于二十条 | 全量重估的成本低于建维护机制的成本 |
| 债务集中在单一模块 | 直接排进该模块的重构计划,不必进台账 |
| 系统两年内计划退役 | 只记影响面,不记关闭条件 |
边界表前两行常被当成"暂不适用",实际含义是:台账机制的成本与团队规模强相关。团队不足一年时,"引入原因"这个字段没人能填准——当事人就在旁边,口头问一句比写字段便宜;条目少于二十条时,一次全量重估的成本低于建立状态机、字段规范与重估议程的成本。第三行则提示另一种替代:债务集中在单一模块时,"台账"往往退化为该模块重构计划里的一个章节,独立成表只会增加同步成本。
度量只要四个数:条目净变化(新增 − 关闭)、平均存续时长、关闭率、重估后失效比例。四个数都看趋势,不取绝对值。净变化接近零不代表没有债务,只代表新欠的和还掉的相当;平均存续时长下降才是台账真的在流动的证据。
// 用改动频率代替主观感受: 某个目录近半年被改了多少次
git log --since="6 months ago" --oneline -- path/to/module | wc -l
git log --since="6 months ago" --name-only --pretty=format: -- path/to/module | sort | uniq -c | sort -rn | head
// 度量记录(每季度一行)
季度: 2026Q1
新增: N 关闭: M 冻结: K
净变化: N − M
平均存续时长: 取中位数(月)
关闭率: 关闭数 / 期初条目数
重估后失效比例: 因判据不成立而被清零的条目 / 参与重估的条目
6. 自测
- 台账的关单权为什么应当跟模块走,而不是跟提出者走?
- "问题已随重构消失"这条判据,需要什么证据才算成立?
- 为什么"定期检查"不会减少条目,而"定期重估"会?
- 冻结状态与活跃状态不分,会带来哪一种误判?
- 一次性清零为什么必须写明"不复盘"?
- 条目少于二十条时,为什么正式台账的收益低于维护成本?