zoukankan      html  css  js  c++  java
  • 重构改善既有代码设计--重构手法04: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;
    
                }
    
    ………
    
    private int BasePrice()
    
            {
    
                return _quantity* _itemPrice;
    
            }

    引用书中原文来说:

    动机:临时变量的问题在于:它们是暂时的,而且只能在所属函数内使用。由于临时变量只是在所属函数内可见,所以它们会驱使你写出更长的函数,因为只有这样你才能访问到需要的临时变量。如果把临时变量替换为一个查询,那么同一个类中的所有函数都可以获得这份信息。这将带给你极大帮助,使你能够为这个类编写更清晰地代码。

             Replace Temp with Query (以查询取代临时变量)往往是你运用Extract Method (提炼函数)之前必不可少的一个步骤。局部变量会使代码难以被提炼,所以你应该尽可能把它们替换为查询式。

             这个重构手法较为简单的情况是:临时变量只被赋值一次,或者赋值给临时变量的表达式不受其他条件影响。其他情况比较棘手,但也可能发生。你可能需要先运用Split Temporary Variable (分解临时变量)或Separate Query form Modifier (将查询函数和修改函数分离)使情况变得简单一些,然后再替换临时变量。如果你想替换的临时变量是用来收集结果的)例如循环中的累加值),就需要将某些程序逻辑(例如循环)复制到查询函数去。

    做法:1、找出只被赋值一次的临时变量。如果某个临时变量被赋值超过一次,考虑使用Split Temporary Variable (分解临时变量)将它们分解成多个变量。

             2、将该变量声明为final。

             3、编译。这可确保临时变量的确只被赋值一次。

             4、将“对该临时变量赋值”之语句的等号右侧部分提炼到一个独立函数中。首先将函数声明为private。日后你可能会发现有更多的类需要使用它。那是放松对它的保护也很容易。确保提炼出来的函数无任何副作用,也就是说该函数并不修改任何对象内容。如果它有副作用,就对它进行Separate Query form Modifier (将查询函数和修改函数分离).

             5、编译,测试。

             6、在该变量身上实施 Inline Temp (内联临时变量)。

             我们常常使用临时变量保存循环中的累加信息。在这种情况下,这个循环都可以被提炼为一个独立函数,这也使原本的函数可以少掉几行扰人的循环逻辑。有时候,你可能会在一个循环中累加好几个值。这种情况下你应该针对每个累加值重复一遍循环,这样就可以将所有临时变量都替换为查询。当然,循环应该很简单,复制这些代码才不会带来危险。

             运用此手法,你可能会担心性能问题。和其他问题一样,我们现在不管它,因为它十有八九根本不会造成任何影响。若是性能真的出了问题,你也可以在优化时期解决它。代码组织良好,你往往能发现更有效的优化方案。如果没用进行重构,好的优化方案就可能与你失之交臂。如果性能实在太糟糕,要把临时变量放回去也很容易。

    那么如何使用eclipse来快速重构呢?

    Eclipse refactor菜单中没有直接的对应项,

    不过仍可以简单的组合[ExtractMethod] + [Inline] 完成对应的重构

    //  选中_quantity * _itemPrice,应用[Extract Method]
    
    double getPrice() {
    
            final int basePrice = basePrice();
    
            final double discountFactor;
    
            if (basePrice > 1000)discountFactor = 0.95;
    
            else discountFactor = 0.98;
    
            return basePrice *discountFactor;
    
        }
    
        private int basePrice() {
    
           return _quantity * _itemPrice;
    
        }
    
     
    
    //  选中basePrice, 应用[Inline] 
    
        double getPrice() {
    
            final int basePrice = basePrice();
    
            final double discountFactor;
    
            if (basePrice() > 1000) discountFactor = 0.95;
    
            else discountFactor = 0.98;
    
            return basePrice() * discountFactor;
    
        }
    
        private int basePrice() {
    
            return _quantity * _itemPrice;
    
        }

    总结:使用此种手段重构,一般仅限于在此函数内部存在局部变量,并且这个局部变量只赋值一次,其它地方都是引用;那么这个时候就可以采用使用查询来代替临时变量了;但是如果这个变量只是赋值一次,并且也就只使用了一次,那么简易直接采用临时变量内联的方式解决。

    小技巧:如何看这个临时的局部变量是否只赋值一次,我们可以将其声明为final类,如果再出现赋值,那么就会报错了。

  • 相关阅读:
    基于python实现自动化办公学习笔记一
    [django]上下文管理器
    [django]中间件
    分布式锁实现
    为什么Redis可以方便地实现分布式锁
    索引字段说明
    COUNT 和 IFNULL函数
    占用空间区别
    java排序算法(七):折半插入排序
    java排序算法(六):直接插入排序
  • 原文地址:https://www.cnblogs.com/pony1223/p/7523442.html
Copyright © 2011-2022 走看看