架构师技能3:如何做code review

Posted hguisu

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了架构师技能3:如何做code review相关的知识,希望对你有一定的参考价值。

目前该文只是简单理论的总结,后续优化增加例子来说明。

前言


CodeReview的目的是提升代码质量,尽早发现潜在缺陷与BUG,降低修复成本,同时促进团队内部知识共享,帮助更多人更好地理解系统。

如何做好code review,可以参考谷歌 code review 指南。原文地址: https://google.github.io/eng-practices/review/reviewe

1、code review从大的方面来说:

1、业务层面:业务逻辑是否正确等相关内容。例如

     1)数据库字段的设计是否合理。

     2)业务流程是否按照详细设计的流程走。

     3)业务扩展性,设计是否影响后续业务的拓展。

2、代码层面:是否符合优秀特质。优秀代码--改善代码三部曲https://guisu.blog.csdn.net/article/details/7658644

没有“完美”的代码,只有更好的代码。由于每个团队的code review的方法论或者流程不一样,本文单纯从reviewer的角度来总结如审查提交的代码是否符合优秀的代码特质。

2、优秀代码说明

能做好code review,前提是reviewer理解什么是更好的代码。这是需要一定具备很强的编程能力,不仅需要熟练运用相关设计,还具备丰富编码实战经验。

 好代码就像 玩笑无需解释。

好代码的总体愿景指标是:

  • 代码整洁易读
  • 可维护性高
  • 可扩展性强
  • 高性能

但这些愿景指标都是宽泛笼统,没有具体的衡量指标。是一种团队内心的愿望,是脑筋的一幅图画,是一种驱动力,愿意实践、追求,来达到某一个境界,能追求到某一种成就。

再具体一点就是优秀代码的特质

•内聚Cohesive:  内聚的代码更容易理解和查找 bug

松耦合Loosely Coupled:  松耦合的代码让实体之间的副作 用更少,更容易测试、复用、扩展

•封装Encapsulated:  封装良好的代码有助于管理复杂度,  也更容易修改

•自主 Assertive:  自主的代码其行为和其所依赖的数据放在 一起,不与其它代码互相干预(Tell but not Ask)
• 无重复Nonredundant:  无冗余的代码意味着可以只在一个  地方修复bug和进行更改。
 

内聚:一个模块内各个元素彼此结合的紧密程度
耦合:一个软件结构内不同模块之间互连程度的度量。

松耦合:系统的模块与模块之间,尽可能的使其独立存在,也就是单一职责。
模块与模块之间的接口,尽量的少而简单。

高耦合:模块相互之间依赖性比较多,模块与模块之间的关系也比较复杂。导致的问题是一个模块出现了问题,其他功能模块都不能正常运行,然后定位问题也比较困难。

系统如何“高内聚、低耦合”?将程序积木化。

内聚性越强,则要求的函数越多(每个函数只作一件“事”),这样,将它们组合成“大”的功能,也就越复杂,就不可能达到松耦合。因此,应在二者之间作出平衡与折衷的选择,这也体现程序员的水平。

应该从系统论的角度来看:

首先系统是有层次的,即系统可以分为子系统。

其次模块化:模块可分为子模块。

“强内聚、松耦合”的“度”的把握,应结合系统的次层性来考虑,即通常应在层次性上作出折衷,如:模块内子程序(下一个层次上)应共享数据(有一定的耦合度),而减少全局变量能降低子程序性间的耦合性。

  面向对象的语言进一步强化了“强内聚、松耦合”,类的封装性既强调了相关内容(数据及其操作)的内聚,又强调了类的独立性和私密性。

比如类之间的关系,继承就组合的耦合性强,组合是类与类之间通常通过接口的契约实现服务提供者/服务请求者模式,这就是典型的松耦合。

3、优秀代码层面的code review 主要内容:

一、设计层面


1、功能性设计:

        是否符合功能性设计:如果存在代码和设计有出入的地方需要问询为什么要变动,因为这些变动有可能是出于开发者在真正设计代码时候的深入考虑,或者是由于一时大意出现偏差。

2、设计重构

      1)、抽象原则:两个方法有相似逻辑时,应该抽取相似逻辑,处理不同逻辑,而不是将相似的逻辑再写一遍。

      2)、模块化原则:模块划分确保是模块内具有高内聚度、模块间具有低耦合度,最终程序积木化。CR就要审查类的边界是否合理以及类和类直接的耦合程度。

      3)、封装原则:隐藏对象的属性和实现细节,仅对外公开接口,并且控制访问级别。code review主要审查成员变量的可见性,哪些方法应该是public,哪些方法应该是private。方法封装是否彻底。
      4)、层次结构原则:代码分层,让不同层次的代码做不同的动作。层次结构清晰的代码,提高可读性,从代码结构就大概能了解到代码是如何分层,每层大概功能是什么。例如常用的Controller、Service、Mapper/Dao三层代码结构,其各层的代码逻辑范围。CR的时候检查代码逻辑放在哪层是否比较合理,是否符合团队工程规范。java工程规范和浅析领域模型VO、DTO、DO、PO

3、设计原则

  设计模式原则详解很早之前的博文:《设计模式原则详解

一)、解藕原则:解决耦合性问题,尽少依赖外部。

     1、单一职责:CR就要检查类的职责是否过多,而方法尽量设计为干一件事。

     2、开闭原则:CR审查抽象类/接口是否合理。

    3、迪米特法则:在类的划分上、结构设计上、以及对其他类的引用是否合理。

二)、接口原则

    4、依赖倒置:依赖接口编程。是否符合面向接口编程的思想。

    5、接口隔离:接口分类和专职。

三)、继承父子原则:既有解藕又有接口。
    6、里氏替换原则:CR审查继承关系违反了里氏代换原则(尽量不要重写和重载父类的方法)。同时建议在程序尽量使用基类类型来对对象进行定义,而在运行时再确定其子类类型,用子类对象来替换父类对象 。

    7、合成/聚合原则。建议要尽量使用对象组合,而不是继承关系达到软件复用的目的

二、实现层面


1、一致性

     代码中使用的格式、符号、结构、命名等风格是否保持一致。

     1)比如命名的一致性问题:

      private UserRepo userDao;

     2)比如注释和代码的逻辑是否一致。

2、复杂性

     圈复杂度过高的方法应该分类抽离进行处理,适当的场景可以用多态代替分支。
      1)源文件不能有重复代码块

      2)控制流 "if", "for", "while", "switch", "try" 等不能嵌套太深

      3) 类之间不耦合或轻耦合

      4)类不能有太多方法

      5)类不能有太多域

      6)不能使用魔数

      7)"switch" 不能有太多的 "case"

   

3、命名

     1、编码规范只是规范命名规则,如使用驼峰命名法还是其他命名法;而好的命名风格应该是看到变量或者函数名字就能“望文生义”,毕竟我们不能把自己写的所有代码都做注释。        Java工程规范和浅析领域模型VO、DTO、DO、PO

     2、不论是类名,变量名,方法名都要有实际的意义。

     

4、可测性:

    1)、函数不能太复杂。

    2)、函数不能有太多参数。

    3)、表达式不能太复杂。

5、性能、并发、安全检查等等。

1)、字符串的连接操作应该考虑StringBuffer,StringBuilder。

2)、字符串的很多操作都可以用StringUtil工具类。

3)、是否采用通用的线程池、对象池模块等cache技术以提高性能,建议多线程中使用executors而不是task和thread。

4)、同步方法的使用是否得当,是否过度使用,建议并发同步代码的范围尽量小。
5)、 I/O方面是否使用了合适的类或采用良好的方法以提高性能(如减少序列化,使用buffer类封装流等)
-

三、规范层面


1、代码规范

      团队的编码规范。

2、文档和注释

      1)、团队要求完善的文档。

      2)、无用的逻辑要及时清理, 并且要清理干净,   避免造成干扰。

      3)、是否注释的代码。

以上是关于架构师技能3:如何做code review的主要内容,如果未能解决你的问题,请参考以下文章

架构师技能5:如何做code review 代码简洁之道

架构师成长之路--架构师必备技能(目标)

架构师技能3-彻底深入理解和分析Java中内存溢出OutOfMemoryError

[架构之路-3]:架构师 - 软件架构师也是魔法师,架构师应具备的四大方面的技能

ARTS打卡计划第6周-REVIEW-超越编码的避免项目失败的软技能

关于Code Review