标签:
代码的坏味道:
1、Duplicated Method(重复代码)
(1)同一个类的两个函数含有相同的表达式 用 Extract Method(110)
(2)两个互为兄弟的子类内含相同表达式 两个类都用 Extract Method,然后对用Pull Up Method(332)推入超类
两个互为兄弟的子类内含类似表达式 两个类都用 Extract Method 将相似和差异部分隔开。
运用Form Template Method(345) 获得一个Template Method设计模式。
不同的算法作相同的事,选择较清晰的一个,Substitute Algorithm(139) 将其他替换掉
(3)不相关的类方法重复。其中一个类使用Extract Class,重复代码提炼到一个独立类中,在另一个类中使用这个新类。
或者这个代码本就应在在两者之一的类中,而不是新的类,需要判断。
2、Long Method(过长函数)
“间接层”所能带来的全部利益:解释能力、共享能力、选择能力——都是由小型函数支持的。
程序愈长愈难理解。过短函数让代码阅读者必须经常转换上下文去看看子程序做了什么,然短函数容易理解的真正关键在于一个好名字。如果你能给函数起个好名字,读者就可以通过名字了解函数的作用,根本不必去看其中写了些什么。
可遵循的一条原则:每当感觉需要以注释来说明点什么的时候,我们就把需要说明的东西写进一个独立函数中,并以其用途(而非其实现手法)命名。
哪怕替换后的函数调用比函数自身还长,只要函数名称能够解释其用途,就要做——关键在函数“做什么”和“如何做“之间的语义距离。
3、Large Class(过大的类)
如果想利用单个类做太多事情,其内往往就会出现太多实例变量。
可以将几个变量一起提炼至新类内。提炼时应该选择类内彼此相关的变量,将它们放在一起。例如depositAmount和depositCurrency可能应该隶属同一个类。
通常如果类内的数个变量有着相同的前缀或字尾,这就意味着有机会把它们提炼到某个组件内。如果这个组件适合作为一个子类,你会发现Extract Subclass往往比较简单。
如果类内有太多代码,最简单的解决方案是把东西消弭于类内部,比如有五个“百行函数”,它们之中很多代码都相同,那么或许你可以把它们变成五个“十行函数”和十个提炼出的“双行函数”。
和"拥有太多实例变量"一样,一个类如果拥有太多代码,往往也适合使用 Extract Class和Extract Subclass. 这里有个技巧:先确定客户端如何使用它们 ,然后运用为每一种使用方式提炼出一个接口。这或许可以帮助你看清楚如何分解这个类。
如果你的Large Class是一个GUI类,你可能需要把数据和行为移到一个独立的领域对象去。你可能需要两边各保留一些重复数据,并保持两边同步。Duplicate
Observed Data(189)
4、Long Parameter List(过长参数列)
因为太长的参数列难以理解,太多参数会造成前后不一致、不易使用,而且一旦你需要更多数据,就不得不修改它。如果将对象传递给函数,大多数修改都将没有必要,因为你很可能只需在传入对象内增加一两个字段,就能得到更多数据。
如果向已有的对象发出一条请求就可以取代一个参数,那么你应该激活重构手法Replace Parameter with Method(292)。在这里,"已有的对象"可能是函数所属类内的一个字段,也可能是另一个参数。你还可以运用Preserve Whole Object(288)将来自同一对象的一堆数据收集起来,并以该对象替换它们。如果某些数据缺乏合理的对象归属,可使用Introduce Parameter Object(295)为它们制造出一个"参数对象"。
5、Divergent Change(发散式变化)
如果某个类经常因为不同的原因在不同的方向上发生变化,Divergent Change就出现了。
6、Shotgun Surgery(霰弹式修改)
如果每遇到某种变化,你都必须在许多不同的类内做出许多小修改,你所面临的坏味道就是Shotgun Surgery。
7、Feature Envy(依恋情结)
有一种经典的气味是:函数对某个类的兴趣高过对自已所处类的兴趣。
8、Data Clumps(数据泥团)
你常常可以在很多地方看到相同的三四项数据:两个类中相同的字段、许多函数签名中相同的参数。这些总是绑在一起出现的数据真应该拥有属于它们自已的对象。
9、Primitive Obseession(基本类型偏执)
10、Switch Statements(switch惊悚现身)
面向对象程序的一个最明显特征就是:少用switch语句。从本质上主,switch语句的问题在于重复。你常会发现同样的switch语句散布于不同地点。
11、Parallel Inhertance Hierarchies(平行继承体系)
每当你为某个类增加一个子类,必须也为另一个类相应增加一个子类,便是这种坏味道。
12、Lazy Class(冗赘类)
如果一个类的所得不值其身价,它就应该消失。
13、Speculative Generality(夸夸其谈未来性)
用不上的装置只会挡你的路,所以,把它搬开吧。
14、Temporary Field(令人迷惑的暂时字段)
有时你会看到这样的对象:其内某个实例变量仅为某种特定情况而设。这样的代码让人不易理解,因为你通常认为对象在所有时候都需要它的所有变量。
15、Message Chains(过度耦合的消息链)
如果你看到用户向一个对象请求另一个对象,然后再向后者请求另一个对象,然后再请求另一个对象.....这就是消息链。
16、Middle Man(中间人)
人们可能过度运用委托,也许你会看到某个类接口有一半的函数都委托给其他类,这就是过度委托。
17、Inappropriate Intimacy(狎昵关系)
一个类过多访问另一个类的私有成员
18、Alternative Classes with Different Interfaces(异曲同工的类)
如果两个函数做同一件事,却有不同的函数名,请运用rename method方法根据它们的用途重命名。
19、incomplete library class(不完美的库类)
库类构筑者没有未卜先知的能力,因此,库往往构造得不够好,而且往往不可能让我们修改其中的类使它完成我们希望的工作。这时有两个重构方法可采用:(1)如果你只想修改库类的一两个函数,可以运用introduce foreign method;(2)如果想要添加一大堆额外行为,就得运用introduce local extension。
20、Data Class(纯稚的数据类)
所谓Data Class是指:它们拥有一些字段,以及用于访问(读写)这么字段的函数,除此之外一无长物。Data Class就像小孩子,作为一个起点很好,但若要让它们像成熟的对象那样参与整个系统的工作,它们就必须承担一定责任。
21、Refused Bequest(被拒绝的遗赠)
Refused Bequest是指子类继承了父类的函数和数据,但子类只从中挑选几样来玩,不需要接受父类这么多的东西。按传统做法:你需要为这个子类新建一个兄弟类,再运用Push Down Method和Push Down Field把所有用不到的函数和变量下推给那个兄弟。这样一来,超类就只持有所有子类共享的东西。但是作者不建议你每次都这么做,这种坏味道十之八九很淡,不值得理睬。
22、Comments(过多的注释)
Comments可以带我们找到上面提到的各种坏味道。找到坏味道后,我们首先应该以各种重构手法把坏味道去除。完成之后我们常常会发现:注释已经变得多余了,因为代码已经清楚说明了一切。
如果你不知道该做什么,这才是注释的良好运用时机。除了用来记述将来的打算之外,注释还可以用来标记你并无十足把握的区域。你可以在注释里写下自已“为什么做某某事”。这类信息可以帮助将来的修改者,尤其是那些健忘的家伙。
Extract Method(110)
Pull Up Method(332)
Form Template Method(345)
Substitute Algorithm(139)
Extract Interface(341)
Duplicate Observed Data(189)
标签:
原文地址:http://www.cnblogs.com/maxiaodoubao/p/4629816.html