zoukankan      html  css  js  c++  java
  • 重构手法之重新组织函数【4】

    返回总目录

    本小节目录

    6 Split Temporary Variable(分解临时变量)

    概要

    你的程序有某个临时变量被赋值超过一次,它既不是循环变量,也不被用于收集计算结果。

    针对每次赋值,创造一个独立、对应的临时变量。

    动机

    临时变量有各种不同的用途。

    1、循环变量;

    2、结果收集变量;

    3、保存一段冗长代码的运算结果,便于稍后使用。

    其中第三种情况的临时变量应该只被赋值一次。如果它们被赋值超过一次,就意味着它们在函数中承担了一个以上的责任。如果临时变量承担了多个责任,它就应该被分解为多个临时变量,每个变量只承担一个责任。同一个临时变量承担两件不同的事情,会令代码阅读者糊涂。

    范例

    double GetTotalCost()
    {
        double result = 0;
    
        double money = _chickMoney + _chipMoney;
    
        result += money;
    
        money = _cocoaMoney + _coffeeMoney;
    
        result += money;
    
        return result;
    }

    可以看到在这个范例中,临时变量money被赋值两次。并且它没有做到累积结果的作用,累积结果给了result。所以,我们需要做重构,让这个变量的意图变的更加明确。

    所以我们第一步,寻找这个变量第一次声明的地方,并且将他改名,然后修改在第二次赋值之前的所有引用点,并且在第二次赋值处进行重新声明:

    double GetTotalCost()
    {
        double result = 0;
    
        double mealMoney = _chickMoney + _chipMoney;
    
        result += mealMoney ;
    
        double money = _cocoaMoney + _coffeeMoney;
    
        result += money;
    
        return result;
    }

    现在,新的临时变量只承担原先money的第一个责任。而且我们在原先money变量第二次被赋值处重新声明了money。然后,继续处理money临时变量的第二次赋值。

    double GetTotalCost()
    {
        double result = 0;
    
        double mealMoney = _chickMoney + _chipMoney;
    
        result += mealMoney ;
    
        double drinkMoney = _cocoaMoney + _coffeeMoney;
    
        result += drinkMoney ;
    
        return result;
    }

    可以看到,我们完成了变量的重构之后,函数对于临时变量之前的money的困惑已经没有了,整体因为变量名字的本身使得逻辑更加清晰。

    如果在这里你的代码还是比较复杂的话,可以尽情使用其他的重构手法。

     小结

    这个重构手法的重点在于:临时变量不是用于循环变量和结果收集,但却被赋值超过两次,那就对它进行分解,使其每次只承担一个责任。

    7 Remove Assignments to Parameters(移除对参数的赋值)

    概要

    代码对一个参数进行赋值。

    以一个临时变量取代该参数的位置。

    动机

    首先要明确这里“对参数赋值”的意思。如果你把一个名为foo的对象作为参数传给某个函数,那么“对参数赋值”就意味着改变foo,使它引用另一个对象。如果在“被传入对象”身上进行什么操作,那是没问题的。Java只采用按值传递的方式,而C#分为值传递和引用传递,关于C#的值传递和引用传递,请看我的另一篇文章,或者自行百度。

    int test(int a)
    {
        if (a > 50)
        {
            a = 1;
        }
        return a;
    }

    这个就违反了这个原则,因为你对传入参数进行重新赋值会让代码阅读者产生歧义,降低了代码的清晰度。他们搞不清甚至看不懂你参数到底代表什么含义,甚至会对你这个参数的稳定性表示担忧。

    在值类型按值传递的情况下,对参数的任何修改,都不会对调用端造成任何影响。这个重构手法也是针对值类型按值传递的。

    范例

    int GetDiscount(int inputVal, int quantity, int yearToDate)
    {
         if (inputVal > 50)
         {
             inputVal -= 2;
         }
         if (quantity > 100)
         {
             inputVal -= 1;
         }
         if (yearToDate > 1000)
         {
             inputVal -= 4;
         }
         return inputVal;
    }

    以临时变量取代对参数的赋值动作,得到以下代码:

    int GetDiscount(int inputVal, int quantity, int yearToDate)
    {
         int result=inputVal;
         if (inputVal > 50)
         {
             result-= 2;
         }
         if (quantity > 100)
         {
             result-= 1;
         }
         if (yearToDate > 1000)
         {
             result-= 4;
         }
         return result;
    }

     小结

    如果参数只表示“被传递进来的东西”,那么代码会很清晰。

    To Be Continued...

  • 相关阅读:
    实习期收获(一)
    实习期上班两天感触
    做bbs论坛项目的收获(1)
    ios多线程
    C 预处理小结
    Xcode8 问题
    Unity3d收藏链接/ 小马哥视频
    H5(1)
    ios-loadView
    iOS开发UI篇—程序启动原理和UIApplication
  • 原文地址:https://www.cnblogs.com/liuyoung/p/7846156.html
Copyright © 2011-2022 走看看