代码审查的真相:大多数CR流程都在浪费时间

前几天团队来了个新人,看到我们的CR流程后很兴奋:"你们的Code Review好规范啊,每个PR都要两个Approver才能合并。"我笑了笑没说话。

因为我知道,这套看起来"规范"的流程,实际上每天都在发生这样的事情:开发者提交一个几百行的PR,半天没人review;着急上线就去钉钉群里@几个人;被@的人打开看一眼,觉得代码没大问题就点了Approve;测试环境跑了一遍没报错,代码就合并了。

整个过程看起来很严谨,实际上谁也不知道这段代码到底干了什么。

 

大多数CR都是形式主义

 

我见过太多团队把Code Review当成一种"仪式感"——必须要有这个环节,但没人在乎它到底有没有效果。

最常见的场景是:PR提交后,reviewer们象征性地打开看一眼,扫过去没发现明显的bug或者格式问题,就点了Approve。至于这段代码的设计是否合理、是否有更好的实现方式、是否会给系统带来潜在风险,没人去深究。

为什么会这样?因为review代码比写代码累。

写代码的时候,思路是连贯的,上下文都在脑子里。但review的时候,你要先理解需求背景,再理解代码逻辑,还要判断这个实现是否合理,这个过程需要大量的认知负荷。而大部分reviewer手上都有自己的任务要做,不可能花大量时间去深入理解别人的代码。

于是CR就变成了一种"集体责任转移"——我review了,我点了Approve,出了问题不能怪我。

 

PR越大,CR越没用

 

我看过最离谱的一个PR,改动了50多个文件,新增3000多行代码,涉及前后端多个模块。提交者在PR描述里写:"重构了xxx功能,优化了性能"。

这种PR根本不可能被认真review。

首先,没人有时间读完3000行代码;其次,即使读完了,也很难判断这些改动是否合理,因为缺少对原有代码的完整理解;最后,即使发现了问题,reviewer也不愿意提太多意见,因为改动太大了,提了意见意味着作者要花大量时间返工。

所以大家心照不宣地选择了"睁一只眼闭一只眼"——反正测试环境跑起来了,没报错,那就合并吧。

但问题往往就埋在这里。这种大规模重构带来的问题,往往不是逻辑bug,而是架构层面的问题:增加了模块间的耦合、破坏了原有的抽象、引入了不必要的复杂度。这些问题在短期内看不出来,但会在未来持续消耗团队的时间和精力。

我的观点是:如果一个PR超过500行代码,那它基本上不可能被有效review。与其让reviewer走个过场,不如拆分成多个小PR,每个PR只解决一个明确的问题。

 

时机比流程更重要

 

很多团队把CR流程设计得很复杂:必须要两个Approver,必须要测试通过,必须要符合代码规范,必须要没有conflict……但很少有人去思考一个更基本的问题:什么时候做CR?

大部分团队的CR发生在代码写完之后。这是最糟糕的时机。

因为这个时候,代码已经成型了,架构已经确定了,作者已经投入了大量时间。如果这时候reviewer提出"这个设计不合理,应该换个思路",作者的心理压力会非常大——换思路意味着之前的工作白做了。于是大部分情况下,作者会选择"局部修改"而不是"推倒重来",哪怕他自己也知道这个设计有问题。

更好的方式是:在开始写代码之前就进行review。

我们团队现在的做法是:对于复杂的需求,开发者先写一个技术方案文档,描述清楚要做什么、怎么做、为什么这么做。然后找相关的人讨论,听听大家的意见。这个阶段的讨论可以随意得多,因为还没有代码,推翻重来的成本很低。

等到真正写代码的时候,大方向已经确定了,剩下的就是实现细节。这时候的CR就会轻松很多,因为reviewer只需要关注"实现是否符合设计",而不需要重新思考"这个设计是否合理"。

 

并不是所有代码都值得review

 

这是一个很不政治正确的观点,但我觉得是真的:有些代码根本不值得review。

比如简单的文案修改、样式调整、配置变更,这些改动的风险很低,逻辑也很清晰,没必要拉两个人过来点Approve。与其浪费大家的时间,不如直接合并,出了问题再回滚就是了。

再比如一些实验性的代码,本来就不确定能不能work,需要快速试错。这时候严格的CR流程反而是障碍,会拖慢迭代速度。更好的方式是:先合并,快速验证,然后再根据反馈决定是继续还是回滚。

真正需要认真review的,是那些"不容易回滚"的代码:数据库schema变更、核心算法修改、公共组件升级、架构调整……这些改动一旦上线,回滚的代价很高,所以必须在合并之前就确保没有问题。

我们团队现在的做法是:给每个PR打标签,标明风险等级。高风险的PR必须要两个senior以上的人review;中风险的PR只需要一个人review;低风险的PR可以self-merge,但要在群里知会一声。

这样做的好处是:大家的时间都花在刀刃上,真正需要关注的代码得到了充分的review,而不重要的代码不会占用太多精力。

 

工具不是问题,人才是

 

很多团队觉得CR效果不好,是因为工具不够好。于是花大量时间引入各种静态检查工具、自动化测试工具、代码质量扫描工具……但往往效果不明显。

因为工具只能解决"显性问题":代码格式不对、潜在的null pointer、没写测试……但解决不了"隐性问题":设计是否合理、抽象是否恰当、是否有更好的实现方式。

后者才是CR真正的价值所在。

我见过一些团队,CR流程非常简单,就是几个人坐在一起,过一遍代码,边看边讨论。没有复杂的流程,没有强制的Approver数量,但效果很好。因为大家的关注点是"这段代码是否能更好",而不是"这段代码是否符合规范"。

也见过一些团队,CR流程非常严格,但每个reviewer都只是走个过场,点个Approve就完事了。因为大家的关注点是"不要耽误进度",而不是"代码质量"。

所以问题不在工具,在人。或者更准确地说,在团队文化。

如果一个团队真的在乎代码质量,哪怕没有任何工具,大家也会主动去review代码,主动去提意见,主动去思考"有没有更好的方式"。但如果一个团队只是把CR当成一个流程环节,那再好的工具也救不了。

 

我的建议

 

如果你正在负责一个团队,想让CR变得更有效,我的建议是:

先问问团队成员:你们觉得现在的CR有用吗?如果没用,是哪里出了问题?

不要急着改流程,先搞清楚问题出在哪里。是PR太大了?是reviewer没时间?是缺少上下文?还是大家根本不在乎代码质量?

然后再针对性地调整。可能是要求PR必须拆分到一定大小;可能是要求提交PR之前先写技术方案;可能是引入"CR时间",每天固定一个时间段专门用来review代码;也可能是调整团队文化,让大家意识到代码质量的重要性。

但不要指望通过增加流程环节来解决问题。大部分情况下,流程越复杂,执行越打折扣。

 

最后

 

Code Review本身是个好东西,但被误用的Code Review比没有还糟糕——它给了团队一种"我们很规范"的错觉,但实际上并没有带来价值。

如果你的团队现在每天都在进行形式主义的CR,也许是时候停下来想想:我们到底在review什么?这个过程到底有没有用?能不能换个方式?

有时候,少做一些无用的事情,比多做一些无用的事情更有价值。

You voted 5. Total votes: 34

添加新评论