导图社区 31天重构
重构是持续改进代码的基础,是减少问题的关键,是写出优美代码的前提,是贯穿整个开发过程的事情。
编辑于2022-02-24 14:45:3531天重构
一般重构
封装集合
当业务需求只需要给调用者提供一个可读的集合(数据的查询和展示),我们就应该使用IEnumerable<T> 来代替IList<T>
因为IEnumerable只有数据的遍历功能,而IList具有对集合的所有操作
当集合作为返回参数时,应使用适合业务需求的集合类型,不宜提供过多的集合操作给调用者
避免给调用者提供业务外的接口
封装条件
当条件判断语句比较复杂时,我们可以根据检项是否需要参数来进行封装,如果检查项不需要参数,则可以将其提取为属性;如果需要参数,则将其提取为方法
过为复杂的条件判断语句会导致代码的可读性降低,难以清晰的传递判断意图
用布尔变量代替判断条件
适用于判断语句比较长,并且条件个数较多的情况
将复杂的判断逻辑封装为方法或是属性
分解大括号
尽快返回
把原来复杂的条件判断等语句用尽快返回的方式简化代码(如果某个条件判断可以得到结果,就尽快返回该结果)
节省阅读代码的时间;避免执行无效的逻辑;增强代码可读性
分解复杂判断
结合尽快返回技巧,减少大括号的嵌套使用
逻辑分析,尽快返回;控制大括号的嵌套层数(2层内)
避免双重否定
将代码中的双重否定修改为简单的肯定语句
"!"很容易被忽略和遗漏,导致逻辑错误,产生bug
增强代码可读性;方便维护
用"正向思维"去理解业务
使用条件判断代替异常
把没有必要使用的异常做的判断改为条件判断
没有"危险"代码,就没有避免使用try catch
流程控制语句、循环控制语句中避免使用try catch语句
异常发生的时候,进入到catch语句块,CLR需要创建异常对象,保存堆栈信息,逐层查找异常表,会较大的影响程序的性能
异常只在有"危险"代码的地方使用
重命名(方法、类、参数)
编码时给类,方法、参数等元素取一个有意义的名称
见名知意
方法、字段重构
移动方法
把方法放在合适的类中
当某个类的方法实现的功能更多地适用于另一个类,且符合它的语义时,就应该将该方法移到另一个类中
找方法的功能和对应功能的语义
提升方法、字段
把一个很多继承类都需要的方法、字段提升到基类中去
降低方法、字段
把基类中只有某些少数类要用到的方法、字段降低到对应的子类中去
提取方法对象
按照对象的语义(不同职责)进行隔离封装
便于精确类的职责,控制类的粒度
提取方法
如果一个方法包含多个逻辑,我们应该把每个逻辑提取出来,封装到一个小方法中,确保每个小方法只做一件事
分解方法
把某个大方法不停地分解,直到将它分解为名称有意义且可读性更好的若干个小方法
每个方法只做一件事
移除重复内容
把一些很多地方都用到的逻辑提炼出来,封装为方法,然后提供给调用者使用
方便维护,减少代码量
为布尔方法命名
如果一个方法中含有大量的布尔参数,可以将一些布尔参数提取出来,结合适当的方法命名来取代布尔参数
大量布尔参数导致方法不易被理解,给使用者造成困扰,产生预期之外的结果
引入参数对象
当一个方法有超过3个以上的参数,就应该把这些参数封装为一个单独的类
调用时更加干净整洁;参数有变动时不用动方法的参数列表
类、接口重构
用委派替代继承
当一个类依赖于另一个类并且他们之间不存在"父子"关系的时候,就应该采用委派
当一个类依赖于另一个类时,处理两个类的关系有两种方式:继承;委派
继承是一种强关联的关系
委派是一种若关联的关系
提取接口
当多个类要使用某一个类中的部分方法,就应该解开他们之间的依赖,让调用者使用接口
一种解耦策略
分解依赖
对部分不满足我们需求的类和方法进行分解(例如我们写单元测试只想测试功能本身,而不想测试他们依赖的代码)
在目标代码和需要被忽略的代码之间加一层进行隔离
分离职责
当一个类有许多职责时,应按照职责将它拆分为多个类,每个类承担"单一"职责
提取父类
超过一个类有相似的功能,应该提取到出一个基类,并将共同的功能放在基类中
提取子类
如果基类中的方法或属性不是所有子类都需要的,就应该将他们提取到对应的子类中去
合并继承
当所有的方法、属性完全适用于基类时,应该将这些方法和属性提取到基类,并移除子类
去除上帝类
把一个看似功能很强大很难以维护的类,按照职责把自己的方法、属性分派到各个类中或是分解成功能明确的类
去除中间类(去除中间人对象)
把在中间关联而不起任何作用的类移除,让有关系的两个类直接进行交互
使用多态代替条件判断
如果需要检查对象的类型或是根据不同的类型处理不同的逻辑和算法,就因该实用多态而非条件判断
设计模式
使用策略模式代替分支
实用策略模式来替换分子(switch case / if else)
分子固定,分子逻辑简单就没必要进行替换了
引入契约式设计
我们应该对输入和输出进行验证,以确保系统不会出现我们想象不到的异常和得不到我们想要的结果
提取工厂类
如果创建的对象很多,使用工程类是很适合的方法
Sean Chambers,Simone Chiaretta