#java #c_sharp #cpp #entity_framework #ddd
В книге Эванса написано что "repositories" должны возвращать только "aggregate root". А как тогда быть с обычными entities. Простой пример: есть класс City по определению это entity у него есть id и name его не уникален, как его получать, добавлять, изменять в "парадигме" DDD ? Получается что для каждой сущности нужен свой репозиторий а не только для корней агрегации? Для примера кусок простого интернет магазина (ниже), получается и для tag и для region свои репозитории? потому что то как то надо их создавать, изменять итд. public class Tag { private string _name ; } public class Region { private string _name } public class City { private Guid _id; private string _name private Region _region; } public class User { private Guid _id; private City _city; // всякие методы } public class Product { private Guid _id; private City[] _cities; private Tag[] _tags; // всякие методы }
Ответы
Ответ 1
Насколько я раздумывал над этими проблемами - Эванс говорит о следующем: Одна и та же сущность/entity предметной области может как являться (в одних сценариях) Aggregation root, так и не являться в других. Как правило, почти всегда найдётся сценарий, когда тот или иной класс является Aggregation root. В качестве примера я обычно привожу пример Contact с набором Phone[]. При этом я могу создать класс Phone, но не сохранять его в отдельную таблицу и не делать отдельный репозиторий. Посмотрите теперь на связку классов Product с набором Tag[]. Если Tag - какая-то вспомогательная сущность, то смысла делать для неё репозиторий нет и можно спокойно сохранять строкой набор тегов в таблице продуктов. Если же у вас начинается какая-то аналитика и построение отчётов по тегам - у вас и внешний ключ появится с отдельной таблицей и репозиторий. получается и для tag и для region свои репозитории? потому что то как то надо их создавать, изменять итд. Надо создавать изменять - ничто вам не запрещает создавать и изменять их без отдельного репозитория. При условии, что этот объект просто используется в сценариях, когда теги нужны только продукту. Поэтому смотрим, что нужно в приложении, а потом уже подбираем подходящее решение (с отдельным репозиторием или без). Этот приём (проверить, нужна ли отдельная таблица или можно встроить в основную таблицу) можно использовать в качестве проверки, является ли класс value object'ом и соответственно, нужен ли репозиторий. Не панацея, но часто работает. Недавний пример из моего вопроса: есть отдельный класс для точки на яндекс:карте, но репозитория нет. Другой пример. Паттерн Money - типичный value object, отдельного репозитория нет и не нужно. В подобных задачах всегда очень хочется создать репозиторий про запас. Но если бы вы отталкивались от сценариев использования, реальных, согласованных заказчиком (читай: подтверждённых рублём) - то увидели бы, что часто и не нужно столько репозиториев. Вы вот по-честному начали проработку приложения со сценариев или по привычке подтаскиваете CRUD во все классы?Ответ 2
Репозиторий должен быть только у корней агрегатов. Озвученный вами сценарий по манипулированию сущностю говорит о том, что у вас City является корнем агрегата и этот агрегат состоит из 1 сущности. Не могу вспомнить источник информации где озвучивалась статистика, 70% агрегатов состоят из одной сущности. Замечания по вашему коду. У Tag и Region нет уникального идентификатора по которому остальные сущности могут на них ссылаться. В таком виде они больше напоминают value object. User не должен хранить навигационную ссылку на City как и на любые сущности из других агрегатов. Только идентификтор сущности. Навигационные ссылки допускаются только внутри агрегата. То же самое относится и к Product.
Комментариев нет:
Отправить комментарий