• 重复代码Duplicated Code---要重构的信号


    什么时候需要重构,当你在项目代码里面嗅到这个味道的时候,就要进行重构。

     

    首个介绍的味道是重复代码的味道。

     

    它表现出来的特征是这些:

     

    1.一个类里面,两个函数中,含有相同的代码,类似的代码;或者三个函数中,含有相同的代码,类似的代码。这是重复代码的味道。

     

    2.两个互为兄弟的子类内含有相同的表达式。这也是重复代码的味道。

     

    3.两个不相关的类,出现了重复代码。这也是重复代码的味道。

     
     

    如何处理,如何重构

     

    1.对于两个函数,出现重复代码,使用Extract Method方法。把某段代码组织到一个新的函数中,然后,将原来函数的某段代码替换为对新函数的调用。

     
     

    Extract Method手法介绍
    使用Extract Method手法处理原函数某段重复代码时,会面遇到如下几种情况:

     

    a.该段代码没有局部变量。
    对于a,直接将代码复制到一个新建的函数体中。

     
     

    b.该段代码有局部变量。
    如果,在段代码中,只是读取局部变量,并没有修改局部变量;或者,局部变量是个对象,这段代码只是调用该对象的某个方法。那么,只需要把这个局部变量当作新建函数的参数便可。

     
     

    c.该段代码对局部变量再赋值。
    被提炼代码段中,对源函数的某个局部变量进行了修改。
    c1.并且,在被提炼代码段的后面,使用该修改后的局部变量。
    这个处理手法是这样:
    1.局部变量被修改后的结果作为新建函数的返回值。
    2.源函数接收新建函数的返回值。

     

    遵守的准则:一个函数,只有一个返回值。

     
     

    ------------------------------------------------------------------------------------------

     

    2.两个互为兄弟的子类内含有相同的表达式。这也是重复代码的味道。

     

    处理方式,首先使用Extract Method手法;然后,再对Extract Method手法处理后的结果使用Pull up Method,把提炼出来的代码推入超类。

     

    Pull up Method(函数上移)手法介绍

     
    针对不同情况的做法:
     
    1.如果,兄弟类中,出现了相同的函数体。那么,在超类中新建一个函数,存放函数体,在各个子类冲调用该新建函数。
     
    2.如果,兄弟类中,出现了相同的函数体,但是,该函数体还使用了所在类的一个字段,可以把该字段也提升到超类。
     
    3.如果,兄弟类中,出现了相同的函数体,并且该函数体,还调用了所在类的一个函数。那么,可以考虑,在超类中声明一个抽象函数,由子类实现。然后,在新建的函数体中,调用超类声明的抽象函数。
     
    4.兄弟类,有时候,不是出现完全相同的函数体,但是,是相似,这些函数体可以通过某种形式的参数调整,最后将相似的多个函数体调整为一个可以使用某种参数表示新函数。
     
     
    -------------------------------------------------------------------------------------------------------
    3.Form Template Method
     
    两段函数体,它们以相同的顺序执行类似的操作,区别只是每个具体操作是不同的。那么,这是执行顺序的相同,也可以列为重复代码。
     
    如下,兄弟类,各自某段函数执行操作顺序相同,每个操作的含义相同,区别只是操作的具体实现不同。
    那么,可以这样做,把每段操作,抽象为一个父类函数。
    然后,父类新建一个函数,该函数包含的是兄弟类中执行顺序和操作含义相同的代码。
     
    比如:
    类A
    double base = _units*_rate*0.5; ----------------getBaseAmount();
    double tax = base*Site.TAX_RATE*0.2;---------getTaxAmount();
    return base+tax;-----------------return getBaseAmount()+getTaxAmount();
     
    类B
    步骤一样,操作步骤含义一样。
     
    将getBaseAmount(),getTaxAmount()提到超类中,作为抽象函数,由具体的子类实现。
    在超类中,实现 getBillableAmount()函数,它的返回值是getBaseAmount()+getTaxAmount()。
    这样,就可以将类B,类A中类似的代码,提取为超类的 getBillableAmount()函数。
     

     ---------------------------------------------------------------------------

    4.Extract Class 提炼类
     
    两个不相关的类,出现了重复代码。这也是重复代码的味道。针对这种重复代码的重构手段,是使用Extract Class方法。
     
     
    Extract Class手法的介绍
     
    一个类,随着开发的进行,你不断往类里面添加方法和字段,不断给类添加各种职责。有一天,你回头,再来看这个类的时候,你发现,这个类过于庞大。
    于是,你需要对这个类进行分解,提炼。
    提炼的步骤简单的概括为:
    1.关键是识别出类里面的各个职责。比如,在一个Person类中,识别出了专门用来打电话的代码,将电话相关的代码提炼到一个TelephoneNumber类中。这样就分离出了Person类中,打电话的职责。
     
     2.然后,在Person类中,使用一个提炼出来的类,作为成员。Person类中,原来需要的打电话功能,可以委托这个TelephoneNumber成员来执行。只保留,从Person到TelephoneNumber的单向连接。
     
    3.决定,提炼出来的类,是一个引用类,还是一个值不可变的类。引用类,就是,值会被修改;值不可变类,则是值不会被修改,在首次初始化之后。
     
    4.决定,提炼出来的类,是只放在原来的类中,作为原来类中的成员;还是公开,public,被其它类使用。这要考虑。
     
    Extract Class手法处理两个不相关的类中的重复代码
     
    1.识别出,两个类中,相同的重复代码。
    2.将重复代码,提炼到一个新建的类中。
    3.新建的类,包含了原来两个类的重复代码。新建的类,作为原来两个类的成员。
    4.原来的两个类,委托新建的成员类进行访问,获得原有重复代码的功能。
  • 相关阅读:
    【洛谷 4613】Olivander
    【洛谷 1385】密令
    【洛谷 4439】Aron
    【洛谷 3383】线性筛素数
    【洛谷 2412】查单词
    【洛谷 1980】计数问题
    【洛谷 3372】(模板)线段树 1
    Luogu P3743 kotori的设备
    Luogu P2340 [USACO03FALL]Cow Exhibition G
    Luogu P3047 [USACO12FEB]Nearby Cows G
  • 原文地址:https://www.cnblogs.com/ttylinux/p/4545213.html
Copyright © 2020-2023  润新知