#domain-driven-design #aggregateroot #domain-model
#доменно-ориентированный дизайн #агрегатная установка #домен-модель
Вопрос:
В настоящее время я разрабатываю модуль на основе imap сообщений в приложении crm и пытаюсь соединить точки с помощью участников DDD.
Я начал с трех основных сущностей, все они связаны Совокупностью учетных записей:
- Учетная запись — Учетная запись электронной почты. Имеет несколько Папок.
- Папка — Папка в учетной записи электронной почты (например. Входящие, Отправленные, Черновик). Имеет несколько сообщений.
- Сообщение — Сообщение электронной почты.
В этом случае инвариант находится в фактических коллекциях, в основном между учетной записью и папкой:
- В учетной записи не может быть двух папок с одинаковым именем,
- Учетная запись не может иметь несколько специальных папок (например, Входящие или отправленные).,
- В почтовом ящике должно быть фактическое количество сообщений.
Этот дизайн был не менее чем безупречен. Он остается неизменным, но почти у каждой учетной записи есть около шести папок, которые могут содержать тысячи сообщений. Объем данных, загруженных в память, который почти никогда не использовался, заставил идею разделить совокупность учетных записей.
Теперь у меня есть варианты:
- Разделите его на два агрегата: Учетная запись (с папкой в качестве локальной сущности) и Сообщение.
В этом случае я нарушаю правило ссылки локальной сущности (Папки) на другую совокупность (Сообщение), поскольку сообщение ограничено определенной папкой. Тем не менее, я могу сохранить большинство инвариантов между учетной записью и Папкой нетронутыми.
- Разделите их на три отдельных агрегата: Учетная запись, Папка и Сообщение.
В этом случае никакие совокупные правила не нарушаются, но я нарушаю инвариант между учетной записью и Папкой. В результате возникает необходимость добавления еще одного уровня сложности с использованием доменных служб и угроза, скорее всего, обновления по крайней мере двух агрегатов в одной транзакции. Кроме того, это заставляет папку, поскольку она является сущностью между агрегатами, становиться корнем агрегата, в то время как это никогда не означало, что она одна.
- Что — то, чего мне, возможно, не хватает.
На данный момент я бы выбрал второе решение, но каков наилучший способ разделения этих сущностей в данном случае?
Ответ №1:
Я не уверен, что в DDD обязательно требуется, чтобы каждая сущность в совокупности загружалась как единое целое (хотя вполне возможно, что многие платформы, ориентированные на DDD, применяют такое ограничение). До тех пор, пока любой доступ осуществляется через совокупный корень и инварианты последовательно поддерживаются, никакие рекомендации DDD фактически не нарушаются.
Это может потребовать кодирования модели, которая допускает ленивую загрузку сущностей; исходя из этого из Scala, Future
кажется разумным кодированием этого аспекта «возможно, еще не здесь».
При отсутствии возможности легко учитывать ленивую загрузку, я бы, вероятно, выбрал вариант первого подхода, но с сообщением, не имеющим прямой ссылки на папку. Можно было бы реализовать Папку таким образом (например, с фильтром цветения), чтобы поиск соответствующей папки был быстрым. Я не уверен, какие инварианты сообщения должны были бы сохраняться в отношении членства в папках (и вы, похоже, их не выражаете).