Code Review Excellence
Transform code reviews from gatekeeping to knowledge sharing through constructive feedback, systematic analysis, and collaborative improvement.
When to Use This Skill
- - Reviewing pull requests and code changes
- Establishing code review standards for teams
- Mentoring junior developers through reviews
- Conducting architecture reviews
- Creating review checklists and guidelines
- Improving team collaboration
- Reducing code review cycle time
- Maintaining code quality standards
Core Principles
1. The Review Mindset
Goals of Code Review:
- - Catch bugs and edge cases
- Ensure code maintainability
- Share knowledge across team
- Enforce coding standards
- Improve design and architecture
- Build team culture
Not the Goals:
- - Show off knowledge
- Nitpick formatting (use linters)
- Block progress unnecessarily
- Rewrite to your preference
2. Effective Feedback
Good Feedback is:
- - Specific and actionable
- Educational, not judgmental
- Focused on the code, not the person
- Balanced (praise good work too)
- Prioritized (critical vs nice-to-have)
CODEBLOCK0
3. Review Scope
What to Review:
- - Logic correctness and edge cases
- Security vulnerabilities
- Performance implications
- Test coverage and quality
- Error handling
- Documentation and comments
- API design and naming
- Architectural fit
What Not to Review Manually:
- - Code formatting (use Prettier, Black, etc.)
- Import organization
- Linting violations
- Simple typos
Review Process
Phase 1: Context Gathering (2-3 minutes)
CODEBLOCK1
Phase 2: High-Level Review (5-10 minutes)
CODEBLOCK2
Phase 3: Line-by-Line Review (10-20 minutes)
CODEBLOCK3
Phase 4: Summary & Decision (2-3 minutes)
CODEBLOCK4
Review Techniques
Technique 1: The Checklist Method
CODEBLOCK5
Technique 2: The Question Approach
Instead of stating problems, ask questions to encourage thinking:
CODEBLOCK6
Technique 3: Suggest, Don't Command
INLINECODE0
Technique 4: Differentiate Severity
CODEBLOCK8
Language-Specific Patterns
Python Code Review
CODEBLOCK9
TypeScript/JavaScript Code Review
CODEBLOCK10
Advanced Review Patterns
Pattern 1: Architectural Review
CODEBLOCK11
Pattern 2: Test Quality Review
CODEBLOCK12
Pattern 3: Security Review
CODEBLOCK13
Giving Difficult Feedback
Pattern: The Sandwich Method (Modified)
CODEBLOCK14
Handling Disagreements
CODEBLOCK15
Best Practices
- 1. Review Promptly: Within 24 hours, ideally same day
- Limit PR Size: 200-400 lines max for effective review
- Review in Time Blocks: 60 minutes max, take breaks
- Use Review Tools: GitHub, GitLab, or dedicated tools
- Automate What You Can: Linters, formatters, security scans
- Build Rapport: Emoji, praise, and empathy matter
- Be Available: Offer to pair on complex issues
- Learn from Others: Review others' review comments
Common Pitfalls
- - Perfectionism: Blocking PRs for minor style preferences
- Scope Creep: "While you're at it, can you also..."
- Inconsistency: Different standards for different people
- Delayed Reviews: Letting PRs sit for days
- Ghosting: Requesting changes then disappearing
- Rubber Stamping: Approving without actually reviewing
- Bike Shedding: Debating trivial details extensively
Templates
PR Review Comment Template
CODEBLOCK16
Resources
- - references/code-review-best-practices.md: Comprehensive review guidelines
- references/common-bugs-checklist.md: Language-specific bugs to watch for
- references/security-review-guide.md: Security-focused review checklist
- assets/pr-review-template.md: Standard review comment template
- assets/review-checklist.md: Quick reference checklist
- scripts/pr-analyzer.py: Analyze PR complexity and suggest reviewers
卓越代码审查
通过建设性反馈、系统分析和协作改进,将代码审查从把关转变为知识共享。
何时使用此技能
- - 审查拉取请求和代码变更
- 为团队建立代码审查标准
- 通过审查指导初级开发人员
- 进行架构审查
- 创建审查清单和指南
- 改善团队协作
- 缩短代码审查周期
- 维护代码质量标准
核心原则
1. 审查心态
代码审查的目标:
- - 发现错误和边界情况
- 确保代码可维护性
- 在团队中分享知识
- 执行编码标准
- 改进设计和架构
- 建设团队文化
非目标:
- - 炫耀知识
- 挑剔格式(使用代码检查工具)
- 不必要地阻碍进度
- 按个人偏好重写
2. 有效反馈
好的反馈应具备:
- - 具体且可操作
- 具有教育意义,而非评判性
- 关注代码本身,而非个人
- 保持平衡(也要表扬好的工作)
- 区分优先级(关键 vs 锦上添花)
markdown
❌ 错误:这是错的。
✅ 正确:当多个用户同时访问时,这可能导致竞态条件。建议在此处使用互斥锁。
❌ 错误:你为什么不使用X模式?
✅ 正确:你考虑过使用仓库模式吗?这样更容易测试。这里有个示例:[链接]
❌ 错误:重命名这个变量。
✅ 正确:[小建议] 为了清晰起见,建议使用 userCount 代替 uc。如果你倾向于保留,也不影响合并。
3. 审查范围
需要审查的内容:
- - 逻辑正确性和边界情况
- 安全漏洞
- 性能影响
- 测试覆盖率和质量
- 错误处理
- 文档和注释
- API设计和命名
- 架构适配性
不需要手动审查的内容:
- - 代码格式(使用Prettier、Black等工具)
- 导入组织
- 代码检查违规
- 简单拼写错误
审查流程
第一阶段:上下文收集(2-3分钟)
markdown
在深入代码之前,先了解:
- 1. 阅读PR描述和关联的问题
- 检查PR大小(超过400行?建议拆分)
- 查看CI/CD状态(测试是否通过?)
- 理解业务需求
- 注意任何相关的架构决策
第二阶段:高层审查(5-10分钟)
markdown
- 1. 架构与设计
- 解决方案是否适合问题?
- 是否有更简单的方法?
- 是否与现有模式一致?
- 是否可扩展?
- 2. 文件组织
- 新文件是否放在正确位置?
- 代码是否按逻辑分组?
- 是否存在重复文件?
- 3. 测试策略
- 是否有测试?
- 测试是否覆盖边界情况?
- 测试是否可读?
第三阶段:逐行审查(10-20分钟)
markdown
对于每个文件:
- 1. 逻辑与正确性
- 是否处理了边界情况?
- 是否存在差一错误?
- 是否检查了null/undefined?
- 是否存在竞态条件?
- 2. 安全性
- 是否验证了输入?
- 是否存在SQL注入风险?
- 是否存在XSS漏洞?
- 是否暴露了敏感数据?
- 3. 性能
- 是否存在N+1查询?
- 是否存在不必要的循环?
- 是否存在内存泄漏?
- 是否存在阻塞操作?
- 4. 可维护性
- 变量命名是否清晰?
- 函数是否只做一件事?
- 复杂代码是否有注释?
- 魔法数字是否已提取?
第四阶段:总结与决策(2-3分钟)
markdown
- 1. 总结关键问题
- 突出你喜欢的部分
- 做出明确决策:
- ✅ 批准
- 💬 评论(小建议)
- 🔄 请求变更(必须处理)
- 4. 如果复杂,提供结对编程
审查技巧
技巧1:清单法
markdown
安全检查清单
- - [ ] 用户输入已验证和清理
- [ ] SQL查询使用参数化
- [ ] 已检查身份验证/授权
- [ ] 密钥未硬编码
- [ ] 错误消息不泄露信息
性能检查清单
- - [ ] 无N+1查询
- [ ] 数据库查询已建立索引
- [ ] 大列表已分页
- [ ] 昂贵操作已缓存
- [ ] 热点路径无阻塞I/O
测试检查清单
- - [ ] 已测试正常路径
- [ ] 覆盖了边界情况
- [ ] 已测试错误情况
- [ ] 测试名称具有描述性
- [ ] 测试是确定性的
技巧2:提问法
通过提问而非陈述问题来鼓励思考:
markdown
❌ 如果列表为空,这将失败。
✅ 如果 items 是空数组,会发生什么?
❌ 这里需要错误处理。
✅ 如果API调用失败,应该如何表现?
❌ 这效率低下。
✅ 我看到这遍历了所有用户。我们是否考虑过在10万用户时的性能影响?
技巧3:建议而非命令
markdown
使用协作语言
❌ 你必须将其改为使用async/await
✅ 建议:使用async/await可能使代码更易读:
typescript
async function fetchUser(id: string) {
const user = await db.query(SELECT * FROM users WHERE id = ?, id);
return user;
}
你觉得怎么样?
❌ 将此提取为函数
✅ 这个逻辑出现了3次。将其提取为共享工具函数是否合理?
技巧4:区分严重程度
markdown
使用标签指示优先级:
🔴 [阻塞] - 合并前必须修复
🟡 [重要] - 应该修复,如有异议可讨论
🟢 [小建议] - 锦上添花,不阻塞合并
💡 [建议] - 考虑替代方案
📚 [学习] - 教育性评论,无需操作
🎉 [表扬] - 做得好,继续保持!
示例:
🔴 [阻塞] 此SQL查询易受注入攻击。请使用参数化查询。
🟢 [小建议] 考虑将 data 重命名为 userData 以提高清晰度。
🎉 [表扬] 测试覆盖很棒!这将捕获边界情况。
特定语言模式
Python代码审查
python
检查Python特定问题
❌ 可变默认参数
def add_item(item, items=[]): # 错误!跨调用共享
items.append(item)
return items
✅ 使用None作为默认值
def add_item(item, items=None):
if items is None:
items = []
items.append(item)
return items
❌ 捕获范围过宽
try:
result = risky_operation()
except: # 捕获所有异常,甚至KeyboardInterrupt!
pass
✅ 捕获特定异常
try:
result = risky_operation()
except ValueError as e:
logger.error(f无效值:{e})
raise
❌ 使用可变类属性
class User:
permissions = [] # 跨所有实例共享!
✅ 在init中初始化
class User:
def
init(self):
self.permissions = []
TypeScript/JavaScript代码审查
typescript
// 检查TypeScript特定问题
// ❌ 使用any破坏类型安全
function processData(data: any) { // 避免使用any
return data.value;
}
// ✅ 使用正确类型
interface DataPayload {
value: string;
}
function processData(data: DataPayload) {
return data.value;
}
// ❌ 未处理异步错误
async function fetchUser(id: string) {
const response = await fetch(/api/users/${id});
return response.json(); // 如果网络失败怎么办?
}
// ✅ 正确处理错误
async function fetchUser(id: string): Promise {
try {
const response = await fetch(/api/users/${id});
if (!response.ok) {
throw new Error(HTTP ${response.status});
}
return await response.json();
} catch (error) {
console.error(获取用户失败:, error);
throw error;
}
}
// ❌ 修改props
function UserProfile({ user }: Props) {
user.lastViewed = new Date(); // 修改prop!
return
{user.name}
;
}
// ✅ 不修改props
function UserProfile({ user, onView }: Props) {
useEffect(() => {
onView(user.id); // 通知父组件更新
},