@TOC
让 AI 审查代码,最容易得到的是一堆正确的废话:
「建议添加错误处理」 「变量命名可以更清晰」 「建议补充单元测试」
这些话对任何一段代码都成立,等于没说。
用了一段时间之后我发现,问题不在于 AI 不会 review,而在于大多数人给它的信息不足以做出有价值的判断。它只看到了你改动的那几十行,看不到这些行在项目里意味着什么。
这篇说清楚三件事:它实际能抓到哪几类问题、哪几类根本抓不到、以及怎么问才能拿到有用的结果。
一、它确实能抓到的 5 类
第一类:改动的影响面遗漏
这是我认为最有价值的一类,前提是工具能看到调用关系。
典型场景:你改了一个函数的返回值语义,本文件内所有调用点都更新了,但另一个包里通过接口间接调用的实现没动。编译能过(接口签名没变),测试也过(那条路径没覆盖)。
这类问题人工 review 很难发现,因为它不在 diff 里。reviewer 看到的是你改的那几个文件,那个漏掉的实现根本不在视野内。
能不能抓到这类问题,取决于工具是否掌握调用关系。如果它只能看到 diff 文本,那和人工 review 的视野是一样的,自然也发现不了。
我现在提交前会做一次自检:
@git:changes 这次改动有没有遗漏的调用方?
特别检查通过接口间接调用的地方。
wescode 能看到 diff,也能看到这些改动涉及的调用关系,所以这个问题它答得比较实。抓到过两次真问题:一次是改了函数签名漏了接口实现,一次是改了返回值语义但没更新依赖这个顺序的下游。
第二类:和项目既有写法不一致
错误处理方式、命名规范、分层约束这些。比如全仓都用 errors.Wrap,你这次用了 fmt.Errorf;handler 都是 Handle 开头,你写了个 processXxx。
这类问题的特点是:单看这段代码完全正确,放在项目里才不对。所以 AI 必须知道项目的既有写法,光看 diff 判断不了。
我在 wescode 里做这步不用额外交代规范——它会对照项目里已有的写法,而不是通用的「最佳实践」。这个区别挺重要:通用最佳实践有时候和项目现状是冲突的,按前者改反而制造了新的不一致。
第三类:机械性的疏漏
这类它抓得又快又准:
- 新增的错误分支没有对应的测试
- 改了函数签名但注释还是旧的
- 加了配置项但文档没更新
- 日志里打了不该打的字段
- 资源申请了没有对应的释放
这些都是「有模式可循」的,不需要理解业务就能发现。人工 review 也能抓,但容易累了就漏,AI 不会累。
第四类:边界条件没处理
空值、空集合、零、负数、越界、并发写。AI 对这类情况相当敏感,因为训练数据里这类 bug 太多了。
我会专门问一句:
这次改动新引入的分支,有哪些输入会走到没处理的路径?
只列你确信没处理的,不要罗列所有可能性。
最后那句很重要。不加的话它会把所有理论可能性都列一遍,一半是噪音。
第五类:安全上的低级错误
SQL 拼接、硬编码密钥、日志打印敏感信息、路径拼接没校验。这几类它识别率很高。
不过要注意,这只覆盖了「模式明显」的部分。复杂的权限逻辑漏洞它看不出来,下面会说。
二、它基本抓不到的 3 类
这部分比上面更重要。知道边界在哪,才不会把 AI review 当成免检通行证。
第一类:业务逻辑对不对
这是最根本的限制。
比如折扣计算,代码写的是先打折再加运费。AI 看不出这有什么问题——从代码角度它完全合理。但如果业务规则是运费不参与折扣、且应该先加运费再整体打折,那这段就是错的。
AI 只能从代码推断意图,而代码可能正好把意图写错了。 这类问题只有懂业务的人能发现,或者靠明确的需求文档和测试用例。
我的做法是:涉及核心业务规则的改动,AI review 只当辅助,人工 review 不能省。
第二类:这个改动该不该做
AI 会告诉你这段代码写得怎么样,不会告诉你这段代码不该存在。
比如为了一个边缘场景加了一层抽象,代码质量没问题,但引入的复杂度不值得。或者这个功能其实和已有模块重复了,应该复用而不是新写。这类判断需要对项目演进方向的理解,AI 给不出来。
第三类:历史原因造成的约束
那段看起来多余的判断,可能是三年前踩过坑加的补丁。AI 看到的是「这个 if 永远为真,建议删除」,但删了线上就炸。
这类信息在 git blame 和当年的 issue 里,不在代码结构里。所以 AI 建议删代码的时候,我一般会先看一眼 blame。
wescode 能告诉我这段代码被谁调用、改了会影响什么,但回答不了「当年为什么要加这个判断」。结构问它,历史问 git,这个分工得拎清楚。
三、怎么问才有用
给 diff,不要给整个文件
review 的对象是改动,不是全部代码。给整个文件,它会把无关的既有代码也评论一遍,噪音很大。
@git:changes 帮我 review 这次改动
这样它聚焦在变化上。改动分散在多个文件时,这个方式比一个个贴文件方便得多。
明确要求「不确定就说不确定」
这条能大幅减少废话:
review 这次改动,要求:
- 只报你确信有问题的地方,不确定的标注「需人工确认」
- 不要提「建议加注释」「建议补测试」这类通用建议
- 每个问题说明:在哪、为什么是问题、怎么改
- 如果没发现问题,就直接说没发现
最后一句很关键。不加的话它总要挤出几条建议来,哪怕代码没问题——模型有「必须给出有用回答」的倾向,你得明确告诉它「没问题」也是合格答案。
分轮次,别一次问全部
一次让它同时看逻辑、性能、安全、风格,每样都浅尝辄止。分开问效果好得多:
第一轮:这次改动有没有遗漏的调用方或影响面
第二轮:新引入的分支有哪些边界情况没处理
第三轮:和项目既有写法有没有不一致的地方
三轮下来比一轮问全面得多,成本也没高多少。
四、放进流程的两个位置
位置一:提交前自检
这是我用得最多的。写完 git add 之前,在 wescode 的 Chat 里让它扫一遍改动。
好处是这时候还没推上去,发现问题改起来没有心理负担。抓到的多是机械性疏漏——漏更新的注释、忘了的测试、不一致的写法。
位置二:review 别人的 PR 之前
拿到一个大 PR,先让 AI 过一遍,把机械性问题列出来。然后我自己的注意力就可以集中在业务逻辑和设计上——那正好是 AI 抓不到的部分。
这个分工我觉得是对的:AI 负责「有模式可循」的部分,人负责「需要判断」的部分。
反过来用就危险了:让 AI 判断业务逻辑对不对,自己只看格式,那是把两边的长处都浪费了。
五、几个实际的坑
它倾向于挑出问题,哪怕没有
前面提过,模型有给出「有用回答」的倾向。如果代码确实没问题,它可能会编几条无关痛痒的建议。
所以看到「建议优化变量命名」这类时,直接忽略就行,别真去改。判断标准是:这条建议有没有说清楚「为什么现在这样是问题」。说不清楚的基本都是凑数的。
大改动会漏
一次改了二十个文件,让它一次 review 完,后面的会明显变敷衍。改动大的话拆开分批看。
它不知道你的测试覆盖情况
它说「这个分支需要测试」,但可能已经有测试了,只是在另一个文件里。这类建议要自己核实一下再动手。
六、什么情况下不用它
改动特别小的时候。 改一行配置,自己看一眼比走一轮流程快。
纯业务规则的改动。 前面说了,这是它的盲区,找产品或者业务方确认更靠谱。
已经有完善 lint 和 CI 的项目。 机械性问题 lint 已经拦住了,AI 再扫一遍收益不大。这种情况下它的价值主要在影响面分析上。
小结
AI 做 code review 的实际价值,我觉得可以概括成一句:它替你完成「需要耐心但不需要判断」的那部分。
漏掉的调用方、不一致的写法、没处理的边界、忘了更新的注释——这些人工也能发现,但需要逐行盯着看,累了就会漏。AI 不累,这部分交给它很划算。
但涉及判断的部分——业务对不对、这个设计该不该做、这行代码为什么当年要这么写——它给不出可靠答案。这些仍然是人的工作,而且应该是 review 时真正投入注意力的地方。
把 AI review 当成一道前置过滤,而不是终审,这个定位比较合适。
文中用到的 diff 引用和调用关系检查都是在 wescode 里做的,官网是 weisyn.com。你们把 AI 放进 review 流程的哪个环节,效果如何,欢迎评论区交流。