代码的坏味道
Duplicated Code(重复代码)
同一个类的两个函数含有相同的表达式,需要将重复的这段代码提出来,让这两个函数都调用这段代码
两个互为兄弟的子类内含相同表达式,需要将代码提炼出来放入父类中
如果两个毫不相关的类出现Duplicated Code,需要将重复代码提炼到一个独立类中,然后在另一个类内使用这个新类,抑或这个函数可能属于第三个类,而另两个类应该引用这第三个类
Long Method(过长函数)
拥有短函数的对象会活得比较好、比较长。解释能力、共享能力、选择能力——都是由小型函数支持的。每当感觉需要以注释来说明点什么的时候,就把需要说明的东西写进一个独立函数中,并以其用途命名
Large Class(过大的类)
一个类如果拥有太多代码,就需要将其拆分,可以先确定客户端如何使用它们,然后为每一种使用方式提炼出一个接口
Long Parameter List(过长参数列)
太长的参数列难以理解,太多参数会造成前后不一致、不易使用,而且一旦需要更多数据,就不得不修改它,可以把函数所需要的东西通过对象传入
Divergent Change(发散式变化)
如果某个类经常因为不同的原因在不同的方向上发生变化,就会出现Divergent Change,如增加一个功能需要修改多处,这时应该把针对某一外界变化的所有相应修改都放在一个类中
Shotgun Surgery(霰弹式修改)
如果每遇到某种变化,就必须在许多不同的类内做出许多小修改,这就是Shotgun Surgery,应该把需要修改的代码放进同一个类,如果没有合适的类就创建一个
Feature Envy(依恋情结)
如果一个函数为了计算某个值,需要用到几个类的数据,就把函数移到最多被此函数使用的数据的类中
Data Clumps(数据泥团)
总是绑在一起出现的数据应该拥有属于它们自己的对象,评判方法是:删掉众多数据中的一项,如果其他数据没有意义了,那就应该为它们产生一个新对象
Primitive Obsession(基本类型偏执)
大多数编程环境都有两种数据:结构类型允许你将数据组织成有意义的形式;基本类型则是构成结构类型的积木块。结构总是会带来一定的额外开销,它们可能代表着数据库中的表,如果只为做一两件事而创建结构类型也可能显得太麻烦
对象技术的新手通常不愿意在小任务上运用小对象,但是对象的一个极大的价值在于:它们模糊(甚至打破)了横亘于基本数据和体积较大的类之间的界限
Switch Statements(switch惊悚现身)
面向对象程序的一个最明显特征就是:少用switch(或case)语句,从本质上来说,switch语句的问题在于重复,如果要为它添加一个新的case子句,就必须找到所有switch语句并修改它们,面向对象中的多态概念可为此带来优雅的解决方法
Parallel Inheritance Hierarchies(平行继承体系)
每当你为某个类增加一个子类,必须也为另一个类相应增加一个子类,这就是平行继承体系,消除这种重复性的一般策略是:让一个继承体系的实例引用另一个继承体系的实例
Lazy Class(冗赘类)
如果一个类的所得不值其身价,它就应该消失
Speculative Generality(夸夸其谈未来性)
当有人说”我想我们总有一天需要做这事”,并因而企图以各式各样的钩子和特殊情况来处理一些非必要的事情,这种坏味道就出现了,这么做的结果往往造成系统更难理解和维护,如果所有装置都会被用到,那就值得这么做;如果用不到,就应该移除
Temporary Field(令人迷惑的暂时字段)
其内某个实例变量仅为某种特定情况而设,这样的代码让人不易理解,因为通常会被认为对象在所有时候都需要它的所有变量,应该把所有和这个实例变量相关的代码都放进一个地方(或一个独立的类中)
Message Chains(过度耦合的消息链)
如果一个用户向一个对象请求另一个对象,然后再向后者请求另一个对象,然后再请求另一个对象…这就是消息链。采取这种方式,意味客户代码将与查找过程中的导航结构紧密耦合,一旦对象间的关系发生任何变化,客户端就不得不做出相应修改
可以先观察消息链最终得到的对象是用来干什么的,看看能否把使用该对象的代码提炼到一个独立的函数中,再把这个函数推入消息链。如果这条链上的某个对象有多位客户打算航行此航线的剩余部分,就加一个函数来做这件事
Middle Man(中间人)
对象的基本特性之一就是封装——对外部世界隐藏其内部细节,封装往往伴随委托
如果某个类接口有一半的函数都委托给其他类,就是过度运用委托,这时应该移除Middle Man,直接和真正负责的对象打交道。如果这样”不干实事”的函数只有少数几个,可以把它们放进调用端。如果这些Middle Man还有其他行为,可以把它变成负责对象的子类,这样既可以扩展原对象的行为,又不必负担那么多的委托动作
Inappropriate Intimacy(狎昵关系)
如果两个类过于亲密,需要花费太多时间去探究彼此的private成分,就是过分狎昵,可以把两个类的共同点提炼到一个新类中
继承往往造成过度亲密,因为子类对超类的了解总是超过后者的主观愿望
Incomplete Library Class(不完美的库类)
如果只想修改库类的一两个函数,可以运用Introduce Foreign Method;如果想要添加一大堆额外行为,就得运用Introduce Local Extension
Data Class(纯稚的数据类)
所谓Data Class是指:它们拥有一些字段,以及用于访问(读写)这些字段函数,除此之外一无长物,这样的类只是一种不会说话的数据容器,它们几乎一定被其他类过分细琐地操控着。需要找出这些取值/设值函数被其他类运用的地点,尝试把那些调用行为搬移到Data Class类,如果无法搬移整个函数,就产生一个可被搬移的函数
---------------------