В соответствии с DDD мне нужно дополнительное хранилище и модель - PullRequest
0 голосов
/ 23 февраля 2020

Согласно DDD для каждого aggregate у меня есть repository. Давайте рассмотрим пример:

Client (model aggregate) > ClientRepository
Visit  (model aggregate)  > VisitRepository

Теперь физически у меня есть таблица ассоциации в базе данных, которая связывает Client и Visit, потому что клиенты могут иметь много визитов.

Вопрос в том, должен ли я создать отдельную модель, например : ClientVisit, который также будет aggregate:

public class ClientVisit
{
     int clientId;
     int visitId;   
}

Кроме того, хранилище типа ClientVisitRepository, которое может ссылаться / использовать ClientRepository и VisitRepository.

Или достаточно придерживаться, например, CLientRepository и получать оттуда данные без модели дополнительности и репозитория

Изменение к сообщению:

Вместо Visit (неправильный пример ) - давайте заменим на Car, поэтому каждый client может иметь many cars. У нас также будет уникальный transactionNumber, поэтому:

Client (model aggregate)  > ClientRepository
Car    (model aggregate)  > CarRepository

Должен ли я затем создать агрегат, такой как:

public class ClientCar
{
    int clientId;
    int visitId;  
    int transactionNumber; 
}

и ClientCarRepository?

Ответы [ 3 ]

1 голос
/ 24 февраля 2020

Repository, в смысле доменного дизайна, - это шаблон управления жизненным циклом. См. Главу 6 «синей книги».

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

Из этого следует, что вам не нужен репозиторий для отношения клиент-машина если только это не root ее собственной совокупности .

Определение того, должно ли это отношение быть в его собственной совокупности или нет, является предметом анализа предметной области - вам придется копать в ваш указанный c домен, чтобы выяснить ответ. Для чего-то вроде домена проката автомобилей я бы предположил , что вы хотите, чтобы это отношение и информация, связанная с его жизненным циклом, находились в отдельном агрегате от автомобиля или клиента. Но я не чувствую уверенности в этом предположении, пока не проработаю несколько крайних случаев с экспертами в области.

1 голос
/ 23 февраля 2020

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

Хранилища предназначены быть не более чем сериализаторами и десериализаторами для ваших сущностей и агрегатов. Между ними не должно быть преднамеренного 1: 1. Фактически, в большинстве случаев у вас не будет 1 к 1. В моем коде я стараюсь размещать репозитории в ограниченном контексте или в подтексте.

Возьмем тривиальный пример: приложение для ведения блогов. У меня может быть хранилище, в котором можно сохранить комментарий. Сохранение комментария означает сохранение самого комментария и обновление количества комментариев пользователя. Метод Save(Comment comment, Usr usr) сделает два вызова моего механизма персистентности для обновления отдельных сущностей или агрегатов.

0 голосов
/ 23 февраля 2020

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

Трудно быть точным, не зная вашего домена, однако, в вашем примере, Client кажется более естественный кандидат на совокупность: клиент может владеть новыми машинами , избавиться от нескольких и т. д .; соответствующие операции (например, добавление или удаление автомобилей) естественным образом вписываются в клиента.

ClientCar (или ClientVisit), с другой стороны, похоже, не имеет никакой другой цели, кроме поиск автомобилей, принадлежащих клиенту . Для этого навигации по сущности должно быть достаточно, агрегат не требуется. Ваш репозиторий Client может представить метод для этой цели, например:

public interface ClientRepository
{
    Client findById(String clientId);

    void store(Client client);

    IList<Cars> carsOwnedBy(String clientId);
}

Тогда реализация метода carsOwnedBy извлекает Client и возвращает только Car s, связанных с ним.

...