Как представить расчеты, доступные только для чтения, из модели бизнес-домена на внутреннем интерфейсе с помощью CQRS? Модель чтения против проблемы записи модели - PullRequest
2 голосов
/ 21 февраля 2020

У меня есть два вопроса, связанных с CQRS и доменно-управляемым дизайном (DDD).

Насколько я понимаю идею сегрегации, стоящую за CQRS, у каждого было бы две отдельные модели: модель чтения и запись модель. Только модель записи будет иметь доступ к модели бизнес-домена и использовать ее с помощью команд. Однако модель чтения напрямую переводит содержимое базы данных в DTO с помощью запросов и вообще не имеет доступа к бизнес-домену.

Для контекста: я пишу серверную часть веб-приложения, предоставляющую услуги для расчета физика частиц. Теперь мои вопросы:

1.) Логика моего бизнес-домена c содержит некоторые функции, которые вычисляют математические значения как выходные данные из заданных конфигураций измерительной системы в качестве входных данных. Таким образом, технически это запросы только для чтения, которые вычисляют значения на лету и не изменяют состояние в любой модели. Таким образом, они должны быть частью модели чтения. Однако, поскольку функции тесно связаны с доменом, они должны быть частью модели предметной области, которая снова является частью модели записи. Как мне сделать эти функции вычисления доступными для внешнего интерфейса через мой API, если модель чтения, которая должна содержать все запросы, не имеет доступа к модели домена?

Действительно ли мне нужно запускать команда для сохранения всех вычислений в базе данных, чтобы модель чтения могла получить доступ к результатам вычислений? Эти «одноразовые» вычисления будут использоваться только внешним интерфейсом, и в дальнейшем никто не будет иметь доступа к постоянным результатам расчетов. Постоянной должна быть конфигурация измерений, а не результаты расчетов. Они будут пересчитываться много раз, когда пользователь нажимает кнопку «Рассчитать» на внешнем интерфейсе.

2.) Мне также кажется, что я дублирую довольно много кода проверки данных, потому что оба читают модель и модель записи должны десериализовать и проверять одинаковые или очень похожие параметры запроса в цепочке процессов http request body -> json -> unvalidated DTO -> validated value -> command/query. Как с этим бороться? Могу ли я поделиться кодом проверки между моделью чтения и моделью записи? Кажется, это растворяет сегрегацию.

Заранее благодарим за помощь и идеи.

Ответы [ 2 ]

5 голосов
/ 22 февраля 2020

Я думаю, что у вас есть набор доменных служб, которые с заданным входом возвращают результат. Как вы сказали, эти сервисы расположены в домене. Но ничто не мешает вам использовать их в модели чтения. Пока вы не измените домен внутри функций, вы можете использовать их в любом слое над доменом. Если по какой-либо причине это решение не является жизнеспособным, поскольку, например, для служб требуются доменные объекты, которые вы не можете / не хотите создавать на стороне запроса, вы всегда можете обернуть доменные службы внутри служб приложений. Там вы вводите базовый объект, делаете все преобразования в домен один, вызываете службу домена и возвращаете полученное значение.

По второму вопросу вы можете создать службу проверки в Доменный уровень, как набор услуг или простых функций. Опять же, ничто не запрещает вам использовать их на этапах проверки. Я сделал то же самое в своем последнем веб-приложении: шаг проверки данных формы вызывает набор служб домена, которые также используются при создании объектов домена во время обработки команды. Изменение валидации в домене также влияет на валидацию, связанную с Интернетом. Вы проверяете два раза (перед сборкой команды и во время построения объекта домена), но это нормально.

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

0 голосов
/ 10 марта 2020

Просто добавьте мою стоимость в два пенса.

У нас есть микросервисы, которые используют mon go в качестве бэкэнда. Мы используем NET Core, используя mediatr (https://github.com/jbogard/MediatR) для реализации шаблона CQRS в MS. У нас есть .Query и .Command функции .

Теперь в нашем мире мы никогда не обращались к Event Sourcing. Итак, на уровне mon go наши модели (сущности) для чтения и записи одинаковы. Поэтому для нас лучше всего было иметь одну сущность модель, которую можно преобразовывать в разные модели (при необходимости) с помощью каждого обработчика (ов) команды / запроса.

Если вы делаете pure CQRS через источник событий (такие разные модели чтения и записи) или что-то еще, тогда, пожалуйста, игнорируйте меня! Но это сработало лучше для нас.

...