提高代码质量的Tips
本文来源:http://r6d.cn/HPg4
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 -
使用解释性变量来解释复杂表达式
墙裂推荐
【深度】互联网技术人的社群,点击了解!
如果资源对你有帮助的话
❤️ 给个 「在看」 ,是最大的支持❤️