2009-12-15 54 views
2

幾年來,我已經寫了一些驗證類,並一直在想,人們認爲是處理它們的最佳方式。驗證結果實踐。布爾還是計數?

我已經看到並完成了以下每一項,並且很好奇你的見解和原因。

場景1中,消息計數

class ValidationClass1 
{ 
    public List<string> ValidationMessage { get; set; } 

    public void Validate(x) 
    { 
     // pseudo-code 
     if (!rule_logic1) 
     { 
      ValidationMessage.Add("Error in logic 1"); 
     } 
     if (!rule_logic2) 
     { 
      ValidationMessage.Add("Error in logic 2"); 
     } 
    } 
} 

方案2,返回一個對象或元組

class ValidationClass 
{ 

    public Tuple<bool, List<string>> Validate(x) 
    { 
     List<string> ValidationMessage = new List<string>(); 
     bool passed = true; 

     // pseudo-code 
     if (!rule_logic1) 
     { 
      ValidationMessage.Add("Error in logic 1"); 
      passed = false; 
     } 
     if (!rule_logic2) 
     { 
      ValidationMessage.Add("Error in logic 2"); 
      passed = false; 
     } 

     return new Tuple<bool, List<string>>(passed, ValidationMessage); 
    } 

} 

在情形1中,ValidationMessage列表可以是返回類型爲好。無論如何,調用代碼將不得不檢查列表的count屬性以查看數據是否通過。如果它只是一個單獨的規則,則返回的字符串長度需要通過string.IsNullOrEmpty(x)來檢查。

在場景2中,自定義對象或元組將是返回類型,以便調用代碼必須知道返回的代碼並評估布爾屬性以查看它是否通過,然後驗證消息。

所以,在你看來,你喜歡哪種方式,或者如果你有不同的偏好,我也很好奇。

感謝

回答

4

我已使用Martin Fowler's Notification Pattern的變體來處理驗證和相關的驗證錯誤消息。

下面是可能解決您的「布爾或計數」問題的具體類:

class Notification... 
    private IList _errors = new ArrayList(); 

    public IList Errors { 
     get { return _errors; } 
     set { _errors = value; } 
    } 
    public bool HasErrors { 
     get {return 0 != Errors.Count;}  
    } 

他的模式使用更精細的成員表示一般驗證失敗是否已經發生(「HasErrors」,返回基於一個布爾值關於「錯誤」收集計數)以及具體失敗的原因(可從中導出計數的「錯誤」集合)運行驗證的實際「驗證」代碼完全是一個單獨的方法(可在需要的業務/域對象上找到驗證)。

該模式可能有點過時(包括my own previous implementation),但它確實使您接觸到一些替代品,並可以給您一些建議。

+0

我以某種方式使用了驗證模式。對於這樣的事情來說,這是一個很好的模式,因爲它將通知方面與邏輯分開。你認爲這與場景2類似嗎?類似的意圖的對象從Validate方法傳回,或者你覺得這有什麼不同嗎?如果不同,怎麼樣? – JamesEggers 2009-12-15 04:13:11

+0

就我所知,場景2並沒有太大的區別,除了Fowler的方法涉及更多的獨立類以提高重用性和增加可測性。情景2可能難以實現,但這一切都取決於您的需求。 – 2009-12-15 04:29:57

2

如果您實現IDataErrorInfo接口,則可以自動將驗證綁定到控件(Winforms和ASP.NET),而無需任何其他代碼。

+0

IDataErrorInfo絕對是WinForm和WebForms應用程序的一個非常好的解決方案;然而,在使用驗證控件之外,它與情景1一樣存在相同的問題。除非我錯過了一些東西。 – JamesEggers 2009-12-15 03:55:01

+0

這不完全相同。當你實現'IDataErrorInfo'時,一旦屬性被設置,驗證通常在現場完成。沒有明確的驗證方法可以調用。這使您可以更細化地進行工作,更不用說向消費者明確告知驗證應該如何工作。當然,沒有必要這樣實現'IDataErrorInfo',這只是慣例,而且如你恰如其分地標記它,這有點主觀。 – Aaronaught 2009-12-15 04:08:04

1

乍一看我會說第一個選項更具可讀性, 但是當你想到它時,第二個選項更合適。

這可能是一個非常主觀的問題,但這是我的想法。

在第一個版本中,使用代碼必須做一個「計數」,我認爲 比簡單地檢查一個布爾值(儘管差異可能在各方面都可忽略)更耗費資源。

然而,第二個版本確實有一個更「清晰」的跡象表明出了問題。 驗證是一個測試,「通過=假」表示測試失敗,而在第一個版本中沒有這樣的表示。

在這兩個版本中,消費代碼都需要知道以下事實:版本1中的 - > Count> 0表示失敗,並且在版本2中傳遞= true意味着失敗。

就我個人而言,我會收集驗證失敗,然後拋出異常並將該列表作爲參數傳遞給該異常。結果,消費代碼被迫處理這個問題。

但我的意見再一次純粹是主觀的。

1

對於對象的驗證,我最近已經走過了使用屬性的方式,其中驗證規則和相關錯誤消息被封裝在實現接口IValidationAttribute的屬性中,並且「驗證中的對象」被傳遞到驗證器對象它使用反射來獲取「IValidationAttribute」的所有實現並調用其中的驗證邏輯。

Validator對象接受一個對象或一個對象列表,執行驗證並返回一個包含結果和錯誤的ValidationResult

我不確定這是否會有所幫助,您的需求尚不清楚,但我發現它是對屬性對象執行驗證的非常快速,清晰和簡潔的方式。

+0

其實這是一件好事,因爲我看到它在EF和其他代碼片段中使用了很多。至於我的需求,這個問題其實只是一個普遍的意見問題。我現在並沒有真正的需要,但我不時提醒自己如何繼續關注這個話題。我想我最終應該問這樣的人。 – JamesEggers 2009-12-15 04:20:19

+0

甜,這是我的2c無論如何,什麼EF? – theringostarrs 2009-12-15 04:23:48

+0

EF =實體框架。我在與WCF Ria Services示例相關的一些代碼片段中也看到了類似的方法。 – JamesEggers 2009-12-15 04:26:36