3.1 Duplicated Code(重复代码)

坏味道行列中首当其冲的就是Duplicated Code.用Template Method 设计模式 将相似和差异分开

3.2 Long Method (过长函数)

间接层所能带来的全部利益

  1. 解释能力
  2. 共享能力
  3. 选择能力
    都是由小型函数支持的

哪怕替换后的函数调用动作比函数自身还长,只要函数名称能够解释其用途,我们也毫不犹豫地那么做.关键不在于函数长度,而在于 做什么 和 如何做 之间的语义距离.

3.3 Large Class(过大的类)

如果想利用单个类做太多事情,其内往往就会出现太多实例变量.一旦如此,Duplicated Code 也就接踵而至了.

3.4 Long Parameter List(过长参数列)

尽量以对象方式传递

3.5 Divergent Change(发散式变化)

一个变化需要多个修改的情况很可怕
需要将其放入同一个类

3.6 Shotgun Surgery(散弹式修改)

一个变化需要多个不同类的修改的情况很可怕,
需要将其放入同一个类

3.7 Feature Envy(依恋情结)

一个对象依赖另一个对象的函数,
应该将需要的函数提炼到一个公共部分中
Strategy(策略)和Visitor(访问者)使你轻松修改函数行为,将少量需要被覆盖的行为隔离开.当然也付出了多一层间接性 的代价.

3.8 DataClumps(数据泥团)

两个类中的数据项组合时,应该用自己的对象包装更好,因为可能有相同的字段名

3.9 Primitive Obsession(基本类型偏执)

不要太倾向基本数据类型,对象数据类型使用帮助你进入炙手可热的对象世界

3.10 Switch Statements(switch 惊悚现身)

少用switch,用多实现,继承 加上 状态/策略模式

3.11 Parallel Inheritance Hierarchies(平行继承体系)

是散弹式修改的特殊情况,在给某个类增加一个子类的同时,也必须为另一个类相应增加一个子类.如果发现两个继承体系的类名称前缀一致,便是问到了这种坏味道.
消除手段:让一个继承体系的实例引用另一个体系的实例

3.12 Lazy Class(冗赘类)

对于几乎没用的组件
如果子类没有做足够的工作,试试Collapse Hierarchy(344)
.对于几乎没用的组件,你应该以Inline Class(154)对付他们

3.13 Speculative Generality(夸夸其谈未来性)

总有一天要做的事,设计了各式各样的狗子和特殊情况.
运用Collapse Hierarchy(344).不必要的委托可以用Inline Class(154)除掉.如果某些参数没被用上,用RemoveParameter(277).如果名称带有多余的抽象意味,用Rename Method(273),让他实现一些.
如果函数唯一用户是测试用例,请把它连测试用例一并删掉.

3.14 Temporary Field(令人迷惑的暂时字段)

如果某实例变量仅为某种特定情况而设.使用Extract Class(149)给这个可怜的孤儿造一个家.
如果类中有一个复杂算法,需要好几个变量,就会使其出现,这时用Extract Class(149)把这些变量和其相关函数提炼到一个独立类中.提炼的新对象是一个函数对象.

3.15 Message Chains(过度耦合的消息链)

对象链式请求,一旦对象间的关系发生变化,客户端就不得不做出相应的修改.
这时候使用Hide Delegate(157).理论上可以重构链上任何对象,但这样做会把一系列对象编程 Middle Man.更好的选择是看看最终用来干嘛,能否以 Extra Method(110)把对象提炼到独立函数中,再运用Move Method(142) 把函数推入消息链

3.16 Middle Man(中间人)

委托过渡时,建议用子类实现行为

3.17 Inappropriate Intimacy(狎昵关系)

两个类话费太多时间去探究彼此. 一般继承会造成这样,运用ReplaceInheritance with Delegation(352)让他离开继承体系.

3.18 Alternative Classes with Different Interfaces(异曲同工的类)

两函数做一样的事情时,请反复运用Move Method(142)将某些行为移入类,直到协议一致.如果必须重复而赘余地移入代码才行,运用Extract Superclass(336)为自己赎点罪

3.19 Incomplete Library Class(不完美的类库)

复用通常被视为对象的最终目的.
修改类库一两个函数-Introduce Foreign Method(162);
如果想要添加一大堆额外行为,就得运用Introduce Local Extension(164);

3.20 Data Class (纯稚的数据类)

他们拥有一些字段,以及用于访问(读写)这些字段的函数,这样的类知识一种不会说话的数据容器,他们几乎一定被其他类过分细琐地操控着.用 Encapsulate Field(206)将他们封装起来. 取值设值的调用搬移到DataClass.把取值设值隐藏起来
Data Class 就像小孩子.作为一个起点很好,但若要让他们像成熟的对象那样参与整个系统的工作,他们就必须承担一定责任.

3.21 Refused Bequest (被拒绝的遗赠)

建议所有超类都是抽象(abstract)的.
不愿意支持超类接口,应用ReplaceInheritance with Delegation(352)来达到目的.

3.22 Comment(过多的注释)

清楚的代码不需要注释.当然注释有时候仍有必要

当你感觉需要撰写注释时,请先尝试重构,试着让所有注释都变得多余.