Поиск дочернего элемента по совокупным корням

Шаблон репозитория предполагает, что вы можете извлекать только совокупные корни. Но как бы вы получили один дочерний элемент, используя только его уникальный идентификатор (Child.ID), если вы не знаете его родителя (root)?

class Parent
{
    public int ID { get; set; }
    IEnumerable<Child> Children { get; private set; }
}

class Child
{
    public int ID { get; private set; }
    public virtual Parent Parent { get; private set; } // Navigational model
}

Мое приложение не имеет состояния (веб), для простоты запрос содержит только идентификатор ребенка.

Я думаю о трех подходах:

  1. Позвоните всем родителям, затем вежливо спросите их, кому принадлежит этот ребенок.
  2. У вас есть специальная процедура в ParentRepository, называемая getChildByID, которая как бы нарушает абстракцию репозитория.
  3. Измените запрос, чтобы включить родителя, но это кажется ненужным, поскольку у вас уже есть уникальный идентификатор.

person Yorro    schedule 25.11.2013    source источник
comment
Создать метод GetChildByID(..) в классе ChildRepository?   -  person Ahmed KRAIEM    schedule 25.11.2013
comment
Ребенок должен быть Агрегатом, если вы можете идентифицировать его без родителей.   -  person Yugang Zhou    schedule 25.11.2013
comment
@Hippoom Мои знания о Aggregate Root ограничены, вы говорите, что, пока сущность имеет уникальную идентичность, ее можно считать корнем? Я обновил образец кода.   -  person Yorro    schedule 25.11.2013
comment
Сущность должна быть совокупной, если эксперты в предметной области хотят отслеживать ее в одиночку. Например, если предположить, что эксперты предметной области не будут отслеживать линию заказов без заказа, тогда заказ является агрегатом, а заказная строка — это просто локальная сущность. Даже если технически мы даем orderLine уникальный идентификатор.   -  person Yugang Zhou    schedule 25.11.2013
comment
@Hippoom +1 Думаю, ты попал в самую точку. Возможно, этот дочерний элемент является совокупным корнем в одном ограниченном контексте и объектом-значением в другом контексте.   -  person MattDavey    schedule 26.11.2013
comment
@AhmedKRAIEM в DDD у вас никогда не будет класса ChildRepository. Это подорвало бы всю цель агрегатов.   -  person MattDavey    schedule 27.11.2013


Ответы (3)


Кажется вероятным, что вы на самом деле смотрите здесь на другой ограниченный контекст. Вы упомянули в своем вопросе, что "репозиторий... может извлекать только совокупные корни."; это верно. В другом ответе также упоминается, что если вам нужно запросить дочерний объект, дочерний объект также может быть совокупным корнем. Это также может быть правильным в другом ограниченном контексте. Вполне возможно, что сущность может быть совокупным корнем в одном контексте и сущностью-значением в другом.

Возьмем, к примеру, домен Users и мобильный/планшет Apps, которые они установили на свои устройства. В контексте пользователя нам могут понадобиться основные свойства пользователя, такие как имя, возраст и т. д., а также нам может понадобиться список приложений, которые пользователь установил на свое устройство. В этом контексте User — это совокупный корень, а App — это объект-значение.

bounded context UserApps
{
    aggregate root User
    {
        Id : Guid
        Name : string
        Age : int
        InstalledApps : App list
    }

    value object App
    {
        Id : Guid
        Name : string
        Publisher : string
        Category : enum
    }
}

В другом контексте мы можем взглянуть на мир с точки зрения App и решить, что App является совокупным корнем. Скажем, например, мы хотели сообщить, какие пользователи установили данное приложение.

bounded context AppUsers
{
    aggregate root App
    {
        Id : Guid
        Name : string
        InstalledBy : User list
    }

    value object User
    {
        Id : Guid
        Name : string
        InstalledOn : Date
    }
}

Оба этих ограниченных контекста будут иметь собственный репозиторий, который возвращает соответствующий совокупный корень. Есть тонкая, но важная разница в вашей точке зрения на данные.

Я думаю, что если вы сделаете шаг назад и подумаете, почему вам нужно запрашивать дочерний объект, вы можете обнаружить, что фактически находитесь в совершенно отдельном ограниченном контексте.

person MattDavey    schedule 26.11.2013
comment
Извините за поздний ответ спасибо. Я приму это как самый близкий ответ, который мне нужен. Теперь я понимаю, что совокупный корень меняется в зависимости от контекста. Я также нашел хорошую статью, которая еще больше помогла мне понять этот вопрос. sapiensworks.com/ блог/сообщение/2012/04/18/ - person Yorro; 16.12.2013

Если вам требуется дочерний элемент для отображения/отчетности/просмотра/отчетности, тогда подойдет простой слой запросов.

Если вы каким-либо образом манипулируете дочерним элементом, тогда у него есть граница согласованности, и это очень похоже на совокупность.

Старайтесь не запрашивать объекты вашего домена. Еще одно простое эмпирическое правило: не включать ссылку на агрегат в другой агрегат, а использовать только идентификатор упомянутого агрегата или даже объект-значение, представляющий отношение.

person Eben Roux    schedule 25.11.2013

Навигация по сущностям не является целью модели предметной области.
Совокупный корень — это композиция сущностей и значений, которые раскрывают бизнес-операции.
В качестве побочного эффекта вы по-прежнему можете выполнять простой запрос или навигацию по AR, но для сложных запросов создание и использование модели запросов более эффективно.
Я говорю о CQRS. .

Надеюсь, это поможет вам.

person Enrico Sanguin    schedule 26.11.2013