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 как о логическом разделении, о том, как люди группируются и существуют отношения между каждым из них. Сказал, что вы можете подумать о том, чтобы сохранить пользователя и игры в едином ограниченном контексте, сохраняя вместе то, что должно быть вместе. Пожалуйста, обратитесь к этому удивительному видео уроки Хидена из большой синей книги.