小结_02:《重构:改善既有代码的设计》

来源:互联网 发布:浙大计算机 专硕 知乎 编辑:程序博客网 时间:2024/06/05 01:51
大型重构


大型重构涉及如下四种工作:

1.  Tease Apart Inheritance(梳理并分解继承体系)

     继承的作用之一:可以明显减少子类中的代码量。
     但是继承很容易被误用:今天为了一项小小的任务而加入一个小小的子类,明天为另一项任务在继承体系的另一个地方加入另一个子类。一个星期(一个月、一年。。)之后,这个体系将变成一个真正的泥淖;变得基本令人无法理解。
    
    混乱的判别方法:判别继承体系是否承担了两项不同的责任的方法:如果继承体系中的某一特定层级上的所有类,其子类名称都以相同的形容词开始,那么这个体系很可能就是承担着两项不同的责任。(见下图所例:)



    重构的做法:
    
    a. 识别出继承体系所承担的不同责任,然后建立一个二维的表格标示出不同的任务。例如从以上继承体系中得到如下表格:

                                                                                   

交易

活动交易

被动交易

表格化显示交易

 

 

                  

      

    b. 现在分辨一下这些不同的责任,发现“表格化显示交易”是一种显示风格,应该被放到另一个继承体系当中去,这样就得到了如下类图:



    c. 针对原来继承体系中的每个子类,建立PresentationStyle的一个个子类,并将Deal类中用来保存PresentationStyle实例的那个实例变量初始化为适当的子类实例。


    d. 然后,使用一些重构技巧,将Deal子类中与显示逻辑相关的函数和变量搬移到PresentationStyle相应的子类当中去。这样就消除了Deal继承体系下的用于显示的子类:



    e. 现在可以分别简化两个继承体系了: 这次重构的效果依简化的结果而定;比如说,一般地我会幸运地发现,显示风格中“主动”和“被动”并不是那么重要,然后类图将被简化如下:

 


    f. 甚至,连“单一显示”和“表格化显示”之间的差别,都可以运用若干变量来捕捉,根本不需要为它们建立相关子类:

 

 


 


第二种工作: Convert Procedural Design to Objects(将过程化设计转化为对象设计)
 

      问题表现:类中有着长长的过程化函数和极少的数据,旁边则是一堆哑数据对象————除了数据访问函数以外没有其他任何函数。
      重构办法:
              a. 针对每一个记录类型(比如说关系数据库当中的每一个表),转变成一个哑数据对象
              b. 针对每一处过程化风格,将该处的代码提炼到一个单独的类当中去。
              c. 针对这个类中每一段长长的程序,实施Extract Method以及其他相关重构将它分解。再将分解后的函数分别移到它所相关的哑数据类中去。
              d. 如果这个被重构的类完全被搬空了,那就把它干掉。

 

第三种工作: Separate Domain from Presentation(将领域和表述/显示分离)
 

      简而言之,此方法将使你的代码具有MVC的风格
      做法:
               a. 为每个窗口(或者任何关于前端处理的责任)建立一个逻辑处理类
               b. 如果窗口包含表格(或者批量数据),为每一行建立一个新类;以一个集合容纳这些新类;
               c. 对窗口包含的数据(或者前台传过来的数据)做检查,如果数据只被用于UI,那么留下;如果数据不会被显示出来,服务于某种逻辑,那么把它移到“逻辑处理类”当中去;如果数据同时被UI和逻辑使用,那么把它复制一份,在UI类和逻辑处理类都存在,并设法使之同步。
               d. 在UI类中隔离涉及“逻辑处理”的模块,将他们统统移到“逻辑处理类”当中去。
               e. 最后进一步重构“逻辑处理类”。

 

第四种工作: Extract Hierarchy(提炼继承体系)
        一开始设计者只想以一个类实现一个概念;但是随着设计方案的演化,最后可能一个类实现了两个、三个乃至十个不同的概念。
        这种类可以被称为“瑞士军刀”般的类,能做各种事情,条件表达式遍布各处。
        例如:一个电费计算程序:使用了大量条件逻辑来计算不同情况下的费用,冬季和夏季的电价不同,私宅用电、小型企业、大型企业、社会救济(包括残障人士)用电的价格也不同,这些将导致复杂的计算逻辑。
        本重构将消除这种状况,但是前提条件是:“条件逻辑”在对象的整个生命周期保持不变。意即,持有该对象的类不会多次改动条件表达式所涉及的变量,并在改动之后调用其中的接口。
 
        重构方法一:渐进法
                a. 鉴别出“一种”变化情况,
                b. 针对这种变化情况,新建一个子类,在源类中使用工厂方法返回这个子类;
                c. 将含有条件逻辑的函数,一次一个地逐一复制到子类中,然后在明确情况下简化这些函数。
                d. 重复上述过程,将所有“变化”的情况都分离出来,直到可以将超类声明为抽象类为止。
                e. 删除超类中那些被所有子类覆写的函数本体,并将它们声明为抽象函数。
 

        重构方法二:一次到位
                a. 针对源类的每一种变化情况,建立一个子类。
                b. 使用 Replace Constructor with Factory Method将原始类的构造函数转变为工厂函数,并令它针对每一种变化情况返回适当的子类实例;
                c. 针对带有条件逻辑的函数,实施“多态化替换条件表达式”
                d. Over

原创粉丝点击