背景
Code Reivew 的主要目的是通过逐步改善团队所输出的代码以确保整体代码结构的健康整洁与可演进。知微产品前端团队在Code Reivew 的近两年探索中,总结出一套适合小型研发团队的Code Reivew 实践,在前端团队内部良性运行一年多的时间内总共评审了近10000个commit,产生了800多个修改建议。随着Code Reivew 的有序推进,每次需要花费的时间和产生的修改建议都在减少。
本文通过全面复盘知微产品前端团队近两年的Code Reivew实践历程:从初次尝试到中途放弃,而后又再次拾起直至运用自如得心应手的过程。通过分析我们遇到的实际问题、改进思路与实践总结,期待能对正在探索的同行伙伴们有所启益。
缘起:Code Review 的那些好
有效的Code Review 可以对代码质量,代码规范,团队代码能力提升带来很大的提升。具体体现在以下几个主要方面:
避免重复造轮子,既节省了人力,又保证了代码逻辑和界面交互的一致性;
尽早发现设计问题,提升系统的可维护性,及早发现潜在缺陷,降低故事成本;
由于交叉审核代码,团队成员在编写代码时就会注意代码质量,避免提交低质量代码而被打回,长期下来可以提升整个团队的能力。
缘灭:为何频频挥别Code Review
海外许多卓越的技术公司都非常重视Code Review,也运行良好,例如Google,亚马逊。但是这一机制到了国内却频现“水土不服”,很多公司在践行Code Review 的时候步步艰难。落地的姿势不对,导致事倍功半,最终一拍两散。总结一下几种常见的情况:
因为 Code Review 导致团队成员之间相互指责,产生间隙,削弱整体凝聚力;
Code Review 流于形式,不仅没有提升代码质量,减少 bug,反而降低开发效率;
Code Review 确实产生了效果,但是因为流程太重,耗时太长,导致团队效率降低;
在我们践行Code Review 的过程中也遇到了以上问题,甚至因此一度放弃了Code Review,但最终还是根据我们的实际情况不断优化,找到适合我们的方案。下面就带领大家进入我们对Code Review 的探索过程。
01
浅尝辄止
在初次引入代码评审机制时,我们同样对其寄予厚望,期待尝到传说中的那些好,然而却事与愿违,最终不欢而散。
引入背景
彼时知微前端团队成员有4个,使用的技术栈主要是React、Type Script;由于知微产品团队的版本迭代速度比较快(两周一个迭代),因此采用的是基于Git工具的主干开发模式,所有的开发人员仅在一个主干分支上进行协作开发,一般不允许新建其他长期存在的开发分支,所有的代码提交均需要在主干分支上完成,要求commit尽量原子化,可回退,每天pull/push代码的频率尽可能高,确保开发环境始终以最新的代码运行。
在目前产品的开发过程中,知微前端团队主要按功能模块来划分人员开发任务,成员之间各司其职,各自沉淀;当然,在版本迭代过程中,遇到某些模块的需求过多,这些模块的负责人应付不过来,这时就会协调其他成员来支援。
最初并没有任何反馈的机制,每个人都只关注自己的代码,无意识也无暇关注其他人提交的代码,久而久之出现了一系列问题:
重复造轮子
代码风格千人千面,可读性差
代码质量参差不齐,包括复用度低、设计不合理、还在使用旧的 API、性能差等,最终导致需要对整个功能模块进行重构
缺陷未及时同步,同样的坑不同的人重复踩
随着时间的推移、产品的迭代与人员的变更,项目的维护成本越来越高,产品的质量愈加不可控。因此,我们决定引入Code Review 来规范我们的代码,防止问题愈演愈烈直至失控。
方案摸索
在讨论制定流程时,我们遇到了一些分叉口,具体落地有不同的形式,该如何选择?同时我们也意识到引入评审机制可能带来的潜在问题:
是否以 PR 的形式来进行 Code Review
Code Review 可能影响到团队开发效率
Code Review 可能会导致相互指责
问题1中,以PR的形式来进行Code Review 是比较传统的方式,但我们团队的迭代速度较快,有完善的CI/CD设施,开发环境始终保持最新代码有助于缺陷的左移,如果使用PR则必须等整个功能模块开发完成并通过Code Review 才能进入开发环境,无法达到小步快跑的目的,所以我们抛弃了这种形式,以主干分支上的每个commit来进行Code Review。
对于问题2,其实也是很多团队不做Code Review的共同原因:觉得浪费时间,降低了团队的研发效率。但长期下来项目代码越发混乱,频繁出现线上问题,然后开发人员疲于奔命修复线上事故缺陷。由此可见,虽然短期来看功能是快速上线了,但是考虑到修复和维护的时间,长期来看整体还是低效的。因此,采纳Code Review 需要团队管理者具备远见卓识,短期主义者难以投入其中。
问题3的话则需要遵守Code Review礼节,明确一个基本原则:对事不对人,同时避免只批评而不提供背景。换句话说,就是花些时间解释为什么出了问题,哪出了问题,以及如何解决问题。体现出对被评审者的尊重可以加强团队凝聚力,提高工程意识,并有助于统一对技术定义的理解。
最终我们大致制定了以下几点实践准则:
每天下午 5:00 开始 Code Review;
Code Review 的过程中由团队负责人投屏,针对当天提交的每一个 commit 所有人一起评审;
评审的代码主要包括代码风格和功能设计;
评审的过程标记下待修改的部分,提交者应事后进行处理;
无奈挥别
以上方案在我们团队内运行了大概3个月,令人遗憾的是,这一期间逐渐暴露出许多问题:
1.Code Review 整体过程耗时较长
评审的过程中过于注重需求细节,知微又是一个逻辑比较重的产品,每个成员每天都开发着不同的功能模块,经常遇到需要讲解自己代码背后的故事和设计,占用了大量的时间,导致Code Review整个流程平均下来最少也要一个小时,甚至有时达到了两个多小时。而这整个流程是全员全程参加的,也就是说整个团队每天必须花费一至两个小时在这上面,严重压缩了需求开发的时间,导致迭代的延迟。虽然有组织的理解与支持,但我们内部成员始终认为太费时间了。
2.高付出低收益
如果有与第一点的高代价相符的高收益或许还勉强可以接受,但实际上在每次的Code Review 上,大家最开始还能够全部精力投入,但因为代码背后的需求背景和设计过于复杂,并且整个过程中还有好几个需求,随着Code Review 的进行,每个人的脑力负担很重,注意力也就越来越分散,到了后面,可能就只剩需求负责人在自嗨,其他人可能(都在想下班后吃啥了)参与度不高。
3.难以形成良好的闭环
Code Review 的过程中,经过讨论得到的修改意见,会通过评论来标记,以便提交者进行修改和后续跟进,但因为我们采用的是主干开发模式,在Code Review之前代码就已经合并到主干分支的,并且可能已经通过了桌面检查和测试,这很容易降低提交者修改的意愿,同时也存在潜在的质量风险。
Code Review实行初期大家的热情还比较高,因此这问题还不存在,但随着时间的推进,问题不断积累,提交者和评审者的热情都大大地下降,最终导致了一堆修改意见的堆积。
以上种种原因,我们的Code Review 最终流于形式,于是经过讨论一致决定暂时先放弃Code Review。
02
破镜重圆
虽然初试Code Review 以失败告终,但不可否认整个流程下来,我们还是能从中获得一些收益:
避免了重复造轮子,提升了项目的可扩展性和可维护性
团队成员对其他人编写的代码有一定的了解
提升了代码的质量,由于会有人评审代码,所以提交者会有意识地提高编写代码的质量
而在放弃Code Review 的这段时间内,项目的代码明显又回到最初的状态。
于是我们想探索一种适合我们团队和业务发展,小步快跑模式的Code Review,尽可能在保留以上优点的同时消除存在的问题。
缩短Code Review 整体时长
通过复盘,整个Code Review 主要耗时在于:
团队全员一起对每个 commit 进行评审;
讲解 commit 背后的业务背景比较耗时;
针对问题1,我们提出了以下方案:
设置 Code Review 总负责人,由该人负责整体代码的评审;
将团队全员认可的人选取进 Code Review 负责人范围;
将每个的 commit 平均分配给提交人之外的 Code Review 负责人;
方案1 Code Review 负责人的负担会比较重,也会大量占用他的时间;
方案2 通过增加Code Review 负责人来降低负担,但每天的commit负担也不少,很难长期坚持下去并保持热情;
综合考量之后,最终我们选取了方案3,在方案2的基础上进行了优化,保证每人每天都能够一起参与,又降低了整体的负担和耗时;
如果团队有新人加入,则会给新人一个过渡期,在过渡期是以PR的方式进行开发,待功能开发完成后提PR,经过Code Review 后再合入主干分支,等新人水平达到标准并适应了团队的开发模式后再转变模式。
问题剥离,聚焦可覆盖范围
在第一次Code Review 实行过程中,大家对于自己不熟悉的功能模块的关注明显并不是很高,因此我们决定暂时将业务背景的讲解从Code Review 中移除,编码风格交给eslint/prettier等工具,只针对代码设计和一些无法通过工具约束的规则进行评审;对于比较核心的功能模块,另开专项会议对整个功能模块的设计和实现进行评审。
经过调整,每天Code Review 的耗时在15分钟至45分钟左右,相比原先大大缩短了时间,并且每个人的负担也减小了。
借力工具打通落地最后一环
为了能够整体地跟踪修改意见切实修缮代码以形成闭环,使用一些工具来记录跟进待修改记录是一种比较合适的解决方案。目前我们采用的是看板,通过看板将所有的修改意见记录下来,每次Code Review 都打开该看板,这样就能比较好地跟进所有修改意见的状态。
方案总结
通过以上的分析,最终我们基于第一次的Code Review 流程进行调整并制定了以下方案:
每天下午5:00通过工具提取当天所有人的commit,在Code Review 看板上生成每个commit对应的卡片,平均分给各评审者,卡片上显示提交者和评审者;
各评审者针对分配给自己的卡片对应的commit进行查看,有修改意见或疑惑就评论到对应的卡片上,并将卡片拖到【待讨论】,如果没问题则直接拖到【评审通过】;
所有卡片都评审完成后,再一起针对【待讨论】的卡片进行讨论或对齐,如果最终确定需要修改,则将该卡片拖至【待修改】,后续由提交者修改并拖到【待评审】,如果评审者通过了,则直接进入【评审通过】,否则重新回到【待讨论】阶段,待下次Code Review 重新对齐。
(图:借助知微优化代码评审落地)
运行效果
上述方案从去年下半年开始启动,至今运行良好,在这期间总共评审了近10000个commit,产生了800多个修改建议。并随着Code Reivew 的进行,每次需要花费的时间和产生的修改建议都在减少,团队所有人也从中有所收获:
避免重复造轮子,既节省了人力,又提高了代码逻辑的一致性;
提升系统的可维护性,及早发现潜在缺陷,降低事故成本;
由于交叉审查代码,每个人在编写代码时都会注意代码质量,避免提交低质量代码而被打回;
有助于团队成员间传递知识、互相学习,提升团队的整体工程实践水平;
Code Review 这一过程也是一个团队内部成员交流的过程,可以增进团队成员的感情,促进团队凝聚力提升。
03
小结
以上就是我们团队在Code Review 中的实践和总结。
尽管初次尝试没有达到理想的成效,但秉承对其理念的认可与追求工程技术不断改进的初衷,我们再次审视自身,结合实际情况,吃了一把成功的“回头草”。
Code Review关键还是要结合团队的具体情况选择合适的审查方式,动员团队的每一个成员参与其中,尊重各自的想法和意见,建立起所有人都能认同并践行的方式,并根据实际运行情况持续优化迭代,这样就能形成适合自己团队的一套Code Review 实践方法。
理论都是理想的,实践都是具体的。到底如何是好?只有做了才有答案。
作者|欧阳城,Agilean知微产品团队前端开发负责人
附录:知微产品简介
知微产品是一套企业级数字化管理和效能提升工具。借助知微,企业能够快速搭建内部人事合一的数字化管理与组织协同平台。支持对包括基础的工作协同、项目管理、团队部门管理、目标管理、团队效能分析、风险预警、行为分析、决策优化等功能在内的快速配置。覆盖产品研发、业务运营、人财事等全方位场景,致力于协助企业逐步构建数智化-效能提升管理闭环。
往期回顾
01
02
03
04