Хорошо, давайте разделим этот вопрос на две части:
- Можно ли объекту-члену хранить ссылку на его совокупный корень?
- Общие правила моделирования агрегатов
Начнем с 1:
Нет, как правило, дочерние объекты не должны содержать ссылки на корни агрегатов. Корень агрегата является точкой входа для всего агрегата и должен поддерживать свои границы согласованности. Это означает, что каждое изменение агрегата должно быть перенаправлено через корневой объект (в oop путем вызова методов корневого объекта). Совокупный корень может возвращать ссылки на дочерние объекты, но они должны быть временными. Кроме того, клиент не должен вносить изменения в дочерние объекты за пределами корня агрегата, иначе может быть нарушена согласованность. Имея это в виду, я действительно не вижу причин для дочерних сущностей хранить ссылки на свой корень (с точки зрения клиента — у вас уже есть доступ к корню, не так ли?). Единственное исключение, которое я вижу прямо сейчас, это когда вам нужно преобразовать модель в некоторые конкретные потребности (например, уровень представления требует идентификатора корневого объекта для получения значимого вывода JSON). Однако даже в этом случае вы, вероятно, создадите отдельную модель чтения или предоставите специализированные ассемблеры для создания необходимых DTO.
Хорошо, теперь ко второму пункту:
Кажется, вы пытаетесь смоделировать свои доменные сущности так же, как вы строите модель своей базы данных. В DDD мы должны сначала сосредоточиться на бизнес-требованиях и поведении нашей модели. Отношения данных не так важны при построении значимой модели предметной области (мы уточним это чуть позже). Итак, в первую очередь вам следует сосредоточиться на сборе сценариев бизнес-кейсов от экспертов в вашей области. Агрегаты должны строиться на реальных бизнес-инвариантах. Вы должны создать общую модель вместе со своей командой (включая представителей бизнеса). Очень вероятно, что ваш дизайн будет выглядеть совершенно по-другому после нескольких сеансов обработки знаний. Может быть, Person на самом деле не совокупный корень, а просто объект-значение? Может быть, вам даже не нужна сущность PopulationMembership? Наиболее распространенный дизайн для агрегатов — это всего лишь один (корневой) объект с несколькими объектами-значениями. Кроме того - я часто создаю полностью отдельную модель базы данных, практически не привязываясь (кроме id) к модели предметной области. Я использую слой перевода (компоненты сопоставления) для преобразования между domain‹->dbmodel. В моем недавнем проекте моя модель базы данных сильно отличалась от уровня предметной области (она была адаптирована специально к потребностям уровня постоянства — так, например, использовалось много плоских свойств — не полные объекты, а простые примитивные значения). В случае реляционной базы данных вы можете даже явно указать двунаправленную связь (на самом деле вам даже не нужно использовать какую-либо форму). Есть много преимуществ в отделении вашей модели БД от модели предметной области. Дизайн определенно стал более гибким. Однако стоимость сопоставления (работа разработчика) между db ‹-> доменным уровнем может быть слишком большой для простых проектов. В таком случае я обычно начинаю с общей модели, а затем выполняю рефакторинг на отдельные слои.
О, еще одна важная вещь - обычно рекомендуется ссылаться на другие совокупные корни только по идентификатору. Таким образом, у вас не будет проблем со сложным графом объектов, и вам не нужно беспокоиться об изменении других агрегатов в рамках одной транзакции (корень агрегата не должен изменять другие корни). Если вам нужно обмениваться данными между агрегатами, используйте вместо этого события.
Пожалуйста, обратитесь к замечательной серии статей Вона Вернона:
http://dddcommunity.org/library/vernon_2011/
Я думаю, что эти статьи могут помочь вам понять концепции агрегатного моделирования.
person
Mike Wojtyna
schedule
07.03.2017