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

Я новичок в DDD. Я проверил ответы на: Может ли хранилище получить доступ к другому с помощью DDD? до запроса, но не смог найти соответствующую информацию.

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

Мой вопрос: должен ли первый хранилище обращаться ко второму хранилищу или должен ли приложение вызывает два репозитория и объединяет их;

Например:

для двух классов:

public class Foo1
{
    public int Id { get; set; }

    // .... More data

    public Foo2 foo2 { get; set; }
}

public class Foo2
{
    public int Id { get; set; }

    public int Type { get; set; }
}

Если код выглядит следующим образом:

public class Foo1Repository
{
    public Foo1 Get() { 
        return new Foo1();
    }
}

public class Foo2Repository
{
    public Foo2 Get(int foo1Id)
    {
        return new Foo2();
    }
}

public class Application
{
    public void main()
    {
        Foo1 foo1 = new Foo1Repository().Get();
        foo1.foo2 = new Foo2Repository().Get(foo1.Id);
    }
}

или больше как:

public class Foo1Repository
{
    public Foo1 Get() {
        Foo2Repository foo2Repository = new Foo2Repository();
        Foo1 foo1 = new Foo1();
        foo1.foo2 = foo2Repository.Get(foo1.Id);

        return foo1;
    }
}

public class Foo2Repository
{
    public Foo2 Get(int foo1Id)
    {
        return new Foo2();
    }
}

public class Application
{
    public void main()
    {
        Foo1 foo1 = new Foo1Repository().Get();
    }
}

Конечно, я был бы признателен, если бы была лучшая архитектура?

Спасибо!

Ответы [ 2 ]

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

DDD рекомендует выделить хранилище для извлечения и хранения одного агрегата root; Совокупные корни - это сущности , играющие важную роль в домене. Модификации сущностей должны происходить через агрегат root: извлечь агрегат root с его хранилищем, внести необходимые изменения и сохранить его обратно. Агрегированные root составляющие сущности не должны извлекаться и изменяться независимо , поэтому для них нет репозиториев.

В вашем случае, в зависимости от контекста, Foo1 представляется совокупным root. Только один репозиторий для Foo1 должно быть достаточно; хранилище для Foo2 является избыточным. Вы можете и должны изменить свойство Foo1 Foo2 - Foo1 после получения экземпляра Foo1; Foo2 нельзя извлекать и изменять независимо, поэтому нет необходимости в Foo2 хранилище.

Однако, опять же, в зависимости от контекста, если вы обнаружите, что Foo2 является совокупностью root вместе с Foo1, только тогда он заслуживает своего собственного хранилища. В этом случае, однако, Foo1 не должен содержать ссылку на Foo2 (то есть прямую ссылку на другой агрегат root, что не рекомендуется) и изменять его в транзакции; вместо этого он должен ссылаться на Foo2 только по своему идентификатору , как показано ниже для вашего примера:

public class Foo1
{
    public int Id { get; set; }

    // .... More data

    public int foo2Id { get; set; } // Foo2 identfier only, not a Foo2 instance
}

public class Foo2
{
    public int Id { get; set; }

    public int Type { get; set; }
}

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

Foo1 foo1 = foo1Repository.findById(foo1Id);

// modify foo1 state

Foo2 foo2 = foo2Repository.findById(foo1.foo1Id);

// modify foo2 state

// persist changes
foo1Repository.store(foo1);
foo2Repository.store(foo2);
1 голос
/ 23 февраля 2020

Нет, не должно. Вы не полностью реализуете концепцию репозитория, как предполагалось.

Репозиторий - это просто интерфейс для сохранения ваших DDD объектов. Я не могу предположить, что существует требование вездесущего языка, для которого потребуется, чтобы в одном репо содержался другой. Другими словами, ваш эксперт по предмету никогда не скажет что-то вроде «Пользователь должен быть сохранен в плоский файл, который находится внутри базы данных»; это не имеет смысла.

Ваш первый пример наиболее близок к DDD. Обратите внимание, что между хранилищем и фабрикой существует небольшая разница, и, строго говоря, newing up объект домена принадлежит фабрике или методу фабрики, который является частью агрегата (обычно это лучше соответствует UL). Поскольку репозитории предназначены для сохранения объектов домена, они имеют тенденцию много взаимодействовать с Persisis Apis (например, с базой данных Apis). Поэтому, если вам нужен репозиторий для объединения, например, двух баз данных, вам нужно взаимодействовать с двумя разными API внутри репозитория, и ваш потребитель не должен ничего знать об этой детали.

...