zoukankan      html  css  js  c++  java
  • 重构方法之一:提炼方法(Extract Method)读书笔记

    第六章 重新组织你的函数

    6.1  Extract Method(提炼方法)

    对付过长函数,一般重要的重构方法就是Extract Method,他把一段代码从原先的函数中提取出来,放在单独的函数中。简洁而清晰,短小而精炼。

     

    1 void printOwing (douoble amount)
    2 {
    3     printBanner();
    4     //print details
    5     System.out.println(“name:”+_name);
    6     System.out.println(“amount”+amount);
    7 }

     

    提炼后:

     1 void printOwing (douoble amount)
     2 
     3 {
     4 
     5     printBanner();
     6 
     7     printDetails();
     8 
     9 }
    10 
    11 Void printDetails(double amount)
    12 
    13 {
    14 
    15     System.out.println(“name:”+_name);
    16 
    17     System.out.println(“amount”+amount);
    18 
    19 }

    Extract Method最大的困难就是处理局部变量,所以需要注意一下步奏。

    做法:

    1、创造一个新的函数,根据这个函数的意图来给他命名(以它[做什么]命名,而不是以它[怎么做]命名)。

    2、将提炼出来的代码从源函数(source)拷贝到新建的目标函数(target)中。

    3、仔细检查提炼出来的代码,是否引用了[作用域限于源函数]的变量(包括局部变量和源函数参数)。

    4、检查是否有[仅用于被提炼代码]的临时变量。如果有,在目标函数中将他们声明为临时变量。

    5、检查被提炼码,看看是否有任何局部变量的值被它改变,或者被修改的变量不止一个,就不能原封不动的提炼出来了。

    6、将被提炼码中需要读取的局部变量,当做参数传给目标函数。

    7、处理完所有的局部变量,在原函数中调用。

    实例:

    范例一:无局部变量

    提炼前:

     1 Void printOwing()
     2 
     3 {
     4 
     5     Enumeration e=_orders.elements();
     6 
     7     Ddouble outstanding=0.0;
     8 
     9  
    10 
    11     //print banner
    12 
    13     System.out.println(“*****************************”);
    14 
    15     System.out.println(“********Customer Owes********”);
    16 
    17     System.out.println(“*****************************”);
    18 
    19  
    20 
    21     //calculate outstanding
    22 
    23     While(e.hasMoreElements())
    24 
    25     {
    26 
    27     Order each=(Order) e.nextElement();
    28 
    29     Outstanding+=each.getAmount();
    30 
    31     }
    32 
    33  
    34 
    35     //print details
    36 
    37     System.out.println(“name:”+_name);
    38 
    39     System.out.println(“amount”+outstanding);
    40 
    41 }
    View Code

    我们可以轻松的提炼出 print banner 的代码。

     1     Void printOwing()
     2     
     3     {
     4 
     5     Enumeration e=_orders.elements();
     6 
     7     Ddouble outstanding=0.0;
     8 
     9     print Banner();
    10 
    11     //calculate outstanding
    12 
    13     While(e.hasMoreElements())
    14 
    15     {
    16 
    17     Order each=(Order) e.nextElement();
    18 
    19     Outstanding+=each.getAmount();
    20 
    21     }
    22 
    23     //print details
    24 
    25     System.out.println(“name:”+_name);
    26 
    27     System.out.println(“amount”+outstanding);
    28 
    29     }
    30 
    31     Void printBanner()
    32 
    33     {
    34 
    35     //print banner
    36 
    37     System.out.println(“*****************************”);
    38 
    39     System.out.println(“********Customer Owes********”);
    40 
    41     System.out.println(“*****************************”);
    42 
    43     }
    View Code

    范例二:有局部变量

    局部变量最简单的情况是:被提炼码只是读取这些变量的值,并不修改它们,这种情况下可以简单地将它们当做参数传给目标函数。

    提炼前:

     1     Void printOwing()
     2 
     3     {
     4 
     5     Enumeration e=_orders.elements();
     6 
     7     Ddouble outstanding=0.0;
     8 
     9     print Banner();
    10 
    11     //calculate outstanding
    12 
    13     While(e.hasMoreElements())
    14 
    15     {
    16 
    17     Order each=(Order) e.nextElement();
    18     
    19     Outstanding+=each.getAmount();
    20 
    21     }
    22 
    23     //print details
    24 
    25     System.out.println(“name:”+_name);
    26 
    27     System.out.println(“amount”+outstanding);
    28     }
    View Code

    提炼后:

     1   void printOwing()
     2 
     3     {
     4 
     5     Enumeration e=_orders.elements();
     6 
     7     Ddouble outstanding=0.0;
     8 
     9     print Banner();
    10 
    11     //calculate outstanding
    12 
    13     While(e.hasMoreElements())
    14 
    15     {
    16 
    17     Order each=(Order) e.nextElement();
    18 
    19     Outstanding+=each.getAmount();
    20 
    21     }
    22 
    23     printDetails(outstanding);
    24 
    25     }
    26 
    27     Void printDetails(double outstanding)
    28 
    29     {
    30 
    31     System.out.println(“name:”+ _name);
    32 
    33     System.out.println(“amount”+ outstanding);
    34 
    35     }
    View Code

    处理多个局部变量也可以使用上述这种方法。

    范例三:对局部变量再赋值

    如果被提炼码对局部变量赋值,问题就变得复杂了,这里我们只讨论临时变量的问题。

    被赋值的临时变量也分为两种情况。比较简单的情况是:这个变量只是在被提炼码中使用,这样,可以将这个临时变量的声明一道被提炼码中,然后一起提炼出去。另一种情况是:被提炼码之外的代码也是用了这个变量。

    提炼前:

     1     Void printOwing()
     2 
     3     {
     4 
     5     Enumeration e=_orders.elements();
     6 
     7     Ddouble outstanding=0.0;
     8 
     9     print Banner();
    10     
    11     //calculate outstanding
    12 
    13     While(e.hasMoreElements())
    14     {
    15 
    16     Order each=(Order) e.nextElement();
    17 
    18     Outstanding+=each.getAmount();
    19 
    20     }
    21 
    22     printDetails(outstanding);
    23 
    24     }
    View Code

    提炼后:

     1  void printOwing()
     2 
     3     {
     4 
     5     print Banner();
     6 
     7     Double outstanding=getOutstanding();
     8 
     9     printDetails(outstanding);
    10 
    11     }
    12 
    13     Double getOutstanding()
    14 
    15     {
    16 
    17     Enumeration e=_orders.elements();
    18 
    19     Ddouble outstanding=0.0;
    20 
    21     While(e.hasMoreElements())
    22 
    23     {
    24 
    25     Order each=(Order) e.nextElement();
    26 
    27     Outstanding+=each.getAmount();
    28 
    29     }
    30     
    31     Return outstanding();
    32 
    33     }
    View Code

    Enumeration 变量e只是在被提炼码中使用到,所以可以将它整个搬到新函数中。Double 变量 outstanding在被提炼码内外都被用到,所以必须让提炼出来的新喊出返回它。

    这个例子中,outstanding变量只是很简单的被初始化为一个明确的值,所以可以只在新函数中对它初始化。如果代码还对这个变量做了其他处理,就必须将它的值作为参数传给目标函数。对于这种变化,最初的代码可能是这样:

     1 Void printOwing(double previousAmount )
     2 
     3 {
     4 
     5     Enumeration e=_orders.elements();
     6 
     7     Ddouble outstanding=previousAmount * 1.2;
     8 
     9     print Banner();
    10 
    11     //calculate outstanding
    12 
    13     While(e.hasMoreElements())
    14 
    15     {
    16 
    17     Order each=(Order) e.nextElement();
    18 
    19     Outstanding+=each.getAmount();
    20 
    21     }
    22 
    23     printDetails(outstanding);
    24 
    25 }
    View Code

    提炼后:

    Void printOwing()
    
    {
    
        Ddouble outstanding=previousAmount * 1.2;
    
        print Banner();
    
        Double outstanding=getOutstanding(outstanding);
    
    //Double outstanding=getOutstanding(previousAmount * 1.2);
    
        printDetails(outstanding);
    
    }
    
        Double getOutstanding(double initialValue))
    
    {
    
        Ddouble outstanding=initialValue;
    
        Enumeration e=_orders.elements();
    
        While(e.hasMoreElements())
    
        {
    
        Order each=(Order) e.nextElement();
    
        Outstanding+=each.getAmount();
        
        }
    
        Return outstanding();
    }
                                                                                                        
    View Code

     

  • 相关阅读:
    Mybatis 的 xml 文件语法错误,启动项目时控制台一直循环解析但是不打印错误
    在一个由 'L' , 'R' 和 'X' 三个字符组成的字符串(例如"RXXLRXRXL")中进行移动操作。一次移动操作指用一个"LX"替换一个"XL",或者用一个"XR"替换一个"RX"。现给定起始字符串start和结束字符串end,请编写代码,当且仅当存在一系列移动操作使得start可以转换成end时, 返回True。
    【Important】数据库索引原理
    服务化的演变和负载均衡
    【问题集】redis.clients.jedis.exceptions.JedisDataException: ERR value is not an integer or out of range
    【Spring】Spring中用到的设计模式
    【设计模式】责任链模式
    【!Important】Zookeeper用来做什么的,有几种类型的节点
    【!Important】如何保证线程执行的先后顺序
    【!Important】Java线程死锁查看分析方法
  • 原文地址:https://www.cnblogs.com/yynzh21/p/3951795.html
Copyright © 2011-2022 走看看