重构 :改善既有代码的设计

重构 :改善既有代码的设计笔记 回顾 重构改善既有代码的设计

大家好,欢迎来到IT知识分享网。

目录

1. 建立一组可靠的测试环境。

2. 列表

3.WWWH

4.代码的坏味道

5.重构列表

5.1重新组织函数

5.2 在对象之间搬移特性

5.3 重新组织数据

5.4 简化条件表达式

5.5 简化函数调用

5.6 处理概括关系

5.7 大型重构

5.8 重构,复用与现实


最基本要求:“不改变软件行为”;

保持代码易读、易修改的关键,就是重构。

什么是重构  (对现有代码整理改进使其易读易改

        所谓重构(refactoring)是这样一个过程:在不改变代码外在行为的前提下,对代码做出修改,以改进程序的内部结构。重构是一种经千锤百炼形成的有条不紊的程序整理方法,可以最大限度地减少整理过程 中引入错误的几率。本质上说,重构就是在代码写好之后改进它的设计。

目标

        可控且高效的进行重构。

问题

(1)重构的一般性原则、定义?What

        重构(名词):对软件内部结构的一种调整,目的是在不改变软件可观察行为的前提下,提高其可理解性,降低其修改成本。

        重构(动词):使用一系列重构手法,在不改变软件可观察行为的前提下,调整其结构。

(2)进行重构的原因?(为什么应该重构)Why

  •         重构改进软件设计;
            重构使软件更容易理解;
            重构帮助找到bug;
            重构提高编程速度;


  • (3)如何嗅出代码中的“坏味道”,以及如何运用重构清除这些坏味道?(该在什么地方重构)Where / How

(4)开源的测试框架?构筑测试环境?

重构的第一步

1. 建立一组可靠的测试环境。

        必须让测试有能力自我检验:(知道错误发生在何处)

        唯有写出人类容易理解的代码,才是优秀的程序员。

2. 列表

#

坏味道

常用重构

1

Alternative Classes with Different Interfaces(异曲同工的类)

Rename Method(273),

Move Method(142)

2

Comments

(过多的注释)

Extract Method(110),

Introduce Assertion(267)

3

Data Class

(纯稚的数据类)

Move Method(142),

Encapsulate Field(206),

Encapsulate Collection(208)

4

Data Clumps

(数据泥团)

Extract Class(149),

Introduce Parameter Object(295),

Preserve Whole Object(288)

5

Divergent Change

(发散式变化)

Extract Class(149)

6

Duplicated Code

(重复代码)

Extract Method(110), Extract Class(149),

Pull Up Method(322), Form Template Method(345)

7

Feature Envy

(依恋情结)

Move Method(142). Move Field(146). Extract Method(110)

8

Inappropriate Intimacy

(狎昵关系)

Move Method(142), Move Field(146),

Change Bidirectional Association to Unidirectional(200)

Replace Inheritance with Delegation(352),

Hide Delegate(157)

9

Incomplete Library Class

(不完美的库类)

Introduce Foreign Method(162)

Introduce Local Extension(164)

10

Large Class

(过大的类)

Extract Class(149),

Extract Subclass(330)

Extract Interface(341)

Replace Data Value with Object(175)

11

Lazy Class

(冗赘类)

Inline Class(154),

Collapse Hierarchy(344)

12

Long Method

(过长函数)

Extract Method(110)

Replace Temp With Query(120).

Replace Method with Method Object(135).

Decompose Conditional(238)

13

Long Parameter List

(过长参数列)

Replace Parameter with Method(292),

Introduce Parameter Objec1(295),

Preserve Whole Object(288)

14

Message Chains

(过度耦合的消息链)

Hide Delegate(157)

15

Middle Man(中间人)

Remove Middle Man(160)

 Inline Method(117)

Replace Delegation with Inheritance(355)

16

*Parallel Inheritance Hierarchies

(平行继承体系)

Move Method(142),

Move Field(146)

同步增减

17

Primitive Obsession

(基本类型偏执)

Replace Data Value with Object(175),

Extract Class(149),

Introduce Parameter Object(295)

Replace Array with Object(186)

Replace Type Code with Class(218)

Replace Type Code with Subclasses(223)

Replace Type Code with State/Strategy(227)

  

18

Refused Bequest

(被拒绝的遗赠)

Replace Inheritance with Delegation(352)

19

Shotgun Surgery

(霞弹式修改)

Move Method(142),

Move Field(146),

Inline Class(154)

20

Speculative Generality

(夸夸其谈未来性)

Collapse Hierarchy(344),

Inline Class(154),

Remove Parameter(277),

Rename Method(273)

21

Switch Statements

(switch惊悚现身)

Replace Conditional with Polymorphism(255),

Replace Type Code with Subclasses(223),

Replace Type Code with State/Strategy(227),

Replace Parameter with Explicit Methods(285),

Introduce Null Object(260)

22

Temporary Field

(令人迷惑的暂时字段)

Extract Class(149),

Introduce Null Object(260)

3.WWWH

What

        重构(名词):对软件内部结构的一种调整,目的是在不改变软件可观察行为的前提下,提高其可理解性,降低其修改成本。
        重构(动词):使用一系列重构手法,在不改变软件可观察行为的前提下,调整其结构。

Why

        重构的目的是使软件更容易被理解和修改。

     (1)重构改进软件设计;
     (2)重构使软件更容易理解;
     (3)重构帮助找到bug;
     (4)重构提高编程速度;


When/Where

        三次法则:事不过三,三则重构;
        添加功能时重构;(帮助理解)
        修补错误时重构;(错误重构的信号)
        复审代码时重构;团队设计复审,单个复审者代码复审。


How

        间接层的某些价值。

     (1)允许逻辑共享;
     (2)分开解释意图和实现;
     (3)隔离变化;
     (4)封装条件逻辑。多态


        修改接口

                留下旧函数,让旧接口调用新接口。

        难以通过重构手法完成的设计改动

                将不考虑’安全性‘需求时构造起来的系统重构为具备良好安全性的系统。

重构与设计

        可运行的最简化系统+重构;

重构与性能

        三种编写快速软件的方法。

                时间预算法:实时系统;
                持续关注法;
                90%统计数据;

4.代码的坏味道

(1)重复代码

(2)过长函数

        如何确定该提炼哪一段代码?

                找注释;

                条件表达式和循环。

(3)过大的类

        Extract Class

        Extract Subclass

        Extract Interface

        Duplicate Observed Data (189) GUI类

(4)过长参数列

        Replace Parameter with Method

        Preserve Whole Object

        Introduce Parameter Object 引入参数对象

(5)发散式变化

        Extract Class

(6)霰弹式修改

        Move Method 和Move Field:创建类Inline Class

(7)依恋情结

        将总是一起变化的东西放在一块儿。

        保持变化只在一地发生。

(8)数据泥团

        Introduce Parameter Object

        Preserve Whole Object

(9)基本类型偏执

        在小任务上运用小对象:运用Replace Data Value with Object将原本单独存在的数据值替换为对象;

        要替换的数据值是类型码,而它并不影响行为:运用Replace Type Code with Class;

        有与类型码相关的条件表达式,可运用Replace Type Code with Subclass或Replace Type Code with State/Strategy

        有一组应该总是被放在一起的字段,可运用Extract Class

        在参数列中看到基本型数据,不妨试试Introduce Parameter Object

        从数组中挑选数据,可运用Replace Array with Object

(10)switch惊悚现身

        *Extract Method提炼独立函数;

        *Move Method 搬移到多态类;

        *决定是否使用Replace Type Code with Subclasses 或Replace Type Code with State/Strategy;

        *完成继承结构之后,运用Replace Conditional with Polymorphism。

        单一函数中有些选择事例,且并不想改动它们:Replace Parameter with Explicit Methods;

        选择条件之一是null,可以试试Introduce Null Object。

(11)平行继承体系

        重复性:当你为某个类增加一个子类,必须也为另一个类相应增加一个子类。如果你发现某个继承体系的类名称前缀和另一个继承体系的类名称前缀完全相同

        策略:让一个继承体系的实例引用另一个继承体系的实例。如果再接再励运用Move Method和Move Field(把所有需要修改的代码放进同一个类),就可以将引用端的继承体系消弭于无形

(12)冗赘类

        子类没有做足够的工作:Collapse Hierarchy;
        几乎没用的组件:Inline Class。

(13)夸夸其谈未来性

        某个抽象类其实没有太大作用:Collapse Hierarchy;

        不必要的委托可运用Inline Class除掉。

        函数的某些参数未被用上,可对它实施Remove Parameter;

        函数名称带有多余的抽象意味,应该对它实施Rename Method。

(14)令人迷惑的暂时字段
        对象内某个实例变量仅为某种特定情况而设。
                使用Extract Class (149)给这个可怜的孤儿创造一个家;
                还可以使用Introduce Null Object (260)在“变量不合法”的情况下创建一个Null对象,从而避免写出条件式代码。


5.重构列表
5.1重新组织函数
5.2 在对象之间搬移特性

        决定把责任放在哪儿
    Move Method
    Move Field
    Extract Class;臃肿类分离责任;
    Inline Class:类内“不负责任”部分提取;
    *Hide Delegate:隐式的求人办事(组合),提高封装,方便修改;
    *Remove Middle Man:去除过度委托,直接搞定;
    *Introduce Foreign Method:现事现办;
    *Introduce Local Extension:新增责任(继承||组合)







5.3 重新组织数据
5.4 简化条件表达式
5.5 简化函数调用
5.6 处理概括关系

    继承关系
    Pull Up Field;共性上移
    Pull Up Method
    Push Down Method:特性下移
    Push Down Field
Pull Up Constructor Body:我们不会将构造函数往下推,因为Replace Constructor with Factory Method 通常更管用。
    Form Template Method:流程相同,内容不同;将若干函数的共同点和不同点分开。
    Extract Subclass:类中的某些行为只被一部分实例用到;特性下移;
        Extract Class是Extract Subclass之外的另一种选择,两者之间的抉择其实就是委托和继承之间的抉择。
        Extract Subclass通常更容易进行,但它也有限制:一旦对象创建完成,你无法再改变与类型相关的行为。
        但如果使用Extract Class,你只需插入另一个组件就可以改变对象的行为。此外,子类只能用以表现一组变化。如果你希望一个类以几种不同的方式变化,就必须使用委托。
    Extract Superclass;共性上移
    Extract Interface:想在类型系统中标示一小部分函数
        Extract Interface只能提炼共通接口,不能提炼共通代码。
        使用Extract Interface可能造成难闻的“重复”坏味道,幸而你可以运用Extract Class先把共通行为放进一个组件中,然后将工作委托该组件,从而解决这个问题。
        如果有不少共通行为,Extract Superclass会比较简单;
    Collapse Hierarchy:父子差异不大;继承体系中的某些类没有存在必要
    *Replace Inheritance with Delegation:不完全继承,+拥有功能的类为成员,自己主导需要的数据和接口;
    *Replace Delegation with Inheritance:经常为整个接口编写许多极简单的委托函数。

















5.7 大型重构

    Tease Apart Inheritance(梳理并分解继承体系)
    Convert Procedural Design to Objects (将过程化设计转化为对象设计)
    Separate Domain from Presentation (将领域和表述/显示分离)
    Extract Hierarchy(提炼继承体系)


    《重构面向对象框架》
    “Refactoring Object-Oriented Frameworks.”
    
        试探法则

5.8 重构,复用与现实

免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://haidsoft.com/104521.html

(0)

相关推荐

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注微信