改善代碼設計 —— 簡化函數調用(Making Method Calls Simpler)

作者: Create Chen  來源: 博客園  發布時間: 2011-05-31 21:59  閱讀: 3054 次  推薦: 2   原文鏈接   [收藏]  

  系列博客

      1. 改善代碼設計 —— 優化函數的構成(Composing Methods)

      2. 改善代碼設計 —— 優化物件之間的特性(Moving Features Between Objects)

      3. 改善代碼設計 —— 組織好你的數據(Composing Data)

      4. 改善代碼設計 —— 簡化條件表達式(Simplifying Conditional Expressions)

      5. 改善代碼設計 —— 簡化函數調用(Making Method Calls Simpler)

      6. 改善代碼設計 —— 處理概括關系(Dealing with Generalization)

  1. Parameterize Method (令函數攜帶參數)

  解釋:

      "令函數攜帶參數" 并不是簡單的讓你在函數里加上參數, 如果函數里需要某個參數, 我們誰都會加上它. 你可能發現這樣的幾個函數: 它們做著類似的事情, 只是因為極少的幾個值導致函數的策略不同, 這時可以使用 Parameterize Method 消除函數中那些重復的代碼了, 而且可以用這個參數處理其它更多變化的情況.

      下面有一個非常簡單的例子.

  沖動前:

 
public double FivePercentRaise()
{
_salary
*= 1.05;
return _salary;
}

public double TenPercentRaise()
{
_salary
*= 1.10;
return _salary;
}

  沖動后:

 
public double Raise(int percent)
{
_salary
*= (1 + percent / 100);
return _salary;
}

  2. Replace Parameter with Explicit Methods (用明確的函數取代參數)

  解釋:

      Replace Parameter with Explicit Methods 與 Parameterize Method 是相反的操作. 如果函數內根據不同的參數作出了不同的行為, 那么可以考慮使用明確的函數取代參數. 不過這一條很少用到, 很少出現類似下面例子的垃圾代碼, 建議使用 C# 里的屬性, 即使是"沖動后"的代碼, 在實際中也不是很多見.

  沖動前:

 
public void Set(string name, int value)
{

if(name.Equals("height"))
{
_height
= value;
return;
}

if(name.Equals("width"))
{
_width
= value;
return;
}
}

  沖動后:

 
public void SetHeight(int height)
{
_height
= height;
}

public void SetWidth(int width)
{
_width
= width;
}

  3. Preserve Whole Object (保持對象完整)

  解釋:

      你從某個物件中取出若干值, 將這些值作為參數傳遞給某個函數, 為何不考慮下把整個物件作為傳遞進去呢? 當然具體情況具體分析, 有時你確實需要按你原來做的那樣做.

  沖動前:

 
int height = rectangle.Height;
int width = rectangle.Width;

int area = CalculateArea(height, width);

  沖動后:

 
int area = CalculateArea(rectangle);

  4. Replace Parameter with Methods (以函數取代參數)

  解釋:

      如果函數的某個參數值可以通過方法直接獲得, 這種情況下, 很多時候函數不應該通過參數來獲取該值, 應該在函數里直接通過方法獲取需要的值.

  沖動前:

 
double basePrice = basePrice * num;
double discount = GetDiscount();
double charge = DiscountPrice(basePrice, discount);

  沖動后:

 
double basePrice = basePrice * num;
double charge = DiscountPrice(basePrice);

  5. Introduce Parameter Object (引入參數對象)

  解釋:

      你是否發現有幾個參數總是同時的出現在一些函數的參數列表里? 這幾個參數有一個響亮的臭名 —— 數據泥團(Data Clump), Introduce Parameter Object 讓你將數據泥團封裝成一個對象, 從而在原先的函數直接傳入整個對象即可, 以后還可以對這個對象進行擴展.

      我不主張對于所有的數據泥團都這么做, 哪怕這個數據泥團出現過幾十次上百次, 如果數據泥團的各個數據直接的聯系并不是那么緊密, 它們不能用一個物件籠統的包含它們, 這樣的情況下"引入參數對象"可能并不是很適合.

  6. Remove Setting Method (移除設值函數)

  解釋:

      這一條沒什么好說的, 如果你的類中某個值域只應該在對象初始化時被設值, 那么類中就不應該再有關于這個值域的設值函數, 應該通通把它們刪掉.

  7. Hide Method (隱藏某個函數)

  解釋:

      這一條也沒什么好說的, 如果你的類中某個函數只可能用于類本身的函數調用, 其它類從來沒有用到過, 最好將這個函數的訪問權限設置為 private. 當然這一步要謹慎, 現在沒有被其它類調用過, 不代表以后不會!

  8. Replace Constructor with Factory Method (用工廠函數取代構造函數)

  解釋:

      "以工廠函數取代構造函數" 讓我想起了 "以多態取代條件", 如果你在創建對象的時候不是僅僅對它做簡單的構造, 例如你構造一個 Employee 對象, Employee 可能是工程師, 銷售員, 也有可能是設計師, 應該根據不同的類別的職工創建 Employee 對象.

  9. Encapsulate Downcast (封裝向下轉型動作)

  解釋:

      要找到需要進行 Encapsulate Downcast 重構的函數并不困難, 如果你的函數返回的是 object 類型, 在別的地方調用這個函數獲取一個 object 之后還要進行一下轉型(如將這個 object 轉成 int 類型), 你應該在函數里封裝一下轉型的操作.

  沖動前:

 
public object LastPerson()
{

return _persons.LastElement();
}

  沖動后:

 
public Person LastPerson()
{

return (Person)_persons.LastElement();
}

  10. Replace Error Code with Exception (用異常取代錯誤碼)

  解釋:

      你的函數返回的是一個 int 型, 你約定返回 1 代表這個函數運行正常, 返回 –1 代表某個地方出錯了, 錯誤碼就是指這里的 "1" 和 "-1". 你想想你的函數返回的是錯誤碼, 在調用這個函數的時候極有可能可能還需要判斷你返回的是什么錯誤碼, 如果你收到的是 –1 就停止程序的運行, 書中形容這樣的做法很有趣: 就好像因為錯過一班飛機而自殺一樣, 如果真那么做, 哪怕我是貓, 我的九條命 (注: 貓生命力比較強) 也早就賠光了.

      別忘了 C# 里的異常處理, 這是一個很重要的概念, 是時候使用它們了.

  11. Replace Exception with Test (用測試取代異常)

  解釋:

      "異常處理" 是一個很不錯的功能, 但不要濫用, 對于肯定不會出現異常的代碼塊就不要將它們放入 try...catch 中.

      對于在一定條件下代碼會拋出異常的某些情況, 建議使用 Replace Exception with Test, 你可以在可能拋出異常的代碼前先測試一下運行正常的條件是否滿足, 滿足之后再運行, 不滿足的話則是另一種運行方案, 通過這樣可以代替 try...catch 的使用.

  沖動前:

 
try
{
return _persons[index];
}

catch (IndexOutOfRangeException e)
{

//...
}
//...

  沖動后:

 
if (index < _persons.Length)
return _persons[index];
//...
2
0
 
標簽:重構
 
 

文章列表

arrow
arrow
    全站熱搜
    創作者介紹
    創作者 大師兄 的頭像
    大師兄

    IT工程師數位筆記本

    大師兄 發表在 痞客邦 留言(0) 人氣()