DDD: агрегатный корневой вопрос


Допустим, у меня есть 2 сущности - Foo и Bar. Foo является агрегатным корнем и содержит бар. Насколько я понимаю, это должно выглядеть так:

public class Foo{
    private readonly Bar Bar;
}

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

Если предполагается, что репозитории предназначены только для агрегатных корней, это означает, что не будет репозитория для сущности Bar.

Это приводит к тому, что панель задач не может быть создана/обновлена самостоятельно без ссылки на Foo.

Означает ли это, что бар должен иметь хранилище, несмотря на то, что он не имеет смысла без Foo?

3 16

3 ответа:

Если вы хотите выбрать из списка баров, где они не связаны с Foo, то это не агрегатный корень. Например, вы не можете получить список OrderItems без их порядка, поэтому это один агрегатный корень (Order), но вы можете получить список продуктов для назначения OrderItems, поэтому продукт не является частью агрегатного корня Order.

Обратите внимание, что, хотя OrderItem является частью агрегатного корня Order, вы все еще можете создавать и обновлять его независимо. Но, вы не можете получить его без ссылка на порядок. То же самое для вашего бара, даже если он был частью Foo, вы могли бы получить каждый(Foo.Бары) и работать с ним, или делать Фу.AddBar (новый бар ()). Но если вам нужно получить список без Foo, Bar не является частью Foo aggregate. Это отдельная сущность.

Ну, вот как я вижу DDD здесь, но я, конечно, не Эрик Эванс.

Причины наличия агрегатных корней следующие:

  1. они обеспечивают контролируемый и направленный доступ к составным сущностям
  2. они могут применять правила, чтобы гарантировать, что вся совокупность действительна

Мой дубль: Если вам нужно выбрать Bar объекты без Foo, используйте BarRepository.

Но..... Что делать, если вы обновите Bar, и это нарушит правило проверки для его родителя Foo? Если это может произойти, вы должны получить доступ к Bar через родитель Foo.

Если, однако, вам нужно получить доступ к группе объектов Bar (например, для пакетного задания или отчета), и вы знаете, что Foos не будет сломан, продолжайте и получите доступ к ним через BarRepository.

Помните, что агрегатные корни могут состоять из других агрегатных корней. Вы можете обнаружить, что Bar - это сам агрегатный корень, дающий вам обоснование для a BarRepository :)

Вы уверены, что бар должен быть сущностью? Есть ли у вас необходимость отслеживать его и изменять в домене? Если вы можете рассматривать его как объект ценности, я бы предложил вам извлечь его из сервиса,а затем "подключить" выбранный объект ценности к сущности Foo. На мгновение через выпадающий список.