Вопрос

Предполагая, что проблема домена переполнения стека и следующее определение событий:

UserRegistered(UserId, Name, Email)
UserNameChanged(UserId, Name)
QuestionAsked(UserId, QuestionId, Title, Question)

Предполагая следующее состояние хранения событий (в порядке появления):

1) UserRegistered(1, "John", "john@gmail.com")
2) UserNameChanged(1, "SuperJohn")
3) UserNameChanged(1, "John007")
4) QuestionAsked(1, 1, "Help!", "Please!")

Предполагая, что следующая денормализованная модель чтения для листинга вопросов (для первой страницы так):

QuestionItem(UserId, QuestionId, QuestionTitle, Question, UserName)

И следующий обработчик событий (который создает денормализованную модель чтения):

public class QuestionEventsHandler
{
    public void Handle(QuestionAsked question)
    {
        var item = new QuestionItem(
            question.UserId, 
            question.QuestionId, 
            question.Title, 
            question.Question, 
            ??? /* how should i get name of the user? */);
        ...
    }
}

Мой вопрос есть Как я могу найти имя пользователя Кто задал вопрос? Или более распространены: как я должен обрабатывать события, если мою денормализованную модель чтения требует дополнительных данных, которые не существует в конкретном событии?

Я осмотрел существующие образцы CQRS, включая Simplesqrs. Грега молодых и FOHJIN Образец марки Nijhof. Но мне кажется, что они работают только с данными, которые включены в события.

Это было полезно?

Решение

Просто обогайте мероприятие со всей необходимой информацией.

Подход Грега, как я вспоминаю, - обогащайте мероприятие при создании и храните / публикуем это так.

Другие советы

Лично я думаю, что нет ничего плохого в том, чтобы искать имя пользователя в обработчике событий. Но если вы находитесь в положении, где вы не можете запрашивать имя от модели чтения пользователя, я бы представил дополнительный обработчик событий для справки, которые обрабатывают пользовательское событие.

Таким образом, вопросники могут поддерживать свой собственный репозиторий имена пользователей (вам не нужно будет хранить почту пользователей). Обработанный обработчик может затем запросить имя пользователя прямого от его собственного репозитория (так как Rinat Abdullin сказал, что хранение дешево!).

Кроме того, помимо того, что ваша модель чтения выполняет имя пользователя, вам нужно будет обрабатывать мероприятие на USERNAMECHanged в рамках вопросов, а также для обеспечения актуального поля имени в вопросе.

Для меня это кажется меньше усилий, чем «обогащать события» и имеет преимущество нет Строительные зависимости от других частей системы и их моделей чтения.

Потяните события из EventStore.

Помните, что ваши модели чтения должны иметь доступ только для чтения к EventStore уже. Читать модели одноразовые. Они просто кэшированные взгляды. Вы должны быть в состоянии удалить / истекать ваши модели чтения в любое время - и автоматически восстановить ваши ReadModels из EventStore. Итак - ваши readmodelbuilders должны быть в состоянии запросить прошедшие события.

public class QuestionEventsHandler
{
    public void Handle(QuestionAsked question)
    {
        // Get Name of User
        var nameChangedEvent = eventRepository.GetLastEventByAggregateId<UserNameChanged>(question.UserId);

        var item = new QuestionItem(
            question.UserId, 
            question.QuestionId, 
            question.Title, 
            question.Question, 

            nameChangedEvent.Name
    }
}

Также реализуйте - репозиторий EventStore не должен быть настоящим EventStore, хотя это, безусловно, может быть. Преимущество распределенных систем заключается в том, что вы можете легко повторить EventStore, если вам нужно, ближе к вашим ReadModels.

Я столкнулся с этим точно таким же сценарием ... где мне нужно больше данных, чем было доступно в одном событии. Это особенно верно для событий Create-Type, которые требуют заполнения нового ReadModel с исходным состоянием.

Из моделей чтения: вы можете потянуть из других моделей чтения. Но я действительно не рекомендую это, так как вы ввели бы большой шар грязи зависимости, где представления зависят от просмотров, зависят от видов.

Дополнительные данные в событиях: вы действительно не хотите раздувать свои события со всеми дополнительными данными, которые вам понадобится для представлений. Это действительно повредит вам, когда ваш домен меняется, и вам нужно мигрировать события. События домена имеют определенные цели - они представляют изменения состояния. Не просмотреть данные.

Надеюсь это поможет -

Райан

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top