Страницы

Поиск по вопросам

воскресенье, 15 декабря 2019 г.

DDD, aggregate root, entity, repository?

#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.

Комментариев нет:

Отправить комментарий