Extract Method(提炼函数)

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

修改后:

void printOwing(double amount){ 
    printBanner();
    printDetails(amount);
}

void printDetails(double amount){ 
    System.out.println("name:" + _name);
    System.out.println("amount" + amount);
}

做法

  • 创造一个新函数,根据这个函数的意图来对它命名(以它”做什么”来命名,而不是以它”怎么做”命名)

    即使你想要提炼的代码非常简单,例如只是一条消息或一个函数调用,只要新函数的名称能够以更好的方式昭示代码意图,你也应该提炼它。但如果你想不出一个更有意义的名称,就别动

  • 将提炼出来的代码从源函数复制新建的目标函数中

  • 仔细检查提炼出的代码,看看其中是否引用了”作用域限于源函数”的变量(包括局部变量和源函数参数)

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

  • 检查被提炼代码段,看看是否有任何局部变量的值被它改变。如果一个临时变量值被修改了,看看是否可以将被提炼代码段处理为一个查询,并将结果赋值给相关变量。如果很难这样做,或如果被修改的变量不止一个,你就不能仅仅将这段代码原封不动地提炼出来。你可能需要先使用Split Temporary Variable(分解临时变量),然后再尝试提炼。也可以使用Replace Temp with Query(以查询取代临时变量)将临时变量消灭掉

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

  • 处理完所有局部变量之后,进行编译

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

    如果你将任何临时变量移到目标函数中,请检查它们原本的声明式是否在被提炼代码段的外围。如果是,现在你可以删除这些声明式了

  • 编译,测试

范例

范例:无局部变量

void printOwing(){
        Enumeration e = _order.elements();
    double outstanding = 0.0;

      // pring 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);
    System.out.println("amount"+outstanding);
}

修改后:

void printOwing(){
    Enumeration e = _order.elements();
    double outstanding = 0.0;

    printBanner();

    // calculate outstanding
    while (e.hasMoreElements()){
        Order each = (Order) e.nextElement();
        outstanding += each.getAmount();
    }

    // print details
    System.out.println("name:"+_name);
    System.out.println("amount"+outstanding);
}

void printBanner(){
    System.out.println("*************************");
    System.out.println("***** Customer Owes *****");
    System.out.println("*************************");
}

范例:有局部变量

void pringOwing(){
    Enumeration e = _order.elements();
    double outstanding = 0.0;

    printBanner();

    // calculate outstanding
    while (e.hasMoreElements()){
        Order each = (Order) e.nextElement();
        outstanding += each.getAmount();
    }

    // print details
    System.out.println("name:"+_name);
    System.out.println("amount"+outstanding);
}

修改后:

void printOwing(){
    Enumeration e = _order.elements();
    double outstanding = 0.0;

    printBanner();

    // calculate outstanding
    while (e.hasMoreElements()){
        Order each = (Order) e.nextElement();
        outstanding += each.getAmount();
    }

    printDetails(outstanding);
}

void printDetails(double outstanding){
    System.out.println("name:"+_name);
    System.out.println("amount"+outstanding);
}

范例:对局部变量再赋值

void printOwing(){
    Enumeration e = _order.elements();
    double outstanding = 0.0;

    printBanner();

    // calculate outstanding
    while (e.hasMoreElements()){
        Order each = (Order) e.nextElement();
        outstanding += each.getAmount();
    }

    printDetails(outstanding);
}

修改后:

void printOwing(){
    printBanner();
    double outstanding = getOutstanding();
    printDetails(outstanding);
}

double getOutstanding(){
    Enumeration e = _order.elements();
    double result = 0.0;
    while (e.hasMoreElements()){
        Order each = (Order) e.nextElement();
        result += each.getAmount();
    }
    return result;
}
void printOwing(double previousAmount){
    printBanner();
    double outstanding= getOutstanding(previousAmount * 1.2);
    printDetails(outstanding);
}

double getOutstanding(double initialValue){
    double result = initialValue;
    Enumeration e = _order.elements();
    while (e.hasMoreElements()){
        Order each = (Order) e.nextElement();
        result += each.getAmount();
    }
    return result;
}