#aggregate #domain-driven-design #cqrs #event-sourcing
#агрегат #проектирование, управляемое доменом #cqrs #поиск событий
Вопрос:
Мне трудно понять форму state
, полученную с применением событий этого объекта, по сравнению с проекцией данных этого объекта.
Используется ли состояние агрегата ТОЛЬКО для определения того, может ли команда быть успешно применена? Или это состояние должно использоваться другими способами?
Пример — у меня есть объект Post для стандартного сообщения в блоге. У меня могут быть такие события postCreated
, как postPublished
, postUnpublished
, и т.д. Для моих прогнозов, которые я буду сохранять в своих таблицах чтения, мне нужна проекция для базы posts
(которая будет включать все записи, независимо от статуса, с большим количеством деталей), а также published_posts
проекция (которая будет представлять только публикации, опубликованные в данный момент, с информацией, необходимой только для рендеринга.
В приведенной выше ситуации предполагается ли использовать мое агрегированное состояние ТОЛЬКО для определения, например, может ли сообщение быть опубликованным или неопубликованным и т. Д.? Если это так, определяется ли форма моего состояния в совокупности исключительно тем, что требуется для этих проверок? Например, в моей базовой post
проекции я хочу иметь список всех пользователей, которые внесли изменения в сообщение. Что касается проверки для aggregate / commands, мне было наплевать на список пользователей, которые внесли изменения. Означает ли это, что этот список не должен быть частью моего состояния в моем агрегате?
Ответ №1:
TL; DR: да — ограничьте «состояние» в агрегате теми данными, которые вы выбираете для кэширования в поддержку изменения данных.
В моих агрегатах я различаю две разные идеи:
- история, то есть последовательность событий, которая описывает изменения во времени существования агрегата
- кэш, он же значения данных, которые мы убираем, потому что каждый раз запрашивать историю событий — отстой.
В кэшировании результатов, которые мы никогда не будем использовать, не так много пользы.
Один из основных уроков CQRS заключается в том, что нам не нужны агрегаты везде
АГРЕГАТ — это кластер связанных объектов, которые мы рассматриваем как единое целое с целью изменения данных. — Эванс, 2003
Если мы не изменяем данные, мы можем безопасно работать напрямую с неизменяемыми копиями данных.
Ответ №2:
Единственная существенная цель агрегата — определить, какие события, если таковые имеются, необходимо применить, чтобы привести состояние агрегата в соответствие с командой (если агрегат можно привести в соответствие). Все состояния, которые не нужны для этой цели, могут быть выгружены на сторону чтения, которую можно рассматривать как ремикс потока событий (при этом каждая сторона чтения поддерживает только то состояние, которое ей нужно).
Тем не менее, на практике существуют причины для непосредственного использования агрегированного состояния, причем основной из них является стремление к большей согласованности для агрегата: CQRS по своей сути в конечном итоге согласован. Как и во всех вопросах согласованных обновлений, важно понимать, что согласованность не бесплатна и очень часто даже не дешева; я склонен думать о проекте как о бюджете согласованности, и я довольно скупо трачу его.
В вашем случае, вероятно, нет причин включать список пользователей, изменяющих сообщение в агрегированном состоянии, если, например, нет чего-то вроде «ни один пользователь не может изменять данное сообщение более n раз».