Как команды Add / Create * должны обрабатываться в архитектуре CQRS + Event Sourcing

11

Я хочу реализовать свое первое приложение, используя шаблон CQRS вместе с Event Sourcing. Мне интересно, как с созданием совокупных корней нужно обращаться правильно. Допустим, кто-то отправляет команду CreateItem. Как это должно быть обработано? Где должно храниться событие ItemCreated? Как первое событие нового предмета? Или у меня должна быть какая-то сущность ItemList, которая объединяет все элементы, а ее список событий состоит только из событий ItemCreated?

Уди Дахан предлагает не создавать совокупные корни и всегда использовать вместо этого какой-то метод извлечения. Но как я могу получить что-то новое и, конечно, не назначенный идентификатор. Я понимаю идею, лежащую в основе, и вполне разумно думать, что новый объект - это объект, состояние которого состоит из нулевых событий, ответивших на него. Но как мне это использовать? Должен ли я иметь отдельный метод в моем репозитории, например, getNewItem()или сделать мой get(id)метод принятия Optional<ItemId>вместо этого?

Редактировать: После некоторого времени копания я нашел действительно интересную реализацию вышеупомянутых шаблонов с использованием актеров. Автор вместо того, чтобы создавать агрегат, извлекает его из какого-то репозитория с недавно созданным UUID. Недостаток этого подхода заключается в том, что он допускает временное несоответствие состояния. Мне также интересно, как я могу реализовать deleteметод с таким подходом. Просто добавить удаленное событие в список событий агрегата?

Mequrel
источник
1
Я подозреваю, что заголовок Уди вводит в заблуждение. ИМХО это звучит как его реальная цель состоит в том, что свежеприготовленный ARs всегда должен быть доступен из другого места, таким образом , что захватывает контекст о том, почему / как / , кто решил , что новый AR необходимо создать. Все остальное - о том, как конкретная реализация (NHibernate?) Может упростить управление.
Дариен
2
Обратите внимание, что в статье Udi Dahan, на которую вы ссылаетесь, специально упоминается, что его совет может не относиться к источнику событий: udidahan.com/2009/06/29/dont-create-aggregate-roots/…
EZ Hart

Ответы:

13

Идея в посте Уди, как я понимаю, заключается в том, что ни один предмет не появляется из воздуха. Существует (почти) всегда что-то, или, более конкретно, некоторая операция с доменом, которая привела к созданию элемента. Точно так же, как пример Уди, когда пользователь действительно родился от посетителя, зарегистрировавшегося на сайте. В этой точке и в этом ограниченном контексте посетитель является совокупным корнем, который извлекается по его IP-адресу. Затем этот посетитель создает новый «элемент», пользователь на этом этапе, через операцию домена, называемую « Регистрация» . То же самое относится и к предыдущему шагу, который является еще одним ограниченным контекстом: Referrer - это AR, который извлекается URL-адресом и имеет доменную операцию с именем BroughtVisitorWithIp , где родился посетитель.

Уди также очень хорошо пишет об удалении: http://www.udidahan.com/2009/09/01/dont-delete-just-dont/ . Основная идея в том, что вы ничего не удаляете, никогда. За этим всегда стоит доменная операция, которую мы хотим зафиксировать. Как заказ отменяется, а не удаляется. Прочитайте это, это очень хороший пост.

Главное в обоих случаях, связанных с DDD и особенно Event Sourcing, заключается в том, что вы никогда не должны выполнять прямые CRUD-операции. Если вы оказались в ситуации, когда вам действительно нужно просто вставить, обновить или удалить некоторые данные, а за ними действительно нет операции домена, то, возможно, DDD и Event Sourcing не очень подходят для этого ограниченного контекста . Вы можете комбинировать эти два значения по своему усмотрению, пока один ограниченный контекст придерживается одного принципа. Таким образом, ограниченный контекст в стиле CRUD может создать некоторую строку в базе данных, которая станет сущностью и Агрегированным корнем в другом ограниченном контексте, где вы теперь можете получить AR и не создавать его.

Туукка Хаапаниеми
источник
2
«возможно, DDD и Event Sourcing не очень подходят для этого ограниченного контекста». Вы правильно поняли смысл DDD. Это не должно быть реализовано в каждом случае только для славы сатаны, но только тогда, когда нужно иметь дело со сложной областью, полной неопределенных правил. Лично я сделал это для легального программного обеспечения, где требования не основаны на логике.
Егор Чумаков
2
+1 за одно это предложение "за этот ограниченный контекст". :)
Сонго
2
+1 использование глаголов «добавить» и «создать» убедительно свидетельствует о том, что вы все еще думаете о своем домене с точки зрения взаимодействия со старой доброй табличной базой данных. Не зная вашего домена / ограниченного контекста, я не могу сказать, подходит ли это или нет. Не обращайте внимания на постоянство, сначала сосредоточьтесь на КОМАНДАХ и СОБЫТИЯХ (иначе как НАМЕРЕНИЯ и РЕЗУЛЬТАТЫ), которые являются уникальными для вашего домена, а затем подумайте о том, как сохранить состояние, которое было решено сотни тысяч раз раньше.
Мэтт
«Использование глаголов« Добавить »и« Создать »настоятельно предполагает, что вы все еще думаете о своем домене с точки зрения взаимодействия со старой доброй табличной базой данных» Хммм. Если у вас есть дизайн пользовательского интерфейса с большой кнопкой «Добавить что-то», то, к сожалению, это и есть намерение; буквально добавить что-то новое. Я в целом согласен с вами, но мы здесь не говорим об уровне базы данных, иногда «Добавить» или «Создать» на самом деле являются подходящими словами для использования.
designermonkey
1
@designermonkey Когда у вас есть эти кнопки в пользовательском интерфейсе, у вас действительно есть операция над доменом? Возможно, но в 9 случаях из 10 действительно нет необходимости в сложной операции домена в этом ограниченном контексте. А чистая операция CRUD - это всего лишь чистая операция CRUD, и она должна обрабатываться как таковая. Только тогда, когда есть необходимость в сложности модели предметной области, она должна использоваться. Таким образом, разные ограниченные контексты с разными принципами проектирования.
Туукка Хаапаниеми