2011-06-24 18 views
3

這是一個簡單的設計決策,似乎對每一方都有重大的熱情。我正在努力去真正瞭解哪種設計的負面影響最小。設計決策:通過方法進行溝通

我要補充一個香蕉的方法:

public Banana AddBanana(string name) 
{ 
    // add the banana 
    var _Banana = new Banana { Name = name }; 
    this.Bananas.Add(_Banana); 
    return _Banana; 
} 

但在某些情況下,我不能添加一個香蕉,像這樣:

public Banana AddBanana(string name) 
{ 
    // test the request 
    if (this.Bananas.Count > 5) 
     return null; 
    if (this.Bananas.Where(x => x.Name == name).Any()) 
     return null; 
    // add the banana 
    var _Banana = new Banana { Name = name }; 
    this.Bananas.Add(_Banana); 
    return _Banana; 
} 

現在,我想回去傳達給呼叫者爲什麼他們不能。

哪種方式更好?

方法1:用一個異常

public Banana AddBanana(string name) 
{ 
    // test the request 
    if (this.Bananas.Count > 5) 
     throw new Exception("Already 5 Bananas"); 
    if (this.Bananas.Where(x => x.Name == name).Any()) 
     throw new Exception("Banana Already in List"); 
    // add the banana 
    var _Banana = new Banana { Name = name }; 
    this.Bananas.Add(_Banana); 
    return _Banana; 
} 

方法2進行通信:與測試

public Class CanAddBananaResult 
{ 
    public bool Allowed { get; set; } 
    public string Message { get; set; } 
} 

public CanAddBananaResult CanAddBanana(string name) 
{ 
    // test the request 
    if (this.Bananas.Count > 5) 
     return new CanAddBananaResult { 
      Allowed = false, 
      Message = "Already 5 Bananas" 
     }; 
    if (this.Bananas.Where(x => x.Name == name).Any()) 
     return new CanAddBananaResult { 
      Allowed = false, 
      Message = "Banana Already in List" 
     }; 
    return new CanAddBananaResult { Allowed = true }; 
} 

public Banana AddBanana(string name) 
{ 
    // test the request 
    if (!CanAddBanana(name).Allowed) 
     throw new Exception("Cannot Add Banana"); 
    // add the banana 
    var _Banana = new Banana { Name = name }; 
    this.Bananas.Add(_Banana); 
    return _Banana; 
} 

在方法1進行通信,消費者知道基於所述exception.Message的問題。

在方法2中,消費者可以防止發生異常而不是抓住異常。

哪種方法更好?

我讀過這樣的內容:設計類,以便在正常使用中不會拋出異常。例如,FileStream類公開了另一種確定是否已到達文件末尾的方法。這樣可以避免在讀取文件末尾時引發的異常。 http://msdn.microsoft.com/en-us/library/seyhszts(v=vs.71).aspx

但「特殊」的方法似乎是少代碼。這是否意味着更簡單/更好?

+1

無法添加香蕉作爲例外情況,還是可以在正常操作過程中發生? – BrokenGlass

+0

這不是特例,請看測試。重複和限制。沒有什麼特別的。 「例外情況是特殊情況」是一個流行的短語,但這裏真正的決定點是什麼? –

回答

1

您應該同時使用兩者。

如果可以在方法被調用之前確定它是否會成功,那麼使用Can()方法(或者屬性,如果失敗的條件不是特定於方法參數的話)是合適且有用的。框架中有很多例子:TypeConverter.CanConvertFrom /立即想到。

但是,在調用方法之前,您不能保證調用者將使用您提供給他們的方法。所以如果方法調用不正確,你仍然需要拋出適當的異常(TypeConverter.ConvertFrom將拋出與TypeConverter.CanConvertFrom返回false相同的條件)。

+0

如果Can()很貴? –

+0

你仍然可以實現它,並留給呼叫者來決定成本是否值得。如果給定的方法不可用,則調用者可能能夠更改控制流或UI,因此能夠確定其是否可用仍然可以是有用的。顯然這高度依賴於上下文;如果你想發佈你的具體情況的更多細節,我可以給你一個更詳細的答案。 –

+0

我同意你的答案;這也是我們選擇的設計。 –

0

我想說這取決於情況。

如果班級的消費者知道如果不能添加香蕉或者不能添加香蕉是常規事件,那麼使用第二個選項。

另一方面,如果「不能添加香蕉」的處理邏輯是呼叫鏈上的幾層,或者如果不能處理香蕉是很少見的(只發生在網絡中斷的情況下,邏輯錯誤,磁盤錯誤等),然後更多地依賴異常 - 這就是他們的目標!

+0

我認爲你必須假設消費者永遠不會知道。今天的開發團隊可能知道。但明天的維護者可能不會。 –

2

第二種方法似乎不必要的複雜,所以我傾向於選擇第一種方法。

爲了給調用者進行檢查自己的機會,我想補充以下成員:

public bool IsFull 
{ 
    get { return this.Bananas.Count > 5; } 
} 

public bool ContainsBanana(string name) 
{ 
    return this.Bananas.Any(b => b.Name == name); 
} 

我可能也返回現有香蕉如果名稱已經存在:

public Banana GetOrAddBanana(string name) 
{ 
    var banana = this.Bananas.FirstOrDefault(b => b.Name == name); 
    if (banana == null) 
    { 
     if (this.IsFull) throw new Exception("Collection is full"); 
     banana = new Banana { Name = name }; 
     this.Bananas.Add(banana); 
    } 
    return banana; 
} 

如果不能添加香蕉不是特例,但可以在正常操作過程中發生,我會使用Try ...模式:

public bool TryGetOrAddBanana(string name, out Banana banana) 
{ 
    banana = this.Bananas.FirstOrDefault(b => b.Name == name); 
    if (banana == null) 
    { 
     if (this.IsFull) return false; 
     banana = new Banana { Name = name }; 
     this.Bananas.Add(banana); 
    } 
    return true; 
} 
+0

如果像IsFull/ContainsBanana這樣的測試數量超級長列表,或者它可能隨時間而改變,那麼您的方法非常麻煩。對於消費者來說,它也比單個Can()方法更能夠測試。更簡單的API似乎對您的消費者更友善;不太可能是錯誤。 –

+0

@Jerry Nixon:你的問題很難回答。您似乎有一個非常詳盡的用例,並不反映在您的簡化示例中。我給出了一個答案,我將如何設計您的簡化示例,而不是您的具體使用案例。我能給出的唯一一般答案是:這取決於。這取決於您的班級如何使用,誰使用它,如何演變,檢查的成本如何,操作失敗時調用者可以執行的操作,性能要求等。分析您的用例並選擇最適合什麼的解決方案你需要。 – dtb

+0

謝謝。我只是尋找談話要點來幫助決策過程。某處總有一條總體規則。 –