Code Review 失败后总结的几个实践技巧

{"type":"doc","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"资深的程序员都知道 Code Review 可以对代码质量,代码规范,团队代码能力提升带来很大的提升,还有著名的技术专家“左耳朵耗子”也说过:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"blockquote","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"我认为没有 Code Review 的公司都没有必要呆(因为不做 Code Review 的公司一定是不尊重技术的)"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"- 出自《程序员的练级攻略 - 修养篇》"}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"国外很多技术公司都非常重视 Code Review 也都做的特别好,例如 Google,亚马逊,但是国内很多公司在践行 Code Review 的时候却是步履蹒跚,步步艰难,选用的方法不对,最终导致事倍功半的结果,总结一下我见过的几种情况:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"bulletedlist","content":[{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"因为 Code Review 导致团队成员之间相互指责,团队凝聚力产生间隙"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"Code Review 形式化,没有提升代码质量,减少 bug,反而降低开发效率"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"Code Review 确实产生了效果,但是因为流程太重,导致团队效率降低"}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"我们也在践行 Code Review,探索的路上也遇到一些障碍和经验,总结分享一下,如果你也遇到这些问题,或许可以花一点时间读一读这篇文章,说不定会有帮助。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"Code Review 能带来哪些好处,本文就不说了,大家都很熟悉了,本文主要简单说一下 Code Review 有哪几个基本的共识和原则:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"numberedlist","attrs":{"start":"1","normalizeStart":1},"content":[{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":1,"align":null,"origin":null},"content":[{"type":"text","text":"Code Review 高效的原则是用机器去做大部分的事情"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":2,"align":null,"origin":null},"content":[{"type":"text","text":"Code Review 的时机(天时地利人和)"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":3,"align":null,"origin":null},"content":[{"type":"text","text":"推行 Code Review 的关键原则"}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"Code Review 高效的原则是用机器去做大部分的事情"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"不同的语言的格式和风格都是比较固定的,例如我最熟悉的 Java 语言常见的风格有以下几种规范:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"numberedlist","attrs":{"start":"1","normalizeStart":1},"content":[{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":1,"align":null,"origin":null},"content":[{"type":"link","attrs":{"href":"https://www.oracle.com/technetwork/java/codeconvtoc-136057.html","title":""},"content":[{"type":"text","text":"Order Java SE 的标准规范:https://www.oracle.com/technetwork/java/codeconvtoc-136057.html "}]}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":2,"align":null,"origin":null},"content":[{"type":"link","attrs":{"href":"https://google.github.io/styleguide/javaguide.html","title":""},"content":[{"type":"text","text":"Google Java 开发规范: https://google.github.io/styleguide/javaguide.html"}]}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":3,"align":null,"origin":null},"content":[{"type":"link","attrs":{"href":"https://github.com/alibaba/p3c","title":""},"content":[{"type":"text","text":"阿里巴巴 Java 开发手册:https://github.com/alibaba/p3c "}]},{"type":"text","text":" (国内常用)"}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"还有我最近常用的 Ruby 语言,官方所推崇的几种风格规范:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"numberedlist","attrs":{"start":"1","normalizeStart":1},"content":[{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":1,"align":null,"origin":null},"content":[{"type":"link","attrs":{"href":"https://github.com/rubocop-hq/ruby-style-guide","title":""},"content":[{"type":"text","text":"Ruby Style Guide:https://github.com/rubocop-hq/ruby-style-guide"}]}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":2,"align":null,"origin":null},"content":[{"type":"link","attrs":{"href":"https://github.com/airbnb/ruby","title":""},"content":[{"type":"text","text":"Airbnb Ruby Style:https://github.com/airbnb/ruby"}]}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"但凡是标准规范都是比较机械化的条条框框,应该交给机器去检查(常用的工具由:P3C,Rubocop,SonarQube 等),机器静态扫描效率不仅比人高出一个数量级,而且非常严谨,不容易出错,"},{"type":"text","marks":[{"type":"strong"}],"text":"甚至可以武断的说:所有的自动化工具的本质,都是为了要减少对人的依赖性"},{"type":"text","text":",因为人本身是具备很多种不确定性,所以并不适合做一些需要确定性并且反复重复的事情"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"Code Review 的时机(天时地利人和)"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"在以往的工作经验中,"},{"type":"text","marks":[{"type":"strong"}],"text":"Code Review 越是靠左移,修改代码的成本越低,开发人员的修改意愿也就越高"},{"type":"text","text":",那什么叫左移?"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"我们看一下软件开发的流水线和个人认为最合理的 code review 时机:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/fc/fc74675de2b45bec1cd1bbd4efce0ad3.png","alt":"常规的开发流水线","title":null,"style":null,"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"软件工程的开发流水线(图)"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"从流水线上来说,有些人会在临近上线,"},{"type":"text","marks":[{"type":"strong"}],"text":"在靠右的地方"},{"type":"text","text":"合并 master 的时候才进行 code review,这个时候修改成本就很高,因为代码已经测试过,如果因为 code review 有问题需要重新修改代码,那么"},{"type":"text","marks":[{"type":"strong"}],"text":"功能本身又要回归测试,占用的测试双倍的时间,对于人力资源是双倍的浪费"},{"type":"text","text":",因为已经临近上线,却因为 code review 被打回,开发人员愿意重构代码的意愿也会很低,如果明明发现问题,又因为上线压力,不打回不符合规范的代码,那么久而久之大家失去对 code review 的敬畏心理,code review 也会慢慢变成形式化,应用发布流程而已,既不能提高代码质量,降低系统 Bug,也不能提升开发人员的水平,反而降低的开发团队的效率,所以"},{"type":"text","marks":[{"type":"strong"}],"text":"选择在上线前进行 code review 不是一个好主意"},{"type":"text","text":",所以从性价比上来说 code review 最好的时机应该是在 "},{"type":"text","marks":[{"type":"strong"}],"text":"功能分支自测完成后,需要合并到 develop 分支申请提测前"},{"type":"text","text":" 通知项目组成员对增量的代码进行 code review。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"所以,代码审查要高效的话,核心就是要追求"},{"type":"text","marks":[{"type":"strong"}],"text":"快速反馈"},{"type":"text","text":",越早发现代码问题修改的成本就越低,具体参考下图:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/62/62a1aa34f8c4959ffcb33a36b468a433.png","alt":"极客时间-研发效率破局之道(图)","title":null,"style":null,"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"这里需要注意的是,代码在经过机器扫描后("},{"type":"text","marks":[{"type":"strong"}],"text":"这里有一个技巧就是可以在 GitLab CI 加入自动的代码风格检查,代码静态扫描是一个高频操作,一天可能会有几十,甚至上百次的 Commit,如果接入 GitLab CI 实现自动化静态扫描,大家不需要在自己本地执行静态扫描,那么效率也会大大的提升"},{"type":"text","text":"),项目组成员只需要把注意力放在 "},{"type":"text","marks":[{"type":"strong"}],"text":"代码逻辑结构,功能设计的可维护,可扩展性 等机器不容易发现问题的地方上"},{"type":"text","text":",然后就完成代码审查。因为代码还未提测,所以就算 Merge Request 不合格被打回后,因为还未提测,也不会占用测试人员的资源,开发人员的修改意愿也会更高,总体来说是可以达到高效和质量的要求"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":5},"content":[{"type":"text","text":"Code Review 要计入开发的工作量"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"很多团队不做 code review 都有一个共同的原因是觉得"},{"type":"text","marks":[{"type":"strong"}],"text":"浪费时间"},{"type":"text","text":",结果导致糟糕的代码合并入库,频繁出现线上问题,然后开发人员疲于奔命的去修复线上事故 BUG,虽然短期来看功能是快速上线了,但是算上覆工的时间,"},{"type":"text","marks":[{"type":"strong"}],"text":"长期来看整体的交付周期还是被拉长了,整体还是低效的"},{"type":"text","text":",而且糟糕的生产质量人很容易打击开发人员的持续生产高质量代码的信心,所以"},{"type":"text","marks":[{"type":"strong"}],"text":"将 code review 计入开发的工作量是重视长期利益的一种做法,也是 code review 能够成功落地的重要前提"},{"type":"text","text":",从团队管理的角度来说,不计入工作量的事情就不会被重视,不被重视的话那么 code review 最终在团队只会被废弃或者流于应付形式,并未发挥作用。也是很多团队推行 code review 失败的原因。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"推行 Code Review 的关键原则"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"想要在审核代码的时候,避免团队成员因为某些模糊不清的细节争论不休的情况,那么就要提前让团队建立对代码审核的原则和方法达成共识,我就曾经见过团队的技术人员在代码审核的时候因为某个函数方法的实现方式争吵不休,各自都认为自己的实现是正确的,那么提前建立一下这种共识:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":5},"content":[{"type":"text","text":"相互尊重原则"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"站在代码作者的角度:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"numberedlist","attrs":{"start":"1","normalizeStart":1},"content":[{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":1,"align":null,"origin":null},"content":[{"type":"text","text":"审核人花费时间和精力阅读他不熟悉的代码,并且帮忙指出代码中的问题来帮助代码作者提高,代码作者应该尽可能的为审核人提供配合和方便"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":2,"align":null,"origin":null},"content":[{"type":"text","text":"代码作者提交高质量的代码,就是对审核人和审核团队的最基本尊重(提交一堆乱如麻花的代码,没有自测错误百出的代码是极度不负责任的表现)"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":3,"align":null,"origin":null},"content":[{"type":"text","text":"最好要有清晰的 commit 历史,让人可以一目了然代码的提交内容,如果代码过度复杂,那么就需要和审核人面对面沟通,才能足够的高效"}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"站在代码审查者的角度:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"numberedlist","attrs":{"start":"1","normalizeStart":1},"content":[{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":1,"align":null,"origin":null},"content":[{"type":"text","text":"一定要懂得相互尊重,提出建议要懂得换位思考,考虑代码作者的感受,不要用主观的批评或者情绪化的语气指责团队的同事"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":2,"align":null,"origin":null},"content":[{"type":"text","text":"提出代码改进建议,必须是基于事实,或者明确的代码规范文档,不可强行把个人喜好强加在对方身上(例如用不同的语法实现相同的功能 for/while )"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":3,"align":null,"origin":null},"content":[{"type":"text","text":"不要钻进代码的牛角尖和抠细节,人工审查更多的要把精力放在代码逻辑,功能设计等无法扫描的问题上"}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":5},"content":[{"type":"text","text":"建立共识"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"站在团队的角度:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"numberedlist","attrs":{"start":"1","normalizeStart":1},"content":[{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":1,"align":null,"origin":null},"content":[{"type":"text","text":"code review 的目标长期来看,收益是提升团队的项目质量,减少团队陷入反复修复 bug 的困境中,让团队有机会去面对更多的挑战"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":2,"align":null,"origin":null},"content":[{"type":"text","text":"code review 对个人和团队而言都是成长的机会,放下不必要的自尊心,要用开放的包容的心态去接受不同的意见,取其精华"}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"总结"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"以上就是我个人和团队在 code review 中的实践和总结,Code Review 关键还是要结合团队的情况选择合适的审查方式,如果团队追求敏捷开发,快速迭代那么集中式的代码审查会可能就不太适合你们当前的团队,可能项目成员 1 对 1 的结对编程可以更加高效的完成代码审查,每个团队的发展阶段不同,适用的 GitFlow 开发流程也不同,反正没有最好的工具,最有最合适的工具。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}}]}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章