返回探索
指南VibeFix 编辑部更新于 2026年10月27日

AI 代码合并前怎么审:比审人写的代码更严的四步法

模型写代码是按概率拼出最像正确的代码,而不是按理解推导正确的代码——错误往往藏在完全正确的语法里。本指南给出合并前四步:先读 diff、跑模型没跑过的路、查安全与隐私、问三个关于未来的问题,附可直接贴进 PR 模板的速查表。

真实照片:两位开发者一起看屏幕讨论代码;非产品截图
真实照片:两位开发者一起看屏幕讨论代码;非产品截图

先讲一个反直觉的结论:AI 代码的评审标准应该比人写的更严,而不是更松

很多人对 AI 生成代码有一个温柔的错觉:既然是模型写的、测试也过了,那就比人手写更不容易出错。这个错觉错在两个地方。第一,模型写代码的方式是“按概率拼出最像正确的代码”,而不是“按理解推导出正确的代码”——它可以在完全正确的语法里藏一个完全错误的业务假设,而且这个假设看起来还非常合理。第二,模型最擅长的是让代码“看起来像能跑的样子”:命名规范、注释体贴、结构工整,这些信号会让评审者的大脑提前进入“没问题”的状态,恰恰在最该警惕的时候放松下来。

所以这篇指南的立场很明确:AI 生成代码的合并评审,要比评审人写的代码更严、更慢、更不信任“看起来没问题”。不是因为模型差,而是因为它的错误模式不同:人的错误往往是粗心、拼写、边界条件漏掉;模型的错误往往是“自信地把错误的前提当成事实”,比如调用了一个不存在的接口、假设了一个不存在的字段、把两个相似但不同的业务概念混为一谈。这些错误通过肉眼扫读是很难发现的,必须靠一套固定的评审动作把它逼出来。

边界说明:这篇指南不是什么

在进入正文之前,先把这篇指南和站内已有的邻近内容划清界限,避免你拿着错误的文档去解决错误的问题。本篇讲的是“代码已经生成、即将合并之前,人应该怎么审”——审的对象是已经写出来的 diff,审的动作是读、跑、查、问,审的终点是“合并不合并”的决定。它不是 agent 权限契约指南:权限契约管的是 agent 在动手之前被允许做什么、不能碰什么,是事前的授权与隔离;本篇管的是事后的审查与把关,两者一前一后、不能互相代替——权限设得再严,也拦不住一个被授权范围内的错误实现;审查做得再细,也补不回一个越权操作造成的损失。

它也不是 Claude Code Review 这类评审工具的介绍:工具可以帮你把 diff 读出来、把可疑点标出来,但“这个业务假设对不对”“这个边界条件该不该这样处理”这类判断,工具给不了你,只能由熟悉业务的人来做。同样,它也不是任务验收清单:验收清单回答的是“这个任务算不算做完”(功能、文档、测试、发布步骤齐不齐),本篇回答的是“这段代码能不能进主分支”(逻辑对不对、安全有没有洞、会不会给以后埋雷)。一个任务可以验收通过但代码仍然不该合并——比如功能都实现了,但实现里藏了一个只有特定数据才会触发的错误分支。审代码和验任务,是两道不同的关,都要过。最后,它也不同于本站 2026-10-02 的《AI 代码 review 清单:12 个检查点》:那篇是按检查点罗列的清单,本篇是按评审动作顺序展开的四步方法(读 diff、跑未覆盖路径、查安全隐私、问未来问题),并附评审节奏、记录与 PR 模板——清单告诉你查什么,本篇告诉你按什么顺序动手、做到什么程度才点合并。

第一步:先读 diff,不要先读解释

评审 AI 代码最常见的失误,是先读模型给你的解释、再去看代码。模型的解释写得越好,你越容易带着“它已经想清楚了”的先入为主去看代码,然后把所有可疑之处都自动解释过去。正确的顺序是反过来的:先打开 diff,从第一行读到最后一行,自己先形成判断,再去看模型的解释——解释只能用来回答你已经产生的疑问,不能用来替你产生判断。

读 diff 时有三个具体的检查点。第一,检查每一处“新引入的假设”:新调用的函数、新增的字段、新依赖的库、新假设的数据格式——每一个都要问“这个东西真的存在吗?真的是这个语义吗?”模型最常见的错误就是编造一个看起来存在的接口,或者把 A 系统的字段名用到 B 系统上。对策很简单:对每一个不认识的调用,花十秒钟在代码库里搜一下它的定义;搜不到,就是红灯。第二,检查“被删掉的东西”:模型重构时经常悄悄删掉一个边界处理、一个错误分支、一个看似无用的校验——删掉的原因要么是它认为没用,要么是它没注意到。被删的每一行都要有明确的理由,理由只能是“这个逻辑被移到了某某处”,不能是“看起来没用”。第三,检查“改动范围”:一次任务只改三个文件,diff 里却出现了第五个文件的改动——多出来的改动往往是模型“顺手”做的,而顺手做的改动最容易没有经过思考。

第二步:跑起来,而且要跑“它没跑过的路”

测试通过不等于代码正确——这句话对人写的代码成立,对 AI 代码尤其成立。因为模型生成代码时往往也生成了测试,而测试和实现可能共享同一个错误的假设:实现假设字段 A 是字符串,测试也按字符串去断言,于是测试全绿、实现全错。评审时必须跑“模型没跑过的路”:换一组它没见过的输入、走一条它没覆盖的分支、把边界值推到极端。

具体做法有四招。第一,手动构造一个反例:找一个模型声称处理了、但你怀疑它没处理好的场景,亲手跑一次,看结果是不是你预期的。第二,改一个输入再跑一次:如果改动一个数字、一个字符串、一个空值,程序的行为就变得不可解释,说明实现里藏着对输入格式的隐性假设。第三,看错误路径:故意让依赖失败(比如数据库连不上、接口返回错误码),看程序是优雅降级还是直接崩溃——模型最容易在错误路径上偷懒,因为正常路径的测试总是先通过。第四,检查性能陷阱:循环里查数据库、每次请求都重新算一遍全量数据、没有上限的递归——这些问题在小数据测试里完全看不出来,上线后才会在真实数据量下爆炸。

还有一个评审者经常忽略的点:测试本身也要审。模型生成的测试如果只是“把实现的行为原样复述一遍”,那它不是测试,是实现的同义词。好的测试应该来自需求,而不是来自实现:先看需求文档或任务描述,问“这个功能应该在什么情况下输出什么”,再看测试断言的是不是这件事。如果测试只是在断言“实现做了它做的事”,那这套测试通过与否都不能作为合并的依据。

第三步:查安全与隐私,这是最不能“差不多”的部分

安全问题是 AI 代码评审里权重最高的一类,因为它们的代价不对称:一个逻辑错误可能只影响一个功能,一个安全漏洞可能影响整个系统。而且模型在安全问题上有一个系统性弱点:它倾向于写出“能跑”的代码,而不是“安全”的代码——比如直接拼接 SQL、把用户输入拼进命令、把敏感信息打进日志、在前端暴露不该暴露的字段。这些写法在功能测试里全部通过,在安全评审里全部是红灯。

评审时按一张固定清单查,不要凭感觉。输入侧:所有外部输入(用户输入、接口参数、文件内容、环境变量)有没有经过校验和转义?有没有直接拼进 SQL、命令、模板、正则的地方?输出侧:返回给前端或第三方的数据里,有没有不该出现的字段(密码哈希、内部 ID、他人数据)?日志里有没有敏感信息(token、密码、个人身份信息)?权限侧:这个接口有没有做权限检查,还是默认“能调就是能看”?新加的接口有没有被错误地暴露给所有用户?依赖侧:新引入的库是不是可信来源、版本有没有已知漏洞、是不是把一个重量级的依赖只为用一个小函数而引进来?

隐私问题同样要单列一类:新代码有没有收集超出需求的数据?有没有把用户数据写到不该写的地方(日志、缓存、第三方服务)?有没有在不知情的情况下改变数据的保留期限?这些问题在功能上完全看不出来,必须靠评审者对照需求一条一条地问。我的建议是:安全与隐私这两类问题实行一票否决——只要有一处没说清楚,就不合并,不管功能写得多漂亮。合并后再修安全问题,成本永远比合并前高一个数量级。

第四步:问三个“以后会后悔”的问题

前三步审的是“现在对不对”,这一步审的是“以后会不会后悔”。AI 代码有一个特点:它倾向于写出“当下能用”的实现,而不太考虑“以后维护的人怎么办”。评审者要替未来的维护者问三个问题。第一,可读性:半年后一个新人读这段代码,能不能在十分钟内理解它在干什么?如果答案是“要先读模型当时的对话记录才能懂”,那这段代码就不合格——代码的读者是人,不是模型当时的上下文窗口。第二,可改性:需求变一点,这段代码要改多少地方?如果改一个字段要动五个文件,说明抽象错了,模型把本该集中在一处的东西散开了。第三,可删性:这个功能如果以后不要了,能不能干净地删掉?如果删掉它要连带改十处地方,说明耦合太深,现在就该重构,而不是等到真要删的那天。

这三个问题没有自动化工具能替你回答,只能靠评审者对代码库的熟悉程度。所以这里有一个组织层面的结论:AI 代码的评审者不能是“随便找个人看一眼”,必须是熟悉这块业务和这块代码的人。不熟悉的人只能审出语法问题,审不出业务假设错误和维护性问题。团队在排评审时,要把“熟悉度”放在“空闲度”前面——宁可等熟悉的人有空,也不要让不熟悉的人草草通过。

评审的节奏与记录:慢评审、快反馈、留痕迹

评审节奏上,我主张“慢评审、快反馈”。慢评审是指:不要在模型刚交代码的五分钟内就点合并,给自己留出至少一次“放下再看”的机会——很多错误是在第二遍读的时候才看出来的,因为第一遍读的时候你还沉浸在模型的解释里。快反馈是指:一旦发现问题,立刻、具体地反馈给模型或作者,不要攒到最后再一次性提十条——反馈越具体(指出文件、行号、错误假设),下一轮修复的质量越高;反馈越笼统(“这里有点问题”),下一轮越可能改出新的问题。

记录同样重要。每次评审的结论(通过、有条件通过、打回)以及打回的理由,都应该留在 PR 里,而不是只存在聊天记录里。理由要写到“假设”这个粒度:不是“这里不对”,而是“这里假设用户 ID 一定存在,但匿名用户没有 ID,所以匿名流程会崩”。这样的记录有两个好处:第一,下次类似问题出现时可以直接引用;第二,它构成了团队的评审知识库——新人读过去的评审记录,比读十篇指南更快理解“我们团队在意什么”。

最后说一句组织层面的话:不要把 AI 代码评审当成“给模型挑错”,要把它当成“团队代码质量的最后一道关”。模型会换、工具会换、提示词会换,但“合并之前有人认真读过、跑过、查过”这道关不能换。关口一旦松下来,代码库里就会悄悄积累起一批“看起来能跑、实际上埋着错误假设”的代码,而这些代码的代价,永远是在最不方便的时候才一次性付清。

附:评审清单速查表(贴在 PR 模板里直接用)

读 diff:是否先读 diff 再读解释?每个新调用是否在代码库里确认存在且语义正确?被删掉的每一行是否有明确去向?改动范围是否超出任务本身?跑起来:是否跑了模型没跑过的输入和分支?是否手动构造了反例?错误路径是否优雅降级而非崩溃?大数据量下有没有性能陷阱?测试本身是否来自需求而非复述实现?查安全:外部输入是否校验转义?有没有拼接 SQL、命令或模板的地方?返回数据里有没有不该出现的字段?日志里有没有敏感信息?接口权限是否检查到位?新依赖是否可信且必要?问未来:半年后的新人能否十分钟看懂?需求微变要改几处?功能废弃时能否干净删掉?评审者是否熟悉这块业务与代码?结论与记录:结论是合并、有条件合并还是打回?打回理由是否写到了假设粒度并留在 PR 里?把这张表贴进 PR 模板,每次评审逐项打勾——不是为了形式,而是为了让“认真”变成可重复的动作,而不是依赖某个人当天的状态。

再补一条评审者最容易忽略的检查:看 diff 里有没有“模型自己加的、任务没要求的额外功能”。模型常常顺手多做一点——多一个配置项、多一个接口、多一段“以防万一”的兼容逻辑。这些额外功能没有需求背书、没有测试覆盖、没有人承诺维护,合并进去就是未来的负担。评审时对“任务外的新增”要格外警惕:要么让作者证明它确实必要并补上测试与文档,要么直接要求删掉。代码库的干净程度,往往就取决于对这些“顺手之作”是容忍还是拒绝。

一句话总结这篇指南的全部要求:合并之前,评审者必须亲自读过每一行 diff、跑过模型没跑过的路径、查过安全清单里的每一项、并问过三个关于未来的问题——这四件事做完,才点合并;任何一件没做,合并就是在透支代码库的信任。

补充说明:评审意见要写在 PR 里公开留痕,口头说过的问题不算提过——只有写下来的意见才能被追踪、被复核、被后来的人引用,口头意见会在下一轮修改里悄悄丢失。

最后提醒:评审通过不是终点,合并后的第一周要留意相关功能的错误日志与用户反馈——评审时没看出来的问题,往往在真实流量下才会露头,早发现早回滚,代价最小。

阅读 0评论 0

评论 (0)

ME
0/1000
评论加载中...
浏览项目广场发布你的项目

相关文章

真实插图:故障排查主题封面图;非产品截图
指南
写给 agent 的故障报告:目标不是描述清楚,而是一次修好

给人写的报告目标是让人理解,给 agent 写的报告目标是让它一次修好、不返工。本指南把故障报告升级为修复规格:六个必备部分、证据的正确用法、可验证的预期行为、五种返工写法,以及可直接套用的模板。

开发工作流调试排错测试与质量
一把挂锁放在笔记本电脑键盘上,代表为第三方 API 密钥上锁、轮换与泄漏止血。
指南
密钥轮换与泄漏演练:vibe 项目第三方 API 密钥的换血手册

密钥不出事时只是字符串,出事时却是能刷爆账单的通行证。本指南不讲密钥存放,只讲定期换血与出事止血:双活窗口轮换六步、泄漏分级与十五分钟时间线、不支持双活的短窗口切换法,以及四十五分钟泄漏演练剧本。

开发工作流后端工程安全与隐私
真实照片:档案库成捆文件资料照片,与版本历史主题相关;非产品截图
指南
每个项目都缺的那个按钮:文件版本历史与一键回滚实战

自动保存保住的是最新版,回收站装的是删掉的东西,备份恢复的是整个系统——它们都回答不了“回到两小时前”。本指南为 vibe 项目做一套文件版本历史:版本模型、产生策略、对比与恢复铁律、分层保留与权限设计,附可直接验收的用例清单。

开发工作流数据工作流后端工程