2009-02-18 54 views
5

這些年來,我總是忽略了「告訴,不要問」OOP原則,因爲我幾天前第一次瞭解到它。「告訴,不問」適用於用戶輸入驗證嗎?

但是上下文是關於驗證代碼的討論,這些驗證代碼已經從ASP.NET Web窗體頁面移出到數據/業務對象中,並且沒有「Validate()」方法,只是一種保存方法本身做了驗證和(據說)提出了一個例外。我問這是爲什麼這樣設計的,我被引導到OOP的「告訴,不要問」的原理,這是我從來沒有聽說過的,所以我們一起看了谷歌,我立即受到了教育。 ;)

儘管如此,某些東西並沒有正確的味道,但不應該在數據從用戶手中轉移出去並進入處理和/或收集的業務層之前進行清理,而不是反過來?我很困惑這是如何爲優秀的設計做出的。

似乎「告訴,不要問」的規則屬於這樣的想法,即您不應該向目標對象詢問目標對象的狀態,並且該原則從未真正意圖應用於數據正在通過的目標對象。

回答

2

我AviewAview同意,但是woul如果用戶告訴ð只拋出異常(如果沒有他問):

public Foo 
{ 
    bool Validate(Baz bar) 
    { 
     if(!is_number(bar)) return false; 
     return true; 
    } 

    AssignBar(Baz bar) 
    { 
     if (!Validate(bar)) throw numberexception(); 
    } 
} 

TELL:

try 
{ 
    foo.AssignBar(bar); 
} 
catch(numberexception e) 
{ 
    alert('Not a number!'); 
} 

問:

if (foo.Validate(bar) 
{ 
    foo.AssignBar(bar); 
} 
else 
{ 
    alert('Not a number!'); 
} 

所以AssignBar需要一個有效的酒吧和拋出一個異常如果不是,但我們也提供了一個方法來驗證哪些不會拋出異常。

+3

例外情況可用於處理意外情況(內存不足/磁盤已滿/連接已關閉/分佈式事務失敗) - 驗證用戶提交的數據並非意外。使用「處理程序」方法 - 只需調用validate_number(invalid_handler_callback) – 2011-04-03 23:08:33

3

我認爲這聽起來像是一個「最佳實踐」和「設計方法」錯誤的負載,但現在它對我有意義。這樣看待:

想象一下,將驗證放在業務對象中,但是在表示層中「如果驗證失敗,我該怎麼做」,這將允許多個不同的表示層重用相同的驗證邏輯,但處理錯誤是不同的。

public Foo 
{ 
    Validate(Baz bar) 
    { 
     if(!is_number(bar)) throw numberexception(); 
    } 

    AssignBar(Baz bar) 
    { 
     Validate(bar); 
    } 
} 


//... 

try 
{ 
    foo.AssignBar(bar); 
} 
catch(numberexception e) 
{ 
    alert('Not a number!'); 
} 

NB,你可以說你想了解拋出異常,它的意思,例如,返回美國,布爾變量,任何你想要的。

0

我不知道這是否是「分離問題」而不是「告訴別人問題」的問題。它是誰的責任來驗證數據?可以說,這是堅持它的責任。

當然,有時驗證多個圖層中的數據是有用的。如果您的應用程序屬於這種情況,那麼在「用戶」圖層中公開驗證邏輯沒有問題。但我仍然希望它在業務層。