提高代码质量的Tips
1. 如何重构
1.1 为什么要重构代码?
重构是一种对软件内部结构的改善,目的是在不改变软件的可见行为的情况下,使其更易理解,修改成本更低。
即 重构是指保持功能不变的前提下,利用设计思想、原则、模式和编程规范等理论来优化代码,修改设计上的不足,提高代码的质量。
如果没有维护,物体势必会往熵增加的方向去演变的。如果不做代码的维护,代码总归会往越来越混乱的方向演进,当混乱到一定程度,量变引起质变,项目的维护成本已经高过了重新开发一套新代码的成本,再去重构就会变得十分困难了。
1.2 重构的对象
- 大型重构
- 对顶层代码设计的重构
- 包括
- 系统
- 模块
- 代码结构
- 类与类之间的关系
- 重构的手段
- 分层
- 模块化
- 解耦
- 抽象可复用的组件
- 包括
- 对顶层代码设计的重构
- 小型重构
- 对于代码细节的重构
- 针对类,函数,变量等代码级别的重构
1.3 什么时候重构?
持续重构的概念,即没事情的时候,看看项目中有哪些写得不够好,可以优化的代码,主动去重构一下。或者在修改添加某个功能代码的时候,也可以顺手把不符合编码规范,不好的设计重构一下。
1.4 如何解耦代码?
解耦的目的
- 高内聚
- 松耦合
为什么需要解耦
- 控制代码的复杂性
- 使得我们可以聚焦在某一模块或类当中,不需要了解太多其他模块或类的代码
- 使得代码改动相对集中,引入bug的风险就减少了很多
如何判断是否需要解耦
- 在做修改的时候是否需要跨很多个包来进行改动
- 需要通过解耦的方式让依赖关系变得清晰,简单一些
如何进行解耦
封装与抽象
- 有效隐藏实现的复杂
- 隔离实现的易变性
- 给依赖的模块提供稳定易用的抽象接口
引入中间层
- 引入中间层能够简化模块或类之间的依赖关系
- 即我们可以让开发和重构同步进行
- 例如需要进行接口的修改
- 先引入一个中间层,包裹老的接口,提供新的接口定义
- 新开发的代码依赖中间层提供的新接口
- 将依赖老街口的代码改为调用新接口
- 确保所有的代码都调用新接口之后,删掉老接口
模块化
- 对于一个大型复杂系统来说,没有人能够掌控所有细节
- 通过划分成不同的独立模块,让不同的人负责不同的模块
- 这样即便在不了解全部细节的情况下,管理者也能够协调各个模块,让整个系统有效运转起来
- 将每个模块都当做一个独立的library来进行开发,只提供封装了内部实现细节的接口给其他模块使用,以此来减少不同模块之间的耦合度
遵循设计思想和原则
- 单一职责原则
- 基于接口而非实现编程
- 依赖注入
- 多用组合少用继承
- 迪米特法则
- 不应该有直接依赖关系的类
2. 代码的可测试性
做重构,如何保证你做的改动能够按照既定的想法运行,那么我们需要来写单元测试,来保证新的代码仍然能够通过,即原有的逻辑的正确性没有被破坏。
另外,单元测试的阅读实际上是快速熟悉代码的一种方式
一些常见的Anti-patterns:
- 未决行为
- 代码的输出是随机的,或者不确定的
- 全局变量
- 静态方法
- 复杂继承
- 高耦合代码
3. 编程规范
3.1 命名与注释
- 在足够表达含义的情况下,命名尽量短
命名时候的缩写,只对大家比较熟知的使用,减少阅读时候的障碍的感觉。
- 利用上下文简化命名
比如POJO当中,类名往往对这是个什么类做了定义了,成员变量就不用再添加类前缀了
- 命名需要可读,可搜索
英文上可读,方便发音,哪怕是第一次见到,也需要尽可能简单的能够直接读出来
另外需要遵从一些大家约定俗成的规范,即比如使用selectXXX 还是queryXXX 来表示选择,从数据库里面拿东西,一旦选定,就需要一起遵从规定了。
- 对于接口,抽象类的命名
对于接口的命名
- 加前缀I,比如IUserService
- 或者加后缀Impl, UserServiceImpl
抽象类的命名
- 加上前缀Abstract
- 或者不带
皆可,但是需要形式上的统一。
- 注释
目的
- 让代码更容易看懂
写什么
- 是什么,为什么,怎么办 三大问题
- 能够起到总结性和文档的作用
- 总结性注释也能够让整个代码更加清晰
在哪里写
- 一般来说是在类和函数上写注释
- 函数内部尽量通过好的命名,提炼函数,解释性的变量来提高代码的可读性
3.2 代码风格
- 类和函数的大小
软标准,只是要尽量注意,对于很大的类,最好将其分割开
- 一行代码的长度的限制,譬如100字符或者150字符
- 使用空行分割单元块
- 对于比较长的函数,如果逻辑上可以分为几个独立的代码块,可以使用空行来分割各个代码块
- 在类的成员变量和函数之间
- 静态成员变量和普通成员变量之间
- 各个函数之间
- 各个成员变量之间
- 缩进风格的统一
- 类当中成员的排列顺序
- 首先是类的所属包名
- 然后罗列import引入的依赖类
- 类当中
- 大原则
- 先静态,后普通
- 作用域从大到小来排序
- 成员变量
- 各种方法
- 大原则
3.3 编程技巧
- 将代码分割为更小的单元块
大部分人阅读代码的习惯都是先看整体再看细节,因为我们要有模块化和抽象思维,善于将大块的负责逻辑提炼成类或者函数,屏蔽掉细节
通过提炼函数,通过函数名字,直接读懂这段代码是做什么用的
- 避免函数参数过多
- 考虑函数是否职责单一,能否通过拆分多个函数的方式来减少参数
- 将函数的参数封装成对象
- 不要使用函数的参数(true/ false) 来控制逻辑,直接分成几个不同的函数会更好
- 函数的设计,职责单一
- 移除过深的嵌套层次
- 去掉多余的if else语句
- 使用continue break return等关键字,来提前退出嵌套
- 调整执行顺序来减少嵌套
- 将部分嵌套逻辑封装成函数调用,以此来减少嵌套
- 使用解释性变量
- 常量替代magic number
- 使用解释性变量来解释复杂表达式
转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 stone2paul@gmail.com
文章标题:提高代码质量的Tips
文章字数:1.9k
本文作者:Leilei Chen
发布时间:2020-05-25, 13:34:48
最后更新:2020-05-29, 08:49:33
原始链接:https://www.llchen60.com/%E5%85%B3%E4%BA%8E%E6%8F%90%E9%AB%98%E4%BB%A3%E7%A0%81%E8%B4%A8%E9%87%8F%E7%9A%84Tips/版权声明: "署名-非商用-相同方式共享 4.0" 转载请保留原文链接及作者。