DDD - Как создать ассоциации между различными ограниченными контекстами

Я настроил проект домена, который заполняется ORM. Домен содержит различные агрегаты, каждый со своим корневым объектом. Мой вопрос заключается в том, как следует рассматривать свойства, которые пересекают совокупные границы?

  • Должны ли эти свойства просто игнорировать границы, чтобы объект домена в ограниченном контексте A имел ссылку на объект в контексте B?
  • Или не должно быть прямой связи из контекста A с B, и имеет ли объект в контексте A свойство int ContextBId, которое можно использовать для получения объекта домена из B через корень агрегата B?
  • Или же...

Пример:
Контекст A = Пользователи
Контекст B = Игры

Внутри Users контекст есть объект UserOwnedGames, Этот объект имеет свойство User которая является ссылкой на объект в том же Users контекст. Объект также имеет свойство Game что, очевидно, не в пользователях, а скорее в Games контекст.

Как бы (или должно?) Выглядеть это отношение? В базе данных ясно (т.е. 2 внешних ключа), но как должен выглядеть код?

4 ответа

Решение

Это звучит как твой User контекст также нуждается в Game юридическое лицо. Обратите внимание, что это не обязательно то же самое Game сущность, которая является корнем Game контекст. Эти два ограниченных контекста могут иметь разные представления о том, что Game и какими свойствами он обладает. Только идентичность связывает два игровых объекта вместе.

User Context
{
    Aggregate Root User
    {
        Identity;
        Name;
        OwnedGames : List of Game value entities
    }

    Value Entity Game
    {
        Identity;
        Name;
    }
}

Game Context
{
    Aggregate Root Game
    {
        Identity;
        Name;
        Owner : User value entity
        HighScore : int
        TimesPlayed : int
        ... A whole bunch of other properties which are not relevant in the User context
    }

    Value Entity User
    {
        Identity;
        Name;
        // No OwnedGames property, in this context we don't care about what other games the user owns.
    }
}

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

Лучше использовать простые объекты значений для идентификаторов - UserId и GameId - и при необходимости назначать их сущности. Таким образом, эти "удаленные" объекты полностью отсоединяются, поэтому вам не нужно беспокоиться об их подключении. Синхронизация может быть реализована с использованием платформы обмена сообщениями.

Если у вас есть свободное время, прочитайте эти ценные статьи (Вон Вернон):

Это зависит от того, какую стратегию ограниченного контекста вы используете.

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

Но если вы выберете антикоррупционный слой, вам лучше разделить их (используйте только идентификатор, чтобы сохранить связь), используйте адаптер-транслятор для интеграции (и без интеграции с базой данных).

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

Другие вопросы по тегам