DDDD: данные события

Я пытаюсь разобраться с DDDD в стиле Грега Янга.

Есть много разговоров о том, как реализовать DDDD с CQRS+EventSourcing, и есть несколько примеров реализации... и в целом это может быть довольно запутанным...

В представлении Gregs агрегаты не имеют геттеров или сеттеров - только методы с изменением состояния, которые генерируют соответствующее событие.

По сути, событие описывает переходы состояния, которые произошли в прошлом. Это данные описывают то, что изменилось.

Некоторые говорят, что эти данные могут быть " обогащены " дополнительными данными.
Откуда эти дополнительные данные?

т.е. у меня есть User а также Usergroup - оба агрегатных корня (могут существовать независимо, иметь идентичность). User имеет метод, называемый AddToUsergroup,

public class User : AggregateRoot
{
    // ...
    public void AddToUsergroup(Usergroup usergroup)
    {
        // validate state
        RaiseEvent(new UserJoinedUsergroup(this.Id, usergroup.Id));
    }
    // ...
}

public class Usergroup : AggregateRoot
{
    private string _displayName;
    // ...
    public void ChangeDisplayName(string displayName)
    {
        // validate state
        RaiseEvent(new DisplayNameChanged(this.Id, displayName));
    }
    public void Apply(DisplayNameChanged e)
    {
        this._displayName = e.DisplayName;
    }
    // ...
}

Если бы я хотел " обогатить " событие названием группы пользователей (по причинам отладки или как-то так), как бы я это сделал?

  • добытчики не существуют
  • внутреннее состояние группы пользователей недоступно

Внедрение таких вещей, как хранилища в User не допускается (я здесь?!?), как

  • Хранилище на стороне чтения
  • Event-store репозиторий

Итоговые вопросы:

  • Можно Нужно ли вводить что-то вроде репозиториев для объединения корней?
  • Должно ли событие использовать только данные, доступные через параметры и внутреннее состояние агрегата?
  • Должны ли события содержать только минимальные данные, описывающие изменение состояния?

И (немного не по теме, но образец здесь)

  • Должен AddToUsergroup взять Guid вместо полного совокупного корня?

Ждем ваших ответов!

Lg
warappa

1 ответ

Решение

Нужно ли вводить что-то вроде репозиториев для объединения корней?

Нет и не нужно в этом случае. Может оказаться целесообразным передать доменную службу поведенческому методу в совокупности, но, опять же, в этом случае это не требуется.

Должно ли событие использовать только данные, доступные через параметры и внутреннее состояние агрегата?

Да, исходное доменное событие должно быть таким, чтобы его можно было легко скомпилировать с помощью агрегата и можно было воспроизвести детерминированным образом.

Должны ли события содержать только минимальные данные, описывающие изменение состояния?

Да. Однако, чтобы удовлетворить требования внешних подписчиков, именно здесь в игру вступает обогащение контента. Для внешней отправки доменного события оно сначала фиксируется в хранилище событий, затем вы можете отправить его в том же tx или использовать механизм вне процесса, который публикует события извне. На этапе внешней публикации вы обычно будете использовать другой контракт для сообщения, поскольку подписчикам может потребоваться больше, чем то, что указано в самом событии домена. В этом случае вам нужно имя группы пользователей. Затем издатель может найти имя группы пользователей и поместить эти данные в обогащенное событие. Этот издатель может иметь доступ к хранилищу модели чтения для групп пользователей, что позволит ему получить имя.

Должен ли AddToUsergroup взять Guid вместо полного совокупного корня?

Да. Прохождение всей совокупности может быть невозможным, а также создает иллюзию, что можно использовать что-то кроме идентификатора, что не должно иметь место.

Другие вопросы по тегам