2011-08-10 59 views
1

我正在嘗試使用域模型的應用程序。這個想法是將業務邏輯保留在域模型中的對象中。現在很多都是通過訂閱相關對象的對象來對其中的更改作出反應。這是通過PropertyChanged和CollectionChanged完成的。除以下情況外,此工作正常:域模型應該使用事件保持自己的一致性嗎?

複雜操作:應將許多更改作爲一組處理(而不是單個屬性/集合更改)。我應該怎樣「建立」交易?

持久性:我使用NHibernate進行持久性,並且這也使用了公共屬性設置器的類。當NHibernate命中屬性時,許多業務邏輯完成了(這似乎是不必要的)。我應該使用NHibernate的自定義設置器嗎?

總的來說,推動領域模型中的所有邏輯使領域模型相當複雜。有任何想法嗎???

這裏有一個「樣本」的問題(對不起蹩腳的工具我使用):

enter image description here

你可以看到我的項目容器對象位於其下方訂閱反應對方。現在通過NetworkEditor完成對網絡的更改,但此編輯器不知道NetworkData。有時甚至可能在另一個程序集中定義此數據。流程從用戶 - >網絡編輯器 - >網絡 - > NetworkData和所有其他對象感興趣。這似乎沒有規模。

回答

2

我擔心DDD和PropertyChanged/CollactionChanged事件的組合現在可能是最好的主意。問題是,如果您將邏輯基於這些事件,則極難控制複雜性,因爲一個PropertyChanged會導致另一個和另一個PropertyChanged,並且很快就會失去控制權。

ProportyChanged事件和DDD並不完全相符的另一個原因是,在DDD中,每個業務操作都應該儘可能明確。請記住,DDD應該把技術性的東西帶入商業世界,而不是相反。並且基於PropertyChanged/CollectionChanged似乎不是很明確。

在DDD的主要目標是保持一致性內聚集,換句話說,你需要以這樣的方式的總和,即任何操作調用聚合是有效的,一致的(如果進程的操作成功)模型。

如果您建立的模型正確無需擔心「構建」事務 - 對聚合的操作應該是事務本身。

我不知道你的模型是怎麼樣的,但是你可能會考慮將聚合樹中的職責向上移動一層,很可能在流程中增加額外的邏輯實體,而不是依賴於PropertyChanged事件。

例子:

讓我們假設你有狀態,每當付款的變化,要重新計算的客戶訂單的總收支的集合。相反訂閱更改付款收集,並呼籲客戶的方法時收集的變化,你可能會做這樣的事情的:

public class CustomerOrder 
    { 
     public List<Payment> Payments { get; } 
     public Balance BalanceForOrder { get; } 

     public void SetPaymentAsReceived(Guid paymentId) 
     { 
      Payments.First(p => p.PaymentId == paymentId).Status = PaymentStatus.Received; 
      RecalculateBalance(); 
     } 
    } 

您可能已經注意到,我們重新計算單個訂單的平衡,而不是平衡整個客戶 - 在大多數情況下,這是可以的,因爲客戶屬於另一個總計,並且在需要時可以簡單地查詢其餘額。這正是表明這種'只在聚合內一致'的部分 - 我們現在不關心任何其他聚合,我們只處理單一的訂單。如果這不符合要求,那麼域名建模不正確。

我的觀點是,在DDD中,每種情況都沒有單一的好模型 - 您必須瞭解企業如何成功。

如果你看看上面的例子,你會發現沒有必要'建立'交易 - 整個交易位於SetPaymentAsReceived方法。在大多數情況下,一個用戶操作應該導致一個具有聚合的實體的特定方法 - 該方法明確地涉及到業務操作(當然這種方法可能調用其他方法)。

對於DDD中的事件,有一個域事件的概念,但是這些概念與PropertyChanged/CollectionChanged技術事件沒有直接關係。域事件指示已經由聚合完成的業務操作(事務)。

全部測試似乎推動所有邏輯域模型使得 域模型相當複雜

當然有,因爲它是應該被用於與複雜的業務邏輯場景。然而,如果域名建模正確,那麼很容易管理和控制這種複雜性,這是DDD的優勢之一。

新增提供範例之後:有關創建一個名爲Project聚合根

好吧,什麼 - 當你從庫構建聚合根,你可以用NetworkData填充和操作可能是這樣的:

public class Project 
    { 
     protected List<Network> networks; 
     protected List<NetworkData> networkDatas; 

     public void Mutate(string someKindOfNetworkId, object someParam) 
     { 
      var network = networks.First(n => n.Id == someKindOfNetworkId); 
      var someResult = network.DoSomething(someParam); 

      networkDatas.Where(d => d.NetworkId == someKindOfNetworkId) 
       .ToList() 
       .ForEach(d => d.DoSomething(someResult, someParam)); 
     } 
    } 

NetworkEditor不會直接在網絡上運行,而是通過使用NetworkId的Project運行。

+0

現貨。 DDD實體可以合法地報告屬性和集合變化,但僅限於外部觀察者(如表示代碼) - 從不用於域邏輯。 – jnm2

相關問題