代码中的坏味道-重构改善既有代码的设计

3.1 重复代码(若是须要修改该段代码,那么须要修改不少地方,容易致使问题。不易维护。)算法

若是一个类的两个函数有相同的表达式,能够将表达式提炼成函数,两个地方分别调用这个函数。设计模式

若是是两个子类中有相同表达式,将表达式提炼成函数,推入超类。若是代码只是相似,提炼函数的时候须要将类似部分和差别部分分割,构成一个单独函数。其中可能能够运用塑造模板函数或这个模板方法设计模式。数组

若是有些函数以不一样算法作相同的事情,能够选择较清晰的一个,使用替换算法将其替换掉。函数

若是是两个绝不相干的类出现重复代码,能够考虑对其中一个提炼成新类,另外一个类调用这个新类。测试

3.2 过长函数 (函数过长通常说明函数作了太多的事情,违背了单一职责原则。将函数分解成更细粒度的函数,易于改造和使用。)设计

每当感受须要以注释来讲明点什么的时候,咱们就把须要说明的东西写进一个独立函数中,并用其用途命名。(代码比较难懂的时候)对象

百分之九十九的场合,要把函数变小,只须要使用提炼函数找到函数适合集中在一块儿的部分(除了提炼函数,还须要考虑函数存放的位置)继承

若是提炼函数的新函数中内存在大量临时变量和参数,能够经过用查询替代临时变量来消除临时元素(若是查询不耗费资源和时间,通常来讲建立临时变量须要分配额外的地址,建立太多临时变量会浪费不少系统资源,用查询替换临时变量会节省地址空间。固然不是说彻底不能使用临时变量,若是使用临时变量能够方便理解代码也可使用,可是慎用。太多临时变量可能会致使问题)。也可使用引入参数对象,或者保持对象完整来使过长的参数列变得简洁一些。接口

若是作了上述操做以后仍是有太多临时变量和参数,那就应该使用函数对象替代函数。内存

那些部分须要提炼

1、寻找注释,有注释的地方通常说明这个地方很差理解。而很差理解的缘由极可能是作了额外的事情。这就须要提炼出来

2、条件表达式和循环。条件表达式能够经过分解表达式来处理。循环和循环内的代码须要提炼成函数。

3.3 过大的类 (若是类须要作的事情不少,容易出现大量实例变量,那么紧接着就会出现大量重复的代码)

将几个变量提炼到新类,提炼的时候尽可能选择相关的变量。

若是一个类有太多代码,每每适合使用提炼类或者提炼子类。这里有个技巧,先肯定客户端如何使用,而后运用提炼接口为每一种方式提炼出一个接口。

3.4 过长的参数列(参数过多,函数使用成本变高,由于若是没有函数须要的参数就没法调用函数)

若是参数大部分来自一个对象,那么能够直接传入这个对象。从对象里获取参数。若是能够经过给对象发送请求能够获取参数,那么应该使用函数替换参数。使用保持对象完整未来自同一个对象的一堆数据收集起来,用该对象替换他们。若是数据缺少合理的对象归属,可使用引用参数对象来为他们建立一个”参数对象“

3.5 发散式变化 (将分裂成多个类,每一个类处理对应的变化)

针对某一外界变化的全部相应修改,应该发生在单一类中。新类的全部内容都应该反应此变化。应该找出某特定缘由形成的全部变化,而后运用提炼类将其提炼到新类。

3.6 霰弹式修改(将变化统一到同一个地方,统一修改,方便维护)

和发散式变化相反,若是遇到某个变化,须要修改的代码分布在四处,很难修改,并且容易忘记。应该使用移动函数和移动字段把全部修改的代码放到同一个类中,没有合适的类就建立一个。能够运用将类内联化将一系列行为放进同一个类。

发散式变化指一个类受多种变化影响,霰弹式修改指一种变化引起多个类修改。

3.7 依恋情结(将相关的类和函数放到一块儿,更容易管理)

函数对某个类的兴趣高过自身所在的类,某个函数调用其余类的大部分对象。须要将该函数移动到这个类中。若是只有一部分,那么将其提炼成函数再移动。

判断哪一个类拥有最多被此函数使用的数据,而后将这个函数放到该类中

3.8 数据泥团 (数据间有依赖关系,建立新对象更容易管理)

两个类中相同的字段,许多函数签名中有相同的参数,这些老是绑在一块儿的数据应该有本身的对象。

删除众多数据的一项,其余数据有没有失去意义,若是再也不有意义,那么就应该为他们产生一个新的对象。(说明这些数据之间有依赖关系)

3.9 基本类型偏执 (不要偏执于使用基础类型,有时须要建立新的数据类型)

若是有一组应该老是放在一块儿的字段,运用提炼类。若是参数列中有基本型数据,可使用引用参数对象,或者使用对象替换数组。

3.10 switch语句 (使用多态替换switch)

使用提炼函数将switch语句提炼到独立函数,将函数移动到须要多态性的类中。

3.11 平行继承体系(霰弹式修改的特例)

每当你为某个类增长一个子类,也必须为其余的类增长一个子类。让其余类的实例引用另外一个继承体系的实例。

3.12 冗赘类 (去掉没有做用或者做用很小的类,可使代码更清晰,简洁)

若是某些子类没有作足够的工做,能够试试折叠继承体系。对于几乎没用的组件,可使用将类内联化。

3.13 夸夸其谈将来性 (为了可维护性而作了一些操做,可是却没有用到,我的感受和冗赘类相似)

若是类和函数的惟一用户时测试用例,那么能够将其和测试用例一块儿删掉。

3.14 使人迷惑的临时字段 (和过长参数列中临时变量太多相似,太多临时变量会让人难以理解)

对象内的某个实例变量仅为某种特定状况而设,这样的的代码让人不易理解。可使用提炼类存放这些变量。

过长参数列中参数中临时变量太多也属于这种状况

3.15 过分耦合的消息链 (消息链中间有地方须要修改,就不易维护)

一个对象请求另外一个对象,另外一个对象再请求其余的对象。这就是消息链。

先观察消息链最终获得的对象时用来干什么的,可否以提炼函数把使用对象的代码提炼到一个独立函数,再运用移动函数将其推入消息链。

3.16 中间人 (太多无用委托会致使类关系变得复杂)

使用删除中间人去掉过分使用的委托。

3.17 狎昵关系 (类太亲密意味这某个类修改会影响另外一个类)

两个类太多亲密,可使用移动函数和移动字段划清界限。

3.18 殊途同归的类 (重复的工做只须要作一次)

若是两个类作同样的事情,可是名称不一样,那么去掉其中一个类,根据用途给另外一个类更名。

3.19 不完美的类库 

若是只想修改库类的一两个函数,能够运用引入外部方法。若是想添加一堆额外行为,运用引入本地扩展。

3.20 数据类 

拥有一些字段,以及用于访问这些字段的函数,除此以外没有做用

3.21 被拒绝的遗赠

若是子类复用了父类的行为,可是不支持父类的接口。用委托取代继承来修改这个子类。

3.22 过多的注释

 若是须要注释一块代码能够考虑提炼函数。若是已经提炼,可是仍是须要注释,那么能够考虑重命名函数。若是须要注释说明系统的需求规格试试导入断言。

相关文章
相关标签/搜索