[軟體工程] 作業三_軟體程式重構(Refactoring)與先測試(Test-first develompent)開發流程
Q1:請列舉出至少5項Refactoring的方式。-- From 中正大學 熊博安教授 實驗室
A1:
重構的主要目的是使程式碼變簡單,質量更高、更有效率,同時保持架構清楚且有邏輯,令人一目了然。以下是程式碼常見的問題與重構的應用。
A. 保持物件完整
問題: 從某個物件中取值,再把它們變成其他函數的輸入值。
int low = daysTempRange.getLow();
int high = daysTempRange.getHigh();
boolean withinPlan = plan.withinRange(low, high);
解決: 改成傳遞整個物件,可以讓程式碼更精簡,而不是定義多行的程式碼
boolean withinPlan = plan.withinRange(daysTempRange);
B. 以物件取代陣列
問題: 有一個陣列裡面的元素代表不同的東西。例如:第0是Liverpool、第1是15
String[] row = new String[3];
row[0] = "Liverpool";
row[1] = "15";
解決: 以物件代替陣列。對於陣列中的每一個元素以一個欄位表示。例如:setName為Liverpool、setWins為15
Performance row = new Performance();
row.setName("Liverpool");
row.setWins("15");
C. 提煉函數
問題: 一段程式碼中,有一些函數可以整合在一起。
void printOwing() {
printBanner();
//print details
System.out.println("name: " + name);
System.out.println("amount: " + getOutstanding());
}
解決: 移動這段程式碼到一個新的函數中,呼叫函數來替代原有的程式碼
void printOwing() {
printBanner();
printDetails(getOutstanding());
}
void printDetails(double outstanding) {
System.out.println("name: " + name);
System.out.println("amount: " + outstanding);
}
D. 分解條件表示式
問題: 條件式很複雜,無法讓人一眼看出其中的條件判斷。
if (date.before(SUMMER_START) || date.after(SUMMER_END)) {
charge = quantity * winterRate + winterServiceCharge;
}else {
charge = quantity * summerRate;
}
解決: 將條件拆解成幾個函數,可以清楚了解其中的邏輯。
if (notSummer(date)) {
charge = winterCharge(quantity);
}else {
charge = summerCharge(quantity);
}
E. 以查詢取代臨時變數
問題: 正在使用臨時變數basePrice來儲存表示式的結果。
double basePrice = _quantity * _itemPrice;
if (basePrice > 1000){
return basePrice * 0.95;
}
else{
return basePrice * 0.98;
}
解決: 想辦法代替臨時變數,可用呼叫函數的方式。利用basePrice()當作條件式參數,呼叫函數計算_quantity*_itemPrice。
if (basePrice() > 1000){
return basePrice() * 0.95;
}
else{
return basePrice() * 0.98;
}
...
double basePrice() {
return _quantity * _itemPrice;
}
F. 利用符號來替代魔法數字(科學常數、特定意義的數值等等)
問題: 將重力寫成9.81的數值。
double potentialEnergy(double mass, double height) {
return mass * 9.81 * height;
}
解決: 將9.81改寫成GRAVITATIONAL_CONSTANT,再針對常數做定義,避免使用這種魔法數字。
double potentialEnergy(double mass, double height) {
return mass * GRAVITATIONAL_CONSTANT * height;
}
static final double GRAVITATIONAL_CONSTANT = 9.81;
-------------------------我是分隔線-------------------------
Q2: 舉出測試優先(Test-first development)的優點與潛在難處。
A2:
優點:
1. 避免設計難以測試的原件-因為必須先寫好測試程式,這會迫使我們去想元件實現的功能為何,同時可以避免當初寫好的程式碼不知道如何測試,造成必須要重新設計的窘境。
2. 階段性驗證程式-測試程式完成後,可以切割成很多個階段,透過每一段來驗證程式的正確性,可以確保程式在設計的過程中有階段性地達到功能。當發生測試錯誤時,可以退回上一個階段,重新檢視程式。
3. 不會捨棄測試程式-傳統開發流程會著重在需求與設計兩個主軸,有時候會因為時程開發有延遲,而捨棄一些測試的流程,或是直接跳過測試。但是測試導向的開發會先寫好測試程式,再進行設計。
潛在難處:
當我們不知道需求時,很難先寫好測試的程式,因為不知道元件最終會有什麼功能。對於實驗性或是需求不明的程式撰寫,必須先以需求與設計為主軸,才不會本末倒置。一般的資源配置會耗費較多時間在程式撰寫的階段,測試對於利害關係人而言只是驗證程式的一環,而不會願意耗費較多的時間在測試階段。
留言
張貼留言