程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> JAVA編程入門知識 >> Eclipse中自動重構實現探索

Eclipse中自動重構實現探索

編輯:JAVA編程入門知識
 本文用eclipse的自動重構功能對一個程序實例進行重構,目的是探索Eclipse自動重構可以在多大程度上輔助重構這個過程。程序實例使用《Refactoring:Improving the Design of Existing Code》一書中的例子。

Eclipse的自動重構功能能夠很好地支持各種程序元素的重命名,並自動更新相關的引用。Eclipse能夠支持方法、字段在類之間移動,並自動更新引用。Eclipse較好地支持內聯字段、函數的更新替換。Eclipse較好地支持抽取方法、變量等程序元素。

重構的過程是一個不斷嘗試和探索的過程。Eclipse的重構支持撤銷和重做,並且能夠預覽重構結果,這些是很實用的功能。

Eclipse的重命名、抽取方法、移動、內聯功能、更改方法特征符等代碼結構級別的重構方法,是比較成熟同時也值得使用的功能。至於設計結構上的重構,eclipse還不能很好地支持。但是作者相信,自動重構的理念應該是"工具輔助下的重構工作",人仍然承擔大部分重構工作。

一、預備工作

本文使用《Refactoring:Improving the Design of Existing Code》一書第一章的例子。重構前的代碼及每一步重構後的代碼見附件。讀者最好配合《Refactoring:Improving the Design of Existing Code》一書閱讀本文。

Eclipse使用如下版本:


同時安裝了中文語言包。

二、重構第一步:分解並重組statement()

目的:

1、 把statement()函數中的swich語句提煉到獨立的函數amountFor()中。

2、 修改amountFor()參數命名

重構方法:

Extract Method
Rename Method

方法:

1、選中swich語句的代碼塊,在右鍵菜單中選擇"重構/抽取方法",出現參數對話框。Eclipse自動分析代碼塊中的局部變量,找到了兩個局部變量:each和thisAmount。其中,each只是在代碼塊中被讀取,但thisAmount會在代碼塊中被修改。按照重構Extract Method總結出來的規則,應該把each當作抽取函數的參數、thisAmount當作抽取函數的返回值。然而Eclipse並不做區分,直接把這兩個變量當作抽取新方法的參數,如圖。


我們的目的是把在抽取函數中不會被修改的each作為參數;會被修改的thisAmount作為返回值。解決的辦法是,把 double thisAmount = 0; 這行代碼移到switch語句的上面,變成這樣:

double thisAmount = 0;
switch(each.getMovie().getPriceCode()){
case Movie.REGULAR:
thisAmount += 2;
if(each.getDaysRented()>2)
thisAmount += (each.getDaysRented()-2)*1.5;
break;

case Movie.NEW_RELEASE:
thisAmount += each.getDaysRented()*3;
break;

case Movie.CHILDRENS:
thisAmount += 1.5;
if(each.getDaysRented()>3)
thisAmount += (each.getDaysRented()-3)*1.5;
break;
}

選中這段代碼,在右鍵菜單中選擇"重構/抽取方法",eclipse這次變得聰明點了,如圖。


選擇"預覽"按鈕預先查看重構後的結果,符合我們最初的目的。


選擇"確定"按鈕,重構後的代碼片斷如下:

public String statement() {
double totalAmount = 0;
int frequentRenterPoints = 0;
Enumeration rentals = _rentals.elements();
String result = "Rental Record for " + getName() + "";

while(rentals.hasMoreElements()){
Rental each = (Rental)rentals.nextElement();

double thisAmount = amountFor(each);

frequentRenterPoints ++;
if((each.getMovie().getPriceCode())==Movie.NEW_RELEASE &&each.getDaysRented()>1)
frequentRenterPoints ++;

result += "" + each.getMovie().getTitle() + "" +String.valueOf(thisAmount) + "";
totalAmount += thisAmount;
}

result += "Amount owed is " + String.valueOf(totalAmount) + "";
result += "You earned " + String.valueOf(frequentRenterPoints) + " frequent renter points";

return result;
}

/**
* @param each
* @return
*/
private double amountFor(Rental each) {
double thisAmount = 0;
switch(each.getMovie().getPriceCode()){
case Movie.REGULAR:
thisAmount += 2;
if(each.getDaysRented()>2)
thisAmount += (each.getDaysRented()-2)*1.5;
break;

case Movie.NEW_RELEASE:
thisAmount += each.getDaysRented()*3;
break;

case Movie.CHILDRENS:
thisAmount += 1.5;
if(each.getDaysRented()>3)
thisAmount += (each.getDaysRented()-3)*1.5;
break;
}
return thisAmount;
}

2、選中amountFor()的參數each,在右鍵菜單中選擇"重構/重命名",在對話框中輸入新的名稱:aRental,選擇確定,amountFor()中所有each的引用全部被替換成新的名稱。用同樣的辦法修改amountFor()中的局部變量thisAmount為result。重構後的amountFor()代碼如下:

/**
* @param aRental
* @return
*/
private double amountFor(Rental aRental) {
double result = 0;
switch(aRental.getMovie().getPriceCode()){
case Movie.REGULAR:
result += 2;
if(aRental.getDaysRented()>2)
result += (aRental.getDaysRented()-2)*1.5;
break;

case Movie.NEW_RELEASE:
result += aRental.getDaysRented()*3;
break;

case Movie.CHILDRENS:
result += 1.5;
if(aRental.getDaysRented()>3)
result += (aRental.getDaysRented()-3)*1.5;
break;
}
return result;
}
  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved