文章目錄
- 解釋:
- 衝動前:
- 衝動後:
- 解釋:
- 衝動前:
- 衝動後:
- 解釋:
- 衝動前:
- 衝動後:
- 解釋:
- 衝動前:
- 衝動後:
- 解釋:
- 衝動前:
- 衝動後:
- 解釋:
- 衝動前:
- 衝動後:
- 解釋:
- 解釋:
- 衝動前:
- 衝動後:
1. Decompose Conditional (分解條件式)解釋:
"複雜的條件邏輯" 是導致複雜性上升最常見的地方, "條件運算式中堆積的計算過程", "條件式表達得不簡潔"等等都是造成複雜的原因. Decompose Conditional 用於將這些複雜的元素從條件運算式中分離出去, 僅在條件運算式中調用簡潔的函數.
這樣做帶來的直接好處是減少重複, 而且代碼的可讀性提高了.
衝動前:
if (date.After(SUMMER_START) && date.Before(SUMMER_END)) charge = days * _price + _summerServiceTip;else charge = days * _price;
衝動後:
if (date.IsSummer()) charge = SummerCharge(days);else charge = WinterCharge(days);
2. Consolidate Conditional Expression (合并條件式)解釋:
如果代碼中有一連串的 if 檢查語句, 檢查語句中的條件不相同, 但最終的行為都是一樣的. 對於這樣的情況, 應該使用 "邏輯與" 和 "邏輯或" 將它們合并成一個條件運算式, 如果嫌這個合并條件後的運算式太羅嗦, 你還可以將這個運算式提取成一個函數.
衝動前:
if (computer.CPU != "T6670") return false;if (computer.RAM != "1.00GB") return false;if (computer.SytemType != "32-bit Operating System") return false;//other compution
衝動後:
if ((computer.CPU != "T6670") || (computer.RAM != "1.00GB") || (computer.SytemType != "32-bit Operating System")) return false;//other compution
你還可以將 if 裡長長的條件運算式提取成一個方法, 如 bool IsStandard(Computer computer), 這樣在原來的 if 語句中只需要調用這個方法即可
3. Consolidate Duplicate Conditional Fragments (合并重複的條件片段)解釋:
如果條件式的每個分支上都有同樣一段代碼, 如果這段代碼對條件分支在執行這段代碼後執行後面的代碼沒有影響, 請將這段代碼移到條件式的外面.
衝動前:
if (date.IsSummer()){ charge = days * _price + _summerServiceTip; PrintDetail();}else{ charge = days * _price; PrintDetail();}//other compution衝動後:
charge = days * _price;if (date.IsSummer()) charge += _summerServiceTip;PrintDetail();//other compution
4. Remove Control Flag (移除控制標誌)解釋:
很多代碼裡執行一個 for 或者 while 迴圈用於尋找一個數組裡特點的元素, 很多時候在迴圈開頭就執行控制標誌的檢查, 滿足檢查條件就繼續執行迴圈尋找元素. 如果這一次尋找到了想要的元素, 就更改控制標誌的值, 讓它下次被檢查出不符合條件, 從而迴圈結束.
這並不是一個很好的做法, 使用諸如 break, continue, return 語句會讓你的代碼意圖更加直接, 更加明顯.
衝動前:
for (int i = 0; i < suspects.Length; i++){ if (!found) { if (suspects[i].Name == guessName) { sendAlert(); found = true; } }}衝動後:
for (int i = 0; i < suspects.Length; i++){ if (suspects[i].Name == guessName) { sendAlert(); break; }}5. Replace Nested Conditional with Guard Clauses (以衛語句取代嵌套條件式)解釋:
許多程式員覺得函數應該只有一個出口 (return), 結果導致函數中的條件邏輯 (Conditional Logic) 本來完全可以終止下面的代碼繼續執行 (因為沒有必要), 結果卻只在函數最後 return, 使人難以看清程式的執行路徑.
Replace Nested Conditional with Guard Clauses 用來解決這個問題, 它能帶給代碼可讀性的提高, 還有效能上一點點的最佳化.
衝動前:
double charge;if (IsSummer(date)){ //... SummerCharge(charge);}else{ //... WinterCharge(charge);}return charge;衝動後:
double charge;if (IsSummer(date)){ //... SummerCharge(charge); return charge;}else{ //... WinterCharge(charge); return charge;}6. Replace Conditional with Polymorphism (以多態取代條件)解釋:
這條重構手法常常用於消除函數中長長的 switch-case 語句. 雖然寫一個個的子類比較繁瑣, 但隨著項目的進行, 好處會體現出來的.
衝動前:
public double Salary(Employee employee){ switch(employee.Type): { case Employee.Engineer { //... } case Employee.Salesman: { //... } //... default: { //... } }}衝動後:
public abstract double Salary(Employee employee);class Engineer : Employee{ public override double Salary(Employee employee) { //... }}class Salesman : Employee{ public override double Salary(Employee employee) { //... }}7. Introduce Null Object (引入 Null 對象)解釋:
如果代碼中出現很多判斷某值是不是為 null , 諸如 if (XXX != null) {//...} else {//...} 這樣的情況, 可以考慮使用 Introduce Null Object 重構手段. 這個手段其實並不難以理解, 可以簡單理解成為某一個物件在為空白狀態下設定預設的範圍和行為, 可以建立一個子類, 繼承父類中需要對 "為空白" 情況下做出響應的虛函數或者範圍. 它是 Null Object 設計模式裡的最基礎最常見的手段.
8. Introduce Assertion (引入斷言)解釋:
嚴格上說, 引入斷言並不是為了簡化條件運算式, 它主要是為了代替條件運算式上面的注釋, 通常這樣的注釋用來解釋下面的條件運算式是基於什麼樣的假設之上的. 通常經過一系列的測試, 發現所寫的斷言在任何情況下都是正確的, 在系統發布的時候可以把它們全部刪除掉.
在 C# 中引入斷言使用 Debug.Assert() 方法, 如果一切假設都是正確的, 則代碼會順利的進行.
衝動前:
//index should between 0 to 10return (customers[index] == "James") ? true : false;
衝動後:
Debug.Assert((index>=0)&&(index <= 10), "Error", "index should between 0 to 10");return (customers[index] == "James") ? true : false;
如果斷言錯誤, 在啟動並執行時候會有一個訊息框給予錯誤資訊的提示.
本文連結: http://www.cnblogs.com/technology/archive/2011/05/14/2046066.html