主题:如何在团队开展codeReview
团队规模在扩大,代码量在不断增长,对代码质量的控制势在必行,codeReview得搞起来,这道理大家都懂,只不过有人重视,有人无所谓,还有人开始的轰轰烈烈,最终却虎头蛇尾、流于形式
这其中自然是有诸多难处,但本质上还是取决于你对codeReview的价值认知,只有大家真切的从codeReview中得到好处了,认识到这个东西真的香,才有可能搞得好,不然你试试?
我们团队一直在搞codeReview,但是效果不太好,属于流于形式的那种(大家都厌倦了),不然怎么有我上场的机会呢。最近leader要求重新整一套codeReview方案,负责人是我
今天就跟大家谈谈如何制定团队codeReview方案,希望对大家有所帮助
前面说了,必须得大家一致认可cr的价值,才有可能搞得好,所以有必要说下之前我们在codeReview过程中遇到的一个比较大的痛点,据此引出关于codeReview的职责和价值探讨,达成一致后,再讨论下面的方案
我们不能为了cr而cr(下文简称codeReview为cr),那就很没意思了
之前我们主要是在上线前以会议的方式,集中进行cr
最大的痛点:基础问题消耗了很多的时间与耐心,大部分时间都在争论诸如代码风格、编码规范、代码逻辑等比较基础且重复出现的问题(比如命名、日志、异常处理等等)
当然了,还有些其他的痛点,后续会有介绍,这里就不展开了
反思:cr不应该成为保证代码风格和编码规范的手段,也不应该承担发现代码bug的职责,每个人提交review时,代码就应该是符合规范的、充分自测过的,这是默认值,是每个人自己的事
(ps:这不是说不能在cr中报告这些问题,只是说这不应该是cr的意图)
所以我们既然要搞cr,就不能用上面说的基础问题来分散了cr的注意力(这些问题应该由其他方案来保证,下文会说明)
职责与价值:cr的主要精力应该集中在代码的设计、可读性、可扩展性、可维护性、可复用性、耦合性。。这些方面
在发现和讨论这些问题的过程中实现知识共享,提升个人工程能力,同时提高代码质量
你会发现,可读性、可扩展性、可维护性、可复用性、耦合性等概念随处可见,他们都是评价代码质量的常用标准,是程序员内功的基本体现,也是写代码的终极目标,但是..真的好抽象啊!
如果可以在实践中不断讨论、思考这些问题,就可以最直接有效的加深对它们的理解,提高自己的工程能力,对个人来说,这就是cr的最大意义吧
试点项目
实行一个新的方案,试图上来就全面开展,难度不小,团队规模越大,这点尤为明显。可以选择一个试点项目,运行良好后再逐渐推广
项目选择上,应结合团队实际情况,如项目参与人数、人员能力高低、项目迭代周期、代码量等
reviewer人选(谁可以审查别人代码)
原则上所有开发人员都可以审查其他人的代码,这有助于塑造团队的技术氛围,但是编码能力会影响到review的效果,如果前期效果不好,可能导致方案夭折
所以前期选编码能力好的人,慢慢过渡成所有人
这也是检验cr效果的一个标准,如果符合预期,大家的工程能力一定是越来越好的,最终都能作为reviewer
由于前期reviewer人少,所以任务会重一点,能者多劳嘛,不过得让leader对此心里有数,多劳多得嘛
审查工具
取决于团队使用的代码托管工具,我司用的是gitlab,所以我们就基于gitlab,通过merge request在线审查、写comment、驳回、通过等操作来执行审查,可以满足我们的要求,就是分支合并操作多了些..
gitlab以外,市面上流行的像google开源的gerrit,facebook开源的phabricator,都是既可以代码托管、又可以代码审查的,你可以调研下
审查人数
分为一对一审查和大家一起审查两种方式,大家一起审查只能以会议的方式开展,存在会议固有的问题,需要所有人同时抽出时间、容易跑偏,而且会议上跟着coder的节奏看代码,审查质量往往难以保证
所以主要还是以一对一的形式审查,相对来说,reviewer可以按照自己的节奏,时间更自由,审查的质量也由其自行把握
会议方式也可以有,但主题就不完全是review了,还带有一定的分享性质
审查时机
设计时审查+代码入库前审查+代码入库后审查
设计时审查:
在设计阶段进行审查,主要是讨论代码的架构、设计、核心流程是否有问题,这些问题往往影响很大,提前发现可以有效避免后期返工、甚至推倒重来
在会议内容方面,应该尽量详细的展示设计思路和实现思路,包括架构设计、表设计、用例图、流程图等,核心流程最好附有类图
这些都是自由选择,不作具体限制,但原则是尽量全面的评审到设计方案、甚至是实现方案,也可以让reviewer充分了解后续要评审代码的上下文
至于代码是入库前还是入库后审查,这取决于是提测前还是提测后
提测前:代码不着急入库,reviewer可以在一定时间范围内自由选择时间审查代码,要求在入库前审查
这就要求coder不要等到快提测了疯狂提交review,而是每开发完一个小功能就提交
通常情况下,自测良好的代码,提测前的代码量远大于提测后的代码量,所以大部分代码会在入库前被审查
提测后:代码着急入库,要求入库前审查不太现实,只能入库后审查
对于gitlab用户来说,为了方便后续review,提测后也要求提merge request(可以自己提给自己),要求上线前reviewer找时间审查掉,如果是其他工具也要想好提测后的审查方案
审查范围
日常增量代码审查+定期全量代码审查
有些cr资料上还提出了审查范围的概念,分为增量代码审查和全量代码审查,平时的审查肯定是增量的,然后可以定期的检索存量的代码去审查
我们的做法是:定期举行晒码会,由负责人从存量代码中检索其认为可以优化的代码,在会议上发起讨论,并在会后修改上线
结合定期全量检索的方式,可以有效提高不良代码的曝光率和改善率
为了提高review的效率,以及reviewer的幸福感,有必要提出一些要求
代码基本质量保证
文章开头说了,每个人提交review时,代码就应该是符合规范的、充分自测过的。就称它为"代码基本质量保证",如何实现呢
规范是保证团队代码整齐度的重要手段,也可以避免很多低级问题,可以分为基础规范和团队规范
基础规范是通用的、可以由静态代码扫描工具扫描出的规范问题,不同的语言一般都有对应的扫描工具,像java的sonarlint,findbugs,p3c等
每个团队至少应选择一个静态扫描工具,并在团队宣传或者强制执行,要求在提交review前,coder已经解决了基础规范问题
有些公司会将这类工具和CI流程结合在一起,构建后触发静态扫描,不满足规范就不予通过,相当于强制执行了
团队规范是根据公司、团队自身情况定制的规范,比如分层习惯、公共API使用约束,线程池使用规范等
对此应该形成在线文档,长期维护,同样是多加宣传或者强制执行,要求coder保证代码是符合团队规范的
如何保证充分自测?只能是单元测试了,又是一个让人头痛的话题,就不展开了。总之,我们的原则是在提交前尽量减少bug
git commit质量要求
commit原子性、代码行数:commit原子性是指一个commit只做一件事,是一个不可分割的feature/fix/improved,在满足原子性的基础上,要求commit的代码行数不要太多(我们的标准是500行内)
commit说明:要求在commit说明中尽可能明确的表达提交代码的上下文,有些公司推行commit说明模板,你也可以参考
总之,不论哪种审查工具,都是依赖于git commit进行的,原子性、代码行数、说明这些都会直接影响审查者的体验,试想一下审查者看到一堆杂乱无关联的代码、上千行代码、逻辑复杂但毫无说明的代码时是什么感受
对于gitlab用户来说,commit之上还有merge request,一次merge request包含一个或多个commit,审查者基于merge request进行审查,所以merge request的频率和代码行数也要控制,这个没有标准,按团队情况来定
cr定期回顾与总结
开始实施cr流程后,定期回顾是非常必要的,防止走偏
可以通过人工调研+工具统计的方式跟进review的实际落地情况,持续优化
人工调研:通过访谈的方式,收集coder和reviewer在cr过程中遇到的问题、意见
工具统计:主流的cr工具都提供了众多可用于统计各类事件的api,比如commit大小、频率、意见数、驳回数等,这些指标可以帮我们发现很多问题