Постоянство и доменные события с постоянными невежественными объектами

Я изучал предметно-ориентированный дизайн в сочетании сдоменные события, Мне действительно нравится разделение проблем, которые эти события обеспечивают. Я столкнулся с проблемой с порядком сохранения объекта домена и создания событий домена. Я хотел бы вызывать события в доменных объектах, но я хочу, чтобы они оставались невежественными.

Я создал основной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 событие. Одним из недостатков этого подхода является то, что при рассмотренииOrder доменный объект, неясно, какие события и какими методами вызываются. Кроме того, разработчик должен помнить, чтобы поднять событие, когда заказ создается в другом месте. Это не правильно.

2. Очередь доменных событий

Другой вариант - поставить в очередь события домена и вызвать их при успешном сохранении. Это может быть достигнуто путемusing утверждение например:

using (DomainEvents.QueueEvents<OrderCreated>())
{
    var order = new Order(cart, customer);

    _orderRepositorty.Add(order);
    _unitOfWork.Commit();
}

QueueEvents<T> Метод установил бы логическое значение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);
}

Теперь мой вопрос: есть ли у меня другие варианты? Я что-то пропустил? А что вы думаете о решениях, которые я предложил?

Ответы на вопрос(1)

Ваш ответ на вопрос