Я перешел в проект, который активно использует CQRS + event sourcing. С первого взгляда он реализовывался в соответствии со всеми этими книгами и блогами, но, в конце концов, я понял, что именно выглядит в процессе реализации.
Вот архитектура CQRS:
Изначально я сделал это изображение из здесь.
Как видно на рисунке, сторона чтения получает события из очереди и передает ее по одному в разные наборы проекций (denormalizers), а затем полученные ViewModels сохраняются через метод AddOrUpdate, скажем, в DB. Так как я понимаю из изображения denormalizer может полагаться только на само событие плюс данные со стороны db на стороне чтения. Например:
- Просмотр аккаунта уже сохранен в db.
- Придет событие EmailChanged
- Мы читаем "Просмотр учетной записи" из базы данных
- Применение изменения электронной почты к ней
- Мы сохраняем счет обратно в БД.
Другой случай (подсчет количества некоторых элементов, например заказов):
- Прикрепленное событие OrderCreated
- Мы читаем ViewModel, который представляет NumberOf ранее поступившие заказы
- Увеличить и сохранить это.
Что мы имеем в нашем проекте: Мы используем все эти события только как уведомитель, что что-то изменилось в модели домена. Следовательно, что мы делаем:
- Мы берем репозиторий домена и читаем все необходимые агрегаты. Таким образом, мы получаем самое последнее из них.
- Мы просто создаем объект ViewModel с нуля
- Сохранить вновь созданный объект в Db
Подход, который мы используем в нашем проекте, выглядит немного странным для меня, но я не вижу в нем всех недостатков. Если нам нужно перестроить нашу сторону чтения, мы добавим "активный" денормализатор, и в следующий раз, когда он получит конкретное событие, он воссоздает новую модель просмотра.
Если мы используем подход из книг, мне придется иметь отдельную логику utils где-то из моей системы для перестройки. Что нам нужно для этого:
- Отбросить прочитанную сторону
- С самого начала прочитайте все события из хранилища событий.
- Пропустите их через проекции
Итак, мой вопрос:
Каков правильный подход?