Может ли доступ к репозиториям доступа к доменным службам? Или они должны работать с агрегатами/объектами, переданными им службами приложений?
Рассмотрим два примера кода одной и той же бизнес-операции - денежный перевод. В качестве первого шага я изменяю остатки на счетах. Затем я получаю уведомление по электронной почте и отправлю уведомление. Я знаю, мне следовало бы объяснить, как отправляются уведомления (электронная почта, SMS, несущий голубь), но для простоты предположим, что мы поддерживаем только электронные письма.
Вариант 1 использует репозитории внутри службы домена. Вариант 2 разрешает зависимости в службе приложения и передает их в TransferDomainService
.
В этом примере операция проста (вычитайте деньги из одной учетной записи и добавьте ее в другую). Но если бы было вовлечено больше бизнес-правил (возможно, требуется доступ к большему количеству агрегатов)? Если применяется вариант 2, то служба приложения должна иметь представление о том, что именно требуется службе домена. Если выбран вариант 1, служба домена запрашивает репозитории для выполнения своей задачи.
(Заметки о фрагментах: Groovy код для разглаживания многословности Java. Строительные блоки DDD, включенные в имена)
Вариант 1
class TransferApplicationService {
def transferDomainService
def customerDomainService
def emailNotifierInfrastructureService
def transfer(fromAccount, toAccount, amount) {
transferDomainService.transfer(fromAccount, toAccount, amount)
def email = customerDomainService.accountNotificationEmail(toAccount)
emailNotifierInfrastructureService.notifyAboutTransfer(email, amount)
}
}
class TransferDomainService {
def accountRepository
def transfer(fromAccount, toAccount, amount) {
def from = accountRepository.findByNumber(fromAccount)
def to = accountRepository.findByNumber(toAccount)
to.decreaseBalance(amount)
from.increaseBalance(amount)
}
}
Вариант 2
class TransferApplicationService {
def accountRepository
def transferDomainService
def customerDomainService
def notifierInfrastructureService
def transfer(fromAccount, toAccount, amount) {
def from = accountRepository.findByNumber(fromAccount)
def to = accountRepository.findByNumber(toAccount)
transferDomainService.transfer(from, to, amount)
def email = customerDomainService.accountNotificationEmail(toAccount)
notifierInfrastructureService.notifyAboutTransfer(email, amount)
}
}
class TransferDomainService {
def transfer(fromAccount, toAccount, amount) {
to.decreaseBalance(amount)
from.increaseBalance(amount)
}
}