Объекты Value в CQRS - где использовать
Скажем, у нас есть архитектура, основанная на CQRS, с такими компонентами, как Commands, Domain Model, Domain Events, Read Model DTO.
Конечно, мы можем использовать объекты Value в нашей модели домена. Мой вопрос в том, должны ли они также использоваться в:
Я не видел примеров, когда в упомянутых выше компонентах используются объекты Value (VO). Вместо этого используются примитивные типы. Может быть, это просто упрощенные примеры. В конце концов, мое понимание использования VO в DDD заключается в том, что они действуют как клей для всего приложения.
Моя мотивация:
команды.
Пусть пользователь отправляет форму, содержащую поля адреса. У нас есть объект Address Value для представления этой концепции. При построении команды в клиенте мы должны все равно проверять ввод пользователя, и когда он хорошо сформирован, мы можем создать объект Address прямо там и инициализировать команду с ним. Я не вижу необходимости делегировать создание объекта Address в обработчик команд.
События домена.
Модель домена уже работает с точки зрения объектов Value, поэтому, публикуя события с VO вместо их преобразования в примитивные типы, мы можем избежать некоторого кода сопоставления. Я вполне уверен, что в этом случае можно использовать VO.
DTOs.
Если наши DTO на стороне запроса могут содержать объекты Value, это обеспечивает некоторую гибкость. Например, если у нас есть объект Money, мы можем выбрать, показывать ли его в EUR или USD, не нужно изменять Read Model.
Ответы
Ответ 1
Хорошо, я передумал. В последнее время я пытаюсь разобраться с VOs, и после просмотра этого http://www.infoq.com/presentations/Value-Objects-Dan-Bergh-Johnsson он разъяснил мне пару вещей.
Команды и события - это сообщения (а не объекты, объекты - поведение данных +), в некотором отношении, как и DTO, они обмениваются данными о событии и сами не инкапсулируют никакое поведение.
Объекты Value не похожи на DTO. Они представляют собой представление домена, и они, вообще говоря, богаты поведением, как и все другие представления домена.
Команды и события передают информацию в и из домена соответственно, но сами они не инкапсулируют какое-либо поведение. С этой точки зрения кажется неправильным и, возможно, границ контекста нарушения, чтобы пропускать VO внутри них.
Перефразируя Oren (хотя он имел в виду nHibernate и WCF) "Не отправляйте свой домен через провод".
http://ayende.com/Blog/archive/2009/05/14/the-stripper-pattern.aspx
Если вы хотите сообщить объект значения, я предлагаю передать необходимые атрибуты, необходимые для повторной сборки VO внутри них.
Оригинальный текст (для потомков):
Если вы спрашиваете, могут ли объекты-объекты передать объекты домена событиям или переданы командами, я действительно не вижу огромной проблемы с первой, хотя последние могут нарушать некоторые из правил совокупности root является "владельцем" значений.
Таким образом, объект value представляет собой такие понятия, как, например, цвет. У вас нет зеленого, зеленого или нет. Кажется, что ничего не происходит с командой, говорящей вам, что вы зеленые, передавая это.
Чтение главы из DDD в шаблоне Aggregate Root довольно хорошо объясняет объекты и объекты Value и стоит прочитать несколько раз.
Ответ 2
Я говорю, что это плохая идея.
Есть причина, по которой мы не делаем то же самое с сущностями - чтобы не связывать другие части системы с доменом (в неправильных местах). То же самое относится к объектам Value, единственная разница между объектами ценности и сущностями - это пожизненное и владение - эти различия не влияют на то, как мы должны и не должны их связывать.
Представьте, что вы создаете событие, содержащее VO. Изменение вашего домена требует от вас изменения этого VO. Теперь вы включили себя в угол, где ваше событие также принудительно изменилось, а для любых команд или DTO это часть.
Этого следует избегать.
Используйте DTO и/или примитивы. Сопоставьте их (AutoMapper делает это сделкой с 1 строкой).
Ответ 3
Как и в других ответах, в SOA это нарушит инкапсуляцию службы, поскольку домен теперь протекает.
Ответ 4
В соответствии с Clean Code ваши DTO являются структурами данных (просто для добавления другого термина), а объекты значений - объекты. Разница в том, что объекты могут иметь поведение. Смешивание структур данных с объектами, как правило, очень плохое, потому что будет сложно поддерживать полученный вами гибрид.
Я не считаю правильным добавлять объекты ценности в DTO с точки зрения архитектуры. Объекты значения находятся внутри модели домена, а упомянутые вами DTO определяют интерфейс модели. Обычно мы создаем интерфейс, чтобы отделить внешний мир от чего-то. Таким образом, в текущем случае мы добавили DTO, чтобы отделить внешний мир от объектов ценности (и других связанных с моделью материалов). После этого добавление объектов значения в интерфейс сходит с ума.
Итак, вы еще не встретили это решение, потому что это анти-шаблон.