3222 字
约 10 分钟
14
S03-A23 · 评审的粒度:评审到什么层次才算够

一次两小时的方案评审,会议纪要里出现十四条"命名建议"、六条"这段能不能拆成两个方法",而真正决定这次改动能否成立的两个前提——峰值写入是均值的多少倍、上游是否允许重复投递——一句话都没被问。评审结束了,方案通过了,问题留在了上线之后。

这不是评审者不认真,是评审深度和改动的不可逆性不匹配。评审不是越深越好:深一层,成本按小时算,能覆盖的问题类型却更窄。把所有改动都评审到实现层,结果一定是时间被格式和命名吃掉,依据层无人过问;把所有改动都只评审到结论层,结论会很顺,但依据错了没人能发现。

这篇给一个判据:先给改动定不可逆性等级,再决定评审到哪一层。层次不是风格,是一笔时间预算的分配。


1. 失配只有两个方向,判据是改动的不可逆性

失配方向 典型现场 时间去向 被漏掉的缺陷类型
抓小放大 讨论命名、缩进、日志级别、方法拆分 八成时间在实现层 需求理解偏差、跨系统契约冲突、容量假设错误
只看结论 "方向我同意",二十分钟通过 零时间在依据层 前提不成立、失效边界缺失、回滚路径不存在

两种失配的代价不对称:抓小放大浪费的是评审者的时间,只看结论浪费的是上线后的返工。后者往往两周后才暴露,届时没人把它归因到"评审太浅"。

先把"拦什么"说清,层次才有意义:该拦的是不可逆的、影响跨出本模块的、与既有约束冲突的三类;不该拦的是风格偏好、机器能检查的、只有作者自己在意的写法。三类该拦的都落在依据层与方案层——这才是深度要往上抬的根本原因,不是评审者不够努力。

判据落在改动本身,而不是代码量:

不可逆性 判定条件 该评审到哪层 需要的评审者
L0 即时可逆 开关、灰度、配置回滚 结论层 + 线上抽检 负责人
L1 一天内可逆 代码部署,回滚即回退版本 方案层 相邻模块负责人
L2 需迁移才可逆 数据形态变化,回滚要反向迁移 依据层 + 方案层 数据 owner + 方案负责人
L3 不可逆 对外接口承诺、数据删除、破坏性 schema 变更 依据层 + 独立复核 契约双方 + 一名未参与者

把等级写进评审单,不靠主持人现场判断:

// 不可逆性四问:任一为"是",等级至少 L2
1. 回滚是否需要反向数据迁移或人工修数?
2. 是否有外部方(其他团队、客户端、第三方)已按旧行为编码?
3. 失败时的最坏结果是数据不可恢复,还是仅服务短时不可用?
4. 这次改动是否缩小了未来选项(锁死结构、锁死字段语义)?

2. 四个层次:成本叠加,拦截能力互相不覆盖

层次 评审者看到什么 单次成本量级 能拦住 拦不住
结论 一句话方向与代价 分钟级 方向性错误、明显不划算 任何依据错误
依据 前提、约束、容量与负载假设 半小时到一小时 前提不成立、假设与真实负载不符 接口细节、失败路径
方案 结构、接口、失败与回滚路径 一到两小时 契约冲突、边界错位、失败处理缺失 前提错误(会被顺带略过)
实现 代码、命名、格式、单测 随行数线性增长 局部缺陷、可读性、可测性 系统性问题、需求偏差

关键结构:四层成本相加,拦截能力互不覆盖。所以"都评审一遍"不是严格,是把四份成本都付一遍,而其中三份本可由别的机制更便宜地承担。实现层的大部分内容(格式、命名、圈复杂度、明显重复)应由工具承担,评审会讨论它们只说明工具缺位:

// 让机器承担实现层的机械部分,评审只处理机器判断不了的
mvn -q spotless:check          // 格式与导入顺序
mvn -q checkstyle:check        // 命名、行宽、可见性修饰
mvn -q pmd:check               // 重复代码、复杂分支
// 三项都在 CI 里失败即拦,不需要人类再看一遍
// 人类评审只讨论:为什么这么选、契约怎么定、失败怎么办

评审单上标注层次,是最便宜的一道约束——它让"这次要问到多深"变成可判定的问题,也避免主持人在实现层消耗掉全部时间:

// 评审单:层次与不可逆性一起标注,决定时间预算
change_id: CR-2026-0417
irreversibility: L2            // 回滚涉及数据反向迁移
review_layers:
  - {layer: 依据, owner: ROLE_A, budget: 45m, must_answer: [峰值倍数, 上游重投许可]}
  - {layer: 方案, owner: ROLE_B, budget: 60m, must_answer: [失败路径, 幂等键]}
skip_layers:
  - {layer: 实现, reason: CI 覆盖格式命名,人工只看失败分支}

3. 改动类型决定层次,人数与同步方式跟着变

改动类型 合理层次 不该做的 典型时间预算
新系统 / 新模块 依据层为主,方案层抽关键路径 逐行看实现 一到两次、每次一小时
跨系统契约变更 依据层 + 方案层逐字段 只对结论点头 一次,需契约双方在场
单模块重构 方案层(接口与失败路径) 讨论内部命名 半小时到一小时
bug 修复 实现层,对准根因 上升到架构讨论 十五到三十分钟
纯配置 / 参数 结论层 + 自动校验 开会 异步,零会议

人数与有效拦截不是线性关系,超过某个点后新增的评审者只增加会议成本:

评审人数 有效拦截 主要副作用
1 单一视角,依据层常被略过 无人敢否决
2–3 典型量级下拦截效率最高 需明确谁有否决权
4 以上 边际拦截趋近于零 责任分散,结论变成折中

同步方式应当由层次决定,而不是习惯(依据层要逐条核对前提与数字,会议节奏会把"这条假设对吗"压成"应该没问题";方案层歧义多,需要即时追问与画图):

// 分层同步:同一改动,两层走两条通道
依据层  → 异步书面:作者提交数字与假设,评审者逐条标注"接受/存疑/反对"
          存疑项必须在会前收敛,否则不进方案层
方案层  → 会议:只看结构、接口、失败路径,现场画图,会上定否决与否
实现层  → 工具 + 提交时评审:CI 拦机械项,人只看失败分支

把两层混在一场会里,通常的结果是依据层被跳过、方案层被拖长。

"我们评审很严格"这句话本身不是证据。严格的可观测形态只有三个:依据层的必答项被逐条回答、未决项有名字和日期、以及评审后返工率没有上升。

4. 记录与度量:留结论与否决理由,不留讨论过程

评审记录的价值在于半年后被引用,而讨论过程在三天内就失去语境。要留的四类内容:结论、否决理由、未决项、层次标注。

// 评审记录:只保留可被后人引用的事实
{
  "change_id": "CR-2026-0417",
  "layers_reviewed": ["依据", "方案"],
  "decision": "approve_with_conditions",
  "conditions": ["幂等键改为业务主键", "补偿任务上限设为 N"],
  "rejected_options": [
    {"option": "同步双写", "reason": "峰值排队,且失败无补偿路径"}
  ],
  "open_items": [{"item": "容量复算", "owner": "ROLE_A", "due": "2026-05-01"}],
  "not_reviewed": "实现层,交由 CI 与提交时评审"
}

not_reviewed 最容易被省略,也最能防责任错位:它显式声明评审不覆盖哪些内容,"评审通过但实现有 bug"就不再是争议。

指标 口径 异常信号
按层次的时间比 依据/方案/实现各占会议时长 实现层占比超过一半
拦截缺陷数 评审阶段提出且被采纳的问题数 长期为零,说明评审在走流程
评审后返工率 通过后两周内因方案问题返工的比例 与评审时长同向上升
未决项闭环率 有主人和日期的未决项按期关闭比例 低于半数,条件形同虚设

四个指标一起看才有意义:评审时长增加而返工率不降,说明时间加在了错误的层次上。

责任边界要提前说清,否则评审退化成背书:评审者对他看过的层次负责——依据层的错误由依据层评审者负责,实现层缺陷不由方案评审者负责,前提是 not_reviewed 写明了他没看哪层。责任绑在覆盖范围上,比"共同负责"可执行。


5. 排错:五种"评审了但没拦住"的现场

现象 真实原因 处理方向
会上全在争命名 工具缺位,实现层被人肉承担 格式命名进 CI,会议禁谈
通过快、两周后返工 只评审到结论层 按不可逆性补依据必答项
结论对但方案冲突 依据层通过、方案层未展开 契约逐字段过一遍,标注失败路径
评审者多但没人负责 无否决权归属,责任分散 指定一人有否决权,其余为建议
纪要读不出为什么否 只记讨论,不记否决理由 记录改为结论 + 理由 + 未决项

6. 边界:什么时候正式评审应当简化或跳过

情形 处理 理由
单人项目 只保留书面依据自查 没有第二读者,评审退化为自证
紧急修复 结论层 + 事后补依据 当下时间成本高于风险
纯配置 / 参数调整 自动校验 + 变更记录 可由工具与回滚覆盖
已被门禁覆盖的机械改动 跳过人工,留变更记录 人工评审只增加排队
可即时回滚且影响面局部 结论层 + 上线后抽检 不可逆性 L0,深度评审不划算

一句话收口:评审深度跟着不可逆性走,不跟着代码行数走。定不下等级时,问那句最实用的话——"这次改动如果错了,多久能退回去,退回去要谁动手"。


自测

  1. 抓小放大与只看结论,哪一种失配的代价会延后暴露,为什么?
  2. 判据为什么落在"不可逆性"而不是"代码行数"或"影响人数"?
  3. 四个层次里,哪一层能拦下"前提不成立",哪一层拦不住?
  4. 评审会上开始讨论命名和行宽,说明哪一环缺位?
  5. 评审人数从三人增到六人,拦截能力为什么不会同比例上升?
  6. 评审记录里 not_reviewed 字段解决了什么责任问题?
S03-A23 · 评审的粒度:评审到什么层次才算够
https://www.clxhxhhr.top/posts/6361/
作者
clxstart
发布于
2024-12-31
许可协议
CC BY-NC-SA 4.0
评论
0 条
还没有评论,先写一条吧。