重构整理(一) 重新组织函数

      记录一下读《重构-改善代码既有设计》中作者对于重构代码所列举的手法清单。具体的流程细节不多说,书中很详细,这里主要做一个整理和我心中的理解。这个篇章的代码均为java。

1.ExtractMethod(提炼函数)

      简单理解就是把冗长函数中的功能一一提炼成为一个新的函数。重构代码的目的之一是为了让代码更加容易理解,希望上层的代码读起来,就像读注释一样,这对函数的起名也得讲究,一般以“做什么”去起名,而不以“怎么做起名”。

      注意的点就是一些局部或者临时变量的处理,这个我认为不需要多说,写代码熟练的人应该都会有意识的处理这些。

2.InlineMethod(内联函数)

      double basePrice=anOrder.basePrice();
      return (basePrice>1000)


----->
      return (anOrder.basePrice()>1000)

       使用情况一般是,某个临时变量是某个函数调用的返回值,当这个临时变量妨碍到其他重构的手法,就应该将它内联化。

3.Replace Temp with Query(以查询取代临时变量)

       什么叫查询呢,作者其实用查询这个词会有点让人摸不着头脑。其实是当一个临时变量保存了一个表达式的结果,这时候把这个表达式运算放到一个独立的函数,函数返回这个表达式的结果,这样其他地方如果用到这个表达式的结果就可以在这个函数里去“查询”。

       用书中的例子来看一下常见且较简单的使用情况:

double basePrice=_quantity*_itemPrice;
if(basePrice>1000)
    return basePrice*0.95;
else
    return basePrice*0.98;


---->

if(basePrice()>1000)
    return basePrice()*0.95;
else
    return basePrice()*0.98;

double basePrice()
{
    return _quantity*_itemPrice;
}

      首先就将所有引用到这个临时变量的地方全部替换为从函数的调用(从函数中查询)。Replace Temp with Query往往是Extract Method之前必不可少的步骤,因为临时变量会阻碍到我们提炼函数,所以要尽可能的把它们变为查询式。但是这种手法复杂的情况在于临时变量受到其他条件的影响。

再看一个例子:

double getPrice()
{
    int basePrice=_quantity*_itemPrice;
    double discountFactor;
    if(basePrice>1000)
        discountFactor=0.95f;
    else
        discountFactor=0.98f;
    return basePrice*discountFactor;
}


---->替换basePrice

double getPrice()
{
    double discountFactor;
    if(basePrice()>1000)
        discountFactor=0.95;
    else
        discountFactor=0.98;
    return basePrice()*discountFactor;
}

private int basePrice()
{
    return _quantity*_itemPrice;
}

---->替换 discountFactor

double getPrice()
{
    double discountFactor=discountFactor();
    return basePrice()*discountFactor;
}

private double discountFactor()
{
    if(basePrice()>1000)
        return 0.95;
    else
        return 0.98;
}

private int basePrice()
{
    return _quantity*_itemPrice;
}

---->最后使用Inline Temp

double getPrice()
{
    return basePrice()*discountFactor();
}

4.Introduce Explaining Variable(引入解释性变量)

        这个很常见,我们在开发过程中经常会看到很臭长臭长的表达式,这时候我们可以把其中的部分拆分提出来用临时变量保存,这样会有助于我们阅读。然后再配合Extract Method和Replace Temp with Query来使用。

5.Split Temporary Variable(分解临时变量)

 如图,是书中的一个例子。像acc这个临时变量,就被赋值了两次,承担了两种职责,这时候应该重新定义一个新的变量来执行第二个职责,然后再使用上述的一些方法来重构。

6.Replace Method with Method Object(以函数对象取代函数)

           因为局部变量的存在会增加函数分解的难度,如果一个函数局部变量泛滥,那么是很难分解这个函数。Replace Temp With Query可以帮助减轻一些负担,但是有时候却根本无法拆解一个需要拆解的函数。这时候此方法就登场了。直接用书中的例子来解释下它的用法,可能这个例子不那么合适,毕竟这种情况一般需要很长篇幅的例子。

Class Account
    int gamma (int inputVal,int quantity,int yearToDate)
    {
        int importantValue1=(intputVal*quantity)+delta();
        int importantValue2=(inputVal* yearToDate)+100;
        if((yearToDate - importantValue1)>100)
            importantValue2-=20;
        int importantValue3=importantValue2*7;
        ..
        return importantValue3-2*importantValue1;
    }

---->

//这里把函数变成一个函数对象,需要声明一个新的类
class Gamma
    private Account _account;
    private int inputVal;
    private int quantity;
    private int yearToDate;
    private int importantValue1;
    private int importantValue2;
    private int importantValue3;

    Gamma(Account source,int inputValArg,int quantityArg,int yearToDateArg)
    {
        _account=source;
        intputVal=inputValArg;
        quantity=quantityArg;
        yearToDate=yearToDateArg;
    }

    //把原本的函数内容移到Compute,里边引用到Account中成员的部分都替换好
    int compute()
    {    
        int importantValue1=(intputVal*quantity) + _account.delta();
        int importantValue2=(inputVal* yearToDate)+100;
        if((yearToDate - importantValue1)>100)
            importantValue2-=20;
        int importantValue3=importantValue2*7;
        ..
        return importantValue3-2*importantValue1;       
    }

    class Account
    
    //这里就把功能交给Gamma对象
    int gamma(int inputVal,int quantity,int yearToDate)
    {
        return new Gamma(this,intputVal,quantity,yearToDate).compute();
    }

           这样的好处就在于可以轻松的对Compute里面的内容采用Extract Method,不用再担心参数传递的问题。因为参数早已变成了字段。

7.Substitute Algorithm(替换算法)

            这个就不必说了,一定可以在某些时候找到更简单的算法。

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值