审查AI代码的核心步骤:先看diff逐行、理解改动意图、运行测试、探测边界情况、验证安全和回滚路径。强调不能信任AI的自我解释,要追踪实际代码路径。
简短回答:通过检查意图、逐行阅读 diff、运行测试、探测边界情况,以及在合并前验证安全性、状态变更和回滚路径来审查 AI 生成的代码。
审查 AI 生成的代码与审查有风险的人写代码方式相同,但首先要检查契约。问清楚这次变更要做什么、涉及哪些文件、以及什么必须保持不变。AI 代码通常看起来很自信,却会遗漏一个对生产环境至关重要的约束。
从最小可用单元开始:diff。阅读每一个变更的行,而不是摘要。寻找从别处复制过来的代码、未请求的广泛重构、隐藏的行为变更,以及让路径更难追踪的新抽象。看似干净的重写如果改变了输入验证、错误处理或数据结构,仍可能出错。
阅读代码时要想象下个月你必须接手它。如果你无法用通俗语言解释这个变更,审查就没有完成。人们常犯的错误是相信 AI 的解释,而不是追踪实际的代码路径。AI 可以描述一个预期行为,但实现并未完全交付。
运行测试,然后阅读它们覆盖了什么。通过测试只能证明当前的测试集没有失败,不能证明代码是安全的。为 AI 最容易出错的路径添加或检查测试:空输入、畸形输入、权限失败、重复请求、网络超时、重试和部分写入。Google 自身的 AI 辅助代码审查指南强调的是样式检查、测试执行和反馈综合,而不是仅仅解析输出。
检查 AI 代码容易漂移的边界。认证、授权、数据库写入、缓存、后台任务和状态转换值得额外审视。如果代码修改了权限检查、查询或事务,要验证修改前后的确切行为。这些领域的一行变更可能演变成数据泄露、工作流中断或难以复现的故障。
接下来是安全审查。寻找未净化用户输入、字符串拼接 SQL、不安全 shell 执行、日志中的密钥、弱文件处理和过于广泛的网络访问。问自己代码是否创建了新的攻击面,而不只是问它能否编译。AI 通常为演示效果优化,会跳过最安全但可能最狭窄的路径,除非你迫使其说明每个有风险选择的理由。
检查过度扩展。AI 生成的代码经常添加帮助函数、包装器或框架层来解决你没有要求解决的问题。额外的代码不是免费的,因为每条新路径都需要测试、监控、文档和后续审查。如果更小的变更能保留行为,就优先选择更小的变更。目标不是优雅的代码,而是易于信任和维护的代码。
审查运行时路径的故障模式。问自己当数据库不可用时会发生什么、当 API 调用返回不同 schema 时会发生什么、当队列重复投递同一条消息时会发生什么、或者当进程在操作中间重启时会发生什么。AI 代码通常处理愉快路径很好,而恢复路径很差。好的审查会命名具体故障,然后检查代码是否能在不破坏状态的情况下存活。
用仓库本身作为证据。在接受新实现之前,搜索相同的函数、类似的验证和现有工具。AI 经常重新实现代码库中已存在的模式,这会造成行为漂移和不一致。复用不仅是风格问题,它保持代码与系统其余部分一致并降低后续审查成本。
如果变更很大,分层审查。先确认架构,然后是接口,然后是核心逻辑,然后是测试,然后是文档。不要试图一次在脑中Hold住整个功能。把审查分解成你可以验证的声明。例如:"这个端点只读取数据",然后检查路由、服务调用和测试来确认该声明。
使用一个刻意的检查清单。确认功能仍然符合工单、确认输入被验证、确认输出被正确类型化或格式化、确认副作用是有意的、确认错误被处理、确认日志是安全的、确认测试在应该失败时失败、确认回滚是可能的。检查清单防止了常见的失败模式——审查者喜欢代码后就不再寻找证据。
当 AI 添加测试时,也要审查这些测试。坏的测试可能比没有测试更糟糕,因为它们制造虚假信心。寻找只重复实现的断言、没有任何意义的 mock、以及即使行为退化也会通过的快照。好的测试锁定用户可见的行为,而不是临时实现细节的确切形状。
如果 AI 做了重构,用真实例子比较前后的行为。用相同的输入分别喂给旧代码和新代码,看输出、错误和副作用是否一致。这对于解析、格式化、计费、访问控制和数据迁移代码特别有用。审查者只检查最终代码而不比较行为时,会遗漏微妙的回归。
不方便的部分是时间。真正的审查比接受 AI 的第一稿花费更长时间,因为你在核实事实而不是感觉。这种成本是安全使用 AI 的代价。它仍然比调试生产 bug、清理安全错误或向队友解释生成的代码"看起来是对的"更快。
如果你想要一个实用的模式,每次按这个顺序:理解目标、扫描 diff、检查有风险的路径、运行并阅读测试、检查安全和故障处理,然后决定是合并、请求变更还是重写不能通过的部分。保持审查足够短以至于能完成,但不要太短以至于跳过了那条会在生产环境中断裂的路径。
对于经常这样做的团队,共享检查清单有帮助。DevConnect 有一个协调测试工作并保持反馈循环紧密的地方,当代码审查需要真正的设备或账户覆盖时很有用,而且你想把这种交流保持在自己的工作上,而不是建立在借来的信任上。https://devconnectplatform.com?ref=devto
强有力的审查也会留下痕迹。留下注释,命名风险、预期行为和你检查过的证据。"这个输入可以为空而当前代码会抛异常"比"请修复"有用得多。这样的注释让后续审查者更快,并帮助下一次 AI 审查从具体失败而不是模糊偏好中学习。
如果审查后代码仍然不清楚,不要猜测。要求 AI 一次解释一个函数、一个分支或一个测试,然后在仓库中验证答案。审查在你能够指出使变更安全的准确行,以及在假设错误时会断裂的准确行时才算完成。
当你发现错误时,同时修复提示词或工作流以及代码。如果 AI 一直遗漏同类型的问题,那意味着审查流程缺少了一个护栏。在失败发生的地方添加测试模板、lint 规则、检查清单项或人工审批步骤。审查的目的不仅是拒绝坏代码,还要让下一稿更好。
不可信。通过测试只能说明当前的测试集没有catch到失败。阅读实现、检查有风险的路径,并为 AI 最不可能正确处理的边界情况添加测试。
从 diff 和契约开始。确认变更要做什么,然后验证变更的行是否符合该目标,再去看样式或清理。
把它拆分成小块:架构、接口、逻辑、测试,然后是副作用。用真实例子比较新旧行为,看重构是否保留了用户可见的结果。
他们读的是解释而不是代码。第二个错误是在测试通过后就停止,这会让安全 bug、边界情况和状态 bug 未被检查。
可以,作为第一轮。把输出当作检查清单而不是证明。第二轮人工或仔细的手动审查仍需要验证实际行为。
先不要合并。请求更小的解释,一次追踪一个函数,并与仓库中现有模式比较,直到行为清晰。
不可信。通过测试只能说明当前的测试集没有catch到失败。阅读实现、检查有风险的路径,并为 AI 最不可能正确处理的边界情况添加测试。
从 diff 和契约开始。确认变更要做什么,然后验证变更的行是否符合该目标,再去看样式或清理。
把它拆分成小块:架构、接口、逻辑、测试,然后是副作用。用真实例子比较新旧行为,看重构是否保留了用户可见的结果。
他们读的是解释而不是代码。第二个错误是在测试通过后就停止,这会让安全 bug、边界情况和状态 bug 未被检查。
可以,作为第一轮。把输出当作检查清单而不是证明。第二轮人工或仔细的手动审查仍需要验证实际行为。
先不要合并。请求更小的解释,一次追踪一个函数,并与仓库中现有模式比较,直到行为清晰。
Set up an open, closed, or internal test - Play Console Help
Everything about the 12 testers requirement - Google Play Developer Community
Code Review Automation with GenAI | Google Codelabs
Building a Production AI Code Review Assistant with Google ADK | Google Codelabs
Supercharge Code Quality: AI-Assisted Code Review with Antigravity CLI and SDK | Google Codelabs
Originally published at devconnectplatform.com, where it is kept up to date.