重复代码---提炼函数(Extract method)

一、Extract Method:提炼方法java

将有些代码单独提取出来放入到一个独立的函数中,并让函数名称来解释该函数的用途。函数

 

[java]  view plain  copy
 
  1. public void printOwing(double amount) {  
  2.     printBanner();  
  3.     System.out.println("name:" + name);  
  4.     System.out.println("amount:" + amount);  
  5. }  

能够写成:测试

 

 

[java]  view plain  copy
 
  1. public void printOwing(double amount) {  
  2.     printBanner();  
  3.     printDetails(amount);  
  4. }  
  5.   
  6. /** 
  7.  * 描述:打印详情 
  8.  */  
  9. public void printDetails(double amount) {  
  10.     System.out.println("name:" + name);  
  11.     System.out.println("amount:" + amount);  
  12. }  

当看到一个过长的函数或须要注释才能让人理解的代码,应该考虑将这段代码放到一个单独的独立函数中。spa

 

作法:.net

一、建立一个新的函数,根据函数的意图来命名。blog

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

三、仔细检查提炼出来的代码,看其中是否引用了做用域仅限于源函数的变量。作用域

四、检查是否有仅限于被提炼码的临时变量,若是有,在目标函数中将它申明为局部变量。get

五、检查提炼码,看是否有任何局部变量的值被改变,若是有一个临时变量的值被改变,看是否可以将提炼码处理为一个查询,并将结果赋值给临时变量。it

六、被提炼码中须要读取的局部变量,经过参数传递给目标函数。

七、处理完全部局部变量后编译,在源函数中替换目标函数,测试。

例子:

 

[java]  view plain  copy
 
  1. private String name;  
  2. private Vector<Order> orders = new Vector<Order>();  
  3.   
  4. public void printOwing() {  
  5.     Enumeration env = orders.elements();  
  6.     double totalAmount = 0.0;  
  7.     System.out.println("****************");  
  8.     System.out.println("***** test *****");  
  9.     System.out.println("****************");  
  10.   
  11.     while (env.hasMoreElements()) {  
  12.         Order order = (Order) env.nextElement();  
  13.         totalAmount += order.getAmout();  
  14.     }  
  15.   
  16.     System.out.println("name:" + name);  
  17.     System.out.println("amount:" + totalAmount);  
  18. }  

提取没有局部变量的函数:

 

 

[java]  view plain  copy
 
  1. private void printBanner() {  
  2.     System.out.println("****************");  
  3.     System.out.println("***** test *****");  
  4.     System.out.println("****************");  
  5. }  

提取有局部变量的函数:

 

若是被提炼码只是须要读取这些变量的值,并不修改他们,这时候咱们只须要将它做为一个参数传递给目标函数便可,例:

 

[java]  view plain  copy
 
  1. public void printDetails(double amount) {  
  2.     System.out.println("name:" + name);  
  3.     System.out.println("amount:" + amount);  
  4. }  

若是被提炼码对局部变量进行赋值:

 

一、这个变量只是在提炼码区域中使用,那么能够将这个临时变量的申明式移动到提炼码中,而后一块儿提炼出去。

二、若是被提炼码以外的代码也使用了这个变量,可分为:

     1)、若是这个变量在被提炼码以后未再被使用,只须要在目标函数中修改它的值便可。

     2)、若是在提炼码以后还要使用该变量,这个时候就须要让目标函数返回该变量改变后的值。

一、提取getTotalAmount():

 

[java]  view plain  copy
 
  1. /** 
  2.  * 描述:获取总帐户余额 
  3.  */  
  4. public double getTotalAmount() {  
  5.     double totalAmount = 0.0;  
  6.     Enumeration env = orders.elements();  
  7.     while (env.hasMoreElements()) {  
  8.         Order order = (Order) env.nextElement();  
  9.         totalAmount += order.getAmount();  
  10.     }  
  11.     return totalAmount;  
  12. }  

这个时候的getOwing()可写成:

 

 

[java]  view plain  copy
 
  1. public void printOwing() {  
  2.     printBanner();  
  3.     double totalAmount = getTotalAmount();  
  4.     printDetails(totalAmount);  
  5. }  

这里若是totalAmount初始值不是0,而有一个初值,这个时候就须要将这个初值传入到目标函数中去。

 

[java]  view plain  copy
 
  1. public void printOwing(double initAmount) {  
  2.     printBanner();  
  3.     double totalAmount = initAmount * 1.5;  
  4.     totalAmount = getTotalAmount(totalAmount);  
  5.     printDetails(totalAmount);  
  6. }  
  7.   
  8. /** 
  9.  * 描述:获取总帐户余额 
  10.  */  
  11. public double getTotalAmount(double initAmount) {  
  12.     double totalAmount = initAmount;  
  13.     Enumeration env = orders.elements();  
  14.     while (env.hasMoreElements()) {  
  15.         Order order = (Order) env.nextElement();  
  16.         totalAmount += order.getAmount();  
  17.     }  
  18.     return totalAmount;  
  19. }  

临时变量每每不少,这个时候能够考虑Replace Temp with Query(以查询方法替代临时变量),若是这样依旧困难,能够考虑Replace method with method object(以函数变量替换函数)。

相关文章
相关标签/搜索