重构时机----寻找代码的坏味道
2015-04-30 15:22
337 查看
一、Duplicated Code(代码重复)
保证实现只有一份。
如果你在一个以上的地点看到相同的程序结构,那么可以肯定,设法将它们合而为一。
1.同一个类的两个函数含有相同的表达式
重构方法:Extract Method
提炼出重复的代码封装成函数,让这两个地点都调用提炼出来的函数。
2.互为兄弟的子类含有相同(相似)的表达式
重构方法:1.Extract Method,2.Pull Up Method 3.依据情况使用单独的继承/Template Method
3.两个不相关的类出现Duplication Code
重构方法:1.Extract Class
将重复的代码提炼到一个独立类中,然后在另外一个类中使用这个新类。
二、Long Method
短小结构良好的函数价值
解释能力,共享能力,选择能力
重构场景:1.感觉代码需要以注释来说明逻辑和功能时候,我们就需要把不同的注释阶段代码写入独立的函数,并以他们的用途命名
2.函数内部有大量的参数和临时变量,会对函数的提炼形成阻碍,这个时候就要想办法减少变量的个数
重构方法:1.Extract Method 2. Replace Temp With Query 3. Introduce Parameter Object 4. Perserve Whole Object
5.Replace Method with Method Object
三、Large Class(过大的类)
别让单个类做太多的事情,往往会导致Duplication 和 太多实例变量
重构方法:1.Extract Class,将类中彼此相关的变量和方法放入一个新类
2.Extract SubClass,如果这个组建适合作为一个子类,就可以提炼不同的子类来实现不同功能
**如果大类是GUI类,那么就应该使用MVC策略,把数据和行为移动到独立的领域对象中去,划分对象的职责。
四、Long Parameter List(过长参数列表)
太长的参数难以理解,太多的参数会造成前后不一致、不易使用。
重偶方法:1.Replace Parameter with Method ,如果向已有的对象发送一条请求就能替代一个参数,那么完全可以把这个参数用函数替代了
2.Presere Whole Object ,将来自同一对象的一堆数据收集起来,并以此对象替代。
3.Introduce Parameter Object ,如果某些参数缺乏对象归属,那么就制造参数对象
五、Divergent Change(发散式变化)
一个类受多种变化的影响,优化代码,使“外界变化”与“需要修改的类”趋于一一对应
我们总是希望软件是易于修改的-----------------跳转到系统的某一点,只在该处做修改(不影响系统其他部分的功
4000
能)。
重构方法:1.Extract Class,让对象的职责单一。
六、Shot Surgery(散雾弹式修改)
一种变化引发多个类相应修改,优化代码,使“外界变化”与“需要修改的类”趋于一一对应
如果每遇到某种变化,都会在许多不同的类内部作出修改,即使是很小的修改,也该是重构的时候了!!
重构方法:1.Move Method & Move Field & Extract Class ,把需要修改的代码放入同一个类,通常可以运用Inline Class 把一系列的相关行为放进统一个类
七、Feature Envy(依恋情节)
函数的对于某个对象的兴趣高过对自己所处类的兴趣,体现在函数计算某一个指标,从另外一个对象获得了几乎一半以上的数据。我们应该把这个函数移动到它该去的类中
重构方法:1.Extract Method & Move Method ,把动用另外一个对象的代码提炼成方法,在移动到对应的类。
八、Data Clums(数据泥团)
不同的类中相同的字段,许多函数签名中相同的参数,这些总是绑在一起出现的数据真该拥有属于他们自己的对象。
重构方法:1.Extract Class,将字段和与字段相关的方法提炼到类中形成新类,同事避免出现Feature Envy
九、Primitive Obsession(基本类型偏执)
面向对象中要借助对象的封装来实现很多基本类型不能实现的方法。
重构的方法:1.Replace Data Value with Object
2. Repalce Type Code with Class,替换的数据值是类型马,而它不影响对象行为
3.Replace Type Code with Subclass /Replace Type Code with State/Strategy,如果有与类型码相关的条件表达式,类型码影响行为
4.Extract Class,如果有一组总该放一起的字段,可以提炼出类。
5.Introduce Parameter Object,如果在参数中看到基本数据,可以对不同/大量相关的基本数据封装
6.Replace Array with Object
十、Switch Statements(switch 惊悚现身)
少用switch/case语句,从本质上说,switch语句就是重复,你会经常发现相同/相似的switch语句散布于不同的地点,如果要为它添加一个新的case分支,就要找到不同地点的代码,对他们修改。面向对象的多态会带来优雅的实现。
重构方法:1.Extract Method ,把switch/case语句提炼到一个方法中,
2.Move Method ,把这个方法搬到需要多态性的那个类组
3.Replace Type Code with Subclass/Replace Type Code with State/Strategy
4.Replace Conditional with Polymorphism
** 如果只是在单一的函数中有些选择,那么使用多态就杀鸡焉用牛刀了,这种情况下可以使用Replace Paramenter with Explictit Method
十一、Parallel Inheritance Hierarchies(平行的继承体系)
每当未某一个类增加一个子类,必须为另一个相应的类添加一个子类,常常体现在一个继承体系和另外一个继承体系类名称前缀一致。
重构方法:1.Move Method & Move Field,用一个继承体系引用另外一个继承体系
十二、Lazy Class(冗赘类)
类已经失去了存在的价值,就要消失它
重构方法:1.Collapse Hierarchy,把原有复杂的继承体系去掉,保存系统仅有的功能块。
2.Inline Class,对几乎没用的组建。
十三、Speculative Generality(夸夸其谈未来性)
重构方法:1.Collapse Hierarchy,如果某个抽象类没什么用,就去掉他。
2.Inline Class,不必要的委托就去掉,用内部类来代替它
3.Remove Parameter。如果函数的某些参数从未用上,就去掉它吧
4.Rename Method,如果函数名称带有过多的抽象意味,就给一个具体 且体现具体用途的名字。
十四、Temporary Field(令人迷惑的临时字段)
类中某个实例变量仅为某种定情况而设,这样的变量通常不易被理解。
重构方法:1.Extract Class ,提炼出类,把Temporary Field和其相关的方法都放入这个新类
2.Introduce Null Object,在变量不合法的时候,创建一个null对象
十五、Message Chains(过度耦合的消息链)
如果出现对象请求另一个对象,然后再向后者请求另外一个对象。。。。。这就是消息链。这样的代码以来整个链条的紧密耦合,一旦对象关系发生变化, 就会可能就会修改整个链条的代码逻辑。
重构方法:1.Hide Delegate,
2.Extract Method & Move Method
十六、Middle Man(中间人)
某些类有一半的接口都委托给其他类,这就是过多委托。
重构方法:1.Remove Middle Man,移除真中间者,直接和真正和负责的对象打交道
2.InlineMethod ,如果不干实事的函数只有少数几个,那么可以把这些函数封装起来放进调用端
3.Replace Delegation with Inheritance,如果这些Middle Man 还有其他的行为,我们可以运用继承,把它们变成实责对象的子类,这样既可以扩展原实责对象的行为,又避免使用过多委托
十七、Inappropriate Intimacy(过分亲密)
如果两个类话费太多的时间去探究彼此的private成分,从面向的封装特性,可以看出我们有必要重构。
重构方法:1.Move Method & Move Field 将他们划清界限
2.Extract Method,将两个情投意合的类共有部分提炼成新类,让他们使用新类
3.Replace Inheritance with Delagation,继承往往造成过度亲密,我们就运用delegation吧(少用继承多用组合)
十八、Alternative Classes with Diferent Interfaces(异曲同工的类、方法)
如果两个函数、类做同一件事,却有着不同的签名。
重构方法:1.Rename Method ,根据他们实际用途重新命名,并使相同代码只有一份
2.Extract Superclass,把共有的提炼成父类
十九、Incomplete Library Class(不完美的库类)
重构方法:1.Introduce Foreign Method,
2.Introduce Local Extension
二十、Data Classe
重构方法:1.Encapsulate Field ,严格控制访问权限
最好能够承担一定的责任
二十一、Refused Bequest(被拒绝的遗赠)
子类应该继承超类的函数和数据,但是若果它们却只想继承一部分;或者只想超类的实现,却 不想超类的接口
重构方法:1.Replace Inheritance with Delegation
二十二、Comments(过多注释)
看到代码有长长的注释,然后发现,这些注释子所以存在是因为代码太糟糕,那么就重构吧。
重构方法:1.Extract Method && Rename Method ,把不同的注释提炼成方法,然后给他一个具体实际的名字
保证实现只有一份。
如果你在一个以上的地点看到相同的程序结构,那么可以肯定,设法将它们合而为一。
1.同一个类的两个函数含有相同的表达式
重构方法:Extract Method
提炼出重复的代码封装成函数,让这两个地点都调用提炼出来的函数。
2.互为兄弟的子类含有相同(相似)的表达式
重构方法:1.Extract Method,2.Pull Up Method 3.依据情况使用单独的继承/Template Method
3.两个不相关的类出现Duplication Code
重构方法:1.Extract Class
将重复的代码提炼到一个独立类中,然后在另外一个类中使用这个新类。
二、Long Method
短小结构良好的函数价值
解释能力,共享能力,选择能力
重构场景:1.感觉代码需要以注释来说明逻辑和功能时候,我们就需要把不同的注释阶段代码写入独立的函数,并以他们的用途命名
2.函数内部有大量的参数和临时变量,会对函数的提炼形成阻碍,这个时候就要想办法减少变量的个数
重构方法:1.Extract Method 2. Replace Temp With Query 3. Introduce Parameter Object 4. Perserve Whole Object
5.Replace Method with Method Object
三、Large Class(过大的类)
别让单个类做太多的事情,往往会导致Duplication 和 太多实例变量
重构方法:1.Extract Class,将类中彼此相关的变量和方法放入一个新类
2.Extract SubClass,如果这个组建适合作为一个子类,就可以提炼不同的子类来实现不同功能
**如果大类是GUI类,那么就应该使用MVC策略,把数据和行为移动到独立的领域对象中去,划分对象的职责。
四、Long Parameter List(过长参数列表)
太长的参数难以理解,太多的参数会造成前后不一致、不易使用。
重偶方法:1.Replace Parameter with Method ,如果向已有的对象发送一条请求就能替代一个参数,那么完全可以把这个参数用函数替代了
2.Presere Whole Object ,将来自同一对象的一堆数据收集起来,并以此对象替代。
3.Introduce Parameter Object ,如果某些参数缺乏对象归属,那么就制造参数对象
五、Divergent Change(发散式变化)
一个类受多种变化的影响,优化代码,使“外界变化”与“需要修改的类”趋于一一对应
我们总是希望软件是易于修改的-----------------跳转到系统的某一点,只在该处做修改(不影响系统其他部分的功
4000
能)。
重构方法:1.Extract Class,让对象的职责单一。
六、Shot Surgery(散雾弹式修改)
一种变化引发多个类相应修改,优化代码,使“外界变化”与“需要修改的类”趋于一一对应
如果每遇到某种变化,都会在许多不同的类内部作出修改,即使是很小的修改,也该是重构的时候了!!
重构方法:1.Move Method & Move Field & Extract Class ,把需要修改的代码放入同一个类,通常可以运用Inline Class 把一系列的相关行为放进统一个类
七、Feature Envy(依恋情节)
函数的对于某个对象的兴趣高过对自己所处类的兴趣,体现在函数计算某一个指标,从另外一个对象获得了几乎一半以上的数据。我们应该把这个函数移动到它该去的类中
重构方法:1.Extract Method & Move Method ,把动用另外一个对象的代码提炼成方法,在移动到对应的类。
八、Data Clums(数据泥团)
不同的类中相同的字段,许多函数签名中相同的参数,这些总是绑在一起出现的数据真该拥有属于他们自己的对象。
重构方法:1.Extract Class,将字段和与字段相关的方法提炼到类中形成新类,同事避免出现Feature Envy
九、Primitive Obsession(基本类型偏执)
面向对象中要借助对象的封装来实现很多基本类型不能实现的方法。
重构的方法:1.Replace Data Value with Object
2. Repalce Type Code with Class,替换的数据值是类型马,而它不影响对象行为
3.Replace Type Code with Subclass /Replace Type Code with State/Strategy,如果有与类型码相关的条件表达式,类型码影响行为
4.Extract Class,如果有一组总该放一起的字段,可以提炼出类。
5.Introduce Parameter Object,如果在参数中看到基本数据,可以对不同/大量相关的基本数据封装
6.Replace Array with Object
十、Switch Statements(switch 惊悚现身)
少用switch/case语句,从本质上说,switch语句就是重复,你会经常发现相同/相似的switch语句散布于不同的地点,如果要为它添加一个新的case分支,就要找到不同地点的代码,对他们修改。面向对象的多态会带来优雅的实现。
重构方法:1.Extract Method ,把switch/case语句提炼到一个方法中,
2.Move Method ,把这个方法搬到需要多态性的那个类组
3.Replace Type Code with Subclass/Replace Type Code with State/Strategy
4.Replace Conditional with Polymorphism
** 如果只是在单一的函数中有些选择,那么使用多态就杀鸡焉用牛刀了,这种情况下可以使用Replace Paramenter with Explictit Method
十一、Parallel Inheritance Hierarchies(平行的继承体系)
每当未某一个类增加一个子类,必须为另一个相应的类添加一个子类,常常体现在一个继承体系和另外一个继承体系类名称前缀一致。
重构方法:1.Move Method & Move Field,用一个继承体系引用另外一个继承体系
十二、Lazy Class(冗赘类)
类已经失去了存在的价值,就要消失它
重构方法:1.Collapse Hierarchy,把原有复杂的继承体系去掉,保存系统仅有的功能块。
2.Inline Class,对几乎没用的组建。
十三、Speculative Generality(夸夸其谈未来性)
重构方法:1.Collapse Hierarchy,如果某个抽象类没什么用,就去掉他。
2.Inline Class,不必要的委托就去掉,用内部类来代替它
3.Remove Parameter。如果函数的某些参数从未用上,就去掉它吧
4.Rename Method,如果函数名称带有过多的抽象意味,就给一个具体 且体现具体用途的名字。
十四、Temporary Field(令人迷惑的临时字段)
类中某个实例变量仅为某种定情况而设,这样的变量通常不易被理解。
重构方法:1.Extract Class ,提炼出类,把Temporary Field和其相关的方法都放入这个新类
2.Introduce Null Object,在变量不合法的时候,创建一个null对象
十五、Message Chains(过度耦合的消息链)
如果出现对象请求另一个对象,然后再向后者请求另外一个对象。。。。。这就是消息链。这样的代码以来整个链条的紧密耦合,一旦对象关系发生变化, 就会可能就会修改整个链条的代码逻辑。
重构方法:1.Hide Delegate,
2.Extract Method & Move Method
十六、Middle Man(中间人)
某些类有一半的接口都委托给其他类,这就是过多委托。
重构方法:1.Remove Middle Man,移除真中间者,直接和真正和负责的对象打交道
2.InlineMethod ,如果不干实事的函数只有少数几个,那么可以把这些函数封装起来放进调用端
3.Replace Delegation with Inheritance,如果这些Middle Man 还有其他的行为,我们可以运用继承,把它们变成实责对象的子类,这样既可以扩展原实责对象的行为,又避免使用过多委托
十七、Inappropriate Intimacy(过分亲密)
如果两个类话费太多的时间去探究彼此的private成分,从面向的封装特性,可以看出我们有必要重构。
重构方法:1.Move Method & Move Field 将他们划清界限
2.Extract Method,将两个情投意合的类共有部分提炼成新类,让他们使用新类
3.Replace Inheritance with Delagation,继承往往造成过度亲密,我们就运用delegation吧(少用继承多用组合)
十八、Alternative Classes with Diferent Interfaces(异曲同工的类、方法)
如果两个函数、类做同一件事,却有着不同的签名。
重构方法:1.Rename Method ,根据他们实际用途重新命名,并使相同代码只有一份
2.Extract Superclass,把共有的提炼成父类
十九、Incomplete Library Class(不完美的库类)
重构方法:1.Introduce Foreign Method,
2.Introduce Local Extension
二十、Data Classe
重构方法:1.Encapsulate Field ,严格控制访问权限
最好能够承担一定的责任
二十一、Refused Bequest(被拒绝的遗赠)
子类应该继承超类的函数和数据,但是若果它们却只想继承一部分;或者只想超类的实现,却 不想超类的接口
重构方法:1.Replace Inheritance with Delegation
二十二、Comments(过多注释)
看到代码有长长的注释,然后发现,这些注释子所以存在是因为代码太糟糕,那么就重构吧。
重构方法:1.Extract Method && Rename Method ,把不同的注释提炼成方法,然后给他一个具体实际的名字
相关文章推荐
- 类方法代码重构-寻找坏味道
- 代码重构-寻找坏味道
- 在项目中寻找代码的坏味道(综艺命名)
- 【重构】 代码的坏味道总结 Bad Smell (一) (重复代码 | 过长函数 | 过大的类 | 过长参数列 | 发散式变化 | 霰弹式修改)
- 代码的坏味道,重构,模式
- 重构改善既有代码的设计--代码的坏味道
- [读书笔记]代码的坏味道---何时重构
- 重构_改善既有代码的设计-代码的坏味道-纪要
- 重构读书笔记 第3章 代码的坏味道
- 【重构笔记】重构与代码的坏味道
- 重构之代码坏味道
- 《重构》-3-代码的坏味道-读书笔记
- 【重构】 代码的坏味道总结 Bad Smell (一) (重复代码 | 过长函数 | 过大的类 | 过长参数列 | 发散式变化 | 霰弹式修改)
- 代码坏味道与重构
- 代码重构学习笔记二:代码的坏味道导图
- 代码的坏味道,重构,模式
- 代码味道及重构手段
- 《重构》读书笔记(四)——第三章 代码的坏味道
- 重构-代码的坏味道
- 重构:代码的味道与消除方法