name: 代码审查清单 description: “进行彻底代码审查的全面清单,覆盖功能、安全、性能和可维护性”
代码审查清单
概述
提供一个系统性的清单,用于进行彻底的代码审查。这个技能帮助审查者确保代码质量,发现错误,识别安全问题,并在代码库中保持一致性。
何时使用此技能
- 审查拉取请求时使用
- 进行代码审计时使用
- 为团队建立代码审查标准时使用
- 培训新开发者代码审查实践时使用
- 当你想确保审查中不漏掉任何东西时使用
- 创建代码审查文档时使用
工作原理
步骤1:理解上下文
在审查代码之前,我会帮助你理解:
- 这段代码解决了什么问题?
- 需求是什么?
- 哪些文件被修改了,为什么?
- 是否有相关的问题或工单?
- 测试策略是什么?
步骤2:审查功能性
检查代码是否正确工作:
- 它是否解决了所述问题?
- 边界情况是否处理?
- 错误处理是否适当?
- 是否有逻辑错误?
- 是否符合需求?
步骤3:审查代码质量
评估代码可维护性:
- 代码是否可读和清晰?
- 名称是否描述性?
- 是否结构良好?
- 函数/方法是否专注?
- 是否有不必要的复杂性?
步骤4:审查安全性
检查安全问题:
- 输入是否验证?
- 敏感数据是否保护?
- 是否有SQL注入风险?
- 身份验证/授权是否正确?
- 依赖项是否安全?
步骤5:审查性能
寻找性能问题:
- 是否有不必要的循环?
- 数据库访问是否优化?
- 是否有内存泄漏?
- 缓存是否适当使用?
- 是否有N+1查询问题?
步骤6:审查测试
验证测试覆盖:
- 新代码是否有测试?
- 测试是否覆盖边界情况?
- 测试是否有意义?
- 所有测试是否通过?
- 测试覆盖是否充分?
示例
示例1:功能性审查清单
## 功能性审查
### 需求
- [ ] 代码解决了所述问题
- [ ] 所有验收标准都满足
- [ ] 边界情况已处理
- [ ] 错误情况已处理
- [ ] 用户输入已验证
### 逻辑
- [ ] 无逻辑错误或缺陷
- [ ] 条件正确(无差一错误)
- [ ] 循环正确终止
- [ ] 递归有适当的基础情况
- [ ] 状态管理正确
### 错误处理
- [ ] 错误被适当捕获
- [ ] 错误消息清晰且有用
- [ ] 错误不暴露敏感信息
- [ ] 失败操作已回滚
- [ ] 日志记录适当
### 示例问题捕获:
**❌ 不良 - 缺少验证:**
\`\`\`javascript
function createUser(email, password) {
// 无验证!
return db.users.create({ email, password });
}
\`\`\`
**✅ 良好 - 适当验证:**
\`\`\`javascript
function createUser(email, password) {
if (!email || !isValidEmail(email)) {
throw new Error('无效的电子邮件地址');
}
if (!password || password.length < 8) {
throw new Error('密码必须至少8个字符');
}
return db.users.create({ email, password });
}
\`\`\`
示例2:安全性审查清单
## 安全性审查
### 输入验证
- [ ] 所有用户输入已验证
- [ ] 防止SQL注入(使用参数化查询)
- [ ] 防止XSS(转义输出)
- [ ] CSRF保护到位
- [ ] 文件上传已验证(类型、大小、内容)
### 身份验证与授权
- [ ] 在需要的地方进行身份验证
- [ ] 授权检查存在
- [ ] 密码已哈希(从不存储明文)
- [ ] 会话安全管理
- [ ] 令牌适当过期
### 数据保护
- [ ] 敏感数据已加密
- [ ] API密钥未硬编码
- [ ] 使用环境变量存储秘密
- [ ] 个人数据遵循隐私法规
- [ ] 数据库凭证安全
### 依赖项
- [ ] 无已知易受攻击的依赖项
- [ ] 依赖项最新
- [ ] 不必要的依赖项已移除
- [ ] 依赖项版本已固定
### 示例问题捕获:
**❌ 不良 - SQL注入风险:**
\`\`\`javascript
const query = \`SELECT * FROM users WHERE email = '\${email}'\`;
db.query(query);
\`\`\`
**✅ 良好 - 参数化查询:**
\`\`\`javascript
const query = 'SELECT * FROM users WHERE email = $1';
db.query(query, [email]);
\`\`\`
**❌ 不良 - 硬编码秘密:**
\`\`\`javascript
const API_KEY = 'sk_live_abc123xyz';
\`\`\`
**✅ 良好 - 环境变量:**
\`\`\`javascript
const API_KEY = process.env.API_KEY;
if (!API_KEY) {
throw new Error('需要API_KEY环境变量');
}
\`\`\`
示例3:代码质量审查清单
## 代码质量审查
### 可读性
- [ ] 代码易于理解
- [ ] 变量名称描述性
- [ ] 函数名称说明其功能
- [ ] 复杂逻辑有注释
- [ ] 魔法数字已替换为常量
### 结构
- [ ] 函数小而专注
- [ ] 代码遵循DRY原则(不要重复自己)
- [ ] 适当的关注点分离
- [ ] 一致的代码风格
- [ ] 无死代码或注释掉的代码
### 可维护性
- [ ] 代码模块化且可重用
- [ ] 依赖项最小
- [ ] 更改向后兼容
- [ ] 破坏性更改已记录
- [ ] 技术债务已注明
### 示例问题捕获:
**❌ 不良 - 不清晰的命名:**
\`\`\`javascript
function calc(a, b, c) {
return a * b + c;
}
\`\`\`
**✅ 良好 - 描述性命名:**
\`\`\`javascript
function calculateTotalPrice(quantity, unitPrice, tax) {
return quantity * unitPrice + tax;
}
\`\`\`
**❌ 不良 - 函数做太多事:**
\`\`\`javascript
function processOrder(order) {
// 验证订单
if (!order.items) throw new Error('无项目');
// 计算总额
let total = 0;
for (let item of order.items) {
total += item.price * item.quantity;
}
// 应用折扣
if (order.coupon) {
total *= 0.9;
}
// 处理支付
const payment = stripe.charge(total);
// 发送电子邮件
sendEmail(order.email, '订单确认');
// 更新库存
updateInventory(order.items);
return { orderId: order.id, total };
}
\`\`\`
**✅ 良好 - 分离关注点:**
\`\`\`javascript
function processOrder(order) {
validateOrder(order);
const total = calculateOrderTotal(order);
const payment = processPayment(total);
sendOrderConfirmation(order.email);
updateInventory(order.items);
return { orderId: order.id, total };
}
\`\`\`
最佳实践
✅ 这样做
- 审查小更改 - 较小的PR更容易彻底审查
- 先检查测试 - 验证测试通过并覆盖新代码
- 运行代码 - 尽可能在本地测试
- 提问 - 不要假设,请求澄清
- 建设性 - 提出改进建议,不只是批评
- 关注重要问题 - 不要挑剔次要风格问题
- 使用自动化工具 - 代码检查器、格式化器、安全扫描器
- 审查文档 - 检查文档是否更新
- 考虑性能 - 思考扩展和效率
- 检查回归 - 确保现有功能仍工作
❌ 不要这样做
- 不读就批准 - 实际审查代码
- 不要模糊 - 提供具体反馈和示例
- 不要忽略安全 - 安全问题关键
- 不要跳过测试 - 未测试的代码会导致问题
- 不要粗鲁 - 尊重和专业
- 不要橡皮图章 - 每次审查都应增加价值
- 不要疲劳时审查 - 你会错过重要问题
- 不要忘记上下文 - 理解大局
完整审查清单
预审查
- [ ] 阅读PR描述和相关问题
- [ ] 理解解决了什么问题
- [ ] 检查CI/CD中测试是否通过
- [ ] 拉取分支并在本地运行
功能性
- [ ] 代码解决了所述问题
- [ ] 边界情况已处理
- [ ] 错误处理适当
- [ ] 用户输入已验证
- [ ] 无逻辑错误
安全性
- [ ] 无SQL注入漏洞
- [ ] 无XSS漏洞
- [ ] 身份验证/授权正确
- [ ] 敏感数据保护
- [ ] 无硬编码秘密
性能
- [ ] 无不必要的数据库查询
- [ ] 无N+1查询问题
- [ ] 使用高效算法
- [ ] 无内存泄漏
- [ ] 适当使用缓存
代码质量
- [ ] 代码可读且清晰
- [ ] 名称描述性
- [ ] 函数专注且小
- [ ] 无代码重复
- [ ] 遵循项目惯例
测试
- [ ] 新代码有测试
- [ ] 测试覆盖边界情况
- [ ] 测试有意义
- [ ] 所有测试通过
- [ ] 测试覆盖充分
文档
- [ ] 代码注释解释原因,而非内容
- [ ] API文档已更新
- [ ] 如果需要,README已更新
- [ ] 破坏性更改已记录
- [ ] 如果需要,提供迁移指南
Git
- [ ] 提交消息清晰
- [ ] 无合并冲突
- [ ] 分支与主分支同步
- [ ] 无不必要的文件提交
- [ ] .gitignore正确配置
常见陷阱
问题:遗漏边界情况
症状: 代码在正常路径工作,但在边界情况失败 解决方案: 询问“如果…?”问题
- 如果输入为空呢?
- 如果数组为空呢?
- 如果用户未认证呢?
- 如果网络请求失败呢?
问题:安全漏洞
症状: 代码暴露安全风险 解决方案: 使用安全清单
- 运行安全扫描器(npm audit、Snyk)
- 检查OWASP前10
- 验证所有输入
- 使用参数化查询
- 永不信任用户输入
问题:测试覆盖差
症状: 新代码无测试或测试不足 解决方案: 要求所有新代码都有测试
- 函数单元测试
- 功能集成测试
- 边界情况测试
- 错误情况测试
问题:代码不清晰
症状: 审查者不理解代码功能 解决方案: 请求改进
- 更好的变量名称
- 解释性注释
- 更小的函数
- 清晰的结构
审查评论模板
请求更改
**问题:** [描述问题]
**当前代码:**
\`\`\`javascript
// 显示问题代码
\`\`\`
**建议修复:**
\`\`\`javascript
// 显示改进代码
\`\`\`
**原因:** [解释为什么更好]
提问
**问题:** [你的问题]
**上下文:** [你为什么提问]
**建议:** [如果你有]
赞扬好代码
**不错!** [你喜欢什么]
这很棒因为 [解释原因]
相关技能
@请求代码审查- 准备代码审查@接收代码审查- 处理审查反馈@系统调试- 调试审查中发现的问题@测试驱动开发- 确保代码有测试
附加资源
专业提示: 为每次审查使用清单模板,以确保一致性和彻底性。根据团队的具体需求进行自定义!