我一直在研究域驅動設計與domain events。我真的很喜歡這些事件提供的分離關注點。我遇到了一個持久化域對象和引發域事件的問題。我想在域對象中引發事件,但我希望它們是持久性的無知。持久性和域名事件與持久性的無知對象
我已經創建了一個基本的ShoppingCartService
,用這種方法Checkout
:
public void Checkout(IEnumerable<ShoppingCartItem> cart, Customer customer)
{
var order = new Order(cart, customer);
_orderRepositorty.Add(order);
_unitOfWork.Commit();
}
在這個例子中,Order
構造函數將引發OrderCreated
事件可以通過一定的處理程序進行處理。但是,我不希望在實體未持續存在或持續存在失敗時提出這些事件。
爲了解決這個問題,我已經找到了幾種解決方案:在服務
1.引發事件:
而不是在域對象引發事件,我可以提高在服務事件。在這種情況下,Checkout
方法會引發OrderCreated
事件。這種方法的缺點之一是,通過查看域對象,不清楚哪些事件是由什麼方法引發的。另外,開發人員必須記得在其他地方創建訂單時提出該事件。它感覺不對。
2.隊列域事件
另一種選擇是要排隊域事件,並提高他們堅持成功的時候。這可能是由using
聲明例如可以實現:
using (DomainEvents.QueueEvents<OrderCreated>())
{
var order = new Order(cart, customer);
_orderRepositorty.Add(order);
_unitOfWork.Commit();
}
的QueueEvents<T>
方法將一個boolean值設置爲true
和DomainEvents.Raise<T>
方法將排隊的事件,而不是直接執行它。在QueueEvent<T>
的處置回調中,排隊的事件被執行,以確保持續已經發生。這似乎相當棘手,它需要服務知道在域對象中引發哪個事件。在我提供的例子中,它也只支持一種類型的事件被提出,但是,這可以被解決。
3.堅持域事件
我可以使用域事件持續的對象。這似乎沒問題,除了事件處理程序持久化對象應該先執行,但是我在某處讀取域事件不應該依賴於特定的執行順序。也許這並不重要,域名事件可能會以某種方式知道處理程序應該以何種順序執行。例如:假設我有定義域事件處理接口,一個實現應該是這樣的:
public class NotifyCustomer : IDomainEventHandler<OrderCreated>
{
public void Handle(OrderCreated args)
{
// ...
}
}
當我想以處理使用事件處理程序過於堅持,我會創造另一個處理程序,推導從相同的接口:
public class PersistOrder : IDomainEventHandler<OrderCreated>
{
public void Handle(OrderCreated args)
{
// ...
}
}
}
現在NotifyCustomer
行爲取決於被保存在數據庫中的順序,所以PersistOrder
事件處理程序應首先執行。這些處理程序是否可以引入一個屬性來表示它們的執行順序?從DomainEvents.Raise<OrderCreated>()
方法的實現一卡:
foreach (var handler in Container.ResolveAll<IDomainEventHandler<OrderCreated>>().OrderBy(h => h.Order))
{
handler.Handle(args);
}
現在的問題是,我有什麼其他選擇?我錯過了什麼嗎?你對我提出的解決方案有什麼看法?
您是否考慮過使用某種工廠或工廠方法創建新訂單?這將標示實例化訂單對象和「創建新訂單」之間的顯式差異。 – tuespetre