DDD: Ленивая загрузка в агрегаты - PullRequest
0 голосов
/ 18 февраля 2020

Я изучал DDD в течение последних нескольких дней и изо всех сил пытался понять некоторые основные концепции совокупных корней. Может быть, кто-нибудь мог бы дать мне pu sh в правильном направлении и уточнить, что является лучшей практикой в ​​этом сценарии:

Чтобы сделать этот пример менее сложным, скажем, у нас есть область двух сущностей: ресторан и время открытия. Ресторан определяется как совокупность root.

text

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

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

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

Я мог бы подумать о двух возможных решениях:

Ленивая загрузка

Ленивая загрузка времени открытия / суб-сущностей через прокси свойств структуры сущностей. Таким образом, совокупность root может существовать без необходимости загружать их, но всякий раз, когда они необходимы, к ним можно получить доступ. Однако везде, где я искал ответ, я заметил, что ленивая загрузка в совокупных корнях считается плохой практикой. Может быть, кто-то может объяснить, почему.

Меньшие совокупные корни

Конечно, я мог бы определить само время открытия как совокупность root, но тогда мне нужно взять бизнес logi c (в данном случае проверка пересечений) вне модели.

Во всех приведенных выше примерах я говорю только о командной стороне (а не о запросах или сериализации).

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

EDIT Не уверен, почему этот вопрос был закрыт из-за "основанного на мнении". Я спрашиваю передовой опыт и почему ленивая загрузка не в этом случае.

Ответы [ 3 ]

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

Эта проблема классифицируется как проблема проверки набора, и есть несколько потенциальных решений в зависимости от потребностей домена.

Сильная согласованность

  1. Создать AR для защиты всего набора. В приведенном выше примере, если такой набор имеет разумную длину, вы можете создать выделенный RestaurantSchedule AR. Вы можете даже разделить такой AR далее на RestaurantWeekSchedule, где у вас будет 1 AR на каждую неделю. Если вы хотите добавить / удалить дни открытия, это создаст / загрузит AR данной недели. Другим вариантом может быть настройка ORM для загрузки только подмножества коллекции, например schedule = scheduleRepo.loadForWeek(openingTime.week()); schedule.add(openingTime);. Блокировка Optimisti c все еще позволяет обнаруживать конфликты.

  2. Применение правила в БД. Например, если у вас есть реляционная БД, вы можете использовать OpeningTime в качестве AR, а затем использовать уникальные ограничения для предотвращения нарушений. В конечном итоге правило будет жить за пределами домена, но оно может быть приемлемым. Правила уникальности не так уж интересны.

Окончательная согласованность

Очень распространенный способ решения проблем проверки набора - избегать попыток избежать нарушение и сосредоточиться на обнаружении и исправлении его после факта с помощью ручных или автоматических компенсационных действий. Это может быть простой отчет об исключении, в котором отображаются перекрывающиеся записи, или более сложный, например однопоточный прослушиватель событий OpeningTimeAdded, который проверяет наличие конфликтов и помечает такие записи для исправления.

1 голос
/ 20 февраля 2020

Однако везде, где я искал ответ, я заметил, что ленивая загрузка в корнях агрегатов считается плохой практикой.

Это не совсем так. Фактическое ограничение для отложенной загрузки других агрегатов , из-за прямых ссылок, в корнях агрегатов; вместо этого рекомендуется ссылаться на другие агрегаты с их идентификаторами. Это ограничение имеет очень веские причины.

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

Каждый агрегат root определяет свою собственную границу согласованности; каждая транзакция предназначена для обеспечения согласованности одного агрегата . Операции обновления (или транзакции) для агрегатов, передаваемые через события домена , должны быть в конечном итоге согласованными .

Если вы держите прямую ссылку на другой агрегат, тем самым При необходимости отложенной загрузки и выполнения обновлений их необходимо переосмыслить свой дизайн.

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

0 голосов
/ 18 февраля 2020

На ваш вопрос, почему отложенная загрузка считается плохой практикой:

Некоторые проблемы, с которыми я сталкиваюсь при отложенной загрузке, заключаются в том, что вам необходимо постоянно знать о потенциальных проблемах производительности. С другой стороны, однако, LL - достойное поведение по умолчанию для ORM. Хорошо, если у вас есть приложения, которые работают в течение длительного времени, но бессмысленно внедрять их поверх своих сервисов. Я думаю, что это во многом зависит от данных, которые вы используете, так что это ни хорошо, ни плохо.

...