代码审查最佳实践
从一次“灾难级”合并说起:代码审查实践中的血泪与成长

作为一名技术负责人,我经历过无数次代码审查(Code Review)的拉扯。但印象最深刻的,是那一次几乎毁掉整个迭代版本的上线事故。
那是我在一家中型互联网公司负责一个电商后端系统重构时的事了。项目已经进入最后冲刺阶段,大家都处于疲劳作战的状态。某天晚上,一位核心开发提交了一个包含十几个文件修改的大 PR(Pull Request),说是优化了用户下单流程的整体性能。当时他急着下班去接孩子,自测通过后直接提了 Review 请求。
作为项目的负责人,我当时看了几眼觉得结构没问题,就匆忙点了 Merge。结果第二天凌晨,线上监控报警炸锅——部分用户的订单状态一直卡在“待支付”,而支付回调服务疯狂报错,日志里满屏都是 NullPointerException。
后来一查才发现,那位同学在改逻辑时,忽略了某个第三方 SDK 的调用规范,导致原本应该异步触发的操作变成同步阻塞,并且漏掉了异常处理机制。更糟糕的是,测试环境因为数据不全没有暴露这个问题。
这件事虽然最终我们紧急回滚解决了,但也让我们团队整整推迟了一周发版进度,产品和运营部门都炸了锅。从此我下定决心,一定要建立起一套行之有效的代码审查机制。
我们面对的问题:代码审查沦为形式主义
那次事件后,我开始认真思考我们的 Code Review 流程到底出了什么问题。
首先,Review 的节奏太松散。大家平时工作量大,谁也不会花太多时间去细看别人的代码,很多时候只是走个过场,快速点个 LGTM(Looks Good To Me)完事。
其次,PR 太大、改动太多。动辄几十甚至上百个文件的变更,根本没法仔细 review。Reviewers 看到这种 PR 第一反应就是头大,效率极低。
再者,缺乏有效工具支持。我们早期使用的 Git 平台功能非常基础,没有任何自动化检测机制,也没有集成 CI 流水线来辅助判断。
最重要的是,Review 文化不够成熟。很多新同事对 Code Review 的理解还停留在“挑语法错误”的层面,没人真正把它当作保障质量和知识共享的重要环节。
怎么做?我们尝试了这三板斧
第一板斧:拆小 PR,按业务原子性提交
我们先是强制规定了每次 PR 不得超过 30 个文件改动,超过这个数必须说明理由并拆分。刚开始大家很抵触,抱怨“这样反而麻烦”。但我们坚持了几轮之后,所有人都感受到了好处。
比如有一次,前端同学要重构登录页 UI 层次结构,同时还要加埋点。我们就要求他先把结构变动的部分先提一次 PR,确保不影响原有功能;然后再提一个新的 PR 加埋点逻辑。这样一来,Reviewers 能够聚焦在一个具体目标上,效率高很多。
我们还引入了一条硬性规则:每个 PR 必须附带清晰的描述内容,包括:改动目的、涉及模块、影响范围,以及相关联的任务编号(Jira/TAPD)。这些细节帮助我们建立起了基本的质量门槛。
第二板斧:使用工具提升审查效率
我们团队当时有两个选择:
- 继续使用 Gitlab 自带的 Review 功能 + Jenkins CI;
- 换成 GitHub + PullApprove 插件组合,加上 SonarQube 集成。
我们调研后发现,虽然 GitLab 已经能满足基础需求,但在权限控制、审批流定制方面不如 GitHub 成熟生态灵活。最终决定迁移到 GitHub。
迁移之后,我们做了这几件事:
- 每个关键服务设置至少 两位 Reviewer,其中一人必须是该服务的 Owner。
- 使用 GitHub Actions 集成单元测试覆盖率检查,如果低于 75%,自动 Block 合并。
- 配合 SonarCloud 实现静态代码扫描,对于严重问题直接在评论区提醒。
- 引入 DangerJS 做一些通用检查,比如是否写了 changelog、是否有未删除的 console.log。

这套工具链下来,我们在 Review 效率和质量之间找到了不错的平衡点。
第三板斧:打造 Code Review 文化氛围
光有制度和技术是不够的。我们还需要让每个开发者意识到:Code Review 不是为了找茬,而是为了共同进步。
为此我们做了几个小动作:
- 每周一例会抽出 10 分钟进行 “Code Review Highlight”,表扬优秀 PR 或指出典型反面案例;
- 新人第一次提 PR 必须由 Mentor 进行全程辅导式 Review,过程中传授审查要点;
- 对于被频繁提出问题的同学,我们会组织内部分享会,讲解常见问题模式;
- 所有线上故障复盘报告中,都会写一段“如果当时的 Code Review 更严格,是否能提前发现问题”。
慢慢地,团队里 Review 的氛围发生了变化。曾经那个“快点点 LGTM”的风气逐渐消失,大家开始主动讨论实现方式、边界条件、异常处理等等。
收效如何?真实数据说话
经过半年多的持续改进,我们收获了一些实实在在的变化:
| 指标 | 变化 |
|---|---|
| 平均 PR Size | 从原来的 58 文件下降到 21 文件 |
| 单次 Review 平均耗时 | 从 45 分钟降至 20 分钟 |
| 生产缺陷率(Bug per KLOC) | 下降 38% |
| 新人融入周期 | 缩短 26% |
更重要的是,在今年 Q3 的一次重大服务重构中,我们做到了零缺陷上线。Review 中发现的 12 个潜在隐患都被及时修复,大大减少了后期返工成本。
从这段经历中学到了什么?
如果你也在考虑怎么把 Code Review 真正落地,而不是流于形式,这里有几点建议送给你:
从小处着手,不要贪大求全
先抓 PR 的大小、描述规范、Review 人员分配这几个核心要素,等流程稳定后再上工具链。别迷信工具,文化才是关键
再好的自动化也不能取代人的判断,而高质量 Review 的本质,是建立一种相互尊重、持续学习的文化。避免“完美主义陷阱”
有些 Reviewer 总想找出所有可能的问题,甚至对变量命名也要“字斟句酌”。记住一点:Code Review 是帮人写出好代码,不是替别人重写代码。要有重点地关注影响大的地方,比如架构设计、安全边界、外部依赖等。鼓励双向交流,而非单向批评
Review 过程中尽量避免命令式语句,多用“你有没有考虑过……”、“这里是不是可以换成……”这样的提问方式。这样既容易让人接受,又能激发更多技术探讨。设定最低标准,逐步提升
初期可以只要求覆盖主路径,不做异常分支 review,后面再逐步增加检查维度。否则会让大家压力太大,反而抗拒这项机制。定期回顾,持续迭代流程
每个季度抽出一点时间来分析你们的 Review 数据、失败案例、常见问题,然后微调机制。流程是为团队服务的,不是一成不变的。
结尾说点感性的
这几年下来,我发现 Code Review 最大的价值其实不在“发现问题”,而是在人与人之间的思想碰撞中带来的成长。有时候一个不经意的评论、一个灵光一闪的想法,就能启发另一个更好的解决方案。
我也曾遇到那种“你这么写不行”的强硬 Reviewer,也曾收到过让我火冒三丈的评论,但事后回头一看,那些“被挑战”的时刻,恰恰是我成长最快的时候。
所以我想说的是,Code Review 不只是写代码的过程,更是我们作为一个团队如何一起变得更专业、更有凝聚力的关键。
希望这篇文章能给你带来一点点启发,哪怕只是一句话,也算我没白熬这次夜 😄。
如果你也有关于 Code Review 的故事或者实践经验,欢迎留言分享~

评论 0