Ich habe auf Domain-driven Design in Verbindung mit domain events studiert. Ich mag die Trennungen von Sorgen, die diese Ereignisse bieten. Ich stieß auf ein Problem mit der Reihenfolge des Behaltens eines Domänenobjekts und des Anhebens von Domänenereignissen. Ich möchte Ereignisse in den Domain-Objekten auslösen, doch ich möchte, dass sie unwissend bleiben.Persistence und Domain Events mit Persistenz Ignoranten Objekte
Ich habe eine grundlegendes ShoppingCartService
, mit dieser Checkout
Methode erstellt:
public void Checkout(IEnumerable<ShoppingCartItem> cart, Customer customer)
{
var order = new Order(cart, customer);
_orderRepositorty.Add(order);
_unitOfWork.Commit();
}
In diesem Beispiel ist der Konstruktor von Order
würde ein OrderCreated
Ereignis auslösen, die von bestimmten Handler gehandhabt werden kann. Ich möchte jedoch nicht, dass diese Ereignisse ausgelöst werden, wenn die Entität noch nicht persistiert ist oder wenn das Fortbestehen irgendwie fehlschlägt.
um dieses Problem zu lösen, habe ich mehrere Lösungen herausgefunden haben:
1. Heben Ereignisse im Dienst:
Statt das Ereignis in der Domain-Objekt zu heben, ich Ereignisse in den Dienst erhöhen könnte. In diesem Fall würde die Checkout
Methode das Ereignis OrderCreated
auslösen. Einer der Nachteile dieses Ansatzes besteht darin, dass bei der Suche nach dem Domänenobjekt Order
nicht klar ist, welche Ereignisse durch welche Methoden ausgelöst werden. Außerdem muss ein Entwickler daran denken, das Ereignis anzuheben, wenn eine Bestellung an anderer Stelle erstellt wird. Es fühlt sich nicht richtig an.
2. Queue Domain Ereignisse
Eine weitere Option ist Domain Ereignisse in die Warteschlange und sie zu erhöhen, wenn es gelungen persistierenden. Dies könnte durch eine using
Anweisung zum Beispiel erreicht werden:
using (DomainEvents.QueueEvents<OrderCreated>())
{
var order = new Order(cart, customer);
_orderRepositorty.Add(order);
_unitOfWork.Commit();
}
Die QueueEvents<T>
Methode würde setzt einen boolean true
und die DomainEvents.Raise<T>
Methode würde die Ereigniswarteschlange, anstatt sie direkt ausgeführt werden. Im Dispo-Callback von QueueEvent<T>
werden die in der Warteschlange stehenden Ereignisse ausgeführt, die sicherstellen, dass das Persistierende bereits passiert ist. Dies scheint ziemlich schwierig zu sein und es erforderte, dass der Dienst weiß, welches Ereignis im Domänenobjekt ausgelöst wird. In dem Beispiel, das ich zur Verfügung gestellt habe, unterstützt es auch nur einen Ereignistyp, der jedoch behoben werden könnte.
3. Persist in Domain-Ereignisse
ich das Objekt mit einem Domäne Ereignisse bestehen könnte. Dies scheint in Ordnung zu sein, abgesehen von der Tatsache, dass der Ereignishandler, der das Objekt persistent hält, zuerst ausgeführt werden sollte, aber ich habe irgendwo gelesen, dass Domänenereignisse nicht auf einer bestimmten Ausführungsreihenfolge beruhen sollten. Vielleicht ist das nicht so wichtig und Domänenereignisse könnten irgendwie wissen, in welcher Reihenfolge die Handler ausgeführt werden sollten.Zum Beispiel: Angenommen, ich habe eine Schnittstelle einer Domäne Ereignis Handler definieren, wäre eine Umsetzung wie folgt aussehen:
public class NotifyCustomer : IDomainEventHandler<OrderCreated>
{
public void Handle(OrderCreated args)
{
// ...
}
}
Wenn ich auch bei der Verwendung einen Event-Handler behandeln persistierenden wollen, würde ich einen anderen Handler erstellen, Ableiten aus der gleichen Schnittstelle:
public class PersistOrder : IDomainEventHandler<OrderCreated>
{
public void Handle(OrderCreated args)
{
// ...
}
}
}
Jetzt hängt NotifyCustomer
Verhalten auf der Reihenfolge, in der Datenbank gespeichert werden, so dass die PersistOrder
Event-Handler sollten zuerst auszuführen. Ist es akzeptabel, dass diese Handler beispielsweise eine Eigenschaft einführen, die die Reihenfolge ihrer Ausführung angibt? Ein Schnapp aus der Umsetzung der DomainEvents.Raise<OrderCreated>()
Methode:
foreach (var handler in Container.ResolveAll<IDomainEventHandler<OrderCreated>>().OrderBy(h => h.Order))
{
handler.Handle(args);
}
Nun meine Frage ist, habe ich keine andere Optionen? Fehle ich etwas? Und was halten Sie von den vorgeschlagenen Lösungen?
Haben Sie darüber nachgedacht, eine Fabrik- oder Fabrikmethode für die Erstellung neuer Bestellungen zu verwenden? Dies würde einen expliziten Unterschied zwischen der Instanziierung eines Auftragsobjekts und der Erstellung eines neuen Auftrags bedeuten. – tuespetre