你有一段代码可以被组织在一起并独立出来

讲这段代码放在一个独立函数中,并让函数名称解释该函数的用途

范例:无局部变量

void printOwing(double amount){
printBanner();
//printDetail
System.out.println("name:"+_name);
System.out.println("amount:"+amount);
}
重构后代码:
void printOwint(double amount){
printBanner();
printDetail(amount);
}
void printDetail(double amount){
System.out.println("name:"+_name);
     System.out.println("amount:"+amount);
}

动机


Extra Method(提炼函数)是最常用的重构手法之一。当看见一个过长的函数或者一段需要注释才能让人理解用途的代码,就应该将这段代码放进一个独立的函数中去。




范例:有局部变量


果真这么简单?这个重构手法的困难点在哪里?是的,就在局部变量,包括传进源函数的参数和源函数所声明的零时变量。局部变量的作用域仅限于源函数,所以当我使用Extra Method(提炼函数)时,必须花费额外功夫去处理这些变量。某些时候它们可能妨碍我,使我根本无法进行这项重构。


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




void printOwing{
 
Enumeration e=orders.elements();
 
double outstanding=0.0;
 
printBanner();
 
 
 
 
//calculate outstanding
 
 
while(e.hasMoreElements){
 
 
 Order order=(Order)e.nextElement();
 
outstanding +=each.getAmount();
 
} 
 
System.out.println("name:"+_name);
 
System.out.println("amount:"+outstanding);
 

 
}
 
 
 
 
 
 
 
就可以讲打印详细信息提炼为带一个参数的函数:
 
void printOwing{
 
 
Enumeration e=orders.elements();
 
 
double outstanding=0.0;
 
 
printBanner();
 
 
 
  
 
 
//calculate outstanding
 
  
 
while(e.hasMoreElements){
 
 
 
  Order order=(Order)e.nextElement();
 
 
outstanding +=each.getAmount();
 
 
} 
 
 
printDetails(outstading); 
 
 
 
}
 
 

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

 
 
必要的话可以用这种手法处理多个局部变量



范例:对局部变量再赋值




如果被提炼的代码对局部变量赋值,问题就变得复杂了。这里只讨论临时变量的问题。如果你发现源函数的参数被赋值,应该马上使用Remove Assignments to Parameters(131)。


被赋值的临时变量也分为两种情况。较简单的情况是:这个变量只在被提炼的代码段中使用。果真如此,你可以将这个临时变量的声明移动到被提炼的代码段中,然后一起提炼出去。另一种情况是:被提炼代码段之外的代码也使用了这个变量。这又分为两种情况:如果这个变量在被提炼代码段之后再未被使用,你只需要在目标函数中修改它就可以了;如果被提炼代码段之后的代码还使用了这个变量,你就需要让目标函数返回该变量改变后的值。下列代码可以说明这几种不同的情况。




void printOwing(){
 
 
Enumeration e=_orders.elements();
 
 
double outstanding=0.0;
 
 
printBanner();
 
 
//calculate outstanding
 
 
while(e.hasMoreElements){
 
 
Order order=(Order)e.nextElement();
 
 
outstanding+=order.getAmount();
 
 
}
 
 
printDetails(outstanding); 
 
 
 
  
 
 
}
 
 

 
 
现在把“计算”代码提炼出来:
 
 
 
  
void printOwing(){
 
  
printBanner();
 
  
double outstanding=getOutstanding();
 
  
printDetails(outstanding); 
 
  
 
   
 
  
}
 
  
 
 
double getOutstanding(){
 
 
 
  
Enumeration e=_orders.elements();
 
  
double outstanding=0.0;
 
  
while(e.hasMoreElements){
 
  
Order order=(Order)e.nextElement();
 
  
outstanding+=order.getAmount();
 
  
}
 
  
return outstading;
 
 
}