读书笔记随笔-生活工作点滴

重构-读书笔记

2019-07-05  本文已影响2人  手心里得温柔

重构

概念:在不改变代码外在行为的前提下,对代码做出修改,以改进程序的内部结构。
重构技术就是以微小的步伐修改程序。如果你犯下错误,很容易便可发现它。

第一章 重构,第一个案列

  1. 何时重构:如果你发现自己需要为程序添加一个特性,而代码结构使你无法和方便的达成目的,那就先重构那个程序,使特性的添加比较容易进行,然后再添加特性。
  2. 重构的步骤
    • 第一个步骤永远相同:我得为即将修改的代码建立一组可靠的测试环境,这些测试必须有自我检验能力
    • 分解并重组
      1. 找出函数内的局部变量和参数,任何不会被修改的变量都可以被当成参数传入新的函数,如果只有一个变量会被修改,可以将他作为返回值。
      2. 去除临时变量
      3. 运用多态和继承

第二章 重构原则

  1. 概念
    • 名词概念:对软件内部结构的一种调整,目的是在不改变软件可观察行为的前提下,提高其可理解性,降低其修改成本。
    • 动词概念:使用一系列重构手法,在不改变软件可观察行为的前提下,改变其结构。
  2. 重构的目的
    • 改进软件设计:消除重复代码
    • 使软件更容易理解:利用重构来协助理解不熟悉的代码,然后理解其用途,然后进行修改,使其能更好的反映出我的理解
    • 帮助找Bug:对代码进行重构,深入理解代码行为,做出假设。
    • 提高编程速度:良好的设计是快速开发的根本
  3. 什么时候重构
    • 三次法则:事不过三,三则重构(消除重复代码)
    • 添加新功能时:代码的设计无法帮助我轻松添加我所需要的新特性
    • 修补错误时
    • 复审代码时
    • 结论:我们希望程序长这样
      1. 容易阅读
      2. 所有逻辑都只在唯一地点指定
      3. 新的改动不会危及现有行为
      4. 尽可能简单表达条件逻辑
  4. 重构的难题:在重构时,应该实时掌握其过程,注意寻找可能引入的问题
    • 接口的修改:让旧接口调用新接口,留下旧函数,调用新函数。旧的接口或者函数可以使用Java自带的 @Deprecation注解。所以不要过早的发布接口,请修改你的代码所有权政策,使重构更顺畅
  5. 不应该重构:当代码实在太混乱的时候,可能重写比重构更有效,此时应该放弃重构

第三章 代码坏味道

  1. 重复的代码:如果在一个以上的地点看到相同的程序结构,那么可以肯定,设法将他们合二为一,使程序变得更好
    • 同一个类的两个函数含有相同的表达式
    • 两个互为兄弟的子类含有相同的表达式,应该将其抽取并放到父类中
    • 如果两个毫不相关的类出现同样的代码,可以将重复代码提炼到一个独立的类中
  2. 函数体过长
  3. 类过大
  4. 参数列表过长:封装成对象来进行传递
  5. 异曲同工的类:应该重新思考其用途并重新命名。
  6. 过多的注释:当感觉需要些注释的时候,先尝试重构,让所有的注释都变得多余,尽量运用重构手法让我们不写注释。

第四章 构筑测试体系

第五章 重构列表

  1. 重构的记录格式
    • 名称:建造一个重构词汇表
    • 概要:简短的概要
      1. 用一句话介绍这个重构能帮我们解决的问题
      2. 一段简短陈述,介绍该做的事
      3. 一副速写图,展现重构前后实例
    • 动机:告诉你“为啥子需要这个重构”,还有什么情况下“不应该使用这个重构”
    • 做法:介绍如何一步一步的进行重构
    • 范例:用一个简单的例子说明该重构
  2. 重构的基本技巧:小步前进,频繁测试

第六章 重新组织函数

总体:重构手法

  1. Extract Method(提炼函数):把一段代码从原先的函数中提取出来,放到一个单独的函数中
    • 做法:
      1. 创造一个新函数,根据意图来命名(以它“做什么”来命名)
      2. 将被提炼代码中需要读取的局部变量,作为参数来传递
  2. Inline Method(内联函数):将一个函数调用的动作替换为函数本体
    • 做法:
      1. 检查函数,确定它不具有多态性(如果有子类来继承该函数,是不能做内联的)
      2. 找出该函数的所有被调用点
      3. 将这个函数的所有调用点都替换为函数的本体
  3. Inline Temp(内联临时变量):有一个临时变量,只被一个简单的表达式赋值了一次
    1. 检查给临时变量赋值的语句,确保等号右边的表达式没有副作用
    2. 如果该变量没有被声明为final类型,那么可以声明为final,然后编译,这样的目的是确保该变量是否真的被只赋值了一次
    3. 找到该变量的引用点,替换为临时变量的赋值表达式
  4. Replace Temp with Query(以查询取代临时变量):以临时变量保存表达式的结果
    • 做法:
      1. 找出只被赋值一次的变量
      2. 声明为final类型
      3. 将该临时变量右边的表达式提炼到一个函数中去
  5. Introduce Explain Variable(引入解释性变量):将复杂的表达式的结果放入一个临时变量来解释其用途
    • 做法:
      1. 声明一个final类型的临时变量,将待分解的复杂表达式中的一部分运算结果赋值给它
      2. 将表达式中的“运算结果”这一部分,替换为上述临时变量
  6. Split Temporary Variable(分解临时变量):针对每次赋值,创造一个独立,对应的临时变量
    • 做法:如果一个变量被赋值超过一次,意味着在函数中承担了一个以上的责任,那么就应该分解临时变量
      1. 在待分解临时变量的声明及第一次赋值处,修改其名称
      2. 为新的变量声明为final
      3. 以该临时变量的第二次赋值处为界,修改其所有的名称为新定义的变量
  7. Remove Assignments to Parameters(移除对参数的赋值)
    • 做法:
      1. 建立一个临时变量,把待处理的参数值赋予它
      2. 以对参数的赋值为界,将其后所有对此参数的引用点,全部替换为对临时变量的引用
      3. 修改赋值语句,使其改为对新建的临时变量赋值
  8. Replace Method with Method Object(以函数对象取代函数):将这个函数单独放到一个对象中,如此一来局部变量就成了成员变量,然后将这个大型函数分解为多个小型函数
    • 做法:
      1. 建立新类,根据待处理函数的用途来命名
      2. 在新类中建立一个原对象的final变量,用来保存原先大型函数所在的对象
      3. 建立大型函数中每个临时变量作为成员变量
  9. Substitute Algorithm(替换算法)
    • 做法:
      1. 准备好另一个算法,并使之通过编译
      2. 针对现有测试,执行上述算法。如果结果与原本结果相同,重构结束
      3. 如果不同,那么以旧算法为参考

第七章 在对象之间搬移特性

概念:在对象的设计过程中,“决定把责任放在哪儿”即使不是最重要的事情,也是最重要的事情之一”

  1. Move Method(搬移函数):在程序中,有个函数与其所驻类之外的类有更多的交流:调用后者,或者被后者调用。
  1. Move Filed(搬移字段):在程序中,某个字段被其所驻类之外的另一个类用得更多。
  1. Extract Class(提炼类):某个类做了应该由两个或多个类做的事情
  1. Inline Class(将类内联化):类没有做太多事情。
  1. Hide Delegate(隐藏“委托关系”):通过一个委托类来调用另一个对象
上一篇下一篇

猜你喜欢

热点阅读