code-review-playbook
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseCode Review Playbook
《代码评审手册》
Overview
概述
This skill provides a comprehensive framework for effective code reviews that improve code quality, share knowledge, and foster collaboration. Whether you're a reviewer giving feedback or an author preparing code for review, this playbook ensures reviews are thorough, consistent, and constructive.
When to use this skill:
- Reviewing pull requests or merge requests
- Preparing code for review (self-review)
- Establishing code review standards for teams
- Training new developers on review best practices
- Resolving disagreements about code quality
- Improving review processes and efficiency
本技能为高效代码评审提供全面框架,可提升代码质量、促进知识共享并加强团队协作。无论你是给出反馈的评审者,还是准备提交代码待评审的开发者,本手册都能确保评审工作全面、一致且富有建设性。
适用场景:
- 评审拉取请求(PR)或合并请求(MR)
- 准备待评审代码(自我评审)
- 为团队制定代码评审标准
- 培训新开发者掌握评审最佳实践
- 解决关于代码质量的分歧
- 优化评审流程与效率
Code Review Philosophy
代码评审理念
Purpose of Code Reviews
代码评审的目标
Code reviews serve multiple purposes:
- Quality Assurance: Catch bugs, logic errors, and edge cases
- Knowledge Sharing: Spread domain knowledge across the team
- Consistency: Ensure codebase follows conventions and patterns
- Mentorship: Help developers improve their skills
- Collective Ownership: Build shared responsibility for code
- Documentation: Create discussion history for future reference
代码评审具备多重价值:
- 质量保障:捕获bug、逻辑错误和边缘情况
- 知识共享:在团队内传播领域知识
- 一致性:确保代码库遵循约定与模式
- 指导培养:帮助开发者提升技能
- 集体所有权:建立代码的共同责任意识
- 文档记录:创建供未来参考的讨论历史
Principles
核心原则
Be Kind and Respectful:
- Review the code, not the person
- Assume positive intent
- Praise good solutions
- Frame feedback constructively
Be Specific and Actionable:
- Point to specific lines of code
- Explain why something should change
- Suggest concrete improvements
- Provide examples when helpful
Balance Speed with Thoroughness:
- Aim for timely feedback (< 24 hours)
- Don't rush critical reviews
- Use automation for routine checks
- Focus human review on logic and design
Distinguish Must-Fix from Nice-to-Have:
- Use conventional comments to indicate severity
- Block merges only for critical issues
- Allow authors to defer minor improvements
- Capture deferred work in follow-up tickets
友善尊重:
- 评审代码,而非针对个人
- 假设对方出发点是好的
- 赞扬优秀的解决方案
- 以建设性的方式提出反馈
具体且可执行:
- 指向具体的代码行
- 解释为什么需要修改
- 提出明确的改进建议
- 必要时提供示例
平衡速度与全面性:
- 争取在24小时内给出反馈
- 关键评审不要仓促
- 用自动化工具处理常规检查
- 人力评审聚焦逻辑与设计
区分必须修复与建议优化:
- 使用标准化评论标注问题严重程度
- 仅因关键问题阻止合并
- 允许开发者推迟次要改进
- 将推迟的工作记录在后续任务中
Conventional Comments
标准化评论
A standardized format for review comments that makes intent clear.
一种标准化的评审评论格式,可清晰传达意图。
Format
格式
<label> [decorations]: <subject>
[discussion]<label> [修饰符]: <主题>
[讨论内容]Labels
标签
| Label | Meaning | Blocks Merge? |
|---|---|---|
| praise | Highlight something positive | No |
| nitpick | Minor, optional suggestion | No |
| suggestion | Propose an improvement | No |
| issue | Problem that should be addressed | Usually |
| question | Request clarification | No |
| thought | Idea to consider | No |
| chore | Routine task (formatting, deps) | No |
| note | Informational comment | No |
| todo | Follow-up work needed | Maybe |
| security | Security concern | Yes |
| bug | Potential bug | Yes |
| breaking | Breaking change | Yes |
| 标签 | 含义 | 是否阻止合并? |
|---|---|---|
| praise | 突出优秀的实现 | 否 |
| nitpick | 微小的可选建议 | 否 |
| suggestion | 提出改进方案 | 否 |
| issue | 需要解决的问题 | 通常是 |
| question | 请求澄清 | 否 |
| thought | 供参考的想法 | 否 |
| chore | 常规任务(格式、依赖) | 否 |
| note | 信息性说明 | 否 |
| todo | 需要后续跟进的工作 | 可能 |
| security | 安全问题 | 是 |
| bug | 潜在bug | 是 |
| breaking | 破坏性变更 | 是 |
Decorations
修饰符
Optional modifiers in square brackets:
| Decoration | Meaning |
|---|---|
| [blocking] | Must be addressed before merge |
| [non-blocking] | Optional, can be deferred |
| [if-minor] | Only if it's a quick fix |
方括号中的可选修饰符:
| 修饰符 | 含义 |
|---|---|
| [blocking] | 合并前必须解决 |
| [non-blocking] | 可选,可推迟处理 |
| [if-minor] | 仅当修改成本极低时才需要处理 |
Examples
示例
typescript
// ✅ Good: Clear, specific, actionable
praise: Excellent use of TypeScript generics here!
This makes the function much more reusable while maintaining type safety.
---
nitpick [non-blocking]: Consider using const instead of let
This variable is never reassigned, so `const` would be more appropriate:
```typescript
const MAX_RETRIES = 3;issue: Missing error handling for API call
If the API returns a 500 error, this will crash the application.
Add a try/catch block:
typescript
try {
const data = await fetchUser(userId);
// ...
} catch (error) {
logger.error('Failed to fetch user', { userId, error });
throw new UserNotFoundError(userId);
}question: Why use a Map instead of an object here?
Is there a specific reason for this data structure choice?
If it's for performance, could you add a comment explaining?
security [blocking]: API endpoint is not authenticated
The endpoint is missing authentication middleware.
This allows unauthenticated access to sensitive user data.
/api/admin/usersAdd the auth middleware:
typescript
router.get('/api/admin/users', requireAdmin, getUsers);suggestion [if-minor]: Extract magic number to named constant
Consider extracting this value:
typescript
const CACHE_TTL_SECONDS = 3600;
cache.set(key, value, CACHE_TTL_SECONDS);
---typescript
// ✅ 优秀示例:清晰、具体、可执行
praise: 这里TypeScript泛型的使用非常出色!
这让函数在保持类型安全的同时大幅提升了复用性。
---
nitpick [non-blocking]: 考虑使用const替代let
该变量从未被重新赋值,因此使用`const`更合适:
```typescript
const MAX_RETRIES = 3;issue: API调用缺少错误处理
如果API返回500错误,应用会崩溃。
请添加try/catch块:
typescript
try {
const data = await fetchUser(userId);
// ...
} catch (error) {
logger.error('获取用户失败', { userId, error });
throw new UserNotFoundError(userId);
}question: 为什么这里使用Map而不是普通对象?
选择这个数据结构有特定原因吗?
如果是出于性能考虑,能否添加注释说明?
security [blocking]: API端点未做身份验证
/api/admin/users请添加身份验证中间件:
typescript
router.get('/api/admin/users', requireAdmin, getUsers);suggestion [if-minor]: 将魔法数字提取为命名常量
考虑提取该值:
typescript
const CACHE_TTL_SECONDS = 3600;
cache.set(key, value, CACHE_TTL_SECONDS);
---Review Process
评审流程
1. Before Reviewing
1. 评审前准备
Check Context:
- Read the PR/MR description
- Understand the purpose and scope
- Review linked tickets or issues
- Check CI/CD pipeline status
Verify Automated Checks:
- Tests are passing
- Linting has no errors
- Type checking passes
- Code coverage meets targets
- No merge conflicts
Set Aside Time:
- Small PR (< 200 lines): 15-30 minutes
- Medium PR (200-500 lines): 30-60 minutes
- Large PR (> 500 lines): 1-2 hours (or ask to split)
检查上下文:
- 阅读PR/MR描述
- 理解变更的目的与范围
- 查看关联的工单或问题
- 检查CI/CD流水线状态
验证自动化检查结果:
- 测试通过
- 代码无语法检查错误
- 类型检查通过
- 代码覆盖率达标
- 无合并冲突
预留时间:
- 小型PR(<200行):15-30分钟
- 中型PR(200-500行):30-60分钟
- 大型PR(>500行):1-2小时(或要求拆分)
2. During Review
2. 评审进行中
Follow a Pattern:
-
High-Level Review (5-10 minutes)
- Read PR description and understand intent
- Skim all changed files to get overview
- Verify approach makes sense architecturally
- Check that changes align with stated purpose
-
Detailed Review (20-45 minutes)
- Line-by-line code review
- Check logic, edge cases, error handling
- Verify tests cover new code
- Look for security vulnerabilities
- Ensure code follows team conventions
-
Testing Considerations (5-10 minutes)
- Are tests comprehensive?
- Do tests test the right things?
- Are edge cases covered?
- Is test data realistic?
-
Documentation Check (5 minutes)
- Are complex sections commented?
- Is public API documented?
- Are breaking changes noted?
- Is README updated if needed?
遵循以下步骤:
-
整体评审(5-10分钟)
- 阅读PR描述,理解变更意图
- 快速浏览所有变更文件,掌握整体情况
- 验证实现方案在架构上是否合理
- 检查变更是否符合预期目标
-
细节评审(20-45分钟)
- 逐行检查代码
- 验证逻辑、边缘情况和错误处理
- 确认新代码有对应的测试覆盖
- 排查安全漏洞
- 确保代码符合团队规范
-
测试考量(5-10分钟)
- 测试是否全面?
- 测试是否覆盖了正确的场景?
- 边缘情况是否被覆盖?
- 测试数据是否真实?
-
文档检查(5分钟)
- 复杂代码段是否有注释?
- 公共API是否有文档?
- 破坏性变更是否有标注?
- 必要时是否更新了README?
3. After Reviewing
3. 评审完成后
Provide Clear Decision:
- ✅ Approve: Code is ready to merge
- 💬 Comment: Feedback provided, no action required
- 🔄 Request Changes: Issues must be addressed before merge
Respond to Author:
- Answer questions promptly
- Re-review after changes made
- Approve when issues resolved
- Thank author for addressing feedback
给出明确结论:
- ✅ 批准:代码可合并
- 💬 评论:提供了反馈,但无需修改
- 🔄 要求修改:必须解决问题后才能合并
回复开发者:
- 及时回答问题
- 修改完成后重新评审
- 问题解决后批准合并
- 感谢开发者处理反馈
Review Checklists
评审检查清单
General Code Quality
通用代码质量
- Readability: Code is easy to understand
- Naming: Variables and functions have clear, descriptive names
- Comments: Complex logic is explained
- Formatting: Code follows team style guide
- DRY: No unnecessary duplication
- SOLID Principles: Code follows SOLID where applicable
- Function Size: Functions are focused and < 50 lines
- Cyclomatic Complexity: Functions have complexity < 10
- 可读性:代码易于理解
- 命名:变量和函数的名称清晰、有描述性
- 注释:复杂逻辑有说明
- 格式:代码遵循团队风格指南
- DRY原则:无不必要的重复代码
- SOLID原则:适用的代码遵循SOLID原则
- 函数规模:函数职责单一且少于50行
- 圈复杂度:函数圈复杂度低于10
Functionality
功能正确性
- Correctness: Code does what it's supposed to do
- Edge Cases: Boundary conditions handled (null, empty, min/max)
- Error Handling: Errors caught and handled appropriately
- Logging: Appropriate log levels and messages
- Input Validation: User input is validated and sanitized
- Output Validation: Responses match expected schema
- 正确性:代码实现了预期功能
- 边缘情况:处理了边界条件(null、空值、最大/最小值)
- 错误处理:错误被正确捕获和处理
- 日志:日志级别和信息合适
- 输入验证:用户输入已验证和清理
- 输出验证:响应符合预期格式
Testing
测试
- Test Coverage: New code has tests
- Test Quality: Tests actually test the right things
- Edge Cases Tested: Tests cover boundary conditions
- Error Paths Tested: Error handling is tested
- Test Isolation: Tests don't depend on each other
- Test Naming: Test names describe what's being tested
- 测试覆盖率:新代码有对应的测试
- 测试质量:测试确实覆盖了正确的场景
- 边缘情况测试:测试覆盖了边界条件
- 错误路径测试:错误处理逻辑已测试
- 测试隔离:测试之间无依赖
- 测试命名:测试名称清晰描述了测试内容
Performance
性能
- Database Queries: N+1 queries avoided
- Caching: Appropriate caching used
- Algorithm Efficiency: No unnecessarily slow algorithms (O(n²) when O(n) possible)
- Resource Cleanup: Files, connections, memory released
- Lazy Loading: Heavy operations deferred when possible
- 数据库查询:避免了N+1查询
- 缓存:合理使用了缓存
- 算法效率:无不必要的低效算法(如能用O(n)却用了O(n²))
- 资源清理:文件、连接、内存已释放
- 懒加载:重型操作已按需延迟执行
Security
安全
- Authentication: Protected endpoints require auth
- Authorization: Users can only access their own data
- Input Sanitization: SQL injection, XSS prevented
- Secrets Management: No hardcoded credentials or API keys
- Encryption: Sensitive data encrypted at rest and in transit
- HTTPS Only: Production traffic uses HTTPS
- Rate Limiting: Endpoints protected from abuse
- 身份验证:受保护的端点需要身份验证
- 授权:用户只能访问自己的数据
- 输入清理:防止SQL注入、XSS攻击
- 密钥管理:无硬编码的凭证或API密钥
- 加密:敏感数据在静态和传输时已加密
- 仅HTTPS:生产环境流量使用HTTPS
- 限流:端点已做防滥用限流
Language-Specific (JavaScript/TypeScript)
特定语言(JavaScript/TypeScript)
- Async/Await: Promises handled correctly
- Type Safety: TypeScript types are specific (not )
any - Nullability: Null checks where needed (operator)
?. - Array Methods: Using map/filter/reduce appropriately
- Const vs Let: Using const for immutable values
- Arrow Functions: Appropriate use of arrow vs regular functions
- Async/Await:Promise处理正确
- 类型安全:TypeScript类型明确(不使用)
any - 空值处理:必要时做了null检查(使用操作符)
?. - 数组方法:合理使用map/filter/reduce
- Const vs Let:不可变值使用const
- 箭头函数:合理区分箭头函数与普通函数的使用场景
Language-Specific (Python)
特定语言(Python)
- PEP 8: Follows Python style guide
- Type Hints: Functions have type annotations
- List Comprehensions: Used where appropriate (not overused)
- Context Managers: Using for file/connection handling
with - Exception Handling: Specific exceptions caught (not bare )
except: - F-Strings: Modern string formatting used
- PEP 8:遵循Python风格指南
- 类型提示:函数有类型注解
- 列表推导式:合理使用(不过度使用)
- 上下文管理器:使用处理文件/连接
with - 异常处理:捕获特定异常(不使用裸)
except: - F-字符串:使用现代字符串格式化方式
API Design
API设计
- RESTful: Follows REST conventions (if REST API)
- Consistent Naming: Endpoints follow naming patterns
- HTTP Methods: Correct methods used (GET, POST, PUT, DELETE)
- Status Codes: Appropriate HTTP status codes returned
- Error Responses: Consistent error format
- Pagination: Large lists are paginated
- Versioning: API version strategy followed
- REST规范:遵循REST约定(如果是REST API)
- 命名一致性:端点遵循命名模式
- HTTP方法:使用正确的HTTP方法(GET、POST、PUT、DELETE)
- 状态码:返回合适的HTTP状态码
- 错误响应:错误格式一致
- 分页:大型列表已做分页
- 版本控制:遵循API版本策略
Database
数据库
- Migrations: Database changes have migrations
- Indexes: Appropriate indexes created
- Transactions: ACID properties maintained
- Cascades: Delete cascades handled correctly
- Constraints: Foreign keys, unique constraints defined
- N+1 Queries: Eager loading used where needed
- 迁移:数据库变更有对应的迁移脚本
- 索引:创建了合适的索引
- 事务:维护了ACID属性
- 级联操作:删除级联处理正确
- 约束:定义了外键、唯一约束
- N+1查询:必要时使用了预加载
Documentation
文档
- PR Description: Clear explanation of changes
- Code Comments: Complex logic explained
- API Docs: Public API documented (JSDoc, docstrings)
- README: Updated if functionality changed
- CHANGELOG: Breaking changes documented
- PR描述:清晰说明变更内容
- 代码注释:复杂逻辑有注释
- API文档:公共API已文档化(JSDoc、docstrings)
- README:功能变更时已更新
- 变更日志:破坏性变更已记录
Review Feedback Patterns
评审反馈模式
How to Give Constructive Feedback
如何给出建设性反馈
✅ Good Feedback
✅ 优秀反馈示例
issue: This function doesn't handle the case where the user is null
If `getUserById()` returns null (user not found), this will throw:
`Cannot read property 'email' of null`
Add a null check:
```typescript
const user = await getUserById(userId);
if (!user) {
throw new UserNotFoundError(userId);
}
return user.email;
**Why it's good:**
- Specific (points to exact problem)
- Explains the impact (what will happen)
- Suggests a concrete solution
- Provides example codeissue: 这个函数未处理用户为null的情况
如果`getUserById()`返回null(用户不存在),会抛出错误:
`Cannot read property 'email' of null`
请添加null检查:
```typescript
const user = await getUserById(userId);
if (!user) {
throw new UserNotFoundError(userId);
}
return user.email;
**为什么优秀:**
- 具体(指出了确切问题)
- 说明了影响(会发生什么)
- 给出了明确的解决方案
- 提供了代码示例❌ Bad Feedback
❌ 糟糕反馈示例
This is wrong. Fix it.Why it's bad:
- Not specific (what's wrong?)
- Not helpful (how to fix?)
- Sounds harsh (not constructive)
这不对,修复它。为什么糟糕:
- 不具体(哪里错了?)
- 无帮助(怎么修复?)
- 语气生硬(没有建设性)
How to Receive Feedback
如何接收反馈
As an Author:
- Assume Good Intent: Reviewers are trying to help
- Ask Questions: If feedback is unclear, ask for clarification
- Acknowledge Valid Points: Accept feedback graciously
- Explain Your Reasoning: If you disagree, explain why
- Make Changes Promptly: Address feedback quickly
- Say Thank You: Appreciate the reviewer's time
Responding to Feedback:
markdown
✅ Good Response:
> Good catch! I didn't consider the null case.
> I've added the null check in commit abc123.
✅ Good Response (Disagreement):
> I chose a Map here because we need O(1) lookups on a large dataset.
> An object would work but performs worse at scale (n > 10,000).
> I added a comment explaining this tradeoff.
❌ Bad Response:
> This works fine. Not changing it.作为代码提交者:
- 假设善意:评审者是在提供帮助
- 提问澄清:如果反馈不明确,请询问细节
- 认可合理建议:欣然接受正确的反馈
- 解释你的思路:如果不同意,请说明原因
- 及时修改:尽快处理反馈
- 表达感谢:感谢评审者付出的时间
回复反馈的示例:
markdown
✅ 优秀回复:
> 好发现!我之前没考虑到null的情况。
> 我已经在提交abc123中添加了null检查。
✅ 优秀回复(有分歧):
> 我选择Map是因为我们需要对大数据集进行O(1)查找。
> 对象也能工作,但在数据量较大时(n > 10,000)性能更差。
> 我已经添加了注释说明这个权衡。
❌ 糟糕回复:
> 这个没问题,我不改。Code Review Anti-Patterns
代码评审反模式
For Reviewers
评审者的反模式
❌ Nitpicking Without Clear Value
nitpick: Add a space here
nitpick: Rename this variable to `userInfo` instead of `userData`
nitpick: Move this import to the topBetter: Use automated tools (Prettier, linters) for formatting.
❌ Reviewing Line-by-Line Without Understanding Context
Better: Read PR description first, understand the big picture.
❌ Blocking on Personal Preferences
This should be a class instead of functions.Better: Only block on objective issues (bugs, security). Discuss preferences separately.
❌ Rewriting Code in Comments
Better: Suggest improvements, don't provide full implementations (unless very helpful).
❌ Review Fatigue (Approving Without Reading)
Better: If you don't have time, say so. Don't rubber-stamp.
❌ 无意义的吹毛求疵
nitpick: 这里加个空格
nitpick: 把变量名从`userData`改成`userInfo`
nitpick: 把这个导入移到顶部更好的做法: 用自动化工具(Prettier、代码检查器)处理格式问题。
❌ 不理解上下文就逐行评审
更好的做法: 先读PR描述,理解整体情况。
❌ 因个人偏好阻止合并
这应该用类而不是函数。更好的做法: 仅因客观问题(bug、安全)阻止合并,偏好问题单独讨论。
❌ 在评论中重写代码
更好的做法: 提出改进建议,不要提供完整实现(除非特别有帮助)。
❌ 评审疲劳(未阅读就批准)
更好的做法: 如果没时间,直接说明,不要草率批准。
For Authors
提交者的反模式
❌ Giant Pull Requests (> 1000 lines)
Better: Break into smaller, focused PRs.
❌ No Description
Better: Write clear PR description with context and testing notes.
❌ Submitting Failing Tests
Better: Ensure all automated checks pass before requesting review.
❌ Getting Defensive About Feedback
Better: Accept feedback gracefully, discuss respectfully.
❌ Force-Pushing After Review
Better: Add new commits so reviewers can see what changed.
❌ 超大PR(>1000行)
更好的做法: 拆分成更小、聚焦的PR。
❌ 无PR描述
更好的做法: 写清晰的PR描述,包含上下文和测试说明。
❌ 提交测试未通过的代码
更好的做法: 确保所有自动化检查通过后再请求评审。
❌ 对反馈有抵触情绪
更好的做法: 欣然接受反馈,礼貌讨论。
❌ 评审后强制推送
更好的做法: 添加新提交,让评审者能看到变更内容。
Review Templates
评审模板
Standard PR Template
标准PR模板
markdown
undefinedmarkdown
undefinedDescription
描述
Brief summary of what changed and why.
Fixes #[issue number]
变更内容及原因的简要说明。
修复了 #[工单号]
Type of Change
变更类型
- Bug fix (non-breaking change which fixes an issue)
- New feature (non-breaking change which adds functionality)
- Breaking change (fix or feature that would cause existing functionality to not work as expected)
- Refactoring (no functional changes)
- Documentation update
- Bug修复(非破坏性变更)
- 新功能(非破坏性变更)
- 破坏性变更(会导致现有功能无法正常工作)
- 重构(无功能变更)
- 文档更新
How Has This Been Tested?
测试情况
- Unit tests added/updated
- Integration tests added/updated
- Tested manually in local environment
- Tested in staging environment
- 添加/更新了单元测试
- 添加/更新了集成测试
- 在本地环境手动测试
- 在预发布环境测试
Checklist
检查清单
- My code follows the style guidelines of this project
- I have performed a self-review of my own code
- I have commented my code, particularly in hard-to-understand areas
- I have made corresponding changes to the documentation
- My changes generate no new warnings
- I have added tests that prove my fix is effective or that my feature works
- New and existing unit tests pass locally with my changes
- Any dependent changes have been merged and published
- 代码符合项目风格指南
- 我已对自己的代码做了自我评审
- 复杂代码段已添加注释
- 已同步更新相关文档
- 我的变更未产生新警告
- 我添加了测试以证明修复有效或功能可用
- 新的和现有的单元测试在本地都能通过
- 所有相关依赖变更已合并并发布
Screenshots (if applicable)
截图(如适用)
[Add screenshots for UI changes]
[添加UI变更的截图]
Additional Notes
补充说明
[Any additional context or notes for reviewers]
undefined[给评审者的额外上下文或说明]
undefinedSecurity Review Template
安全评审模板
markdown
undefinedmarkdown
undefinedSecurity Review Checklist
安全评审检查清单
Authentication & Authorization
身份验证与授权
- Endpoints require appropriate authentication
- User permissions are checked before actions
- JWT tokens are validated and not expired
- Session management is secure
- 受保护的端点需要身份验证
- 用户权限已在操作前检查
- JWT令牌已验证且未过期
- 会话管理安全
Input Validation
输入验证
- All user inputs are validated
- SQL injection prevented (parameterized queries)
- XSS prevented (input sanitization, CSP headers)
- CSRF protection in place for state-changing operations
- 所有用户输入已验证
- 已防止SQL注入(使用参数化查询)
- 已防止XSS攻击(输入清理、CSP头)
- 状态变更操作已做CSRF保护
Data Protection
数据保护
- Sensitive data is encrypted at rest
- TLS/HTTPS used for data in transit
- API keys and secrets not hardcoded
- PII is properly handled (GDPR/CCPA compliance)
- 敏感数据在静态时已加密
- 数据传输使用TLS/HTTPS
- API密钥和密钥未硬编码
- PII数据已按GDPR/CCPA合规处理
Dependencies
依赖
- No known vulnerabilities in dependencies (npm audit / pip-audit)
- Dependencies from trusted sources
- Dependency versions pinned
- 依赖无已知漏洞(npm audit / pip-audit)
- 依赖来自可信源
- 依赖版本已固定
Logging & Monitoring
日志与监控
- Sensitive data not logged (passwords, tokens)
- Security events logged (failed auth attempts)
- Rate limiting in place for public endpoints
Security Concerns Identified:
[List any security issues found]
Reviewer Signature:
[Name, Date]
---- 日志中未包含敏感数据(密码、令牌)
- 安全事件已记录(如失败的登录尝试)
- 公共端点已做限流
发现的安全问题:
[列出发现的所有安全问题]
评审者签名:
[姓名,日期]
---Review Metrics and Goals
评审指标与目标
Healthy Review Metrics
健康的评审指标
| Metric | Target | Purpose |
|---|---|---|
| Review Time | < 24 hours | Fast feedback loop |
| PR Size | < 400 lines | Manageable reviews |
| Approval Rate (first review) | 20-30% | Balance speed vs quality |
| Comments per PR | 3-10 | Engaged but not overwhelming |
| Back-and-Forth Rounds | 1-2 | Efficient communication |
| Time to Merge (after approval) | < 2 hours | Avoid stale branches |
| 指标 | 目标 | 目的 |
|---|---|---|
| 评审耗时 | <24小时 | 快速反馈循环 |
| PR规模 | <400行 | 便于评审 |
| 首次评审批准率 | 20-30% | 平衡速度与质量 |
| 每个PR的评论数 | 3-10 | 充分参与但不过度 |
| 往返次数 | 1-2 | 高效沟通 |
| 批准后合并耗时 | <2小时 | 避免分支过时 |
Warning Signs
预警信号
- ⚠️ PRs sitting unreviewed for > 3 days (review capacity issue)
- ⚠️ 90%+ approval rate on first review (rubber-stamping)
- ⚠️ Average PR size > 800 lines (PRs too large)
- ⚠️ 15+ comments per PR (overly nitpicky or unclear requirements)
- ⚠️ 5+ review rounds (poor communication or unclear standards)
- ⚠️ PR超过3天未评审(评审能力不足)
- ⚠️ 首次评审批准率90%+(草率批准)
- ⚠️ 平均PR规模>800行(PR过大)
- ⚠️ 每个PR的评论数>15(过度吹毛求疵或需求不明确)
- ⚠️ 评审往返次数>5(沟通不畅或标准不清晰)
Integration with Agents
与Agent集成
Code Quality Reviewer Agent
代码质量评审Agent
- Uses this playbook when reviewing code
- Applies conventional comments format
- Follows language-specific checklists
- Provides structured, actionable feedback
- 使用本手册进行代码评审
- 应用标准化评论格式
- 遵循特定语言检查清单
- 提供结构化、可执行的反馈
Backend System Architect
后端系统架构师Agent
- Reviews for architectural soundness
- Checks design patterns and scalability
- Validates API design against best practices
- 评审架构合理性
- 检查设计模式与可扩展性
- 验证API设计是否符合最佳实践
Frontend UI Developer
前端UI开发者Agent
- Reviews component structure and patterns
- Checks accessibility and responsive design
- Validates UI/UX implementation
- 评审组件结构与模式
- 检查可访问性与响应式设计
- 验证UI/UX实现
Security Reviewer (Future Agent)
安全评审Agent(未来规划)
- Focuses on security checklist
- Identifies vulnerabilities
- Validates compliance requirements
- 聚焦安全检查清单
- 识别漏洞
- 验证合规要求
Advanced Pattern Detection (Opus 4.5)
高级模式检测(Opus 4.5)
Extended Thinking for Complex Reviews
复杂评审的深度思考
For large PRs or systemic analysis, leverage Opus 4.5's extended thinking to perform deep pattern detection:
When to Use Extended Thinking:
- PR touches > 10 files across multiple modules
- Reviewing security-critical code paths
- Analyzing architectural consistency
- Detecting cross-file code smells
- Evaluating breaking change impact
Extended Thinking Review Pattern:
Based on Anthropic's Extended Thinking API:
typescript
import Anthropic from '@anthropic-ai/sdk';
interface ReviewResult {
issues: ReviewIssue[];
patterns: DetectedPattern[];
recommendations: string[];
riskScore: number;
}
async function performDeepCodeReview(
prDiff: string,
codebaseContext: string
): Promise<ReviewResult> {
const anthropic = new Anthropic();
// Extended thinking requires budget_tokens < max_tokens
// Minimum budget: 1,024 tokens
const response = await anthropic.messages.create({
model: 'claude-opus-4-5-20251101',
max_tokens: 16000,
thinking: {
type: 'enabled',
budget_tokens: 8000 // Deep analysis for complex reviews
},
messages: [{
role: 'user',
content: `
Perform a comprehensive code review analyzing:
## PR Changes
${prDiff}
## Codebase Context
${codebaseContext}
## Analysis Requirements
1. **Systemic Pattern Detection**: Identify recurring patterns (good and bad)
2. **Cross-File Impact**: Trace how changes affect other modules
3. **Security Analysis**: Deep scan for vulnerabilities (OWASP Top 10)
4. **Architectural Consistency**: Verify alignment with existing patterns
5. **Technical Debt Assessment**: Identify debt being added or resolved
Provide structured output with:
- Critical issues (must fix)
- Warnings (should fix)
- Suggestions (nice to have)
- Detected patterns (positive and negative)
- Risk score (1-10)
`
}]
});
// Response contains thinking blocks followed by text blocks
// content: [{ type: 'thinking', thinking: '...' }, { type: 'text', text: '...' }]
return parseReviewResponse(response);
}对于大型PR或系统性分析,可利用Opus 4.5的深度思考能力进行模式检测:
何时使用深度思考:
- PR修改了10个以上文件,涉及多个模块
- 评审安全关键代码路径
- 分析架构一致性
- 检测跨文件代码异味
- 评估破坏性变更的影响
深度思考评审模式:
typescript
import Anthropic from '@anthropic-ai/sdk';
interface ReviewResult {
issues: ReviewIssue[];
patterns: DetectedPattern[];
recommendations: string[];
riskScore: number;
}
async function performDeepCodeReview(
prDiff: string,
codebaseContext: string
): Promise<ReviewResult> {
const anthropic = new Anthropic();
// 深度思考要求budget_tokens < max_tokens
// 最小预算:1,024 tokens
const response = await anthropic.messages.create({
model: 'claude-opus-4-5-20251101',
max_tokens: 16000,
thinking: {
type: 'enabled',
budget_tokens: 8000 // 复杂评审的深度分析
},
messages: [{
role: 'user',
content: `
执行全面的代码评审,分析以下内容:
## PR变更
${prDiff}
## 代码库上下文
${codebaseContext}
## 分析要求
1. **系统性模式检测**:识别重复出现的模式(好的和坏的)
2. **跨文件影响**:追踪变更对其他模块的影响
3. **安全分析**:深度扫描漏洞(OWASP Top 10)
4. **架构一致性**:验证与现有模式的对齐度
5. **技术债务评估**:识别新增或解决的技术债务
提供结构化输出,包含:
- 关键问题(必须修复)
- 警告(应该修复)
- 建议(优化项)
- 检测到的模式(正面和负面)
- 风险评分(1-10)
`
}]
});
// 响应包含思考块和文本块
// content: [{ type: 'thinking', thinking: '...' }, { type: 'text', text: '...' }]
return parseReviewResponse(response);
}Systemic Code Smell Detection
系统性代码异味检测
Detect patterns that span multiple files:
typescript
interface CodeSmellPattern {
type: 'duplication' | 'coupling' | 'complexity' | 'naming' | 'architecture';
severity: 'critical' | 'warning' | 'info';
locations: FileLocation[];
description: string;
suggestion: string;
}
const SMELL_PATTERNS = {
// Cross-file duplication
duplication: {
triggers: ['similar logic in 3+ files', 'copy-paste patterns', 'repeated error handling'],
action: 'Extract to shared utility or base class'
},
// Tight coupling
coupling: {
triggers: ['circular imports', 'god objects', 'feature envy'],
action: 'Apply dependency injection or interface segregation'
},
// Complexity creep
complexity: {
triggers: ['nested callbacks > 3 levels', 'functions > 50 lines', 'cyclomatic complexity > 10'],
action: 'Decompose into smaller, focused functions'
},
// Inconsistent naming
naming: {
triggers: ['mixed conventions', 'unclear abbreviations', 'inconsistent pluralization'],
action: 'Align with codebase naming conventions'
},
// Architectural drift
architecture: {
triggers: ['layer violations', 'missing abstractions', 'inappropriate intimacy'],
action: 'Refactor to follow established architectural patterns'
}
};检测跨多个文件的模式:
typescript
interface CodeSmellPattern {
type: 'duplication' | 'coupling' | 'complexity' | 'naming' | 'architecture';
severity: 'critical' | 'warning' | 'info';
locations: FileLocation[];
description: string;
suggestion: string;
}
const SMELL_PATTERNS = {
// 跨文件重复
duplication: {
触发条件: ['3个以上文件有相似逻辑', '复制粘贴模式', '重复的错误处理'],
行动: '提取到共享工具类或基类'
},
// 紧耦合
coupling: {
触发条件: ['循环导入', '上帝对象', '特性羡慕'],
行动: '应用依赖注入或接口隔离'
},
// 复杂度攀升
complexity: {
触发条件: ['嵌套回调>3层', '函数>50行', '圈复杂度>10'],
行动: '分解为更小、聚焦的函数'
},
// 命名不一致
naming: {
触发条件: ['混合命名规范', '模糊的缩写', '复数形式不一致'],
行动: '与代码库命名规范对齐'
},
// 架构漂移
architecture: {
触发条件: ['层级违反', '缺少抽象', '不当亲密'],
行动: '重构以遵循既定架构模式'
}
};Security Deep Analysis
安全深度分析
Extended thinking enables comprehensive security review:
typescript
interface SecurityFinding {
category: 'injection' | 'auth' | 'crypto' | 'exposure' | 'config';
severity: 'critical' | 'high' | 'medium' | 'low';
cwe: string; // CWE ID
location: FileLocation;
description: string;
remediation: string;
}
async function performSecurityReview(
code: string,
context: SecurityContext
): Promise<SecurityFinding[]> {
const anthropic = new Anthropic();
const response = await anthropic.messages.create({
model: 'claude-opus-4-5-20251101',
max_tokens: 12000,
thinking: {
type: 'enabled',
budget_tokens: 6000 // Security analysis needs deep reasoning
},
messages: [{
role: 'user',
content: `
Perform security analysis on this code:
${code}
Context:
- Language: ${context.language}
- Framework: ${context.framework}
- Exposure: ${context.isPublicFacing ? 'Public' : 'Internal'}
Check for:
1. Injection vulnerabilities (SQL, XSS, command)
2. Authentication/Authorization flaws
3. Cryptographic weaknesses
4. Sensitive data exposure
5. Security misconfiguration
For each finding, provide CWE ID and specific remediation.
`
}]
});
return parseSecurityFindings(response);
}深度思考能力支持全面的安全评审:
typescript
interface SecurityFinding {
category: 'injection' | 'auth' | 'crypto' | 'exposure' | 'config';
severity: 'critical' | 'high' | 'medium' | 'low';
cwe: string; // CWE编号
location: FileLocation;
description: string;
remediation: string;
}
async function performSecurityReview(
code: string,
context: SecurityContext
): Promise<SecurityFinding[]> {
const anthropic = new Anthropic();
const response = await anthropic.messages.create({
model: 'claude-opus-4-5-20251101',
max_tokens: 12000,
thinking: {
type: 'enabled',
budget_tokens: 6000 // 安全分析需要深度推理
},
messages: [{
role: 'user',
content: `
对以下代码进行安全分析:
${code}
上下文:
- 语言: ${context.language}
- 框架: ${context.framework}
- 暴露程度: ${context.isPublicFacing ? '公开' : '内部'}
检查内容:
1. 注入漏洞(SQL、XSS、命令注入)
2. 身份验证/授权缺陷
3. 加密弱点
4. 敏感数据暴露
5. 安全配置错误
每个发现请提供CWE编号和具体修复建议。
`
}]
});
return parseSecurityFindings(response);
}Cross-File Impact Analysis
跨文件影响分析
Trace how changes ripple through the codebase:
typescript
interface ImpactAnalysis {
directImpact: FileImpact[];
indirectImpact: FileImpact[];
breakingChanges: BreakingChange[];
testCoverage: TestCoverageGap[];
}
async function analyzeChangeImpact(
changedFiles: string[],
dependencyGraph: DependencyGraph
): Promise<ImpactAnalysis> {
// Build impact graph
const directlyAffected = new Set<string>();
const indirectlyAffected = new Set<string>();
for (const file of changedFiles) {
// Files that import this file
const dependents = dependencyGraph.getDependents(file);
dependents.forEach(d => directlyAffected.add(d));
// Second-level dependents
for (const dependent of dependents) {
const secondLevel = dependencyGraph.getDependents(dependent);
secondLevel.forEach(d => {
if (!directlyAffected.has(d)) {
indirectlyAffected.add(d);
}
});
}
}
// Use extended thinking for breaking change analysis
const breakingAnalysis = await analyzeBreakingChanges(
changedFiles,
Array.from(directlyAffected)
);
return {
directImpact: Array.from(directlyAffected).map(f => ({ file: f, type: 'direct' })),
indirectImpact: Array.from(indirectlyAffected).map(f => ({ file: f, type: 'indirect' })),
breakingChanges: breakingAnalysis.breaking,
testCoverage: breakingAnalysis.gaps
};
}追踪变更在代码库中的连锁反应:
typescript
interface ImpactAnalysis {
directImpact: FileImpact[];
indirectImpact: FileImpact[];
breakingChanges: BreakingChange[];
testCoverage: TestCoverageGap[];
}
async function analyzeChangeImpact(
changedFiles: string[],
dependencyGraph: DependencyGraph
): Promise<ImpactAnalysis> {
// 构建影响图
const directlyAffected = new Set<string>();
const indirectlyAffected = new Set<string>();
for (const file of changedFiles) {
// 导入了该文件的文件
const dependents = dependencyGraph.getDependents(file);
dependents.forEach(d => directlyAffected.add(d));
// 二级依赖文件
for (const dependent of dependents) {
const secondLevel = dependencyGraph.getDependents(dependent);
secondLevel.forEach(d => {
if (!directlyAffected.has(d)) {
indirectlyAffected.add(d);
}
});
}
}
// 使用深度思考分析破坏性变更
const breakingAnalysis = await analyzeBreakingChanges(
changedFiles,
Array.from(directlyAffected)
);
return {
directImpact: Array.from(directlyAffected).map(f => ({ file: f, type: 'direct' })),
indirectImpact: Array.from(indirectlyAffected).map(f => ({ file: f, type: 'indirect' })),
breakingChanges: breakingAnalysis.breaking,
testCoverage: breakingAnalysis.gaps
};
}Review Automation with Model Tiering
模型分层的评审自动化
Optimize review costs with intelligent model selection:
typescript
type ModelTier = 'opus' | 'sonnet' | 'haiku';
interface ReviewConfig {
model: ModelTier;
thinkingBudget?: number;
focus: string[];
}
function selectReviewModel(pr: PullRequest): ReviewConfig {
// Critical path - use Opus with extended thinking
if (pr.touchesCriticalPath || pr.isSecurityRelated) {
return {
model: 'opus',
thinkingBudget: 8000,
focus: ['security', 'architecture', 'breaking-changes']
};
}
// Large PRs - use Opus for systemic analysis
if (pr.filesChanged > 10 || pr.linesChanged > 500) {
return {
model: 'opus',
thinkingBudget: 5000,
focus: ['patterns', 'impact', 'consistency']
};
}
// Standard PRs - Sonnet for thorough review
if (pr.linesChanged > 100) {
return {
model: 'sonnet',
focus: ['correctness', 'style', 'tests']
};
}
// Small changes - Haiku for quick review
return {
model: 'haiku',
focus: ['correctness', 'style']
};
}通过智能模型选择优化评审成本:
typescript
type ModelTier = 'opus' | 'sonnet' | 'haiku';
interface ReviewConfig {
model: ModelTier;
thinkingBudget?: number;
focus: string[];
}
function selectReviewModel(pr: PullRequest): ReviewConfig {
// 关键路径 - 使用Opus并开启深度思考
if (pr.touchesCriticalPath || pr.isSecurityRelated) {
return {
model: 'opus',
thinkingBudget: 8000,
focus: ['security', 'architecture', 'breaking-changes']
};
}
// 大型PR - 使用Opus进行系统性分析
if (pr.filesChanged > 10 || pr.linesChanged > 500) {
return {
model: 'opus',
thinkingBudget: 5000,
focus: ['patterns', 'impact', 'consistency']
};
}
// 标准PR - 使用Sonnet进行全面评审
if (pr.linesChanged > 100) {
return {
model: 'sonnet',
focus: ['correctness', 'style', 'tests']
};
}
// 小型变更 - 使用Haiku快速评审
return {
model: 'haiku',
focus: ['correctness', 'style']
};
}Review Comment Generation
评审评论自动生成
Generate conventional comments automatically:
typescript
interface GeneratedComment {
label: 'praise' | 'nitpick' | 'suggestion' | 'issue' | 'question' | 'security' | 'bug';
decoration?: 'blocking' | 'non-blocking' | 'if-minor';
subject: string;
discussion: string;
location: { file: string; line: number };
}
function formatConventionalComment(comment: GeneratedComment): string {
const decoration = comment.decoration ? ` [${comment.decoration}]` : '';
return `${comment.label}${decoration}: ${comment.subject}\n\n${comment.discussion}`;
}
// Example output:
// security [blocking]: SQL injection vulnerability in user search
//
// The search query is constructed using string concatenation:
// ```typescript
// const query = `SELECT * FROM users WHERE name = '${searchTerm}'`;
// ```
//
// Use parameterized queries instead:
// ```typescript
// const query = 'SELECT * FROM users WHERE name = $1';
// const result = await db.query(query, [searchTerm]);
// ```自动生成标准化评论:
typescript
interface GeneratedComment {
label: 'praise' | 'nitpick' | 'suggestion' | 'issue' | 'question' | 'security' | 'bug';
decoration?: 'blocking' | 'non-blocking' | 'if-minor';
subject: string;
discussion: string;
location: { file: string; line: number };
}
function formatConventionalComment(comment: GeneratedComment): string {
const decoration = comment.decoration ? ` [${comment.decoration}]` : '';
return `${comment.label}${decoration}: ${comment.subject}\n\n${comment.discussion}`;
}
// 示例输出:
// security [blocking]: 用户搜索存在SQL注入漏洞
//
// 查询语句使用字符串拼接构建:
// ```typescript
// const query = `SELECT * FROM users WHERE name = '${searchTerm}'`;
// ```
//
// 请改用参数化查询:
// ```typescript
// const query = 'SELECT * FROM users WHERE name = $1';
// const result = await db.query(query, [searchTerm]);
// ```Quick Start Guide
快速入门指南
For Reviewers:
- Read PR description and understand intent
- Check that automated checks pass
- Do high-level review (architecture, approach)
- Do detailed review (logic, edge cases, tests)
- Use conventional comments for clear communication
- Provide decision: Approve, Comment, or Request Changes
For Authors:
- Write clear PR description
- Perform self-review before requesting review
- Ensure all automated checks pass
- Keep PR focused and reasonably sized (< 400 lines)
- Respond to feedback promptly and respectfully
- Make requested changes or explain reasoning
Skill Version: 2.0.0
Last Updated: 2025-11-27
Maintained by: AI Agent Hub Team
评审者:
- 阅读PR描述,理解变更意图
- 确认自动化检查已通过
- 进行整体评审(架构、方案)
- 进行细节评审(逻辑、边缘情况、测试)
- 使用标准化评论进行清晰沟通
- 给出明确结论:批准、评论或要求修改
提交者:
- 写清晰的PR描述
- 提交前先做自我评审
- 确保所有自动化检查通过
- 保持PR聚焦且规模合理(<400行)
- 及时、礼貌地回复反馈
- 根据反馈修改代码或解释思路
技能版本: 2.0.0
最后更新: 2025-11-27
维护团队: AI Agent Hub Team