如何做好 Code Review
问题
你们团队是怎么做 Code Review 的?你觉得好的 CR 应该关注什么?
回答思路
1. 为什么要做 Code Review
| 目的 | 说明 |
|---|---|
| 发现缺陷 | 另一双眼睛比自测更容易发现问题 |
| 知识共享 | 团队成员互相学习代码风格和技术方案 |
| 统一规范 | 保持代码库风格一致 |
| 提升质量 | 从设计层面提出改进意见 |
| 减少 Bus Factor | 至少两个人了解每段代码 |
提示
CR 不是"找茬",而是团队一起让代码变得更好。
2. CR 关注的层次
3. CR Checklist
作为 Reviewer
## Code Review 检查清单
### ✅ 功能正确性
- [ ] 逻辑完整,覆盖正常和异常路径
- [ ] 边界条件处理(空数组、null、undefined)
- [ ] 错误处理完善(try-catch、错误边界)
### ✅ 代码设计
- [ ] 函数/组件职责单一
- [ ] 没有过度设计,也没有设计不足
- [ ] 复用已有的工具函数/组件
- [ ] 新增文件的位置合理
### ✅ 代码可读性
- [ ] 变量和函数命名准确、一致
- [ ] 复杂逻辑有必要的注释
- [ ] 代码结构清晰,容易理解
### ✅ TypeScript 类型
- [ ] 类型定义完整,避免 any
- [ ] 使用合适的泛型和工具类型
- [ ] 类型导出位置合理
### ✅ 性能
- [ ] 没有不必要的重渲染
- [ ] 大数据量有分页或虚拟滚动
- [ ] 没有内存泄漏风险
### ✅ 安全
- [ ] 用户输入有验证
- [ ] 不存在 XSS 风险(如 dangerouslySetInnerHTML)
- [ ] 敏感信息不暴露在前端
作为 Author(提交者)
PR 提交前的自检:
## PR 描述模板
### What(做了什么)
简述变更内容
### Why(为什么这么做)
背景和技术方案说明
### How(如何验证)
- [ ] 本地测试通过
- [ ] 相关单元测试已添加/更新
- [ ] CI 检查通过
- [ ] 影响范围评估
### Screenshots(截图)
如有 UI 变更,附截图
4. 好的 CR 评论示例
❌ 不好的 CR 评论
// "这段代码有问题" ← 没说什么问题、怎么改
// "这样写不好" ← 没解释为什么、没给替代方案
✅ 好的 CR 评论
// 🔴 问题:这里直接拼接 HTML 可能产生 XSS 风险
// 建议:使用 DOMPurify 或 React 的 JSX 自动转义
// 参考:https://owasp.org/www-community/xss-filter-evasion-cheatsheet
// 💡 建议:这个函数已经有 50 行了,建议拆分为:
// 1. validateInput() - 参数校验
// 2. transformData() - 数据转换
// 3. formatOutput() - 格式化输出
// 这样每个函数职责更清晰,也更容易测试
// ❓ 疑问:这里为什么选择 useRef 而不是 useState?
// 如果有特殊原因,建议加个注释说明
5. CR 流程最佳实践
| 实践 | 说明 |
|---|---|
| PR 保持小 | 每个 PR 不超过 400 行,大需求分多次提交 |
| 及时 Review | 24 小时内完成 Review,不要 block 别人 |
| 最少 1 个 Approve | 至少一个人 Approve 才能合并 |
| 自动化兜底 | ESLint + 单元测试 + CI 门禁处理格式和基础问题 |
| 区分严重级别 | 🔴 Must Fix / 🟡 Suggestion / 🟢 Nitpick |
| 先整体后细节 | 先看整体设计,再看代码细节 |
常见面试问题
Q1: 你在 CR 中发现过什么典型问题?
答案:
举一个具体例子:
CR 中发现的内存泄漏
// ❌ 提交的代码 —— 组件卸载后定时器没清理
function PollingComponent() {
const [data, setData] = useState(null);
useEffect(() => {
const timer = setInterval(async () => {
const res = await fetchData();
setData(res); // 组件卸载后仍然 setState → 内存泄漏
}, 5000);
// 缺少 cleanup!
}, []);
return <div>{data}</div>;
}
// ✅ CR 后修正
function PollingComponent() {
const [data, setData] = useState(null);
useEffect(() => {
let active = true;
const timer = setInterval(async () => {
const res = await fetchData();
if (active) setData(res);
}, 5000);
return () => {
active = false;
clearInterval(timer);
};
}, []);
return <div>{data}</div>;
}
Q2: 团队抵触 CR 怎么办?
答案:
- 找原因:是觉得浪费时间?CR 评论太刻薄?还是 PR 太大导致 Review 困难?
- 降低成本:PR 保持小、自动化处理格式问题、提供 CR 模板
- 改善体验:培训 Review 技巧、约定评论礼仪(对事不对人)
- 展示价值:统计 CR 发现的 Bug 数量,让数据说话
- 以身作则:Lead 先做、做好,带动团队
Q3: 自动化能替代人工 CR 吗?
答案:
不能完全替代,但可以互补:
| 自动化 | 人工 |
|---|---|
| 代码格式 ✅ | 设计合理性 ✅ |
| 语法错误 ✅ | 业务逻辑正确性 ✅ |
| 简单 Bug ✅ | 架构层面建议 ✅ |
| 安全扫描(基础)✅ | 复杂安全问题 ✅ |
最佳实践:让机器做重复性检查,人聚焦在设计和逻辑上。AI Code Review 工具(如 CodeRabbit)可以进一步减少人工负担,但核心设计决策仍需人工判断。