Tutorial 8: AI 辅助代码审查

Abstract

使用 AI 进行代码审查

Authors

Walter Fan

Status

WIP

Updated

2026-02-07

为什么用 AI 做代码审查

代码审查是软件开发的重要环节,但传统方式有一些问题:

  • 耗时: 审查者需要花大量时间理解代码

  • 主观: 不同审查者标准不一

  • 疲劳: 审查质量随时间下降

  • 延迟: 等待审查者有空

AI 辅助代码审查可以:

  • 即时反馈: 提交后立即获得反馈

  • 一致标准: 始终按照相同标准审查

  • 全面覆盖: 检查安全、性能、风格等多个维度

  • 学习工具: 从 AI 的建议中学习

AI 代码审查的维度

AI 代码审查维度

┌─────────────────────────────────────────────────────────────────┐
│                                                                 │
│   ┌─────────────┐  ┌─────────────┐  ┌─────────────┐            │
│   │  代码质量   │  │   安全性    │  │   性能      │            │
│   ├─────────────┤  ├─────────────┤  ├─────────────┤            │
│   │ • 可读性    │  │ • SQL 注入  │  │ • 时间复杂度│            │
│   │ • 命名规范  │  │ • XSS       │  │ • 空间复杂度│            │
│   │ • 代码重复  │  │ • 认证授权  │  │ • 数据库查询│            │
│   │ • 复杂度    │  │ • 敏感数据  │  │ • 内存泄漏  │            │
│   └─────────────┘  └─────────────┘  └─────────────┘            │
│                                                                 │
│   ┌─────────────┐  ┌─────────────┐  ┌─────────────┐            │
│   │  最佳实践   │  │   测试覆盖  │  │   文档      │            │
│   ├─────────────┤  ├─────────────┤  ├─────────────┤            │
│   │ • 设计模式  │  │ • 单元测试  │  │ • 注释      │            │
│   │ • 错误处理  │  │ • 边界测试  │  │ • Docstring │            │
│   │ • 日志记录  │  │ • 异常测试  │  │ • README    │            │
│   └─────────────┘  └─────────────┘  └─────────────┘            │
│                                                                 │
└─────────────────────────────────────────────────────────────────┘

在 Cursor 中进行代码审查

基本审查

选中代码或打开文件,使用 Chat 进行审查:

@current_file

请审查这段代码,关注以下方面:
1. 代码质量和可读性
2. 潜在的 bug
3. 性能问题
4. 安全漏洞
5. 最佳实践

专项审查

安全审查:

@current_file

作为安全专家,请审查这段代码的安全问题:
1. SQL 注入
2. XSS 攻击
3. 认证/授权问题
4. 敏感数据处理
5. 输入验证

性能审查:

@current_file

作为性能优化专家,请审查这段代码:
1. 时间复杂度
2. 空间复杂度
3. 数据库查询效率
4. 缓存使用
5. 并发处理

架构审查:

@folder/

作为架构师,请审查这个模块的设计:
1. 职责是否单一
2. 依赖是否合理
3. 接口设计是否清晰
4. 是否易于测试
5. 是否易于扩展

代码审查 Checklist

通用 Checklist

## 代码审查 Checklist

### 功能正确性
- [ ] 代码实现了预期功能
- [ ] 边界条件处理正确
- [ ] 错误处理完善

### 代码质量
- [ ] 命名清晰有意义
- [ ] 函数/方法长度适中(< 50 行)
- [ ] 圈复杂度合理(< 10)
- [ ] 没有重复代码
- [ ] 注释适当

### 安全性
- [ ] 输入已验证
- [ ] 无 SQL 注入风险
- [ ] 无 XSS 风险
- [ ] 敏感数据已加密
- [ ] 权限检查正确

### 性能
- [ ] 无 N+1 查询
- [ ] 适当使用缓存
- [ ] 无内存泄漏风险
- [ ] 大数据集有分页

### 测试
- [ ] 有单元测试
- [ ] 测试覆盖关键路径
- [ ] 测试边界条件

### 文档
- [ ] 公共 API 有文档
- [ ] 复杂逻辑有注释
- [ ] README 已更新

Python 专项 Checklist

请根据以下 checklist 审查 Python 代码:

### Python 特定
- [ ] 使用类型注解
- [ ] 遵循 PEP 8
- [ ] 使用 f-string 而非 % 或 format
- [ ] 使用 pathlib 而非 os.path
- [ ] 使用 context manager 管理资源
- [ ] 异常处理具体(不用 bare except)
- [ ] 使用 dataclass 或 Pydantic
- [ ] import 顺序正确

JavaScript/TypeScript 专项 Checklist

请根据以下 checklist 审查 TypeScript 代码:

### TypeScript 特定
- [ ] 类型定义完整(无 any)
- [ ] 使用 const/let,不用 var
- [ ] 使用 async/await,不用回调
- [ ] 使用可选链 ?.
- [ ] 使用空值合并 ??
- [ ] 组件 props 有类型定义
- [ ] 正确处理 Promise 错误
- [ ] 避免不必要的 re-render

实战:审查示例代码

示例 1:发现安全问题

待审查代码:

def get_user(user_id):
    query = f"SELECT * FROM users WHERE id = {user_id}"
    result = db.execute(query)
    return result.fetchone()

def login(request):
    username = request.form['username']
    password = request.form['password']
    user = get_user_by_name(username)
    if user and user.password == password:
        session['user_id'] = user.id
        return redirect('/dashboard')
    return "Login failed"

审查提示词:

请审查这段代码的安全问题

AI 审查结果:

发现以下安全问题:

1. SQL 注入(严重)
   位置:get_user 函数
   问题:直接拼接 SQL 字符串
   修复:使用参数化查询

2. 明文密码比较(严重)
   位置:login 函数
   问题:密码没有哈希
   修复:使用 bcrypt 比较

3. 会话固定攻击风险
   位置:login 函数
   问题:登录成功后没有重新生成 session
   修复:登录后调用 session.regenerate()

4. 信息泄露
   位置:login 函数
   问题:"Login failed" 没有区分用户不存在和密码错误
   建议:统一返回 "Invalid credentials"

修复后的代码:

from werkzeug.security import check_password_hash

def get_user(user_id: int) -> User | None:
    query = "SELECT * FROM users WHERE id = :id"
    result = db.execute(query, {"id": user_id})
    return result.fetchone()

def login(request):
    username = request.form.get('username', '')
    password = request.form.get('password', '')

    if not username or not password:
        return "Invalid credentials", 401

    user = get_user_by_name(username)
    if user and check_password_hash(user.password_hash, password):
        session.regenerate()
        session['user_id'] = user.id
        return redirect('/dashboard')

    return "Invalid credentials", 401

示例 2:发现性能问题

待审查代码:

def get_order_details(order_ids: list[int]) -> list[dict]:
    results = []
    for order_id in order_ids:
        order = Order.query.get(order_id)
        user = User.query.get(order.user_id)
        items = OrderItem.query.filter_by(order_id=order_id).all()
        products = []
        for item in items:
            product = Product.query.get(item.product_id)
            products.append({
                'name': product.name,
                'quantity': item.quantity
            })
        results.append({
            'order_id': order.id,
            'user_name': user.name,
            'products': products
        })
    return results

审查提示词:

请审查这段代码的性能问题,假设 order_ids 可能有 1000 个

AI 审查结果:

发现严重的 N+1 查询问题:

对于 1000 个订单,这段代码会执行:
- 1000 次 Order 查询
- 1000 次 User 查询
- 1000 次 OrderItem 查询
- N 次 Product 查询(N = 订单项总数)

总计可能超过 5000 次数据库查询!

优化建议:
1. 使用 eager loading 一次性加载关联数据
2. 使用 IN 查询批量获取
3. 考虑使用 joinedload 或 selectinload

修复后的代码:

from sqlalchemy.orm import joinedload, selectinload

def get_order_details(order_ids: list[int]) -> list[dict]:
    # 一次查询获取所有数据
    orders = (
        Order.query
        .filter(Order.id.in_(order_ids))
        .options(
            joinedload(Order.user),
            selectinload(Order.items).joinedload(OrderItem.product)
        )
        .all()
    )

    return [
        {
            'order_id': order.id,
            'user_name': order.user.name,
            'products': [
                {
                    'name': item.product.name,
                    'quantity': item.quantity
                }
                for item in order.items
            ]
        }
        for order in orders
    ]

# 现在只需要 3 次查询:
# 1. Orders
# 2. Users (joinedload)
# 3. OrderItems + Products (selectinload + joinedload)

自动化代码审查

Git Hook 集成

创建 pre-commit hook,在提交前进行 AI 审查:

#!/bin/bash
# .git/hooks/pre-commit

# 获取暂存的文件
FILES=$(git diff --cached --name-only --diff-filter=ACMR | grep -E '\.(py|js|ts)$')

if [ -z "$FILES" ]; then
    exit 0
fi

echo "Running AI code review..."

# 使用 aider 或其他工具进行审查
for FILE in $FILES; do
    echo "Reviewing $FILE..."
    # 这里可以调用 AI API 进行审查
done

CI/CD 集成

在 GitHub Actions 中集成 AI 审查:

# .github/workflows/ai-review.yml
name: AI Code Review

on:
  pull_request:
    types: [opened, synchronize]

jobs:
  review:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3

      - name: Get changed files
        id: changed-files
        uses: tj-actions/changed-files@v35

      - name: AI Review
        env:
          OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
        run: |
          for file in ${{ steps.changed-files.outputs.all_changed_files }}; do
            echo "Reviewing $file"
            # 调用 AI API 进行审查
          done

      - name: Post Review Comments
        uses: actions/github-script@v6
        with:
          script: |
            // 将审查结果作为 PR 评论发布

审查反馈处理

理解 AI 建议

AI 的建议分为几个级别:

级别

描述

处理方式

🔴 Critical

安全漏洞、严重 bug

必须修复

🟠 Major

性能问题、设计缺陷

应该修复

🟡 Minor

代码风格、命名问题

建议修复

🟢 Suggestion

改进建议

可选

判断建议质量

AI 的建议不一定都是正确的,需要判断:

  1. 理解上下文: AI 可能不了解完整的业务背景

  2. 权衡利弊: 有些建议可能引入新的复杂性

  3. 验证建议: 对于重要修改,要验证正确性

  4. 保持批判: 不要盲目接受所有建议

常见误判

  • 过度优化: 建议优化不是瓶颈的代码

  • 过度抽象: 建议创建不必要的抽象

  • 忽略约束: 建议使用项目中不允许的库

  • 风格偏好: 将个人偏好作为问题

代码审查对话

多轮对话进行深入审查:

第一轮:

@file.py
请审查这段代码

第二轮:

你提到了 SQL 注入问题,能详细解释一下攻击场景吗?

第三轮:

修复后的代码如下,请再次审查:
[粘贴修复后的代码]

第四轮:

除了安全问题,这段代码的测试应该怎么写?

小结

本教程介绍了 AI 辅助代码审查:

  • 审查维度: 质量、安全、性能、最佳实践

  • 审查方法: 基本审查、专项审查、Checklist

  • 实战案例: 安全问题、性能问题

  • 自动化: Git Hook、CI/CD 集成

关键要点:

  1. AI 审查是补充,不是替代人工审查

  2. 要判断 AI 建议的质量

  3. 建立团队的审查 Checklist

下一步

在下一个教程中,我们将学习 AI 辅助测试和调试。

练习

  1. 用 AI 审查你最近写的代码

  2. 创建你的代码审查 Checklist

  3. 设置 pre-commit hook 进行自动审查

  4. 对比 AI 审查和人工审查的结果

参考资源