重构改善既有代码的设计

这本书已经看过一遍了,还做过一个分享,想来想去还是做下记录,这样更加熟悉些。

初读之感

其实这本书是经典早已知道,随便看看一些列了计算机必读书目的地方都有这本书,我记得第一次读的时候没觉得怎样,但是当我看别人的代码的时候(当然是一些开源的项目)我发现了一些地方竟然与书中的描述不谋而合。说实话,读源码是一件痛苦的事情,你是在沙漠中寻找水源,而这不谋而合的一瞥便是一席绿洲之地,沁人心脾!这种感觉很棒,这也促使了我再次深入的去细细阅读这本书。

这本书是需要有基础才可以阅读的,我觉得应该有的基础如下:

  • 懂得面向对象思想,至少应该写过几个类,类的每一分部的都要知道,比如构造方法、工厂方法、实例变量
  • 对面向对象的三大特征有一定的理解,不仅仅是知道,最好可以直接通过代码演示出来,个人觉得不要用 Objective-C 来演示,最好是 Java 、 C++ 或者是 Swift,因为 Objective-C 中的许多叫法和这本书中的叫法真的不一样
  • 懂得一些设计模式,不需要深入理解,但是至少对一些名词要有一些认知,可以看看 《大话设计模式》当然 F4 也未尝不可
  • 熟练的写过一两个项目,整体的布局都要知道

如果对上面这些东西没有认知的话,这本书还是不要读了,因为你真的会不明白他的含义的。

这是一本书需要入乡随俗的书籍,因为书中列举了大量的自造(或者大家达成共识,而你不知道这个共识)的方法词汇,大部分的地方就直接用了着样的名词来进行描述,所以如果你不知道这种名词的话,真的很难阅读下去,比如这一句 ”如果你发现继承体系中的某些类没有存在的必要,可以用 Collapse Hierarchy(344)将它们移除。“ 我第一次读到这里的时候,瞬间不想再读下去了,因为好多地方都是这么叙述的,真心看不懂怎么一个意思,其实这个和看源码也差不多,就是你读到了一个函数调用,然后再去看看函数里面实现了什么东西,如果见名知意的话,那么就可以继续往后阅读,如果不知道那么你就要进入函数,当然进入函数之前你要存储上下文,阅读的话你就需要用书签或者脑袋来存储上下文了。

Collapse Hierarchy(344)这个的意思是:超类和子类没有太大的区别,那么就可以将子类去掉,直接使用超类,反过来也一样,只要合二为一就可以了,译文叫做——折叠继承体系

总览

先看书的大体结构:

  • 去了书皮,第一页便是重构列表,根据字母顺序排列,第一个是 Add Parameter(添加参数)
  • 全书共 15 章节,其实感觉书本的目录便是一个学习资源从中阅读你就知道了这是什么
  • 前五章:什么是重构、那些地方需要重构(坏味道)、测试体系和重构列表
  • 第六章-第十一章,这一部分是具体的重构方法:组织、简化函数以及组织数据和处理逻辑数据等,这部分就是学习的具体细节了,深究体会
  • 最后是 12 ~ 15 这部分就是尾声了,可以放松下浏览一下

章节阅读记录

下面这部分就是阅读记录了,读取每一章节将我体会所得做以记录:

第 11 章 处理概括关系

这一章节一共 12 个技巧,

Pull Up Field

两个子类拥有相同的字段,那么需要将着两个子类的相同字段移至超类。

具体做法就是:

1
2
3
4
5
6
7
8
9
10
11
12
13
st=>start: Pull Up Field 重构:>http://www.google.com[blank]
e=>end:>http://www.google.com
op1=>operation: 观察并记录各个子类之间相同字段
sub1=>subroutine: 统一字段名字
cond=>condition: 相同字段名字是否一致?:>http://www.google.com
io1=>operation: 编译测试
io2=>operation: 在超类中新建一个字段
io3=>operation: 移除子类字段
io4=>operation: 编译测试
io4=>operation: 选择性对超类新建字段使用 Self Encapsulate Field
st->op1->cond
cond(yes)->io1->io2->io3->io4->e
cond(no)->sub1(right)->op1

注意事项:

  1. 观察两个或者多个子类对这个字段行为是否一致,或者大体相似才能用这个技巧来进行优化
  2. 如果子类的字段的是 private 的,那么提升到超类之后必须是 protected
  3. 针对超类新建字段使用 Self Encapsulate Filed(171), 就是为了解耦,通过封装方法来访问字段值,常见方式就是 settergetter 方法

一句话:将子类字段提升到父类,减少了代码重复,降低了代码修改复杂度

Pull Up Method

有些函数,在各个子类中产生完全相同的结果,可以将该函数移动到超类中。

具体做法:

1
2
3
4
5
6
7
8
9
st=>start: Pull Up Method 重构:>http://www.google.com[blank]
e=>end:>http://www.google.com
op1=>operation: 检查待提升函数,确定它们行为是否一致
io1=>operation: 修改不一致的地方,编译测试
io2=>operation: 在超类中新建一个函数,复制子类函数到父类
io3=>operation: 移除子类函数内容,每次一处都需要测试
io4=>operation: 编译测试
io4=>operation: 观察该函数的调用者,看看是否可以改为超类类型的帝乡
st->op1->io1->io2->io3->io4->e

一句话: 将子类中行为完全相同的函数提升到父类中,即使不完全相同也可以先调整让其相同再进行提升操作

Pull Up Constructor Body

你在各个子类中拥有一些构造函数,它们的本体几乎完全一致。
在超类中新建一个构造函数,并在子类构造函数中调用它

这个技巧主要是针对构造函数的,因为构造函数是创建对象的函数,所以比较特殊,在这里就有了这么一个专门处理的技巧。

具体操作:

  • 在超类中定义一个构造函数
  • 将子类构造函数中的共同代码搬迁到超类的构造函数中:
    • 被搬迁的可能是子类构造函数的全部内容,这种比较好操作
    • 如果不是全部,设法将共同代码搬移到构造函数起始处,然后再复制到父类构造函数中
  • 将子类中共同代码删掉,改调动新建父类的构造函数
  • 测试(如果日后子类构造函数中再出现共同代码,可以首先使用 Extract Method 将那一部分单独提炼到一个独立函数中,然后使用 Pull Up Method 将该函数上移。

阅读技巧

这里记录了在阅读这本的时候的小技巧:

  • 不要阅读电子版本的,你会崩溃的
  • 阅读之前准备几个书签放在旁边
  • 不要吝啬,不要懒惰,看到不明白的技巧名字就直接翻到那一页看看是什么意思,不明白不要紧
  • 书中代码都是 Java 的,最好用 Java 写过项目

读书心得

心得一:如果你不知道怎么把你的代码写好那就看看这本书

当你在写完代码之后,不知道自己到底写的好与不好的时候,该怎么办?以前我的做法是,到 GitHub 上去看看别人写的,或者是别人用的方法,然后结果还是没有找到我想要得到的。因为别人可能做的事情和你的大体类似,但是需求可能不一样,而想要知道代码的好与坏跟他们的实现其实关系不大,你要做的是让你的代码舒服,或者是没有坏的味道,那么首先你要知道哪些是坏味道?这本书中的每种技巧都是针对了每一种坏的味道,慢慢体会领悟,然后写几行代码看看,自然就知道是怎么回事,这样你就可以对着这本书的重构列表慢慢的看你自己写的类,写的方法,写的字段,就知道哪里哪里该怎么进行优化了,不要觉得这些小技巧没什么,他们综合起来就可以让代码质量上升为一个等级。

-------------本文结束谢谢欣赏-------------
Alice wechat