banner
NEWS LETTER

AI 辅助代码审查:从 diff 到可执行整改

Scroll down

代码审查最重要的价值,不是把变量名挑得更整齐,而是尽早发现行为风险、边界遗漏和维护成本。AI 工具可以快速阅读 diff、追踪调用链、补充测试思路,但如果直接问“这段代码有没有问题”,得到的答案往往很泛,甚至会把风格偏好包装成严重缺陷。

更稳定的做法,是把 AI 放进一个明确的审查流程里:先限定审查范围,再按风险分层阅读,最后把发现的问题转成可执行的整改项。这样它不是替代人工判断,而是帮助维护者更快看清变化背后的影响面。

一、先明确审查目标

同一份 diff,在不同目标下需要看的重点并不一样。

如果目标是上线前风险审查,重点应该放在:

  • 是否改变核心业务行为。
  • 是否存在崩溃、数据丢失、权限绕过。
  • 失败路径是否被正确处理。
  • 是否缺少关键测试或回滚方案。

如果目标是长期维护审查,重点可以放在:

  • 模块边界是否变清晰。
  • 命名是否表达真实业务含义。
  • 重复逻辑是否被收敛。
  • 新抽象是否真的降低复杂度。

如果目标没有说清楚,AI 很容易把所有维度混在一起,输出一堆优先级不明的建议。审查前可以先写一句:

1
请以发布风险为主审查这次 diff,优先指出会导致错误行为、崩溃、数据问题和缺失测试的地方。风格建议只有在影响可维护性时再提。

这句话会把 AI 的注意力从“挑毛病”拉回“找风险”。

二、让 AI 先读上下文

只看 diff 可能不够。很多问题隐藏在调用关系、配置约定和历史兼容里。

例如一个接口字段从 status 改成 state,diff 本身看起来只是命名调整,但实际可能影响:

  • 服务端序列化字段。
  • 客户端解析逻辑。
  • 数据库存量数据。
  • 埋点和报表。
  • 第三方回调协议。

因此审查时应该让 AI 先读取相邻上下文:

1
2
请先阅读本次变更文件、直接调用方、相关测试和配置文件。
先总结你看到的调用链和外部约束,再进入问题清单。

这个步骤能减少“只根据片段猜测”的问题。尤其是 Android、后端服务、嵌入式 Linux 这类工程,很多约束不在单个文件里,而在生命周期、服务启动顺序、线程模型、部署脚本或设备环境中。

三、按风险分层审查

AI 输出的问题需要分层,否则 review 很难推进。比较实用的分层方式是:

  • 必须修复:会导致错误结果、崩溃、安全问题、数据破坏或构建失败。
  • 建议修复:现在不一定出错,但会增加边界风险或维护成本。
  • 可选优化:风格、命名、拆分方式、局部可读性。

审查时可以要求它使用固定结构:

1
2
3
4
5
6
7
请按严重程度列出发现:
1. 问题标题
2. 文件和行号
3. 触发条件
4. 影响
5. 建议修改
如果没有高风险问题,请明确说明。

这比单纯列出“建议”更适合工程协作。因为每个问题都必须回答“什么时候发生”和“会造成什么影响”,不能只停留在感觉层面。

四、重点看行为变化

代码审查的核心是行为变化。AI 很擅长发现明显异常,但也容易漏掉“看起来合理、实际改变语义”的地方。

常见风险包括:

  • 默认值变化导致旧数据表现不同。
  • 异常被吞掉,调用方无法感知失败。
  • 同步逻辑改成异步后,调用顺序变化。
  • 缓存 key 或过期策略改变。
  • 分页、排序、过滤条件出现边界差异。
  • Android 生命周期回调中引入了重复注册或泄漏。

例如下面这种修改看起来是在简化逻辑:

1
val name = user.name ?: ""

但如果旧逻辑会在 name == null 时显示“未登录”,新逻辑就改变了 UI 语义。空字符串不是无害默认值,它可能绕过了调用方对缺失状态的判断。

审查提示可以写得更直接:

1
2
请重点检查这次修改是否改变了空值、异常、默认值、排序、缓存和重试行为。
不要只评价代码是否更简洁。

五、测试不是数量问题

AI 经常会建议“增加单元测试”,但这句话本身价值有限。更有用的是指出缺哪一种测试。

可以按行为路径拆分:

  • 正常路径:常见输入能得到预期结果。
  • 边界路径:空值、空列表、最大值、最小值、非法格式。
  • 失败路径:网络失败、磁盘失败、权限失败、服务不可用。
  • 并发路径:重复点击、重复请求、生命周期切换、取消任务。
  • 回归路径:修复过的问题不会再次出现。

例如一个 Repository 增加缓存逻辑,测试建议不应该只是“补测试”,而应该具体到:

1
2
3
4
5
需要覆盖:
1. 首次请求走网络并写入缓存。
2. 网络失败时返回旧缓存。
3. 强制刷新时不读取过期缓存。
4. 并发请求不会重复写入互相覆盖。

这种建议更容易被开发者直接转成测试用例。

六、让 AI 做第二遍自查

当 AI 给出修改建议后,可以让它再做一遍反向检查:

1
2
请重新检查上面的发现,删除没有明确触发条件或影响不足的问题。
保留的问题必须能说明具体文件、具体场景和具体后果。

这个步骤很有用。第一次输出通常偏发散,第二次会收敛掉一些“可能更优雅”的建议。代码审查不需要把所有想法都塞进评论里,真正重要的是让开发者知道哪些问题必须处理。

如果 AI 声称某个问题存在,还可以继续追问:

1
2
请说明这个问题是否能从当前代码直接推导出来。
如果只是推测,请标记为假设,并说明需要补充查看哪个文件才能确认。

这能避免把不确定判断当成确定缺陷。

七、把评论改成整改清单

审查结束后,问题清单还需要变成行动清单。比较适合落地的格式是:

1
2
3
4
5
6
7
8
9
10
11
必须修改:
- 修复 xxx 条件下的空指针崩溃。
- 恢复 xxx 接口的失败返回语义。
- 增加 xxx 边界测试。

建议修改:
- 将重复的状态判断提取到 xxx。
- 为 xxx 增加日志,方便线上定位。

暂不处理:
- xxx 命名调整,当前不影响行为,可放到后续重构。

这样 review 不会停在讨论阶段。开发者可以按优先级逐项处理,审查者也能快速确认是否闭环。

对于较大的变更,整改清单还可以按提交拆分:

1
2
3
4
第一步:补测试,固定当前行为。
第二步:修复失败路径和空值处理。
第三步:整理重复逻辑,不改变接口。
第四步:运行构建和相关测试。

AI 很适合帮助做这种拆分,但是否拆得合理,仍然需要维护者结合发布节奏和风险判断。

八、适合日常使用的审查提示

下面是一段可以复用的提示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
请审查当前变更。

目标:
以工程风险为主,不做泛泛的风格点评。

请先做:
1. 阅读 diff 涉及文件、直接调用方和相关测试。
2. 总结本次变更的意图和影响范围。

请重点检查:
1. 行为变化、兼容性、空值和异常路径。
2. 并发、生命周期、资源释放和重复调用。
3. 缓存、排序、分页、权限和数据一致性。
4. 是否缺少能证明行为正确的测试。

输出要求:
1. findings 放在最前面,按严重程度排序。
2. 每个问题包含文件位置、触发条件、影响和建议。
3. 不确定的判断标记为假设。
4. 如果没有明确问题,请直接说明,并指出剩余风险。

这段提示的重点是把 AI 的输出限制在可审查、可验证、可执行的范围内。

九、不要把 AI 评论直接当结论

AI 辅助审查可以提高覆盖面,但它不能替代维护者对业务语义的判断。尤其是以下场景,必须人工确认:

  • 业务规则是否符合产品预期。
  • 接口兼容是否符合历史约定。
  • 权限和数据边界是否符合组织要求。
  • 线上发布是否需要灰度、回滚或监控。
  • 测试覆盖是否足以支撑发布风险。

更好的协作方式是:AI 负责扩大检查范围和整理问题,人负责确认事实、判断优先级和决定取舍。

十、总结

AI 辅助代码审查的关键,不是让工具多说几条建议,而是让它在正确的问题框架里工作。

一个稳定的流程可以概括为:

  1. 明确审查目标。
  2. 读取 diff 之外的上下文。
  3. 按风险分层输出问题。
  4. 关注行为变化和测试缺口。
  5. 把评论整理成整改清单。
  6. 最后用构建和测试验证闭环。

当审查流程足够清晰,AI 的价值会从“生成评论”变成“提升发现风险的密度”。这对个人项目和团队协作都很实用,因为真正节省时间的不是少写几句 review,而是少放过一次难以定位的线上问题。

其他文章
目录导航 置顶
  1. 1. 一、先明确审查目标
  2. 2. 二、让 AI 先读上下文
  3. 3. 三、按风险分层审查
  4. 4. 四、重点看行为变化
  5. 5. 五、测试不是数量问题
  6. 6. 六、让 AI 做第二遍自查
  7. 7. 七、把评论改成整改清单
  8. 8. 八、适合日常使用的审查提示
  9. 9. 九、不要把 AI 评论直接当结论
  10. 10. 十、总结
请输入关键词进行搜索