zoukankan      html  css  js  c++  java
  • 第2章 重新组织函数(1):提炼函数

    1. 提炼函数(Extract Method)

    1.1 动机

    (1)函数的粒度小,被复用的机会就会更大。而且细粒度的函数覆写也会更容易。

    (2)简短而命名良好的函数,会使高层函数读起来就像一系列注释

    1.2 做法

    (1)创建一个新函数,并根据函数的意图命名(以它“做什么”来命名,而不是以它“怎么做”命名)

    (2)将提炼出的代码从源函数复制到新建的目标函数中。

    (3)仔细检查提炼出的代码,看看其中是否引用了“作用域限于源函数”的变量(即是否使用了源函数中的局部变量或参数)

    (4)检查是否有“仅用于被提炼代码段”的临时变量。如果有,在目标函数中将它们声明为临时变量。

    (5)检查被提炼代码段,看看是否有任何局部变量的值被它改变。如果有一个临时变量的值被修改了,看看是否可以被将提炼代码炼处理为一个查询,并将结果赋值给相关变量。如果被修改的变量不止一个,可以先用Split Temporary Variable,然后再尝试提炼。也可以使用Replace Temp with Query将临时变量消灭掉。

    (6)将被提炼代码段中需要读取的局部变量,当作参数传给目标函数。

    (7)在源函数中,将被提炼代码段替换为对目标函数的调用。

    1.3 范例

    //重构前(Java)

    //源函数
    void printOwing(double previousAmount)
    {
        Enumeration e = _orders.elements(); //_orders是类的成员变量
        double outstanding = previousAmount * 1.2;
        
        //print banner(无局部变量)
        System.out.println("*****************************");
        System.out.println("********Customer Owes********");
        System.out.println("*****************************");
        
        //calculate outstanding
        while(e.hasMoreElements())
        {
            Order each = (Order) e.nextElement();
            outstanding += each.getAmount();
        }
        
        //print details
        System.out.println("name:" + _name);//_name为成员函数
        System.out.println("amount" + outstanding);//outstanding为局部变量
    }

    //重构后

    //经Extract Method 提炼后的函数
    void printOwing(double previousAmount)
    {    
        printBanner();
        
        double outstanding = getOutstanding(previousAmount * 1.2);
        
        printDetail(outstanding);
    }
    
    
    //无局部变量,直接提取(函数名以意图命令)
    void printBanner()
    {
        //print banner
        System.out.println("*****************************");
        System.out.println("********Customer Owes********");
        System.out.println("*****************************");    
    }
    
    //有局部变量outstanding,将其作为参数传递给目标函数(函数名以意图命令)
    void printDetails(double outstanding)
    {
        System.out.println("name:" + _name);
        System.out.println("amount" + outstanding);
    }
    
    //对局部变量再赋值,分为两种情况:(函数名以意图命令)
    //1.该变量只在被提炼代码中使用时,可直接将该变量的声明移到目标函数中
    //2.该变量在被提炼代码之个也使用了这个变量,又分两种情况
    //   A.变量在被提炼代码之后未再被使用,只需直接在目标函数中修改它便可
    //   B.变量在被提炼代码之后还被使用,可让目标函数返回修改后的变量(本例属这情况)
    double getOutStanding(double initValue)
    {
       //源函数中变量e只在被提炼代码段中用到,可搬到新函数中定义
        Enumeration e = _orders.elements();
        
        //源函数中outstanding在被提炼代码段内外都被使用,可让目标函数返回该值
        double result = initValue; //outstanding
        
        //calculate outstanding
        while(e.hasMoreElements())
        {
            Order each = (Order) e.nextElement();
            result += each.getAmount();
        }    
        
        return result;
    }

    1.4 思考

    (1)Extract Method最大的困难是处理局部变量,而临时变量是其中之一。

    (2)可以用Replace Temp with Query去掉所有可去掉的临时变量。

    (3)如果很多地方使用了某个临时变量,可用Split Temporary Variable将它变得比较容易替换。

    (4)也可以用Replace Method with Method Object引入一个新类也处理临时变量。

    (5)参数带来的问题比较容易处理。但如果在函数内赋值给参数了,可以用Remove Assignments to Parameters来处理。

  • 相关阅读:
    Linux查看密码
    zabbix 邮件报警配置
    Linux 修改zabbix server的web访问端口
    Zabbix 配置监控主机
    Linux 安装zabbix
    Json解析注解 ---@SerializedName
    IntelliJ IDEA 设置背景图片
    @Override is not allowed when implementing interface method
    nginx ------反向代理和负载均衡
    IntelliJ IDEA 性能优化
  • 原文地址:https://www.cnblogs.com/5iedu/p/5935614.html
Copyright © 2011-2022 走看看