DDD - Как я могу избежать пересечения агрегированных границ здесь?
-
28-09-2019 - |
Вопрос
Мы работаем над новым проектом (повторное написание существующего приложения), и я бегу в проблемы с моим доменной моделью / дизайном репозитория.
Вот (упрощенная) версия двух ключевых порций в нашей области домена:
Как видите, у меня абстрактная концепция Сообщение, Что может быть вещами, как обзор, обсуждение, фото, видео и т. Д. Посты также могут иметь комментарии.
У меня также есть абстрактная концепция Место нахождения, которые, очевидно, такие как улицы, города, районы и т. Д.
Теперь это естественно посмотрела на меня как два четких совокупных корнях.
Поэтому я создал два репозитория, которые называют Постеперо, и другой под названием РасположениеRepository.
Это все было работать хорошо, я могу добавить / получить любой тип почты (или комментариев) и добавить / получить любой тип местоположения через одну из этих двух репозиториев.
Но теперь я в сценарии «посадочной страницы» для города (например).
На этой странице мне нужно в основном показать «Все сообщения для этого местоположения».
Как это определено? Ну, пост может быть (необязательно) помечен в месте. Деталь внедрения, поэтому я не хочу идти слишком глубоко в данные (как это не то, что о том, что DDD), но по сути, есть геопространственный интеллект для работы, какие посты содержатся в определенном месте по файлу формы местоположения, и широта / долгота помеченного поста.
Но как я могу получить эту информацию без пересечения границ?
Какой репозиторий я использую? Мне нужен новый?
Если это имеет значение (или для любопытного), это веб-приложение (ASP.NET MVC) с базой данных SQL Server 2008 и структурой объекта 4.0.
Если вам нужно уточнить, дайте мне знать.
РЕДАКТИРОВАТЬ
В настоящее время мы используем модифицированную версию шаблона спецификации для получения моделей доменов.
Например, это код в нашем BLL для извлечения всех оценок просмотра> = 4:
var reviews = postRepository // GenericRepository<Post>
.Find() // IQueryable<Post>
.OfType<Review>() // IQueryable<Review>
.Where(x => x.Score >= 4)
.ToList(); // List<Review>
Но теперь мне нужен код, как это:
var reviews = postRepository
.Find()
.OfType<Review>()
.Where( //lat long, or Locations FK )
.ToList();
Проблема в том, что я не знаю, как сделать вышеуказанный запрос без добавления промежуточного объединения (locationPOST - как это много для многих), и добавьте FK к модели домена Post.
Но, делая это, я перехожу агрегатные границы - не так ли?
Решение
Я бы связывал сообщение в местоположение во время создания, чтобы каждое местоположение я могу получить (через репозиторий) список связанных сообщений. Это будет выглядеть так:
Творчество:
var p = new Post(latitude, longitude);
var locations = locationRepository.FindByCoordinates(latitude, longitude);
foreach (var l in locations)
{
l.AssociatePost(p);
}
session.Save(p);
Восстановление:
var associatedPosts = postRepository.FindByLocation(locationId);
foreach (var p in associatedPosts)
{
Display(p);
}
Под капотом ассоциация между постами и местоположением будет реализована как многозначное табличное отношение. С этим решением есть одна проблема: добавление нового местоположения требуется отсканировать все сообщения и назначить их в новое местоположение (если применимо).
Надеюсь, это поможет.
Другие советы
Почему это проблема? По словам Эванса в его книге, один AR может очень хорошо справлять другого AR. (Вы не можете ссылаться на детский элемент в AR из другого AR)
Также есть места, действительно совокупные корни? Определение совокупного корня состоит в том, что он действует как граница совпадения. Это соответствует определению местоположения? Я бы сказал, что местоположение является объектом стоимости.
Здесь почти два лагеря, касающиеся репозиториев и ассоциаций AR:
Тот, который говорит, что все совокупные корни придется быть полученным через их соответствующий репозиторий, а Ar должен использовать мягкие отношения, например, между ними ID
И тот, который говорит, что совокупные корни могут очень хорошо получить другие связанные совокупные корни и что репозиторий - это просто способ найти совокупные корни.
Допустим, вы использовали шаблон спецификации, не могли бы вы построить спецификацию пост, используя объект местоположения? Тогда вы просто проходите спецификацию на ваш почтовый репозиторий и верните результат.