代码重构

关于重构
1.原因
编码之前缺乏有效的设计
成本上的考虑,在原功能堆砌式编程
缺乏有效代码质量监督机制
2.定义
重构(名词):对软件内部结构的一种调整,目的是在不改变软件可观察行为的前提下,提高其可理解性,降低其修改成本。
重构(动词):使用一系列重构手法,在不改变软件可观察行为的前提下,调整其结构。
3.大型重构和小型重构
4。代码的坏味道
1)代码重复
实现逻辑相同、执行流程相同
2)方法过长
方法中的语句不在同一个抽象层级
逻辑难以理解,需要大量的注释
面向过程编程而非面向对象
3)过大的类
类做了太多的事情
包含过多的实例变量和方法
类的命名不足以描述所做的事情
4)逻辑分散
发散式变化:某个类经常因为不同的原因在不同的方向上发生变化
散弹式修改:发生某种变化时,需要在多个类中做修改
5)严重的情结依恋
某个类的方法过多的使用其他类的成员
6)数据泥团/基本类型偏执
两个类、方法签名中包含相同的字段或参数
应该使用类但使用基本类型,比如表示数值与币种的Money类、起始值与结束值的Range类
7)不合理的继承体系
继承打破了封装性,子类依赖其父类中特定功能的实现细节
子类必须跟着其父类的更新而演变,除非父类是专门为了扩展而设计,并且有很好的文档说明
8)过多的条件判断
9)过长的参数列
10)临时变量过多
11)令人迷惑的暂时字段
某个实例变量仅为某种特定情况而设置
将实例变量与相应的方法提取到新的类中
12)纯数据类
仅包含字段和访问(读写)这些字段的方法
此类被称为数据容器,应保持最小可变性
13)不恰当的命名
命名无法准确描述做的事情
命名不符合约定俗称的惯例
14)过多的注释
5.问题
难以复用
系统关联性过多,导致很难分离可重用部分
难于变化
一处变化导致其他很多部分的修改,不利于系统稳定
难于理解
命名杂乱,结构混乱,难于阅读和理解
难以测试
分支、依赖较多,难以覆盖全面
6.评判标准
可维护性、可读性、可扩展性
7.重构遵循的原则
单一职责原则
一个类只负责完成一个职责或者功能,不要存在多于一种导致类变更的原因。

开放-关闭原则
添加一个新的功能,应该是通过在已有代码基础上扩展代码(新增模块、类、方法、属性等),而非修改已有代码(修改模块、类、方法、属性等)的方式来完成。

里氏替换原则
子类对象(object of subtype/derived class)能够替换程序(program)中父类对象(object of base/parent class)出现的任何地方,并且保证原来程序的逻辑行为(behavior)不变及正确性不被破坏。

接口隔离原则
调用方不应该依赖它不需要的接口;一个类对另一个类的依赖应该建立在最小的接口上。接口隔离原则提供了一种判断接口的职责是否单一的标准:通过调用者如何使用接口来间接地判定。如果调用者只使用部分接口或接口的部分功能,那接口的设计就不够职责单一。

依赖反转原则
高层模块不应该依赖低层模块,二者都应该依赖其抽象;抽象不应该依赖细节,细节应该依赖抽象。

迪米特法则
一个对象应该对其他对象保持最少的了解

合成复用原则
尽量使用合成/聚合的方式,而不是使用继承。
8.重构技巧
1)提炼方法
多个方法代码重复、方法中代码过长或者方法中的语句不在一个抽象层级。
方法是代码复用的最小粒度,方法过长不利于复用,可读性低,提炼方法往往是重构工作的第一步。

2)意图导向编程:把处理某件事的流程和具体做事的实现方式分开。
把一个问题分解为一系列功能性步骤,并假定这些功能步骤已经实现
我们只需把把各个函数组织在一起即可解决这一问题
在组织好整个功能后,我们在分别实现各个方法函数

3)以函数对象取代函数
将函数放进一个单独对象中,如此一来局部变量就变成了对象内的字段。然后你可以在同一个对象中将这个大型函数分解为多个小型函数。

4)引入参数对象
方法参数比较多时,将参数封装为参数对象

5)移除对参数的赋值
6)将查询与修改分离
任何有返回值的方法,都不应该有副作用

不要在convert中调用写操作,避免副作用

常见的例外:将查询结果缓存到本地

7)移除不必要临时变量
临时变量仅使用一次或者取值逻辑成本很低的情况下

8)引入解释性变量
将复杂表达式(或其中一部分)的结果放进一个临时变量,以此变量名称来解释表达式用途

9)使用卫语句替代嵌套条件判断
把复杂的条件表达式拆分成多个条件表达式,减少嵌套。嵌套了好几层的if - then-else语句,转换为多个if语句

10)使用多态替代条件判断断
当存在这样一类条件表达式,它根据对象类型的不同选择不同的行为。可以将这种表达式的每个分支放进一个子类内的复写函数中,然后将原始函数声明为抽象函数。

11)使用异常替代返回错误码

12)引入断言

13)引入Null对象或特殊对象

14)提炼类

15)组合优先于继承

16)优先考虑泛型

17)静态成员类优于非静态成员类

18)优先使用模板/工具类

9质量保证
测试驱动开发
1)定义
测试驱动开发(TDD)要求以测试作为开发过程的中心,要求在编写任何代码之前,首先编写用于产码行为的测试,而编写的代码又要以使测试通过为目标。TDD要求测试可以完全自动化地运行,并在对代码重构前后必须运行测试。
2)原则
仅在测试失败时才编写代码并且只编写刚好使测试通过的代码
编写下一个测试之前消除现有的重复设计,优化设计结构
关注点分离是这两条规则隐含的另一个非常重要的原则。其表达的含义指在编码阶段先达到代码“可用”的目标,在重构阶段再追求“整洁”目标,每次只关注一件事

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值