AI代码审查与重构
代码审查和重构是保证代码质量的重要环节。AI可以帮你快速发现问题、提出改进建议,让代码更加健壮和可维护。
为什么用AI做代码审查?
传统代码审查的痛点
- 耗时 - 人工审查需要大量时间
- 遗漏 - 人眼容易漏掉细节问题
- 主观 - 不同审查者标准不一致
- 延迟 - 等待审查结果影响进度
AI代码审查的优势
| 方面 | 传统审查 | AI审查 |
|---|---|---|
| 速度 | 数小时到数天 | 几秒钟 |
| 覆盖面 | 受限于时间和精力 | 全面扫描 |
| 一致性 | 因人而异 | 标准一致 |
| 可用性 | 需要协调时间 | 随时可用 |
AI审查的局限
注意
AI审查不能完全替代人工审查。AI擅长发现:
- 代码规范问题
- 潜在bug
- 性能问题
- 安全隐患
AI不擅长判断:
- 业务逻辑是否正确
- 架构设计是否合理
- 是否符合团队约定
AI代码审查的四种方式
方式一:使用Cursor/Copilot Chat
在编辑器中直接让AI审查代码:
你:请审查这段代码,指出问题并给出改进建议
[Claude/Copilot分析代码并给出建议]适合场景:日常开发中的快速审查
方式二:使用Claude Code终端工具
bash
claude "审查 src/auth.py 文件,指出安全问题和性能问题"适合场景:命令行工作流,需要深度项目理解
方式三:使用GitHub Copilot PR Review
在GitHub PR页面,Copilot会自动给出审查意见。
适合场景:团队协作,PR流程
方式四:自定义审查提示词
构建专用的审查提示词模板,获得定制化的审查结果。
适合场景:有特定审查要求的团队
构建专业的代码审查提示词
审查维度模板
你是一位资深代码审查专家。请审查以下代码,按以下维度分析:
<code>
{代码内容}
</code>
【审查维度】
1. 安全性
- SQL注入、XSS等安全漏洞
- 敏感信息暴露
- 权限控制问题
2. 性能
- 时间复杂度
- 内存使用
- 数据库查询效率
3. 可读性
- 命名规范
- 代码结构
- 注释完整性
4. 健壮性
- 错误处理
- 边界条件
- 输入验证
5. 可维护性
- 代码重复
- 模块耦合
- 扩展性
【输出格式】
| 维度 | 问题 | 严重程度 | 位置 | 改进建议 |
|------|------|----------|------|----------|
| ... | ... | ... | ... | ... |
【综合评分】
X/10分,一句话总结实战案例
案例一:Python代码审查
原始代码:
python
def get_user(user_id):
conn = sqlite3.connect('users.db')
cursor = conn.cursor()
cursor.execute(f"SELECT * FROM users WHERE id = {user_id}")
user = cursor.fetchone()
conn.close()
return userAI审查结果:
| 维度 | 问题 | 严重程度 | 改进建议 |
|------|------|----------|----------|
| 安全性 | SQL注入风险 | 高 | 使用参数化查询 |
| 性能 | 每次创建新连接 | 中 | 使用连接池 |
| 健壮性 | 无错误处理 | 中 | 添加try-finally |
| 可读性 | 缺少类型提示 | 低 | 添加类型提示 |
| 可维护性 | 硬编码数据库路径 | 低 | 使用配置文件 |
综合评分:4/10分,存在严重安全漏洞,需立即修复改进后的代码:
python
from typing import Optional
import sqlite3
from contextlib import contextmanager
DB_PATH = "users.db"
@contextmanager
def get_db_connection():
"""数据库连接上下文管理器"""
conn = sqlite3.connect(DB_PATH)
try:
yield conn
finally:
conn.close()
def get_user(user_id: int) -> Optional[dict]:
"""根据ID获取用户信息
Args:
user_id: 用户ID
Returns:
用户信息字典,如果不存在返回None
"""
with get_db_connection() as conn:
cursor = conn.cursor()
# 使用参数化查询防止SQL注入
cursor.execute("SELECT * FROM users WHERE id = ?", (user_id,))
user = cursor.fetchone()
if user:
return dict(zip([d[0] for d in cursor.description], user))
return None案例二:JavaScript代码审查
原始代码:
javascript
async function fetchUsers() {
const response = await fetch('/api/users');
const data = await response.json();
return data;
}AI审查结果:
| 维度 | 问题 | 严重程度 | 改进建议 |
|------|------|----------|----------|
| 健壮性 | 无错误处理 | 高 | 添加try-catch |
| 健壮性 | 无网络错误处理 | 高 | 检查response.ok |
| 可读性 | 缺少类型定义 | 中 | 添加TypeScript类型 |
| 可维护性 | URL硬编码 | 低 | 提取为常量 |
综合评分:5/10分,缺少必要的错误处理改进后的代码:
typescript
interface User {
id: number;
name: string;
email: string;
}
const API_BASE_URL = '/api';
async function fetchUsers(): Promise<User[]> {
try {
const response = await fetch(`${API_BASE_URL}/users`);
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
const data: User[] = await response.json();
return data;
} catch (error) {
console.error('Failed to fetch users:', error);
throw error; // 重新抛出,让调用者处理
}
}AI辅助代码重构
什么是代码重构?
重构是在不改变代码外部行为的前提下,改进代码内部结构的过程。常见重构类型:
- 提取函数 - 把重复代码提取成函数
- 简化条件 - 把复杂的条件判断简化
- 消除重复 - 合并相似的代码
- 改善命名 - 让变量和函数名更有意义
重构请求模板
请重构以下代码,改进其结构和可读性。
<original_code>
{原始代码}
</original_code>
【重构目标】
- 提高可读性
- 消除重复代码
- 改善函数命名
- 简化复杂逻辑
【约束条件】
- 保持功能不变
- 使用Python 3.10特性
- 遵循PEP 8规范
【输出要求】
1. 重构后的代码
2. 说明每个改动的理由重构案例
原始代码:
python
def process_order(order):
if order['status'] == 'pending':
if order['payment'] == 'credit_card':
result = charge_credit_card(order['card_number'], order['amount'])
if result['success']:
order['status'] = 'paid'
send_email(order['email'], 'Payment received')
return True
else:
order['status'] = 'failed'
send_email(order['email'], 'Payment failed')
return False
elif order['payment'] == 'paypal':
result = charge_paypal(order['paypal_email'], order['amount'])
if result['success']:
order['status'] = 'paid'
send_email(order['email'], 'Payment received')
return True
else:
order['status'] = 'failed'
send_email(order['email'], 'Payment failed')
return False
else:
return False
else:
return False重构后的代码:
python
from enum import Enum
from typing import Dict, Any
class OrderStatus(Enum):
PENDING = "pending"
PAID = "paid"
FAILED = "failed"
class PaymentMethod(Enum):
CREDIT_CARD = "credit_card"
PAYPAL = "paypal"
def process_payment(order: Dict[str, Any]) -> bool:
"""处理订单支付
Args:
order: 订单信息字典
Returns:
支付是否成功
"""
if order.get('status') != OrderStatus.PENDING.value:
return False
payment_handler = get_payment_handler(order.get('payment'))
if not payment_handler:
return False
success = payment_handler(order)
update_order_status(order, success)
notify_customer(order, success)
return success
def get_payment_handler(payment_method: str):
"""获取支付处理器"""
handlers = {
PaymentMethod.CREDIT_CARD.value: handle_credit_card_payment,
PaymentMethod.PAYPAL.value: handle_paypal_payment,
}
return handlers.get(payment_method)
def handle_credit_card_payment(order: Dict[str, Any]) -> bool:
"""处理信用卡支付"""
result = charge_credit_card(order['card_number'], order['amount'])
return result['success']
def handle_paypal_payment(order: Dict[str, Any]) -> bool:
"""处理PayPal支付"""
result = charge_paypal(order['paypal_email'], order['amount'])
return result['success']
def update_order_status(order: Dict[str, Any], success: bool) -> None:
"""更新订单状态"""
order['status'] = OrderStatus.PAID.value if success else OrderStatus.FAILED.value
def notify_customer(order: Dict[str, Any], success: bool) -> None:
"""通知客户支付结果"""
subject = "Payment received" if success else "Payment failed"
send_email(order['email'], subject)重构理由:
| 改动 | 理由 |
|---|---|
| 使用枚举 | 类型安全,避免字符串错误 |
| 提取函数 | 单一职责,易于测试 |
| 消除重复 | 信用卡和PayPal的处理逻辑合并 |
| 使用策略模式 | 新增支付方式只需添加处理器 |
小结
AI代码审查与重构的核心要点:
| 要点 | 说明 |
|---|---|
| 明确维度 | 安全、性能、可读性、健壮性、可维护性 |
| 结构化输出 | 表格形式,问题、严重程度、改进建议 |
| 保持功能不变 | 重构不是改功能,是改进结构 |
| 迭代改进 | 一次解决一个问题,逐步优化 |
最佳实践
建立自己的审查检查清单,每次审查都按照相同的维度进行,确保不遗漏重要问题。
下一步
学会了代码审查后,让我们继续学习 AI写单元测试,让测试不再是负担。