一文梳理 Code Review 方法论与实践总结

作为卓越工程文化的一部分,Code Review 其实一直在进行中,只是各团队根据自身情况张驰有度,松紧可能也不一,这里简单梳理一下 CR 的方法和团队实践。

为什么要CR

  • 提前发现缺陷
    在 CodeReview 阶段发现的逻辑错误、业务理解偏差、性能隐患等时有发生, CR 可以提前发现问题。

  • 提高代码质量
    主要体现在代码健壮性、设计合理性、代码优雅性等方面,持续 CodeReview 可以提升团队整体代码质量。

  • 统一规范和风格
    集团编码规范自不必说,对于代码风格要不要统一,可能会有不同的看法,个人观点对于风格也不强求。但代码其实不是写给自己看的,是写给下一任看的,就像经常被调侃的“程序员不喜欢写注释,更不喜欢别人不写注释”,代码风格的统一更有助于代码的可读性及继任者的快速上手。

  • 防止架构腐烂
    架构的维护者是谁?仅靠架构师或应用 Owner 是远远不够的,需要所有成员的努力,所谓人人都是架构师。架构防腐最好前置在设计阶段,但 CodeReview 作为对最终产出代码的检查,也算是最后一道关键工序。

  • 知识分享
    每一次 CodeReview,都是一次知识的分享,磨合一定时间后,团队成员间会你中有我、我中有你,集百家之所长,融百家之所思。同时,业务逻辑都在代码中,团队 CodeReview 也是一种新人业务细节学习的途径。

  • 团队共识
    通过多次讨论与交流,逐步达成团队共识,特别是对架构理解和设计原则的认知,在共识的基础上团队也会更有凝聚力,特别是在较多新人加入时尤为重要。

作为代码提交者

  • 发起时机:发起Code Review尽量提前,开发过程小步快跑

  • 代码行数:提交Code Review的代码行数最好在400行以下。根据数据分析发现,从代码行数来看,超过400行的CR,缺陷发现率会急剧下降;从CR速度来看,超过500行/小时后,Review质量也会大大降低,一个高质量的CR最好控制在一个小时以内。

作为代码评审者

代码逻辑

  • 功能完整:代码实现是否满足功能需求,实现上有没有需求的理解偏差,对用户是否友好;

  • 逻辑设计:是否考虑了全局设计和兼容现有业务细节,是否考虑边界条件和并发控制;

  • 安全隐患:是否存在数据安全隐患及敏感信息泄漏,如越权、SQL注入、CSRF、敏感信息未脱敏等;

  • 性能隐患:是否存在损害性能的隐患,如死锁、死循环、FullGC、慢SQL、缓存数据热点等;

  • 测试用例:单元测试用例的验证逻辑是否有效,测试用例的代码行覆盖率和分支覆盖率;

代码质量

  • 编码规范:命名、注释、领域术语、架构分层、日志打印、代码样式等是否符合规范

  • 可读性:是否逻辑清晰、易理解,避免使用奇淫巧技,避免过度拆分

  • 简洁性:是否有重复可简化的复杂逻辑,代码复杂度是否过高,符合KISS和DRY原则

  • 可维护性:在可读性和简洁性基础上,是否分层清晰、模块化合理、高内聚低耦合、遵从基本设计原则

  • 可扩展性:是否仅仅是满足一次性需求的代码,是否有必要的前瞻性扩展设计

  • 可测试性:代码是否方便写单元测试及分支覆盖,是否便于自动化测试

评审注意事项

  • 尽快完成评审

  • 避免过度追求完美

  • 明确评论是否要解决

  • 避免使用反问句来评价

我们主要是通过交叉CR、集中CR相结合的方式,由应用Owner+SM+架构师+TL完成。

  • 团队集中CodeReview尽量不要太正式和严肃,轻松的气氛下更有助于互相理解,来点水果,聊聊业务聊聊代码

  • 在Review过程有时候会陷入谁对谁错的争论,只要是为了寻求真理辩证的去看问题,哪怕是讨论再激烈也是有收获的,注意只对事不对人。

CodeReview后改动太大

  • 发布前发现问题多,改动太大,影响项目计划

  • 大项目要求编码前设计评审,小需求可以事先Review设计思路,避免最后的惊喜

  • 每次Review的代码行数最好控制在数百行以内

评审者没有足够时间

  • 评审者在任务安排上尽量预留好时间

  • 尽快评审,代码在百行以内及时响应,在千行以内当日完结

评审者不了解业务和代码

  • 代码提交人编写清晰的标题和描述

  • 有必要的情况下评审者需要了解PRD

  • 评审者需要提前了解系统和代码

Review建议未修改

  • 应用可以设置Review建议需全部解决的卡点,同时对于非必需修改的建议可以进行打标或说明

CR实践中发现的几个常见代码问题

可以参考《重构:改善既有代码的设计》,书中所列的22种坏味道在CR中基本都会遇到

代码重复

《重构》中对“Duplicated Code(重复代码)”的描述:

坏味道行列中首当其冲的就是Duplicated Code。如果你在一个以上的地点看到相同的程序结构,那么可以肯定:设法将它们合而为一,程序会变得更好。

代码重复的几种场景:

  • 一个类中重复代码抽象为一个方法

  • 两个子类间重复代码抽象到父类

  • 两个不相关类间重复代码抽象到第三个类

不要过度追求DRY,破坏了内聚性,实践中需要平衡复用与内聚

基本类型偏执

大多数编程环境都有两种数据:结构类型允许你将数据组织成有意义的形式;基本类型则是构成结构类型的积木块。结构总是会带来一定的额外开销。它们可能代表着数据库中的表,如果只为做一两件事而创建结构类型也可能显得太麻烦。

如果你有一组应该总是被放在一起的字段,可运用Extract Class(149)。如果你在参数列中看到基本型数据,不妨试试IntroduceParameter Object (295)。如果你发现自己正从数组中挑选数据,可运用Replace Array with Object (186)。

给我们的启示主要有两点:

  • 大部分业务场景和语言环境下,结构化类型导致的开销基本可以忽略

  • 结构化类型带来更清晰的语义和复用

分页查询

完全没有分页

分页size太大

超多分页慢SQL

以上 bad case 的SQL在超多页分页查询时性能极其低下,存在多次回表甚至Using Filesort的问题,在阿里巴巴编码规范中也有明确的规避方案,此处不展开。

猜你喜欢

转载自blog.csdn.net/qq_35789269/article/details/129034796