code-review-excellence by wshobson/agents
npx skills add https://github.com/wshobson/agents --skill code-review-excellence通过建设性反馈、系统性分析和协作改进,将代码审查从把关转变为知识共享。
代码审查的目标:
非目标:
好的反馈是:
❌ 差评:"这是错的。"
✅ 好评:"当多个用户同时访问时,这可能导致竞态条件。考虑在这里使用互斥锁。"
❌ 差评:"你为什么不用 X 模式?"
✅ 好评:"你考虑过 Repository 模式吗?它会让这个更容易测试。这里有个例子:[链接]"
❌ 差评:"重命名这个变量。"
✅ 好评:"[nit] 为了清晰起见,考虑使用 `userCount` 而不是 `uc`。如果你倾向于保留它,这不阻塞。"
广告位招租
在这里展示您的产品或服务
触达数万 AI 开发者,精准高效
审查什么:
不要手动审查什么:
在深入代码之前,先了解:
1. 阅读 PR 描述和链接的问题
2. 检查 PR 大小(>400 行?要求拆分)
3. 审查 CI/CD 状态(测试通过了吗?)
4. 理解业务需求
5. 注意任何相关的架构决策
1. **架构与设计**
- 解决方案是否适合问题?
- 是否有更简单的方法?
- 是否与现有模式一致?
- 它能扩展吗?
2. **文件组织**
- 新文件放在正确的位置了吗?
- 代码是否按逻辑分组?
- 有重复的文件吗?
3. **测试策略**
- 有测试吗?
- 测试覆盖边界情况了吗?
- 测试可读吗?
对于每个文件:
1. **逻辑与正确性**
- 边界情况处理了吗?
- 差一错误?
- 空值/未定义检查?
- 竞态条件?
2. **安全性**
- 输入验证?
- SQL 注入风险?
- XSS 漏洞?
- 敏感数据暴露?
3. **性能**
- N+1 查询?
- 不必要的循环?
- 内存泄漏?
- 阻塞操作?
4. **可维护性**
- 变量名清晰吗?
- 函数是否只做一件事?
- 复杂代码有注释吗?
- 提取了魔法数字吗?
1. 总结关键问题
2. 突出你喜欢的地方
3. 做出明确决定:
- ✅ 批准
- 💬 评论(次要建议)
- 🔄 请求更改(必须解决)
4. 如果复杂,主动提出结对编程
## 安全检查清单
- [ ] 用户输入经过验证和清理
- [ ] SQL 查询使用参数化
- [ ] 检查了身份验证/授权
- [ ] 密钥没有硬编码
- [ ] 错误消息不泄露信息
## 性能检查清单
- [ ] 没有 N+1 查询
- [ ] 数据库查询已建立索引
- [ ] 大型列表已分页
- [ ] 昂贵的操作已缓存
- [ ] 热点路径中没有阻塞 I/O
## 测试检查清单
- [ ] 测试了正常路径
- [ ] 覆盖了边界情况
- [ ] 测试了错误情况
- [ ] 测试名称具有描述性
- [ ] 测试是确定性的
与其陈述问题,不如提问以鼓励思考:
❌ "如果列表为空,这会失败。"
✅ "如果 `items` 是空数组会发生什么?"
❌ "你需要在这里进行错误处理。"
✅ "如果 API 调用失败,这个应该如何处理?"
❌ "这效率低下。"
✅ "我看到这个循环遍历了所有用户。我们考虑过在有 10 万用户时的性能影响吗?"
## 使用协作性语言
❌ "你必须改成使用 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:区分严重性
```text
使用标签来指示优先级:
🔴 [blocking] - 合并前必须修复
🟡 [important] - 应该修复,如有异议请讨论
🟢 [nit] - 锦上添花,不阻塞
💡 [suggestion] - 可考虑的替代方案
📚 [learning] - 教育性评论,无需操作
🎉 [praise] - 做得好,继续保持!
示例:
"🔴 [blocking] 这个 SQL 查询容易受到注入攻击。请使用参数化查询。"
"🟢 [nit] 为了清晰起见,考虑将 `data` 重命名为 `userData`。"
"🎉 [praise] 出色的测试覆盖率!这将捕获边界情况。"
# 检查 Python 特定问题
# ❌ 可变默认参数
def add_item(item, items=[]): # Bug! 在调用间共享
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"Invalid value: {e}")
raise
# ❌ 使用可变类属性
class User:
permissions = [] # 在所有实例间共享!
# ✅ 在 __init__ 中初始化
class User:
def __init__(self):
self.permissions = []
// 检查 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<User> {
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('Failed to fetch user:', error);
throw error;
}
}
// ❌ 修改 props
function UserProfile({ user }: Props) {
user.lastViewed = new Date(); // 修改 prop!
return <div>{user.name}</div>;
}
// ✅ 不要修改 props
function UserProfile({ user, onView }: Props) {
useEffect(() => {
onView(user.id); // 通知父组件更新
}, [user.id]);
return <div>{user.name}</div>;
}
审查重大变更时:
1. **先有设计文档**
- 对于大型功能,在代码之前要求设计文档
- 在实现之前与团队一起审查设计
- 就方法达成一致以避免返工
2. **分阶段审查**
- 第一个 PR:核心抽象和接口
- 第二个 PR:实现
- 第三个 PR:集成和测试
- 更容易审查,迭代更快
3. **考虑替代方案**
- "我们考虑过使用 [模式/库] 吗?"
- "与更简单的方法相比,权衡是什么?"
- "随着需求变化,这将如何演变?"
// ❌ 差测试:测试实现细节
test('increments counter variable', () => {
const component = render(<Counter />);
const button = component.getByRole('button');
fireEvent.click(button);
expect(component.state.counter).toBe(1); // 测试内部状态
});
// ✅ 好测试:行为测试
test('displays incremented count when clicked', () => {
render(<Counter />);
const button = screen.getByRole('button', { name: /increment/i });
fireEvent.click(button);
expect(screen.getByText('Count: 1')).toBeInTheDocument();
});
// 测试的审查问题:
// - 测试描述行为,而不是实现吗?
// - 测试名称清晰且具有描述性吗?
// - 测试覆盖边界情况吗?
// - 测试是独立的吗(无共享状态)?
// - 测试可以按任何顺序运行吗?
## 安全检查清单
### 身份验证与授权
- [ ] 需要的地方是否要求身份验证?
- [ ] 每次操作前是否检查授权?
- [ ] JWT 验证是否正确(签名、过期)?
- [ ] API 密钥/密钥是否妥善保护?
### 输入验证
- [ ] 所有用户输入都验证了吗?
- [ ] 文件上传是否受限制(大小、类型)?
- [ ] SQL 查询是否参数化?
- [ ] XSS 防护(转义输出)?
### 数据保护
- [ ] 密码是否哈希(bcrypt/argon2)?
- [ ] 敏感数据在静态时是否加密?
- [ ] 敏感数据是否强制使用 HTTPS?
- [ ] PII 是否根据法规处理?
### 常见漏洞
- [ ] 没有 eval() 或类似的动态执行?
- [ ] 没有硬编码的密钥?
- [ ] 状态更改操作是否有 CSRF 保护?
- [ ] 公共端点是否有速率限制?
传统:赞扬 + 批评 + 赞扬(感觉虚假)
更好:上下文 + 具体问题 + 有帮助的解决方案
示例:
"我注意到支付处理逻辑内联在控制器中。这使得测试和重用更加困难。
[具体问题]
calculateTotal() 函数混合了税款计算、折扣逻辑和数据库查询,使得单元测试和推理变得困难。
[有帮助的解决方案]
我们能否将其提取到一个 PaymentService 类中?这将使其可测试且可重用。如果需要,我可以和你结对完成。"
当作者不同意你的反馈时:
1. **寻求理解**
"帮助我理解你的方法。是什么让你选择了这种模式?"
2. **承认有效观点**
"关于 X 的观点很好。我没有考虑到这一点。"
3. **提供数据**
"我担心性能问题。我们能添加一个基准测试来验证这个方法吗?"
4. **必要时升级**
"让我们请 [架构师/高级开发人员] 来权衡一下。"
5. **知道何时放手**
如果它有效且不是关键问题,就批准它。完美是进步之敌。
## 总结
[简要概述审查内容]
## 优点
- [做得好的地方]
- [好的模式或方法]
## 必须的更改
🔴 [阻塞性问题 1]
🔴 [阻塞性问题 2]
## 建议
💡 [改进建议 1]
💡 [改进建议 2]
## 问题
❓ [需要澄清 X]
❓ [替代方案考虑]
## 裁决
✅ 解决必须的更改后批准
每周安装量
9.2K
仓库
GitHub 星标
32.3K
首次出现
Jan 20, 2026
安全审计
安装在
opencode7.3K
gemini-cli7.0K
codex6.9K
cursor6.5K
github-copilot6.4K
claude-code6.3K
Transform code reviews from gatekeeping to knowledge sharing through constructive feedback, systematic analysis, and collaborative improvement.
Goals of Code Review:
Not the Goals:
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)
❌ Bad: "This is wrong." ✅ Good: "This could cause a race condition when multiple users access simultaneously. Consider using a mutex here."
❌ Bad: "Why didn't you use X pattern?" ✅ Good: "Have you considered the Repository pattern? It would make this easier to test. Here's an example: [link]"
❌ Bad: "Rename this variable."
✅ Good: "[nit] Consider userCount instead of uc for
clarity. Not blocking if you prefer to keep it."
What to Review:
What Not to Review Manually:
Before diving into code, understand:
1. Read PR description and linked issue
2. Check PR size (>400 lines? Ask to split)
3. Review CI/CD status (tests passing?)
4. Understand the business requirement
5. Note any relevant architectural decisions
1. **Architecture & Design**
- Does the solution fit the problem?
- Are there simpler approaches?
- Is it consistent with existing patterns?
- Will it scale?
2. **File Organization**
- Are new files in the right places?
- Is code grouped logically?
- Are there duplicate files?
3. **Testing Strategy**
- Are there tests?
- Do tests cover edge cases?
- Are tests readable?
For each file:
1. **Logic & Correctness**
- Edge cases handled?
- Off-by-one errors?
- Null/undefined checks?
- Race conditions?
2. **Security**
- Input validation?
- SQL injection risks?
- XSS vulnerabilities?
- Sensitive data exposure?
3. **Performance**
- N+1 queries?
- Unnecessary loops?
- Memory leaks?
- Blocking operations?
4. **Maintainability**
- Clear variable names?
- Functions doing one thing?
- Complex code commented?
- Magic numbers extracted?
1. Summarize key concerns
2. Highlight what you liked
3. Make clear decision:
- ✅ Approve
- 💬 Comment (minor suggestions)
- 🔄 Request Changes (must address)
4. Offer to pair if complex
## Security Checklist
- [ ] User input validated and sanitized
- [ ] SQL queries use parameterization
- [ ] Authentication/authorization checked
- [ ] Secrets not hardcoded
- [ ] Error messages don't leak info
## Performance Checklist
- [ ] No N+1 queries
- [ ] Database queries indexed
- [ ] Large lists paginated
- [ ] Expensive operations cached
- [ ] No blocking I/O in hot paths
## Testing Checklist
- [ ] Happy path tested
- [ ] Edge cases covered
- [ ] Error cases tested
- [ ] Test names are descriptive
- [ ] Tests are deterministic
Instead of stating problems, ask questions to encourage thinking:
❌ "This will fail if the list is empty."
✅ "What happens if `items` is an empty array?"
❌ "You need error handling here."
✅ "How should this behave if the API call fails?"
❌ "This is inefficient."
✅ "I see this loops through all users. Have we considered
the performance impact with 100k users?"
## Use Collaborative Language
❌ "You must change this to use async/await"
✅ "Suggestion: async/await might make this more readable:
`typescript
async function fetchUser(id: string) {
const user = await db.query('SELECT * FROM users WHERE id = ?', id);
return user;
}
`
What do you think?"
❌ "Extract this into a function"
✅ "This logic appears in 3 places. Would it make sense to
extract it into a shared utility function?"
Use labels to indicate priority:
🔴 [blocking] - Must fix before merge
🟡 [important] - Should fix, discuss if disagree
🟢 [nit] - Nice to have, not blocking
💡 [suggestion] - Alternative approach to consider
📚 [learning] - Educational comment, no action needed
🎉 [praise] - Good work, keep it up!
Example:
"🔴 [blocking] This SQL query is vulnerable to injection.
Please use parameterized queries."
"🟢 [nit] Consider renaming `data` to `userData` for clarity."
"🎉 [praise] Excellent test coverage! This will catch edge cases."
# Check for Python-specific issues
# ❌ Mutable default arguments
def add_item(item, items=[]): # Bug! Shared across calls
items.append(item)
return items
# ✅ Use None as default
def add_item(item, items=None):
if items is None:
items = []
items.append(item)
return items
# ❌ Catching too broad
try:
result = risky_operation()
except: # Catches everything, even KeyboardInterrupt!
pass
# ✅ Catch specific exceptions
try:
result = risky_operation()
except ValueError as e:
logger.error(f"Invalid value: {e}")
raise
# ❌ Using mutable class attributes
class User:
permissions = [] # Shared across all instances!
# ✅ Initialize in __init__
class User:
def __init__(self):
self.permissions = []
// Check for TypeScript-specific issues
// ❌ Using any defeats type safety
function processData(data: any) { // Avoid any
return data.value;
}
// ✅ Use proper types
interface DataPayload {
value: string;
}
function processData(data: DataPayload) {
return data.value;
}
// ❌ Not handling async errors
async function fetchUser(id: string) {
const response = await fetch(`/api/users/${id}`);
return response.json(); // What if network fails?
}
// ✅ Handle errors properly
async function fetchUser(id: string): Promise<User> {
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('Failed to fetch user:', error);
throw error;
}
}
// ❌ Mutation of props
function UserProfile({ user }: Props) {
user.lastViewed = new Date(); // Mutating prop!
return <div>{user.name}</div>;
}
// ✅ Don't mutate props
function UserProfile({ user, onView }: Props) {
useEffect(() => {
onView(user.id); // Notify parent to update
}, [user.id]);
return <div>{user.name}</div>;
}
When reviewing significant changes:
1. **Design Document First**
- For large features, request design doc before code
- Review design with team before implementation
- Agree on approach to avoid rework
2. **Review in Stages**
- First PR: Core abstractions and interfaces
- Second PR: Implementation
- Third PR: Integration and tests
- Easier to review, faster to iterate
3. **Consider Alternatives**
- "Have we considered using [pattern/library]?"
- "What's the tradeoff vs. the simpler approach?"
- "How will this evolve as requirements change?"
// ❌ Poor test: Implementation detail testing
test('increments counter variable', () => {
const component = render(<Counter />);
const button = component.getByRole('button');
fireEvent.click(button);
expect(component.state.counter).toBe(1); // Testing internal state
});
// ✅ Good test: Behavior testing
test('displays incremented count when clicked', () => {
render(<Counter />);
const button = screen.getByRole('button', { name: /increment/i });
fireEvent.click(button);
expect(screen.getByText('Count: 1')).toBeInTheDocument();
});
// Review questions for tests:
// - Do tests describe behavior, not implementation?
// - Are test names clear and descriptive?
// - Do tests cover edge cases?
// - Are tests independent (no shared state)?
// - Can tests run in any order?
## Security Review Checklist
### Authentication & Authorization
- [ ] Is authentication required where needed?
- [ ] Are authorization checks before every action?
- [ ] Is JWT validation proper (signature, expiry)?
- [ ] Are API keys/secrets properly secured?
### Input Validation
- [ ] All user inputs validated?
- [ ] File uploads restricted (size, type)?
- [ ] SQL queries parameterized?
- [ ] XSS protection (escape output)?
### Data Protection
- [ ] Passwords hashed (bcrypt/argon2)?
- [ ] Sensitive data encrypted at rest?
- [ ] HTTPS enforced for sensitive data?
- [ ] PII handled according to regulations?
### Common Vulnerabilities
- [ ] No eval() or similar dynamic execution?
- [ ] No hardcoded secrets?
- [ ] CSRF protection for state-changing operations?
- [ ] Rate limiting on public endpoints?
Traditional: Praise + Criticism + Praise (feels fake)
Better: Context + Specific Issue + Helpful Solution
Example:
"I noticed the payment processing logic is inline in the
controller. This makes it harder to test and reuse.
[Specific Issue]
The calculateTotal() function mixes tax calculation,
discount logic, and database queries, making it difficult
to unit test and reason about.
[Helpful Solution]
Could we extract this into a PaymentService class? That
would make it testable and reusable. I can pair with you
on this if helpful."
When author disagrees with your feedback:
1. **Seek to Understand**
"Help me understand your approach. What led you to
choose this pattern?"
2. **Acknowledge Valid Points**
"That's a good point about X. I hadn't considered that."
3. **Provide Data**
"I'm concerned about performance. Can we add a benchmark
to validate the approach?"
4. **Escalate if Needed**
"Let's get [architect/senior dev] to weigh in on this."
5. **Know When to Let Go**
If it's working and not a critical issue, approve it.
Perfection is the enemy of progress.
## Summary
[Brief overview of what was reviewed]
## Strengths
- [What was done well]
- [Good patterns or approaches]
## Required Changes
🔴 [Blocking issue 1]
🔴 [Blocking issue 2]
## Suggestions
💡 [Improvement 1]
💡 [Improvement 2]
## Questions
❓ [Clarification needed on X]
❓ [Alternative approach consideration]
## Verdict
✅ Approve after addressing required changes
Weekly Installs
9.2K
Repository
GitHub Stars
32.3K
First Seen
Jan 20, 2026
Security Audits
Gen Agent Trust HubPassSocketPassSnykPass
Installed on
opencode7.3K
gemini-cli7.0K
codex6.9K
cursor6.5K
github-copilot6.4K
claude-code6.3K
React 组合模式指南:Vercel 组件架构最佳实践,提升代码可维护性
102,200 周安装