第七章:代码审查
代码审查是质量把关——而非形式、表演,也非社交仪式。Superpowers 将代码审查视为一项严谨的技术活动,对请求和接收反馈都有明确的规范。
第一部分:请求代码审查
为什么结构很重要
无结构的代码审查请求("嘿,能帮我看看这个吗?")只会产生无结构的反馈。审查者不知道代码应该做什么、解决什么问题,或做出了哪些权衡。结果是表面化的评论,错过了重要问题。
有结构的请求能给审查者提供真正有用反馈所需的一切信息。
准备上下文
在派遣审查者之前,请准备以下三类信息:
WHAT — 这次变更做了什么?用 2–4 句话描述:
- 正在解决的问题
- 采用的方案
- 关键设计决策及其原因
- 你没有做什么以及原因
PLAN — 实现计划是什么?链接或总结指导本次工作的计划。这让审查者能够验证实现是否符合意图。
BASE_SHA → HEAD_SHA — 被审查的精确 commit 范围:
# 获取 base(你的分支从 main 分叉的位置)
git merge-base main HEAD
# 获取当前 HEAD
git rev-parse HEAD
这确保审查者查看的是正确的 diff——不包含无关 commit,也不是完整历史记录。
派遣审查 subagent
准备好上下文后,按以下结构派遣代码审查 subagent:
REVIEW REQUEST
--------------
WHAT: [2-4 句话描述变更内容]
PLAN: [实现计划的链接或摘要]
DIFF RANGE: [BASE_SHA]..[HEAD_SHA]
FOCUS AREAS: [可选:你希望重点审查的具体区域]
Subagent 将检查 diff、核对计划、运行相关测试,并返回结构化反馈。
按严重性处理审查反馈
并非所有反馈都具有相同的紧迫性。每个严重级别的处理方式不同:
| 严重性 | 定义 | 处理方式 |
|---|---|---|
| Critical(严重) | Bug、安全问题、数据丢失风险、broken contract | 阻塞完成。 在任何其他工作之前立即修复。 |
| Important(重要) | 重大质量问题、缺少测试、性能问题 | 在开始下一个任务前修复。不要积累。 |
| Minor(次要) | 风格偏好、命名建议、可选改进 | 记录下来。 创建后续 ticket。不要对当前 PR 过度完善。 |
最常见的错误是将所有反馈视为同等紧迫。严重问题阻塞进度。次要问题记录存档。混淆两者会导致要么因琐碎的风格反馈而延误,要么忽视真正的 bug。
第二部分:接收代码审查
核心问题:表演性认同
AI agent——以及许多开发者——在代码审查中有一种倾向于表演性认同的习惯。这是当审查者提出建议时,实现者立即说"你说得完全正确!我马上修复!"并在没有真正评估建议是否正确的情况下做出修改。
表演性认同是有害的,因为:
- 它将错误的建议应用到正常运行的代码上
- 它训练审查者期望无条件服从
- 它通过积累错误建议使代码质量随时间下降
- 它提供了审查正在发现真实问题的虚假信心
禁用语
以下短语表明表演性认同,不允许使用:
| 禁用语 | 原因 | 替代表达 |
|---|---|---|
| "你说得完全正确!" | 未经评估就认可 | "已修复。将 X 改为 Y,原因是 [理由]。" |
| "好发现!" | 社交奉承,无实质内容 | "已核实。问题是 Z。" |
| "我马上修复" | 在理解之前做出承诺 | "正在阅读这段内容。" |
| "这完全说得通" | 未经分析就认同 | "我理解这个顾虑。以下是我的评估:……" |
| "你是对的,我本应该……" | 无行动的自我批评 | "已实现。以下是具体变更。" |
替代语言聚焦于事实:什么发生了变化、为何变化、以及核实了什么。
正确的响应模式
收到代码审查评论时,请严格按照以下顺序操作:
READ → UNDERSTAND → VERIFY → EVALUATE → RESPOND → IMPLEMENT
READ(阅读): 阅读完整评论,包括任何引用的代码或文档。阅读期间不要响应。
UNDERSTAND(理解): 你能用自己的话解释审查者的顾虑吗?如果不能,提出澄清问题。不要猜测意图。
VERIFY(核实): 通过查看实际代码来检查顾虑是否成立。如适用,运行相关测试。查看真实行为,而非你对它的心理模型。
EVALUATE(评估): 应用 YAGNI 检验(You Aren't Gonna Need It,你不会需要它):
- 这个变更对当前需求是必要的吗?
- 它解决了一个真实的、已被证明的问题吗?
- 它增加了代码库目前不需要的复杂性吗?
- 这是合理的最佳实践还是个人风格偏好?
RESPOND(响应): 基于你的评估而非本能认同来撰写响应。
IMPLEMENT(实现): 如果建议有效,实现它。如果无效,解释你的理由。
对审查建议的 YAGNI 检验
审查者建议"你应该在这里添加缓存"或"你应该将这个抽象为通用接口"可能是对的——但必须进行 YAGNI 检验:
- 当前需求真的需要缓存吗?是否有性能问题的实测证据?
- 现在是否有超过一个具体的抽象使用场景?
如果答案是否,正确的回应是:"已记录为潜在的未来改进。对于当前需求,更简单的方案已经足够。我已将其记录为后续事项。"
有效的反驳场景
你不仅被允许反驳审查反馈——在以下情况下你必须反驳:
-
建议引入了 bug。 用测试或具体示例证明为什么建议的变更会产生错误行为。
-
建议违反了既定计划。 如果实现计划已经过审查和批准,偏离需要明确的重新批准,而不是在代码审查期间单方面更改。
-
建议超出范围。 建议可能是好的,但它属于单独的任务。现在实现它会扩大范围、延迟交付,并创建混合用途的 commit。
-
建议是风格偏好,对正确性没有影响。 风格偏好应该属于 linter 配置,而不是代码审查反馈。如果它无法自动化,可能不值得阻塞 PR。
-
你已经核实代码是正确的,而审查者是错误的。 清晰、礼貌地提供你的证据。你可能是错的——但你必须陈述理由。
反驳模板
反驳时,使用以下结构:
I've evaluated this suggestion. My assessment:
CONCERN: [准确重述审查者的顾虑]
INVESTIGATION: [我检查了什么来评估它]
FINDING: [我发现了什么]
DECISION: [实现 / 记录以备后用 / 不同意,因为……]
EVIDENCE: [测试输出、参考资料或具体示例]
这使你的推理可被审计,并使审查对话聚焦于事实。
总结
做好的代码审查是最强大的质量工具之一。做得差的代码审查——无论是走形式还是合规表演——比没有审查更糟糕,因为它消耗时间却不产生质量。
Superpowers 规范确保审查的双方都是严格的:审查者获得所需的上下文,而实现者以技术诚实而非社交顺从来评估反馈。