2012-11-30 70 views
6

我有一個用戶在表單中回答問題的系統。我有代表這個模型的對象,但我不確定如何按照DDD組織這些對象。具有適合DDD的深層次結構的聚合根?

  1. 表格(有它自己的列表)部分;
  2. Section - >(擁有自己的列表)Groups;
  3. 集團 - >(擁有自己的清單)問題;
  4. 問題 - >(可以有自己的子問題列表)問題;
  5. 問題 - >(擁有自己的清單)答案​​;
  6. Answer - >(擁有自己的清單)Answer_Details;
  7. Answer_Detail - >(可能有自己的子細節列表)Sub_Answer_Details。

每個對象都有超過15個屬性,每個對象都沒有父類沒有意義。根據DDD,我認爲Form實體應該是一個聚合根,所有其他對象應該是值對象。這意味着我只需要一個表單實體的Repository。在這種情況下,FormRepository將與各種子對象的CRUD方法混雜在一起。我的推理在DDD方面是否正確?那我最終得到一個非常廣泛的聚合?我相信這種表述很容易導致性能問題。

回答

3

是的,深層次結構在DDD中很好。

難道我最終會得到一個非常廣泛的聚合? - 如果現實情況非常複雜,並且您的領域模型儘可能最好,那麼您最終將得到一個複雜的聚合根。

是的,Form應該是聚合根。

所有其他對象應該是值對象 - 錯誤的,所有其他對象應該是非聚合根實體(帶Id),而不需要存儲庫來獲取它們。值對象沒有Id,並且值對等的對象僅由其屬性值確定,而不是通過Ids平等確定(更多信息here)。

在這種情況下FormRepository將各種CRUD方法子對象被堆滿 - 不,一個存儲庫應該只包含關於聚合根的方法,即Get<T> , Save<T> where T : IAggregateRoot,一旦你得到一個聚合根的實例,可以遍歷通過屬性和方法來獲得你所需要的。例如:

var formId = 23; 
var form = _formRepository.Get(formId); 
var firstGroup = form.Sections.First().Group().First(); 

或更好

var groupIndex = 1; 
var firstGroup = form.GetGroupAt(groupIndex); 

其中

public Group GetGroupAt(int groupIndex) 
{ 
    Sections.First().Group().ElementAt(groupIndex); 
} 

我相信這樣的表現很容易導致性能問題 - 如果你使用CQRS,你會被調用一些Form域命令處理程序的方法,如果你使用NHibernate的實體持久性,它將通過默認t使用延遲加載,並且只會從數據庫加載Form,然後它只會加載您真正觸及的實體,因此例如Sections.First()會加載數據庫中的所有部分,但不加載組以及其餘部分。查詢時,您需要創建一個FormDto(數據傳輸對象)和其他可能扁平化的dtos以獲取所需格式的數據(可能與實體結構不同,UI可能會驅動dto結構)。看看我的blog的信息有關DDD/CQRS/NHibernate的/存儲庫

+0

剛剛閱讀[有效骨料設計](https://vaughnvernon.co/?p=139),推薦使用小骨料。一個巨大的聚合體可能會出現性能問題,這些聚合體包含一個具有數千個項目的子實體集合,因爲向該集合添加一個項目會獲取整個集合(例如,nhibernate可以這樣工作) – xhafan

+0

修復了[Effective Aggregate Design] (http://dddcommunity.org/library/vernon_2011) – xhafan

+0

這取決於很多因素。是否會對同一個表單進行同時修改?如果答案是肯定的,那麼你不應該創建一個更大的集羣集合。另外,從用戶界面角度來看,您的用例非常具有CRUD,我想您只需爲整個表單提供所有可編輯的字段並將其保存爲整個文檔。但是,如果您的用戶界面更加分離(例如,允許一次編輯單個組或單個部分等,那麼您將從多個AR中受益)。 – plalx

4

即使一個答案已被接受,我想我可能也加入我的2美分:

深層次的(可能)罰款請記住聚合背後的想法是實際防止這種情況。我傾向於在沿着線的總想實體:

:「這個實體沒有任何意義沒有的AR?」

由於我沒有任何上下文w.r.t.我的模型將使用Order/OrderLine。沒有OrderOrderLine有沒有任何意義?我可以用訂單行自己做任何事情(行爲)嗎?這裏明顯的答案是「不」。

每個模型都需要根據上下文進行處理。但所有權並不一定意味着收容

這可能是更容易看到當你有獨立的限界上下文提供一個獲取的BC糾正:)

在你的情況下,可以Answer沒有任何意義,而不其Question工作。但是,也許一個Question可以生活在公元前QuestionBank和一個特定的問題可能會用於您的Examination公元前和您的Enrollment公元前。所有這些都完全組成,所以這將取決於你的上下文。

因此,如果是Question可以是AR的情況下,那麼您的AR所擁有的問題可能只是一個Value對象,或者甚至是一個簡單的QuestionId。

+0

謝謝你的2美分。我不太明白你的意思是什麼:因此,如果問題可以是AR,那麼表單AR所擁有的問題可能只是一個Value Object_。 – ddv

+0

「問題」是一個AR如何成爲一個價值對象。所有AR應該是實體。實際上,在我的情況下,沒有所有者,所有物體都沒有意義。沒有Form上下文不能訪問它們。我的案例中的章節和小組除了分組問題之外沒有其他含義。請讓我知道,如果你的做法會不同於@ xhafan的。你認爲哪些物體可以是VOs – ddv

+0

啊,我明白了爲什麼可能回答可能沒有意義:) ---抱歉。我的意思是,如果BC-A中的AR用於BC-B,然後是BC-B,則可以使用相關的AR Id *或*作爲Value Object。該模型將取決於您對模型的上下文/理解100%。所以我不能肯定地說,你有什麼是不正確的。不過,我過去以類似的方式模擬AR,事後看來,我知道這不是100%正確的。如果它有效,那就沒問題;如果遇到問題/重複,則需要再次查看模型。 –