Где проходят границы транзакций в DDD

В каком слое архитектуры DDD следует располагать код управления транзакциями? Есть ли какие-либо рекомендации и best-practies на этот счет?

На данный момент я располагаю код управления транзакциями в репозиториях - внутри каждого метода репозитория располагается код отвечающий за открытие и закрытие транзакции.


Ответы (1 шт):

Автор решения: Roman Konoval

У вас неправильно проходит граница транзакций. Контроль целостности и бизнес-правил в DDD делается на уровне агрегата. Операция выглядит так:

  1. читаем агрегат из репозитория
  2. выполняем операцию над агрегатом
  3. сохраняем агрегат в репозиторий

Вот эти три действия должны выполнятся в одной транзакции. Этот код находится в слое приложения (Application Layer). Т.е. есть класс типа:

class AccountApp {
  public void topUpAccount(Long accountId, Long amount) {
     AccountAggregate account = accountRepository.get(accountId);
     account.topUp(amount);
     accountRepository.save(account);
  }
}

Метод topUpAccount должен выполнятся в одной транзакции. Обратите внимание, что слой бизнес-логики в данном случае это только AccountAggregate (сам метод topUp может быть довольно сложным и использовать другие сущности из агрегата Account). И AccountAggregate ничего не знает ни о том:

  1. когда транзакция начинается/заканчивается
  2. как именно реализована транзакция

В идеале сама демаркация транзакций должна быть в слое приложения, а реализация отдельно (в слое инфраструктуры).

Вот пример того, как это делается в spring:

class AccountApp {
  @Transactional
  public void topUpAccount(Long accountId, Long amount) {
     ...
  }
}

Тут @Transactional обозначает, что метод topUpAccount будет выполнятся в транзакции. Как именно это делается, даже класс AccountApp не знает (не говоря уже об слое домена). Собственно реализация транзакций находится в сгенерированном прокси, который оборачивает вызовы к topUpAccount. Этот прокси умеет взаимодействовать в repository определенным образом (обычно через паттерн UnitOfWork).

→ Ссылка