masuo推荐我的一本书。这本书写的通俗易懂,里面的很多技巧看起来很普通却很重要。
看完这本书之后我最大的收获是认识到:重构也是设计的一部分。不再会为初期设计的缺陷感到苦恼。我前面的经验是:初期设计得越完美,后边越苦恼!
何谓重构:使用一系列重构手法对软件内部结构进行调整,目的是在不改变程序功能的前提下,提高其可理解性,降低代码的修改和维护成本。
为何重构:1 改进软件设计 2 使代码更容易理解 3 帮助找BUG(这个理由有点偏?) 4 提高开发效率
何时重构:代码有坏味道的时候
以下内容格式为:
编号 代码的坏味道 [解释]
解决方法
BEGIN
1 重复的代码
<1>若干个函数中有相同的一部分代码,那么把相同的代码提炼为一个新的函数,在把重复的代码段替换为新函数的调用。(Extract Method)
<2>另一种常见的情况是"若干个互为兄弟的子类含有相同的表达"。这时需要分别对这若干类使用Extract Method,把提炼出来的代码推入父类(Pull Up Method)
<3>如果兄弟类之间的两个函数以相同顺序执行大致相近的操作,但是各种操作不完全相同。这时可以将执行操作的序列移动到基类,并借助多态保证各操作仍得以保持差异性。这样的函数被称为Template Method(模板函数)【GOF】(Form Template Method)
2 过长的函数
<1>大多数时候用Extract Method方法提炼出新的子函数
<2>一个比较重量级的方法:Replace Method with Method Object(以函数对象替换函数)。那么原函数中的局部变量成了对象的字段,然后将函数逻辑分解为多个小函数
3 过大的类
<1>Extract Class:一个类做了两个类应该做的事,把它分成两个类
<2>Extract Subclass:类中的特性只能被某些实例用到。新建一个类,将那一部分特性放到它的子类。
4 过长的参数列表
<1>Replace Parameter with Method:对象调用某个成员函数并将结果作为参数传给另一个函数,而接受参数的函数也能调用前一个函数。去掉该参数项在函数体中直接获取。(例外,这个对象接口带有参数,并且这个函数不能获取这些参数)。
<2>Preserve Whole Object:把参数列表中来自同一对象的参数用对象替换掉。
<3>Introduce Parameter Object:创造一个参数对象,以替换过长的参数列表。
5 发散式变化(Divergent Change) 一个类在加入某个新功能时,其中若干个成员函数都需要被改动。在加入另一个新功能时,也需要改变类中若干个方法。
此时应该把类分成两个,这样每个对象就可以只因为一种变化尔需要修改。(Extract Class)
6 散弹式修改(Shotgun Surgery) 与上一点相反。每遇到一种变化,你都需要在许多不同的类里做出许多小的修改。如果需要修改的代码散布四处,并且容易遗漏一些修改。
<1>用Move Method & Move Field把所有需要修改的代码放进同一个类。如果没有这样的类就创造一个。
<2>用Inline Class将一系列相关行为放进同一个类。Inline Class:与Extract Class 相反,把一个没有存在必要的类的内容移动到另一个类中,并把原类删除。
7 依恋情节(Feature Envy) 如果类中某成员函数对其他类的兴趣高于自己所在的类,此时它或许应该被移动到另一个类去。
用到的方法当然是Move Method,如果函数中只有一部分有依恋情节,那么先Extract Method然后Move Method。
8 数据泥团(Data Clumps) 相同的若干项数据,出现在不同的地方(类的成员变量、函数的参数列表等等)。这些绑在一起出现的数据应该有属于它们自己的对象。
9 基本类型偏执(Primitive Obsession) 很多人不愿意在小任务上运用小对象,而更偏向于使用语言内置的基本类型。作者认为可以Replace Data Value with Object。
10 Switch Statements
11 平行继承体系(Parallel Inheritance Hierarchies) 当你为某个累增加一个子类时,也必须为另一个累相应增加一个子类。
12 Lazy Class
13 Speculative Generality 典型过度设计的特征。
14 令人迷惑的暂时字段(Temporary Field) 这里所说的字段是指:一个类的某成员变量仅仅为某种特定情况而设。这时应该把这种字段和与其相关的逻辑移动到一个新类中。
15 过度耦合的消息链(Message Chains) 用户向对象请求另一个对象,然后再请求另一个对象......这意味着,客户代码与对象间的关系紧密耦合。对象间的关系一旦发生变化,客户代码不得不做出相应的修改。
16 过多的中间人 也就是过度运用委托。
17 狎昵关系(Inappropriate Intimacy) 两个类过于亲密,花太多时间去探究彼此的private成分。
18 异曲同工的类(Alternative Classes width Different Interfaces)
19 不完美的类库(Incomplete Library Class)
20 数据类(Data Class) 数据类是指拥有一些字段,以及访问它们的接口,除此之外一无长物。
21 被拒绝的遗赐(Refused Bequest) 基类?(超类)中的函数和数据不没有被完全继承。
22 过多的注释 漂亮的代码本身就是很好的注释。太多的注释往往是代码糟糕的标志。
END
note:读完一本书真的非常快。但是要做笔记备忘的话真得花较多时间。记得不完整的部分后边有空了再补上。