重复代码(Duplicated Code)
1>同一个类的两个函数含有相同的表达式
解决方法:采用Extract Method提炼出重复的代码,然后让两个地点都调用被提炼出来的那一段
2>两个互为兄弟的子类内含相同表达式
解决方法:只需对两个雷都使用Extract Methid,然后再对被提炼出来的代码使用Pull Up Medthod,将它推入超类
3>代码只是类似,并非完全相同
解决方法:运用Extract Method将相似部分和差异部分分隔开,构成单独一个函数,然后可能可以运用Form Template Method 获一个Template Medthod设计模式
4>两个毫不相关的类出现相同代码
解决方法:考虑对其中一个使用Extract Class,将充分代码提炼到一个独立勒种,然后在另一个类使用这个新类
过长函数(Long Method)
程序越长约难理解,而间接层能带来利益:解释能力,共享能力,选择能力,这些能力都是由小型函数支持。小函数容易理解的真正关键在于一个好名字。我们积极的分解函数,应遵循这样一条原则:每当感觉需要以注释来说么点什么的时候,就需要把需要说明的东西写进一个独立函数中,并以其用途命名。
1>把函数变小,只需要使用Extract Method
2>提取函数时,参数和临时变量过多,可以运用Replace Temp With Query,Introduce Parameter Object和Preserve Whole Object可以将参数列变的更简洁一些
3>如何确定该提炼哪一段代码
- 寻找注释。如果代码前方有一行注释,就是在提醒你,可以将代码替换成函数
- 条件表达式和循环常常也是提炼的信号,可以使用Decompose Conditional处理条件表达式。至于循环,应当将循环和其内的代码提炼到一个独立函数中
过大的类(Large Class)
1>太多实例变量
解决办法:运用Extract Class 将几个变量一起提炼至新类内,提炼时应选择类内批次相关的变量。如果类内的数个变量有着相同的前缀或字尾,就可以考了将他们提炼到某一个组件内。如果组件适合作为子类,使用Extract Subclass比较简单
2>太多代码
解决方法:先确定客户端如何使用它们,然后运用Extract Interface的每一种使用方式提炼出一个接口,这样帮助我们看清楚如何分解类
3>是个GUI类
解决方法:需要把数据和行为移到一个独立的领域对象去。
过长参数列(Long Paramter List)
如果向已有的对象发出一条请求就可以取代一个参数。那么你应该激活重构手法Replace Paramter With Method。在这里“已有的对象”可能是函数所属类内的一个字段,也可能是另一个参数。还可以运用Preserve Whole Object 将来自同一对象的一堆数据收集起来,并以该对象替换它们。如果某些数据缺乏合理的对象归属,可以使用Introduce paramter Object 为它们制造出一个参数对象。
发散式变化(Divergent Change)
针对某一外界变化的所有相应修改,都只应该发生在单一类中,而这个新类的所有内容都应该反应此变化。为此,找出某特定原因而造成的所有变化,然后运用Extract Class将它们到另一个类中。
霰弹式修改(Shotgun Surgery)
1>每遇到某种变化,都必须在许多不同的类内做出许多小修改。
解决方法:使用Move Method 和Move Field把所有需要修改的代码放进同一类,如果没有合适的类可以安置代码,就创造一个。通常可以运用Inline Class把一系列相关行为放进同一个类。
divergent Change是指“一个类受多种变化的影响”,而Shotgun Surgery则指“一种变化引发多个类相应修改”。
依恋情节(Feature Envy)
某函数为了计算某个值,从另一个对象那里调用几乎半打的取值函数。
解决方法:用move method把这个函数移到另一个地点
如果一个函数用到几个类的功能,那么要移到哪里?判断哪个类拥有最多被此函数使用的函数,就把这个函数和那些数据摆在一起。最根本的原则:将总是一起变化的东西放在一块,数据和引用这些数据的行为总是一起变化的
数据泥团(Data Clumps)
两个类中相同的字段,许多函数签名中相同参数。这些总是绑在一起出现的数据真应该拥有属于它们自己的对象。首先找出这些数据以字段形式出现的地方,运用Introduce Paramter Object 或者 Preserve Whole Object 为他减肥。这么做的直接好处是可以将很多参数列缩短,简化函数调用。
基本类型偏执(Primitive Obsession)
编程环境中有两种数据:结构类型和基本类型。对象的一个极大的价值在于,它们模糊了横亘于基本数据和体积较大的类的界限。
对象新手通常不愿意在小任务上运用小对象,像结合数值和币种的money类,由一个起始值和一个结束值组成的range类。可以运用replace dats value with object将原本单独存在的数值替换为对象。如果想要替换的数据值是类型码,可以运用replace type code with class将它替换。如果有与类型码相关的条件表达式,可以运用 replace type code with subclass 或 replace type code with state/strategy 处理
Switch惊悚现身(Switch Statement)
Swith应考虑用多态来替换
先用Extract method 将switch语句提炼到一个单独函数,再以move method 将它移到需要多态性的那个类,此时需决定是否用 replace type code with subclass 或 replace type code with state/strategy ,完成继承结构以后,可以运用replace conditional with polymorphism