读《重构》笔记

作者: 阿历Ali | 来源:发表于2018-01-08 17:07 被阅读12次

以项目重构为契机,我读了《Refactoring Improving the Design of Existing Code》(Martin Fowler 著)的中文译本《重构 改善既有代码的设计》(熊节 译)。先附上中、英文电子版下载地址: link.

如果能力允许,读原著是首选。我主要读译本,看不懂的地方再看原著,帮助理解。

书中重构技术的范例介绍主要依托面向对象编程技术Java。英文版因为创作较早,用Java 1.1、1.2举例。而Java 1.1、1.2在2000年之前出版,如今Java已经升级到1.9了,可见书中有些技术已经过时。另外,如今的IDE具有强大的自动化重构功能,比如eclipse、Intellij Idea,书中对于重构的“危险”不用过于担心。本书更重要的是作者推崇的重构理念。

说明:个人认为书写的太啰嗦,以下引用部分做了提炼,并不是原句。

what

重构(refactoring):在不改变代码外在行为的前提下,对代码做出修改,以改进程序的内部结构。
名词定义:对软件内部结构的调整,目的是在不改变软件可观察行为的前提下,提高其可理解性,降低其修改成本。


此书适用范围:单进程程序。

单进程重构与并发和分布式程序设计的重构是完全不同的。
单进程的方法调用成本很低,在分布式软件中,方法的往返必须减至最低限度。


why

短期来看,对错误的修改更容易,不需要维护冗余代码;好的代码结构对追踪问题有帮助。
长期来看,重构可以使你更好理解代码的作用和运作方式,使得添加新功能更容易;有利于复用、扩展。


when

何时重构
不用专门拨出时间重构,不是为了重构而重构。重构必定是为了达到某个目的——因为你想做某件事,重构帮你把这件事做好。

如果你发现要为程序添加一个特性,而代码结构使你无法很方便地达成目的,那就先重构,使特性添加比较容易,再添加特性。
事不过三,三则重构。(类似的事不要重复做)
想理解代码所做的事
修补错误
复审代码:某个团队进行设计复审,和单个复审者进行代码复审。

何时不该重构

现有代码不能正常运行。(应该“重写”而不是重构)
项目已近最后期限。

如果最后没有时间重构了,意味着你早该重构的。


how

以下排序尽为本文组织序列,与原著相差很大。

尽量除去临时变量(传来传去,容易跟丢,用方法代替,方便修改)
让每个方法返回一个值,安排多个方法返回多个值。

但是对于计算复杂度较高的方法,还是建议用临时变量吧。

最好不要在另一个对象的属性基础上运用switch语句。

在对象自己的数据上使用switch语句,或使用多态。

两顶帽子:添加新功能、重构

帽子代指行为:添加新功能,不可修改既有代码;重构,不能添加新功能。
在开发时切换两个角色。

改进设计的一个重要方向是消除重复代码

4.1 如果所有catch区段之内,都重复执行了同一段代码,就将重复代码移到finally区段。

注:书中为final,此处原著译文都有问题。

4.2 当子类中有重复的行为,应将该方法移至超类。
4.3 两个类有相同的方法,将方法子集提炼到一个独立的接口。

找出缺乏“间接层利益之处”,在不修改现有行为的前提下,为它加入一个间接层。
找出不值得的间接层,将它拿掉。

中间层可以提高复用率,也要去掉没有复用价值的中间层。

  1. 技巧

修改某个方法名称时,留下旧方法,让它调用新方法。

不要过早发布接口。修改你的代码所有权政策,使重构更顺畅。

“所有权政策”指的是“我负责的代码不允许其他人修改”。如果没有这么强烈的代码主人意识,合作伙伴重构了他的代码,他就可以修改调用代码。

为整个包定义一个异常基类,再定义异常子类,不影响调用者。

调用者只关心异常基类就好了

创建固定不变的对象。不再每次都创建新对象。
系统把大半时间都耗费再一小半代码身上。

如果创建对象消耗很大的资源,那就创建一个固定不变的对象,可以提升系统速度。

  1. 提炼代码的信号

寻找注释,条件表达式和循环。
当你感觉需要撰写注释时,先尝试重构,试着让注释变得多余。

Replace Inheritance with Delegation(352) 委托模式:用聚合来替代继承

  1. 将只赋值一次,不希望改变的变量声明为final

将临时变量声明为final,确保该临时变量只被赋值一次。
在较长的方法中使用final,帮助检查参数是否做了修改。
在对象创建之后不希望改变的字段,不要提供设值方法,声明为final。

间接访问变量的好处是,子类可以通过复写一个方法而改变获取数据的途径,支持更灵活的数据管理方式。

决定在接到请求时创建新的对象,还是预先将它们创建好。
用注册表对象(Dictionary)保存创建好的对象,比如运用Hashtable, HashMap, ConcurentHashMap...
equals()与hashCode()重写必须同时进行。

  1. 为什么最好不要把数据声明为public?

数据和使用数据的行为集中在一起,修改比较简单。

想想要修改散落在整个程序中的数据...Ouch~

若子类中只有常量方法,就没有存在价值。
在超类中设计与常量方法返回值相应的字段,去除子类,避免因继承而带来的额外复杂性。

保持代码清晰才是最关键的,“单一出口”规则其实不是那么有用。
用卫语句处理罕见情况,及时退出。
if-else结构每个分支是同等重要的。

  1. 引入Null Object的时机

只有当大多数客户端代码都要求对空对象做出相同响应时,声明Null Object才有意义。

  1. 令方法携带参数,以提高灵活性

一些做类似工作的方法,因少数几个数值致使行为不同,此时将这些方法统一起来,通过参数处理变化情况,使问题简化。

  1. 想到可能的情况,避免抛异常。

"异常"只应该被用于异常的、罕见的行为,也就是那些产生意料之外的错误行为,而不应该成为条件检查的替代品。

模板方法:将执行操作的序列移至超类,借助多态保证各操作仍得以保持差异性。

超类中创建这个方法,调用子类重写的方法。


关于测试

  1. 重构之前,首先要有可靠的测试机制,测试必须有自我检查能力。
  1. 撰写测试代码的最有用时机是在开始编程之前。
    明确功能需要做什么,接口设计,考虑意外情况的处理。
  1. 测试的目的是希望找出现在或未来可能出现的错误。
  2. 测试最担心出错的部分。
  3. 考虑可能出错的边界条件,把测试火力集中在那儿。
  1. 当事情被认为应该会出错时,别忘了检查是否抛出了预期的异常。
  1. “花合理时间抓出大多数bug”,好过“穷尽一生抓出所有bug”。
  2. 每当收到bug报告,先写一个单元测试来暴露bug。
  3. 随着测试类愈来愈多,可以生成另一类,专门用来包含由其他测试类所组成的测试套件。(这个类即“主控”测试类)

结语

书中的良言

没有任何量度规矩比得上一个见识广博者的直觉。
培养自己的判断力,一个类内有多少实例变量算是太大、一个方法内有多少行代码才算太长。
"得道"的标志是:你可以自信地停止重构。

真正去做才能有更多体会。
重构不是一劳永逸的,此时你需要这样重构,彼时你需要再用相反的方法改回去。就像书中列出了很多相反的重构技术,它们不是矛盾的,而是要看情况具体情况采用合适的方法。


附: 书中列出的相反重构技术

6.1 Extract Method 6.2 Inline Method
7.3 Extract Class 7.4 Inline Class
8.3 Change Value to Reference 8.4 Change Reference to Value
8.7 Change Unidirectional Association to Bidirectional 8.8 Change Bidirectional Association to Unidirectional
9.1 Decompose Conditional 9.2 Consolidate Conditional Expression
10.2 Add Parameter 10.3 Remove Parameter
11.1 Pull Up Field 11.5 Push Down Field
11.2 Pull Up Method 11.4 Push Down Method
11.11 Replace Inheritance with Delegation 11.12 Replace Delegation with Inheritance

相关文章

  • 读《重构》笔记

    以项目重构为契机,我读了《Refactoring Improving the Design of Existing...

  • 改善既有代码的设计笔记(三)代码的坏味道

    前面两篇笔记涉及到了部分重构的时机,本篇笔记全部为重构代码的时机。重构时机,不是僵硬死板的必须在什么时候执行,下面...

  • 重构:读书笔记

    重构读书笔记 第一章 重构,第一个案例 第二章 重构原则 2.1 何为重构 重构(名词):对软件内部结构的一种调整...

  • 如何实施代码重构?

    阅读《重构》的笔记献上。 重构的定义 重构是在不改变软件可观察行为的前提下改善其内部结构。 重构的节奏 以微小的步...

  • 读重构

    读重构(改善既有代码的设计)一点心得 序言 距离我读重构这本书已经过去了很久,最近需要分享一下读这本书的感悟心得,...

  • 读《重构》

    一. 这本书在谈什么? 《重构》是程序员里面很经典的一本书,有人曾说,做面向对象开发,就是左手设计模式,右手重构,...

  • 重构 笔记

    本书针对单进程软件,书中的重构方法不一定适用于分布式软件 第一章 ,重构——第一个案例 代码结构使得添加新特性异常...

  • 重构笔记

    代码的坏味道 Duplicated Code同一个类的两个函数含有相同表达式两个互为兄弟的子类内含有相同表达式两个...

  • 重构:改善既有代码的设计 读书笔记

    16年读重构时做的笔记,每隔段时间过一遍,总有新的收货。当初读这本书+练习花了有两周时间,现在每次大概只需要花1小...

  • 《重构-改善既有代码的设计》读书笔记

    初读重构,以下下是我使用《幕布》这个软件做的部分读书笔记,后续会继续更新。 幕布还可以生成思维导图,由于我现在的笔...

网友评论

    本文标题:读《重构》笔记

    本文链接:https://www.haomeiwen.com/subject/xhbenxtx.html