2010-12-15 65 views
3

我應該在哪裏將域對象的驗證邏輯放在我的解決方案中?我應該把它們放在域類,業務層還是其他?你在哪裏把驗證放在有域驅動設計的項目中?

我也想利用來自Microsoft企業庫的驗證應用程序塊和策略注入應用程序塊來做到這一點。

我應該用什麼驗證策略來很好地融合所有這些?

非常感謝!

回答

5

這取決於。首先 - 您需要了解您正在驗證的內容。

您可以驗證:

  1. 那些重視您檢索HTTP POST可以被解析爲日期時間,
  2. 即Customer.Name不超過100個符號較大,
  3. 如果客戶有足夠的錢購買東西。

正如你所看到的 - 這些驗證在性質上是不同的,所以他們should be separated。它們的重要性varies too(請參閱「所有規則都不相等」段落)。


事情,你可能要考慮的是not allowing域對象是處於無效狀態。

這將大大降低複雜性,因爲在當前時間範圍內,您知道該對象是有效的,並且您只需要驗證當前任務相關的事情以便進步。

另外,您應該考慮避免使用您的域模型中的工具,因爲它應該儘可能免費提供基礎設施。

另一件事 - 包容使用價值對象。這對驗證封裝非常有用。

+0

嗨Arnis。你能否詳細說明在驗證方面「接受價值對象的使用」?你在這裏意味着什麼? – 2011-02-15 02:41:34

2

我通常把它放在域對象中。這是因爲域對象是我關心驗證的事情,所以如果特定對象的規則發生變化,我知道在哪裏更新它,而不必在某些特定的驗證類/文件中搜索大量不相關的實體規則。

我意識到這可能不被認爲是POCO,但每個項目都有特定的例外,這對我來說通常是有意義的。同樣,在某些項目中,從視圖中引用域實體是有意義的,因此實現IPropertyChanged而不是不斷地將實體中的值複製到整個其他視圖特定對象集。

我做了驗證的老方法是我有一個像下面這樣的IValidator接口,每個實體都實現了。

public interface IValidator 
{ 
    IList<RuleViolation> GetViolations(); 
} 

現在我做到這一點使用NHibernate的驗證(不需要使用NHibernate的ORM趁驗證庫的它是通過屬性簡單地完成

//I can't remember the exact syntax but it is very similar to this 
public class MyEntity 
{ 

[NHibernateValidation(Length(min=1, max=10)] 
public String Name {get;set;} 

} 

//... and then later ... 
NHibernateValidator.Validate(myEntity); 

編輯:我打消了我因爲克里斯告訴我它現在和NHibernate Validation

+0

+1:我幾乎完全一樣。唯一的區別是我在企業庫中使用驗證器。 – NotMe 2010-12-15 21:25:17

+0

很酷。我只查找了企業庫的驗證應用程序塊。看起來它比我記得的更像nhibernate驗證器。 – i8abug 2010-12-15 21:29:07

3

以前一般不會是企業圖書館的巨大粉絲,所以你可以根據自己的需要做任何一項。

將它放在域類中可以確保驗證總是完成,但可能會導致類臃腫。它也可能違背單一責任原則,取決於你如何解釋(它增加了驗證的責任)。將它放在域類中也會將您限制爲一種驗證。另外,除非使用繼承,否則相關規則可能必須在相關類(DRY)中多次執行。如果您以這種方式進行驗證,則通過您的域進行驗證。

外部驗證(您可以通過DI,工廠,業務層或上下文獲取驗證對象)確保您可以根據上下文替換驗證規則(例如,對於要長期保存的部分流程完成狀態,你可以有一個驗證對象只是爲了能夠保存,另一個來檢查域類是否爲真的有效且可以使用)。您的域類將會更簡單(責任更少,但您必須執行最小限度的檢查,如空檢查,以防止運行時錯誤),並且您還可以重複使用相關類的規則集。通過這種方式,驗證以您的域模型的一個小區域爲中心。 B.t.w.您可以將外部驗證注入到域類本身中,確保類自己進行驗證,但不知道他們正在驗證的內容。

雖然無法對驗證應用程序塊進行評論,但您始終必須權衡利弊對比,從未有一個有效的解決方案。

+0

+1 [Martin Folwer提到](http://martinfowler.com/bliki/ContextualValidation.html),我們可以認爲驗證是我們需要根據上下文運行的東西。如果我們想把它保留在實體的類中,它可以像'validateForBlahBlah'這樣的方法。 – prograhammer 2015-07-28 21:28:22

2

首先,我同意@ i8abug。

但我確實想進一步談論架構。這些設計架構中的每一個,如域名驅動,都應該被視爲無非是一個建議,並通過審查來查看。

在每一步中,您都應該問問自己,這個問題的好處和缺點與您的應用程序有關。

很多這些涉及添加大量的代碼和嚴重複雜的項目,沒有什麼好處。

驗證點是一個很好的例子。正如斯特凡所說,單一責任原則基本上說你需要創建一整套其他類,其目的只是驗證原始對象的狀態。很明顯,這爲應用程序增加了很多代碼。也許它是爲你生成的,也許你必須手寫它。無論如何,更多的代碼通常等同於不太健壯,並且等同於更難理解。

分離所有這一切的好處是您可以更換驗證規則。好的。缺點是你現在有兩個文件要查看和創建每個類的定義。即:更多的工作。您的應用程序是否需要更換驗證規則?可能不會。我甚至會打賭說很少。

很坦率地說,如果你沿着這條路走下去,那麼你可以把所有的東西都定義爲一個結構體,並讓所有這些「幫助」類蠕變回來,把驗證,持久性,設置屬性等等當作一個完整的吹課的學生幾乎買不到任何東西。

所有這一切,我傾向於自包含的類。換句話說,他們知道他們的財產如何相互關聯,並知道什麼是可接受的價值。他們也可以對自己和他們的孩子進行操作。換句話說,他們知道他們是什麼。這往往導致簡化的編碼和實施。這也導致瞭解確切地去修改或改變的地方。我真正在這裏做的唯一分離就是實現持久性的控制反轉;這使我可以在運行時交換數據提供者;這是我已經完成的幾個應用程序的要求。

要點是,想想你正在做什麼,並決定是否真的是你的特定情況下最好的方式。所有這些編程「規則」畢竟只是建議。