代码审查速查表
快速参考代码审查的关键要点,帮助审查者高效、系统地进行代码审查。
审查前准备
作为代码作者
- 代码能够编译/运行通过
- 所有测试通过
- 静态检查无错误
- 编写清晰的 PR 描述
- 自测边界情况
作为审查者
- 理解变更背景和目的
- 阅读相关需求文档
- 准备审查清单
- 安排充足的时间
快速审查清单
功能性
| 检查项 | 优先级 | 说明 |
|---|---|---|
| 功能实现正确 | 🔴 高 | 代码实现了预期的功能 |
| 边界条件处理 | 🔴 高 | 空值、越界、异常输入等 |
| 错误处理完善 | 🔴 高 | 异常捕获、错误信息、资源释放 |
| 并发安全 | 🟡 中 | 多线程/并发场景处理 |
代码质量
| 检查项 | 优先级 | 说明 |
|---|---|---|
| 命名清晰 | 🔴 高 | 变量、函数、类名表达意图 |
| 函数长度适中 | 🟡 中 | 建议不超过 50 行 |
| 避免深层嵌套 | 🟡 中 | 建议不超过 3 层 |
| 单一职责 | 🔴 高 | 函数/类职责单一 |
| 消除重复 | 🟡 中 | DRY 原则 |
设计
| 检查项 | 优先级 | 说明 |
|---|---|---|
| 架构合规 | 🔴 高 | 符合项目架构规范 |
| 依赖合理 | 🟡 中 | 模块间依赖关系 |
| 接口设计 | 🟡 中 | 开闭原则、接口隔离 |
| 扩展性 | 🟢 低 | 易于扩展和维护 |
安全性
| 检查项 | 优先级 | 说明 |
|---|---|---|
| SQL 注入防护 | 🔴 高 | 使用参数化查询 |
| XSS 防护 | 🔴 高 | 输出编码、CSP |
| 输入验证 | 🔴 高 | 所有外部输入验证 |
| 敏感信息保护 | 🔴 高 | 密码、密钥等 |
| 权限控制 | 🔴 高 | 正确的认证授权 |
性能
| 检查项 | 优先级 | 说明 |
|---|---|---|
| 算法复杂度 | 🟡 中 | 时间/空间复杂度合理 |
| 数据库优化 | 🟡 中 | 索引、查询优化 |
| 资源释放 | 🔴 高 | 连接、句柄正确关闭 |
| 缓存使用 | 🟢 低 | 合理使用缓存 |
测试
| 检查项 | 优先级 | 说明 |
|---|---|---|
| 测试覆盖 | 🔴 高 | 核心逻辑有测试 |
| 边界测试 | 🔴 高 | 边界条件有测试 |
| 错误测试 | 🟡 中 | 错误场景有测试 |
| 测试质量 | 🟡 中 | 测试独立、可维护 |
意见分级标记
| 标记 | 含义 | 处理方式 |
|---|---|---|
| 🔴 阻塞 | 必须修复 | 修复后才能合并 |
| 💡 建议 | 建议采纳 | 讨论后决定是否修复 |
| 📝 可选 | 仅供参考 | 可选修复 |
| ❓ 疑问 | 需要澄清 | 需要开发者解释 |
| 👍 好评 | 好的实现 | 给予肯定 |
常见代码问题速查
命名问题
// ❌ 不好的命名
int d; // elapsed time in days
int elapsedTime;
// ✅ 好的命名
int elapsedTimeInDays;
int daysSinceCreation;
函数过长
// ❌ 函数过长(超过 50 行)
public void processOrder(Order order) {
// 100+ 行代码...
}
// ✅ 拆分为小函数
public void processOrder(Order order) {
validateOrder(order);
calculateTotal(order);
saveOrder(order);
sendNotification(order);
}
深层嵌套
// ❌ 深层嵌套
if (user != null) {
if (user.isActive()) {
if (user.hasPermission()) {
// do something
}
}
}
// ✅ 提前返回
if (user == null) return;
if (!user.isActive()) return;
if (!user.hasPermission()) return;
// do something
魔法数字
// ❌ 魔法数字
if (status == 3) {
// do something
}
// ✅ 命名常量
private static final int STATUS_COMPLETED = 3;
if (status == STATUS_COMPLETED) {
// do something
}
异常处理
// ❌ 忽略异常
try {
process();
} catch (Exception e) {
// ignore
}
// ✅ 正确处理
try {
process();
} catch (IOException e) {
logger.error("Process failed", e);
throw new BusinessException("处理失败", e);
}
SQL 注入
// ❌ 不安全的 SQL
String query = "SELECT * FROM users WHERE id = " + userId;
stmt.executeQuery(query);
// ✅ 参数化查询
PreparedStatement ps = conn.prepareStatement(
"SELECT * FROM users WHERE id = ?"
);
ps.setInt(1, userId);
语言特定速查
Java
| 检查项 | 说明 |
|---|---|
| Optional | 处理可能为空的值 |
| Stream API | 集合操作 |
| try-with-resources | 资源管理 |
| 泛型 | 类型安全 |
| 不可变集合 | List.of(), Set.of() |
Python
| 检查项 | 说明 |
|---|---|
| 类型注解 | def func(x: int) -> str |
| 列表推导式 | [x for x in items if x > 0] |
| with 语句 | 资源管理 |
| 生成器 | yield 处理大数据 |
| f-string | 字符串格式化 |
JavaScript/TypeScript
| 检查项 | 说明 |
|---|---|
| async/await | 异步处理 |
| 解构赋值 | const { a, b } = obj |
| 模板字符串 | `Hello ${name}` |
| 可选链 | obj?.property |
| 空值合并 | value ?? default |
Go
| 检查项 | 说明 |
|---|---|
| 错误处理 | if err != nil |
| Context | 取消和超时 |
| defer | 资源释放 |
| 接口 | 隐式实现 |
| Goroutine | 并发安全 |
审查意见模板
阻塞性问题
🔴 阻塞:[问题描述]
当前代码:
[代码片段]
建议修改为:
[修复后的代码]
原因:[解释为什么这是问题]
建议性问题
💡 建议:[建议描述]
可以考虑:
[改进代码]
好处:[解释改进的好处]
可选性问题
📝 可选:[建议描述]
仅供参考,不强制修改。
问题澄清
❓ 疑问:[问题]
能否解释一下 [具体部分] 的设计考虑?
好评
👍 这个实现很好!
特别是 [具体部分],[原因]。
审查时间参考
| PR 大小 | 建议审查时间 | 审查速度 |
|---|---|---|
| < 100 行 | 15-30 分钟 | 200 行/小时 |
| 100-300 行 | 30-60 分钟 | 150 行/小时 |
| 300-500 行 | 60-90 分钟 | 100 行/小时 |
| > 500 行 | 建议拆分 | < 100 行/小时 |
响应时间规范
| 场景 | 响应时间 |
|---|---|
| 收到审查请求 | 24 小时内 |
| 紧急修复 | 2 小时内 |
| 审查意见回复 | 24 小时内 |
| 阻塞性问题修复 | 优先处理 |
审查文化检查
- 对事不对人,评论针对代码
- 提供具体、可操作的建议
- 解释问题原因和改进好处
- 认可好的代码和设计
- 保持开放心态,接受不同意见
- 及时响应,避免阻塞
- 区分问题优先级
- 记录决策和理由
提示:将此速查表保存为书签或打印出来,在代码审查时快速参考。