CQRS команды и запросы. Они относятся к уровню приложения или домена с точки зрения DDD? - PullRequest
0 голосов
/ 24 апреля 2019

Читая различную литературу DDD, я сталкиваюсь с одной теоретической проблемой.Проблема заключается в том, следует ли мне размещать команды и запросы на уровне приложений или доменов.

Итак, некоторые авторы, такие как Скотт Влашин (в своей книге «Моделирование домена сделано функциональным»), говорят, что

, есликоманда успешно выполняется, она запускает рабочий процесс, который, в свою очередь, создает соответствующие события домена

. Таким образом, существует соответствие, например, между командой «Разместить заказ» и событием домена «Заказ размещен».Это заставляет меня поверить, что я должен разместить команды и события на одном уровне и организовать их следующим образом:

\Model
    \Message
         \Command
             PlaceOrder.lang
         \Event
             OrderPlaced.lang

Итак, я размещаю все команды на уровне домена, в то время как службы приложений вызывают эти команды и переносят их дляпример в транзакциях.

Однако есть еще одна точка зрения, выраженная в книге Скотта Миллета («Образцы, принципы и практики доменного проектирования»).Цитата гласит:

Команда - это бизнес-задача, вариант использования системы, и она находится на уровне приложений.Вы должны писать команды на языке бизнеса.

Из-за этого противоречия я не совсем уверен, каков наиболее канонический способ обработки команд (и запросов также).В реальном мире они живут на уровне домена или приложения?

Ответы [ 3 ]

2 голосов
/ 27 апреля 2019

Команды и запросы определенно находятся на уровне приложения.

Они вызывают методы службы приложений, которые отвечают за охват транзакций, ведение журнала высокого уровня и делегирование бизнес-объектам.

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

1 голос
/ 24 апреля 2019

Что касается меня, то основная идея DDD - это повсеместный язык, ограниченный контекст и сопоставление контекста.Итак, если мы сосредоточимся на этих концепциях, все остальные части станут деталями реализации.

15 лет назад, когда была написана «Синяя книга», пришло время Java.В настоящее время существуют разные парадигмы, которые приходят и уходят.

Мне нравится разделять команды, запросы, события и ответы на разные уровни.Основная проблема в том, что вам скоро не хватит подходящих слов.Но это хорошо известная проблема с программированием.

В основе реализации лежит словарь.Это не весь вездесущий язык, но, вероятно, большая его часть.Там я моделирую доменные классы и структуры, в основном используя неизменяемые типы данных.Там вы положили фабрики и инварианты.Словарь не зависит от других частей кода.

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

Команды и события являются внутренними для бизнес-ядра системы.Но вы получаете запросы и отправляете ответы в неком проводном формате, таком как JSON, XML, ProtoBuf и так далее.Вы должны маршалировать / демаршировать его, добавлять дополнительные данные, такие как аутентификация / идентификация, различные идентификаторы трассировки, и преобразовывать их в некоторую объектную модель, которая ничего не знает о форматах проводов.Я называю эти объектные модели бизнес-запросом и бизнес-ответом.Они принадлежат прикладному уровню.

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

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

Таким образом, проводные форматы и преобразователи в / из бизнес-запроса / ответа относятся к уровню адаптеров инфраструктуры.Бизнес-запросы и ответы и их преобразователи в / из команды / события / отклонения принадлежат прикладному уровню (а также задаче по подготовке данных для принятия решений и выполнения принятых решений).А команды / события / отклонения принадлежат функциональному ядру.

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

1 голос
/ 24 апреля 2019

Из-за этого противоречия я не совсем уверен, каков наиболее канонический способ обработки команд (и запросов также).В реальном мире они живут на уровне предметной области или приложения?

Литература немного запутанная в этом вопросе, прежде всего по историческим причинам.

Когда мы говорим о messages , то есть API нашего приложения / сервиса;они принадлежат за пределами модели домена.

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

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

Когда Уди Дахан говорит, что сервисы "делят контракт и схему, а не класс или тип", он описывает сообщения, которыми обмениваются.От клиентов не требуется заботиться о том, какой «класс или типы» мы используем при реализации модели предметной области.

Теперь, чтобы быть справедливым, клиентам не нужно заботиться о том, какой «класс или типы» мы используем.при реализации приложения либо .Тот факт, что вы принимаете сообщение PlaceOrder (семантика, выражаемая последовательностью байтов, отправленных вам по сети) и представляете его как расположение в памяти типизированных ссылок на память, является вашим собственным делом.

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

...