2012-01-10 66 views
3

現在,我有一個名爲StyleBundle的域實體。這StyleBundle採用樣式列表:DDD中對象驗證和持久性驗證的區別?

public class StyleBundle 
{ 
    public StyleBundle(List<Style> styles) 
    { 
     this.Styles = styles; 
    } 

    public IEnumerable<Style> Styles { get; private set;} 
} 

所以,在我原來的設計,一個StyleBundle不應該被一個空樣式列表中創建。這是一個領域專家基本上說是好的規則。

我寫這在構造函數中使用保護條款:

if (styles.Count() == 0) 
    throw new Exception("You must have at least one Style in a StyleBundle."); 

這讓我可絕不處於無效狀態創建StyleBundle。我認爲這裏有一個例外是有道理的b/c在沒有至少一個Style的情況下創建的StyleBundle在系統中是例外的。

當然,在項目的其他部分,變化一直沿着這條路走下去,現在用戶可以創建一個沒有樣式的StyleBundle,但是不應該允許他們在沒有樣式的情況下保留一個StyleBundle。

所以現在我正在看我的守衛子句,並意識到我不能從構造函數拋出異常了。向前邁進,我有一個服務/應用程序層,當我們的代碼隱藏與StyleBundles一起工作時,它們與之交互。在我的服務層中,我有一個StyleBundleService類,並且該類向UI公開了基本功能......其中包括「CreateStyleBundle」。

看起來好像我必須讓服務層檢查StyleBundle在沒有任何樣式之前是否保留了數據庫,但是這個決定對我來說是「錯誤的」。

任何人遇到類似的事情?基本上,當「新起來」時對象的狀態是有效的狀態與持久性時相同對象的狀態不同?

謝謝! Mike

回答

6

我會爲您的實體添加一個IsValid方法。這將檢查實體當前是否處於有效狀態(在你的情況下,檢查是否有樣式)。

您可以從您的Repository中調用此方法來檢查實體是否可以被保留。您可以將更多的規則添加到特定實體的IsValid方法中,並且您可以實施類似於收集的驗證錯誤的一些方法,即您想拋出一個有意義的異常。

+0

是存儲庫檢查實體的有效性是好還是壞的想法?對我而言,這聽起來很奇怪。但無論如何,我喜歡爲我的實體提供.IsValid想法。感謝您的反饋! – 2012-01-10 14:54:30

+0

我不認爲您的存儲庫中的最新檢查是一個壞主意。否則,用戶可能會向數據庫添加一些無法捕獲的無效數據。就像Momamed Abed建議的那樣,你可以將它分成IsValid和IsValidForPersistence方法 – 2012-01-11 18:20:04

1

展開式沃特說什麼,加上方便BeforeSaving和BeforeDeleting方法:

public interface IDomainObject<T> 
{ 
    bool IsValid(); 
} 

public interface IEntity<T> : IDomainObject<T> 
{ 

} 

public interface IAggregateRoot<T> : IEntity<T> 
{ 
    void BeforeSaving(); 
    void BeforeDeleting(); 
} 


public interface IAggregateRoot { //or simply IEntity depending on the model 
    bool IsValid(); 
} 

public class StyleBundle : IAggregateRoot<T> { 
    return styles.Count() > 0 
} 

public class StyleBundleRepository : Repository<StyleBundle> { 
} 

public abstract class Repository<T> : IRepository<T> where T : class, IAggregateRoot<T> { 

    public T Save(T t) 
    { 
     t.BeforeSaving(); //for all AggregateRoots, maybe logging what the aggregate was like before the changes 

     if(!t.IsValid()) 
     throw Exeception("Entity invalid"); 

     EntityStore.Current.SaveChanges();   

     // "AfterSaving" here, i.e.: log how the entity looks after the update 

    } 
} 

編輯:我不親自使用IsValid的想法,我有滿級EntityValidationErrors的去的地方我能夠回報給客戶什麼錯了試圖保存之前,事情不應該是零,不應該是空的(如您的樣式等)

+0

你認爲存儲庫對實體進行有效性檢查是一個好還是壞的想法?我想你想保持存儲庫「愚蠢」,並讓服務層調用驗證碼? – 2012-01-10 14:55:38

+0

這確保沒有任何東西被持久化爲無效,無論代碼的其他部分如何,只有實體本身是唯一一個知道它是無效的實體,存儲庫只會強化合約。我可能在閱讀完之後做了一些修改,想了解更多的想法 – 2012-01-10 14:58:30

+0

F.Aquino,非常感謝你的努力和代碼。在接下來的幾天裏,我會看看是否能將這樣的東西帶入我的模型。之後我會回來標記接受的答案。 – 2012-01-10 15:47:50

1

有多種策略:

有些人希望能夠創建實體本身2種方法,一個叫做IsValid(),它根據業務規則驗證實體(一般驗證),另一個叫做IsValidForPersistence(),驗證實體是否存在持久性。

關於IsValid()我寧願不首先通過驗證所有輸入來允許無效狀態,並支持使用工廠或構建器的不變量。

你可以檢查鏈接http://www.codethinked.com/thoughts-on-domain-validation-part-1 有些想法。

+0

穆罕默德,感謝您的鏈接。驗證實現非常複雜,我相信在集合根上實現.IsValid()和.IsValidForPersistence()會有更簡單的方法。我還認爲使用Factory或Builder是一種不允許實體達到無效狀態的好方法,在構造實體之前,您仍然可以將有用的消息返回給用戶/應用層。除非您從實體的構造函數中引發異常,否則一旦您在構造函數中就無法將有用的信息報告迴應用層 – 2012-01-13 15:29:42

0

我知道,這個問題已經三年了,但看到當前的答案是我喜歡迴應的。我們正在討論域數據。因此,不能有0個對象的有效StyleBundle。我想,你有一個前端編輯器,你是否創建了一個「新」StyleBundle,並且必須添加至少一個樣式,然後點擊「保存」按鈕。

在前臺的這一點上,你不會有一個域對象。您可能有一個數據傳輸對象,將通過「CreateNewStyleBundle」命令發送。

在我看來,領域對象必須是不可知的,並應始終處於有效狀態。如果您必須調用「IsValid」方法,那麼您首先會繞過具有域對象的整個想法。

這只是我的愚見。