Может ли транзакция изменить несколько агрегатов в доменно-управляемом дизайне?
В статье "Проектирование на основе доменов: решение сложных задач в основе программного обеспечения" Эванс определяет
Агрегат - это кластер связанных объектов, который мы рассматриваем как единое целое с целью изменения данных.
Очевидно, это означает, что агрегат должен обновляться в одной транзакции.
Однако должна ли транзакция обновлять только один агрегат? Если так, то почему?
Мое исследование
Я спрашиваю, потому что в "Внедрении доменного дизайна", стр. 360, Вернон пишет:
Как ссылочный агрегат, так и ссылочный агрегат нельзя изменять в одной и той же транзакции. Только одна или другая может быть изменена в одной транзакции.
но не дает повода для этого правила.
Я понимаю, что если бизнес-правила требуют одной транзакции, это указывает на скрытый инвариант, который потребовал бы, чтобы сущности были частью одной совокупности. Но что, если бизнесу все равно, а разработчики просто находят это удобным?
На странице 437 Вернон также пишет:
Будьте осторожны, чтобы не злоупотреблять возможностью фиксации изменений в нескольких агрегатах в одной транзакции только потому, что она работает в среде модульного тестирования. Если вы не будете осторожны, то, что хорошо работает при разработке и тестировании, может серьезно сбоить в работе из-за проблем параллелизма.
Какие проблемы с параллелизмом?
1 ответ
Оптимистический параллелизм часто используется, чтобы избежать потери данных в среде, где существует конфликт.
Давайте посмотрим, что может вызвать исключение параллелизма с этим механизмом:
- Пользовательский агрегат загрузки Foo пользователя версии V1.
- Агрегат загрузки пользовательской панели A версии V1.
- Пользователь Foo изменяет агрегат A и сохраняется (версия увеличивается до V2).
- Пользовательская панель изменяет агрегат A и пытается сохранить, но получит исключение параллелизма, потому что его изменения были основаны на V1, но агрегат теперь находится на V2.
Если вы разрешаете изменять более одного агрегата на транзакцию, вы увеличиваете риск исключений параллелизма, которые могут повредить масштабируемости вашей системы до такой степени, что она станет непригодной для использования.
Агрегированные корни (AR) являются транзакционными границами, где инварианты являются транзакционно-согласованными, поэтому, если вы пытаетесь изменить несколько AR в одной транзакции, это означает, что ваши границы AR, вероятно, неверны и что вы можете упустить шанс сделать неявное Понятие явное.
Однако обратите внимание, что не должно быть проблем при создании нескольких AR в одной транзакции.
Распространенные ошибки при разработке AR - создавать большие кластеры, придавая слишком большое значение словам отношения в таких утверждениях, как:
"Сообщения имеют комментарии"
Там нет причин для кластеризации Post
а также Comment
вместе, если нет инвариантного принуждения, которое требует этой композиции. Должны ли два автора, публикующие один и тот же комментарий одновременно, вызвать исключение параллелизма? Ответ, вероятно, нет, в зависимости от вашего домена, но если бы Post
содержал коллекцию Comment
,
Но что, если бизнесу все равно, а разработчики просто находят это удобным?
Что ж, если бизнес не заботится о том, чтобы его система была не масштабируемой из-за неправильных проектных решений, я думаю, что это их выбор, но разработчики не должны создавать привычку для удобства проектирования. DDD - это моделирование домена таким, какой он есть, а не тем, который удобно моделировать.