AI 代码的 Code Review 要点
第一道:自审
AI 写完后,用 reviewer 视角的 prompt 让它再看一遍自己的代码,挑毛病、补测试。
第二道:AI 同侪
启用 code-reviewer subagent / 独立会话做"第二意见",发现单视角盲点。
第三道:人类终审
Tech Lead 或同事对架构、安全、业务边界做最终确认。这一关无法外包。
Review AI 生成的代码与 Review 同事写的代码有本质区别。人类开发者写错了,通常是因为粗心或理解偏差;AI 写错了,往往是因为它在"合理推断"——它生成的代码看起来完全正确,却可能调用了不存在的 API、忽略了关键的边界条件,或者引入了微妙的安全漏洞。
这种"看起来很对"的特性,是 AI 代码最危险的地方,也是 Review 时需要切换心态的根本原因。
一、AI 代码与人类代码的 Review 差异
| 维度 | 人类代码 | AI 代码 |
|---|---|---|
| 常见问题类型 | 逻辑疏漏、命名不规范、缺少注释 | 幻觉 API、过度设计、安全盲区 |
| 意图可追溯性 | 可以问作者为什么这么写 | 无法追溯决策过程 |
| 风格一致性 | 通常与作者习惯一致 | 可能与团队风格不符 |
| 测试覆盖意识 | 开发者通常了解哪里容易出错 | AI 测试常停留在"Happy Path" |
| 依赖引入 | 通常是已知依赖 | 可能引入不必要或过时的依赖 |
| 错误模式的一致性 | 同一开发者常犯相似错误,便于预判 | 错误随机且难以预测 |
核心结论:Review AI 代码时,你需要更主动地"质疑"代码,而不是"信任"它。即使代码通过了所有 Lint 检查和静态分析,也不代表逻辑是正确的。
二、常见问题模式识别
1. 幻觉 API(Hallucinated APIs)
AI 有时会生成看似合理但实际不存在的函数调用。这是 AI 代码中最隐蔽的问题之一,因为名称往往符合直觉,仅在运行时才会暴露。
典型症状:
python
# AI 生成的代码,看起来很合理
import pandas as pd
df.smart_merge(other_df, strategy="fuzzy") # ← 这个方法根本不存在!
# 另一个例子:React 中不存在的 Hook
const ref = useAutoFocus(inputElement); # ← 并不是内置 Hook识别与处理方法:
- 对不熟悉的方法调用,立即查阅官方文档确认,不要仅凭名称判断
- 实际运行代码而不只是阅读代码,让运行时帮助发现问题
- 重点关注链式调用的中间方法,这些最容易被忽略
- 对于库的版本敏感 API,确认当前项目使用的版本中确实存在该方法
2. 过度工程化(Over-engineering)
AI 有时会生成"完美的架构",但对于当前需求来说完全多余。这会增加维护负担,且通常无法获得任何实际收益。
典型症状:
typescript
// 需求:把两个数字相加
// AI 生成了这个:
interface AdditionStrategy {
execute(a: number, b: number): number;
}
class SimpleAdditionStrategy implements AdditionStrategy {
execute(a: number, b: number): number {
return a + b;
}
}
class AdditionContext {
constructor(private strategy: AdditionStrategy) {}
performAddition(a: number, b: number): number {
return this.strategy.execute(a, b);
}
}
// 实际只需要:
const add = (a: number, b: number) => a + b;识别与处理方法:
- 问自己:这个复杂度是否解决了真实存在的问题?
- 检查是否有不必要的接口、抽象类或设计模式
- 如果你无法在 30 秒内向同事解释为什么需要这层抽象,它很可能不必要
3. 安全盲区(Security Gaps)
AI 常见的安全问题集中在输入处理、权限控制和数据暴露三类。由于 AI 通常用最简洁的方式展示功能,安全加固代码往往被省略。
javascript
// 问题一:SQL 注入风险
const query = `SELECT * FROM users WHERE id = ${userId}`; // ← 危险!
// 正确写法(参数化查询):
const query = 'SELECT * FROM users WHERE id = ?';
db.execute(query, [userId]);
// 问题二:缺少输入验证
const data = JSON.parse(userInput); // ← 无任何验证直接使用
const userId = data.userId; // ← userId 可能是任意值
// 问题三:路径遍历漏洞
const filePath = path.join(uploadDir, filename); // ← filename 未净化
// 恶意用户可传入 "../../etc/passwd"
// 正确写法:
const safeName = path.basename(filename); // 去除目录部分
const filePath = path.join(uploadDir, safeName);
// 问题四:过度权限暴露
// AI 生成的 API 常遗漏鉴权中间件
app.get('/api/admin/users', getAllUsers); // ← 应有 requireAdmin 中间件4. 风格不一致
AI 生成的代码可能符合"通用规范",但与你们团队的具体约定不符。这类问题不影响功能,但会增加未来维护者的理解成本。
常见不一致点:
- 错误处理方式(
try-catchvs.Result类型 vs. 回调错误参数) - 日志格式(结构化日志 vs. 字符串拼接)
- 命名规范(驼峰 vs. 下划线,缩写使用习惯)
- 注释语言(中文 vs. 英文)
- 异步处理风格(
async/awaitvs..then()链)
5. 测试用例不完整
AI 生成的测试通常只覆盖"Happy Path",缺少边界和异常场景。
python
# AI 生成的测试(仅覆盖正常情况)
def test_divide():
assert divide(10, 2) == 5
# Reviewer 应检查是否补充了以下场景:
def test_divide_by_zero():
with pytest.raises(ZeroDivisionError):
divide(10, 0)
def test_divide_with_negative():
assert divide(-10, 2) == -5
def test_divide_float_result():
assert divide(1, 3) == pytest.approx(0.333, rel=1e-3)
def test_divide_with_zero_numerator():
assert divide(0, 5) == 0三、AI 代码 Review 完整检查清单
功能正确性
- [ ] 核心逻辑是否与需求一致(不只是"看起来对")?
- [ ] 边界条件是否处理(空值、零值、最大值、负数)?
- [ ] 错误路径是否有对应处理,还是只有 Happy Path?
- [ ] 是否存在幻觉 API 调用?(逐一查文档确认)
- [ ] 依赖库的版本是否与项目一致?
代码质量
- [ ] 复杂度是否与问题匹配?(警惕不必要的抽象层)
- [ ] 是否有重复代码可以提取?
- [ ] 变量和函数命名是否清晰、符合团队规范?
- [ ] 注释是否准确描述了"为什么"而不仅是"是什么"?
安全性
- [ ] 用户输入是否经过验证和净化?
- [ ] 数据库查询是否使用参数化查询,无拼接风险?
- [ ] 文件操作是否防止路径遍历?
- [ ] 是否有敏感信息(密钥、PII)被硬编码或意外记录到日志?
- [ ] API 接口是否有完整的权限校验?
- [ ] 是否有潜在的 XSS、CSRF 或命令注入风险?
测试覆盖
- [ ] 测试是否覆盖主要业务场景?
- [ ] 是否有边界条件和异常场景的测试?
- [ ] Mock 数据是否合理,是否反映真实情况?
- [ ] 测试名称是否清晰描述了被测场景?
依赖与兼容性
- [ ] 新引入的依赖是否必要?是否有更轻量的替代方案?
- [ ] 依赖版本是否与项目当前版本兼容?
- [ ] 是否与现有模块存在潜在冲突?
四、PR 描述规范(AI 辅助代码)
当 PR 中包含 AI 生成的代码时,作者须在 PR 描述中提供以下信息,以帮助 Reviewer 快速定位关注点:
markdown
## 变更说明
[描述本次变更的目标和范围]
## AI 辅助说明
- **使用工具**:Cursor / GitHub Copilot / Claude
- **AI 生成模块**:`src/utils/parser.ts`、`tests/parser.test.ts`
- **人工修改内容**:错误处理逻辑、边界条件测试
- **建议重点 Review**:第 45-67 行的递归逻辑,AI 生成,需验证终止条件
## 测试验证
- [ ] 单元测试已通过
- [ ] 手动测试场景:[描述具体操作路径]
- [ ] 安全敏感点已人工审查(如适用)五、推荐 Review 工作流
1. 先读 PR 描述,了解 AI 参与范围和作者标注的风险点
↓
2. 运行代码,确认基本功能可用(不要只看不跑)
↓
3. 对 AI 生成部分执行安全检查清单
↓
4. 验证所有外部 API 调用确实存在(查文档,不靠印象)
↓
5. 检查测试覆盖率,核对是否有缺失场景
↓
6. 给出分级反馈:必须修改 / 建议优化 / 供参考六、Reviewer 心态建议
- 假设错误,验证正确:默认 AI 代码可能有问题,通过验证来建立信心,而不是通过"看起来对"来放行。
- 不因"看起来合理"而跳过:AI 最危险的地方在于它的输出总是很有说服力,即使是错的。
- 关注意图,不只是实现:代码实现对了,但是否解决了正确的问题?有时 AI 会给出一个技术上无误却不符合实际需求的方案。
- 区分问题严重性:安全漏洞、幻觉 API 是阻塞性问题;过度工程化通常是建议性反馈。避免将所有问题等同对待,这会拖慢团队节奏。
- 给建设性反馈:说明为什么需要改,而不只是标记问题。帮助提交者理解 AI 代码的盲区,是 Review 的教育价值所在。