代码写得越快,评审越像走过场:Java团队的Code Review怎么跟上
一个很具体的画面。
周五下午,评审队列里躺着一个PR:41个文件,三千多行diff。改动里既有新接口,也有两个老Service的重构,还夹带了一处配置调整。作者说"这是AI帮着一起做的,本地测试都过了"。
你打开diff,往下拉了三百行,还没拉到核心逻辑。最后点了个approve。
这个场景,正在越来越多Java团队里重复。而它留下的数据痕迹,比感受更直白。

两个数字
研发效能平台LinearB统计过一个现象:AI参与之后,单个PR的体量平均涨到原来的2.6倍。同时,PR的合并率不到一半。
另一边,GitClear的报告给了一个更刺眼的指标:代码流失率(churn)上涨了39%。churn指的是写完不久就被改掉或删掉的代码——它不是"代码多",而是"白写"。
两件事放在一起看,逻辑链是清楚的:写代码变便宜了,于是代码变多了;代码多到超出人能认真评审的上限,于是该拦的没拦住;没拦住的部分,在几周后以返工的形式还回来。
瓶颈从"写"这一环,转移到了"看"这一环。
为什么Java项目尤其容易堆积
Java的工程结构决定了它"多写"的倾向。
同一个业务对象,在Java项目里通常要经过Entity、DTO、VO、Convertor几层转换。功能上多数时候没有区别,但结构上必须存在。AI看不出"这次其实不需要新加一层"——它只会照着既有模式补齐。
于是下面这几类东西会持续堆积:
- 重复的DTO和Converter,字段几乎一样,只是来源表不同
- 为了兼容老接口写下的if-else分支,旁边备注"历史原因"
- 一次性的数据修复脚本和迁移类,跑完留在仓库里
- 已经没人引用的配置类和常量
它们的共同点是:每一条都不算错,加起来就成了负担。
更麻烦的是,注释、命名、分层这些"表面质量",AI做得比人还好。一份代码看起来越规整,评审的人越容易放松——这是前面那个"拉了三百行就approve"的真正原因。
不算错但该走的代码,谁来清
前面那份堆积清单有个共同点:每一条单独看都有理由。兼容老接口的if-else分支、一次性的迁移脚本、已经没人引用的配置类——没有一条是bug,所以没有一条会被评审拦住。这类存量不会自己消失,只会随着新功能一起变多。
以飞算JavaAI的Java整洁器为例,它的做法是把"该不该清"变成可对照的规则:按Checkstyle规范查出写法问题,按SAST扫描查出静态分析发现的问题,再清理冗余代码。它给出的不是"这里可以优化一下"这类建议,而是逐条对应到具体规则和扫描结果的清理依据。


这对上了churn上涨39%背后的结构性原因。清理之所以一直被推后,是因为它没有触发条件——"有空再说"等于永远不说。当违规项能被规则和扫描逐条列出来,清理就成了一件有清单、有完成标准的事:清了哪些、还剩哪些是可验证的,不再靠感觉判断够不够干净。
边界也清楚:它处理的是规则和静态分析能判定的部分,判不了"这个DTO是不是真的该删"——字段几乎一样、来源表不同的那两个类,删不删取决于业务,工具只会告诉你它们重复。至于让评审的人先有全局视角,那是另一个动作(读源码产出一份架构与模块说明),解决的是理解成本,不是存量清理。
评审这一环,卡在人的注意力上
有个数字常被忽略:人一次能认真读的diff,大概在几百行这个量级。超过这个量,注意力会断崖式下降,剩下的动作变成"扫一遍"。
而AI一次的产出,正好落在这个量级的几倍以上。
所以问题不是"评审不认真",而是流程没有跟上产能的变化。以前一个PR几百行是常态,现在几百行只是AI的一次输出。
三个马上能改的做法
第一,给AI派活时限定改动范围。
不要给一个"帮我优化用户模块"这样的任务,改成"只改UserService的校验逻辑,不要动其他文件"。范围越窄,diff越小,评审越可能真正发生。
第二,让测试在前面说话。
评审的人力和注意力是有限的,应该花在"测试覆盖不到的地方"——业务判断、边界处理、异常分支。那些能被测试验证掉的,交给工具跑,不要占用人眼。
第三,定期做减法,而不是一直做加法。
代码churn上涨39%这件事,一半原因在于我们只习惯新增。清理不会因为"大家注意点"就发生,它需要一个固定的时间点和一份明确的清单——按什么规则查、查到什么程度算清完。把这件事写进迭代节奏里,比写进规范文档里管用。
最后
AI没有让评审变得不重要,它让评审变成了新的瓶颈。
而流程这件事,从来不会自动适配。产能翻倍了,流程不动,多出来的部分就会以返工的形式找回来。
想听听大家的做法:你们团队的PR有没有设diff行数上限?如果AI一次生成三千行,是拆开分批评审,还是有人会直接整份approve?
- 点赞
- 收藏
- 关注作者
评论(0)