二、代码的坏味道
1、Duplicated Code(重复代码)
坏味道首当其冲的就是Duplicated Code,如果你在一个以上的地点看到相同的重复结构,那么这个坏味道就可以确定了,设法将它们合而为一
-
同一个类中两个或更多的函数含有相同的表达式
利用Extract Method(提炼方法)提炼重复代码,然后引用新提炼的函数
-
互为兄弟的子类含有相同的表达式
利用Extract Method(提炼方法)提炼重复代码,然后Pull Up Method(函数上移)堆到超类
-
互为兄弟的子类,含有部分相同的表达式
一般常见相似的两个函数以相同的顺序执行大致的操作,但是各操作不完全一样
利用Extract Method(提炼方法)提炼重复代码,可能发现是可以运用Form Template Method(塑造模板函数)
-
有些函数以不用的算法做相同的事
使用Substitute Algorithm(替换算法)将其他函数替换掉
-
两个互不相关的类出现Duplicated Code
利用Extract Class(提炼类) 将重复代码提炼到一个独立的类中,然后引用新类。
2、Long Method(过长的函数)
很久以前程序员就已经认识到程序越长越难理解,在早期编程语言,调用子程序需要额外开销,所以不愿意使用小函数。现在OO语言几乎已经完全免除了进程内的调用动作开销
函数命名原则:每当感觉需要注释说明点什么的时候,就可以把需要说明的东西写进一个独立函数中,并以其"用途"命名,哪怕函数名比实现还要长,关键是要说明用途(而非实现手法)
-
无局部变量
利用Extract Method(提炼函数)提炼函数即可
-
有局部变量
如果发现局部变量是保存某一个表达式的运算结果,那么用Replace Temp with Query(以查询取代临时变量)使结构清晰后,再Extract Method(提炼函数),如果提炼了函数后发现新函数对参数赋值了,应用Remove Assignments to Parameters(移除对参数的赋值)
3、Large Class(过大的类)
如果想用单个类做太多事情,其内往往就出现了太多实例变量,一旦如此,duplicate code也就要出现了。当发现一个类中,并非所有时刻都使用所有实例变量,或者某个类中出现多个变量有着相同前缀或结尾,构的动机就出现了
- 如果一个类中用于很多相似的字段,而且方法又都只是和某几个字段有关系,那么可以考虑这些字段是不是应该属于另一个类Extract Class(提炼类)
- 如果你发现类中的某些行为只被一部分实例用到,其它没有用到,可以尝试Extract SubClass(提炼子类)或者Extract Class(提炼类),这两种的抉择就是委托和继承之间的抉择,Extract SubClass(提炼子类)通常更容易,但它也有限制:一旦对象创建完成,你无法再改变对象行为。而委托更灵活一些(策略模式)。
4、Long Paramenter List(过长参数列)
太长的参数列难以理解,太多的参数会造成前后不一致,不易使用,而且一旦你需要更多的数据,就不得不修改它。如果将对象传递给函数,大多数修改都将没有必要,因为你很可能只需要在函数内增加一两条请求,就能得到更多数据
- 如果向已有的对象发出一条请求,就可以取代一个参数,那么你应该激活手法 Replace Parameter with Method(以函数取代参数)。在这里"已有对象"可能是函数所属类内的一个字段也可能是另一个参数。
- 你也可以运用 Preserve Whole Object(保持对象完整) 将来自同一个对象的一堆数据收集起来,并以该对象替换它们。如果某些数据缺乏合理的对象归属,可使用Introduce Parameter Object 为它们制造出一个参数对象
- 这里有一个重要的例外:有时候你明显不希望造成"被调用对象"与"较大对象"间的某种依赖关系。这时候将参数句从对象中拆解出来单独作为参数,也很合情合理。但是请注意其所引发的代码。如果参数列太长或变化太频繁,你就需要重新考虑自己的依赖结构了。
5、Divergent Change(发散式变化)
如果某个类经常因为不同的原因在不同方向上发生变化,发散式变化就出现了
- 使用Extract Class(提炼类)把变化的职责提炼到新的类
你看着一个类说:"呃,如果新加入一个数据库,我必须修改这三个函数;如果新出现一种工具,我必须修改这四个函数。"那么此时也许将这个类分成两个会更好,这么一来每个类就可以只因为一种变化而需要修改。当然,往往只有在加入新数据库或者新金融工具后,你才能发现这一点。针对某一个外界变化的所有响应修改,都只应该发生在单一类中,而这个新类内的所有内容都应该发硬此变化。为此,你应该找出某特定原因而造成的所有变化,然后运用Extract Class(提炼类) 将他们提炼到另一个类中。
6、Shotgun Surgery(霰弹式修改)
如果每遇到某种变化,你都必须在许多不同的类作出小修改,你所面临的坏味道就是Shotgun Surgery,你如果需要修改代码有很多处,你不但很难找到它们,也很容易忘记某个重要的修改。
- 这种情况下你应该使用 Move Method (搬移函数)和 Move Field (搬移字段)把所有需要修改的代码放进同一个类。如果眼下没有合适的类,就创造一个。如果将代码移动到同一个类,使原始类几乎为空,请尝试通过Inline Class摆脱这些现在多余的类。
发散式变化(Divergent Change) 是指"一个类受多种变化的影响",霰弹式修改(Shotgun Surgery)是指"一种变化引入引发多个类的修改"。这两种情况下,你都会希望整理代码,使"外界变化"与"需要修改的类"趋于一一对应
标签:重构,函数,读书笔记,代码,提炼,修改,Extract,Method From: https://www.cnblogs.com/wrf1/p/17917825.html