读《重构》笔记

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

设若能力允许,读原著是首选。我根本读译本,看不懂的地方再看原著,协助明白。

书中重构技术的范例介绍主要依托面向对象编程技术Java。英文版因为创作较早,用Java
1.1、1.2比喻。而Java
1.1、1.2在2000年事先出版,方今Java已经擢升到1.9了,可知书中有些技术已经不合时宜。此外,近日的IDE具有强大的自动化重构功能,比如eclipse、速龙lij
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. 重构从前,首先要有保障的测试机制,测试必须有本人检查能力。

  2. 写作测试代码的最管用时机是在始发编程之前。
    鲜明职能须要做什么,接口设计,考虑竟然情形的拍卖。

  3. 测试的目标是愿意找出现在或未来或许出现的失实。

  4. 测试最担心失误的部分。
  5. 考虑或者出错的边界条件,把测试火力集中在当年。

  6. 当事情被认为应当会出错时,别忘了检查是或不是抛出了预想的格外。

  7. “花合理时间抓出半数以上bug”,好过“穷尽毕生抓出富有bug”。

  8. 每当收到bug报告,先写一个单元测试来揭穿bug。
  9. 乘势测试类越来越多,可以变更另一类,专门用来含有由其余测试类所结合的测试套件。(这一个类即“主控”测试类)

结语

书中的良言

尚未任何量度规矩比得上一个有胆有识广博者的直觉。
培植自己的判断力,一个类内有微微实例变量算是太大、一个方法内有些许行代码才算太长。
“得道”的申明是:你可以满怀信心地平息重构。

实在去做才能有越多体会。
重构不是一劳永逸的,此时您须求如此重构,彼时您必要再用相反的法门改回去。似乎书中列出了众多反倒的重构技术,它们不是争辨的,而是要看情状具体情况拔取合适的不二法门。


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

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

相关文章