Skip to content

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-catch vs. Result 类型 vs. 回调错误参数)
  • 日志格式(结构化日志 vs. 字符串拼接)
  • 命名规范(驼峰 vs. 下划线,缩写使用习惯)
  • 注释语言(中文 vs. 英文)
  • 异步处理风格(async/await vs. .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 的教育价值所在。