架构师技能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的主要内容,如果未能解决你的问题,请参考以下文章
架构师技能3-彻底深入理解和分析Java中内存溢出OutOfMemoryError
[架构之路-3]:架构师 - 软件架构师也是魔法师,架构师应具备的四大方面的技能