七、重構4:使用“以查詢取代臨時變量”再次對Statement()方法進行重構
1. 經過了之前幾篇文章的重構后,Customer中的statement()方法的具體代碼,如下圖所示。在計算每部電影的金額和積分時,我們調用的是Rental類的對象的相應的方法。下圖中的方法與充電項計費項目的原始代碼中的方法相比可謂是簡潔了許多,而且易於理解與維護。
2.不過上面的代碼仍然有重構的空間,舉個例子,如果我們要將結果以HTML的形式進行組織的話,我們需要將上面的代碼進行復制,然后修改result變量的文本組織方式即可。這可能就是程序員經常做的事情Ctrl+C、Ctrl+V,很多程序員是這樣來修改代碼的,這種修改代碼快速,功能實現方便,但是這樣的修改代碼會給我們的系統遺留很多無用的代碼。使用Ctrl+C、Ctrl+V這種非常方便的方式來修改代碼,會造成方法中的好多臨時變量都被復制一份,這是完全相同的,這樣就容易產生重復的代碼。在這種情況下,我們需要使用“Replace Temp with Query”(已查詢取代臨時變量)的重構手法來取出上圖所示的紅框中的臨時變量。
上圖中紅框所框出來的每個臨時變量我們都會提取出一個查詢方法,下圖中所示的代碼,就是使用“Replace Temp with Query”(已查詢取代臨時變量)規則重構后的Statement()方法,以及提取的兩個查詢函數。
3.經過上面這些步驟的重構,Customer類的具體代碼如下所示:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace LeasePowerBank { /// <summary>
/// 客戶類 /// </summary>
public class Customer { string Name;//用戶名稱
public List<Rental> listRentals=new List<Rental>();//用戶租賃的充電寶
public Customer(string name) { Name = name; } public void AddRental(Rental rental) { listRentals.Add(rental); } public string Statement() { string result = $"{Name} 的租賃賬單:\n"; result += $"總金額為:{GetTotalAmount()}\n"; result += $"你本次獲得了:{GetTotalFrequentRenterPoints()}積分 "; return result; } /// <summary>
/// 計算總金額 /// </summary>
private decimal GetTotalAmount() { decimal totalAmount = 0M; //總金額
foreach (var item in listRentals) { totalAmount+= item.GetAmount();//總價計算
} return totalAmount; } /// <summary>
/// 計算積分 /// </summary>
private decimal GetTotalFrequentRenterPoints() { int frequentRenterPoints = 0; //用戶積分
foreach (var item in listRentals) { frequentRenterPoints += item.GetFrequentRenterPoints();//計算積分
} return frequentRenterPoints; } } }
4. 我們的測試用例依然不變。在每次重構后我們都需要調用上述的測試用例來檢查重構是否產生了副作用。現在我們的類間的依賴關系沒怎么發生變化,只是相應類中的方法有些變化。在Visual Studio 2019的菜單欄上找到“測試-->運行所有測試”菜單項。或者在“測試資源管理器中”選擇 “在視圖中運行所有測試”按鈕, 運行測試用例。監測重構的結果是否正確。如下圖。