Ответ 1
Это Envelopet Conundrum: набирает номер телефона по номеру телефона, или номер телефона на телефоне?
Вы можете найти Double Dispatch, чтобы быть интересным, хотя я считаю, что переполняю вашу ситуацию.
принцип единой ответственности часто противоречит принципу OO Скажите, не спрашивайте. Мое чувство по этому вопросу колеблется, и я остановился на следующих условиях, когда логика должна перейти в объект домена:
- Логика должна быть логикой домена, т.е. ничего подобного image.load() или image.save()
- Логика не должна давать объекту больше, чем "одна причина" для изменения в домене. Это повторный отчет SRP.
- Логику нельзя вводить в объект. Другими словами, если вы в конечном итоге сделаете что-то как пытающийся вычислить сумму некоторого свойства в списке объектов домена без использования getter, дважды подумайте.
В вашей ситуации я бы предпочел отказаться от вызова службы внутри объекта сущности, главным образом потому, что служба не похоже, что она связана с вашим доменом, но больше связана с сохранением. Объекты домена должны быть связаны с концепциями домена, и я не думаю, что предоставленная вами услуга имеет квалификацию.
Пример, когда я думаю, что вызов службы в сущности может быть приемлемым, было бы, если бы ваше приложение использовало сторонний сервер рабочих процессов для управления частями своего состояния. По сути, это State Pattern с состояниями, определенными во время выполнения.
Я думаю, что допустимо иметь domainObject.moveToNextState() (если этот код "имеет смысл" на вашем вездесущем языке) вызовите службу, которая разговаривает с вашим сервером, потому что сервер рабочего процесса управляет частью модели домена.
Я добавлю, что DDD очень заинтересован в том, чтобы следовать языку домена. Слышали ли вы, что эксперты домена говорят: "Пользовательский образ обнаруживает, соответствует ли его распечатка большого пальца значению в службе поставщиков XYZ"? Или они говорят: "Служба поставщика XYZ, учитывая распечатку большого пальца, указывает, существует ли эта печать большого пальца"? Пойдите с тем, который имеет наибольший смысл в вашем домене.
Еще несколько мыслей (я много думал об этой проблеме, потому что она имеет центральное значение для дизайна):
-
В книге DDD Evans, учетной записи сущность имеет такие методы, как кредит (Сумма), дебет (Сумма), transferTo (Счет, Сумма) и accrue(), но у FundsTransferService есть метод перевода (Account, Account, Amount). Метод transferTo не вызывает никакой службы, а просто обрабатывает логику, которая включает учетные записи, такие как кредитование и дебетование правильных сумм.
FundsTransferService, помимо координации, имеет свои собственные правила проверки, правила, которые не вписываются в учетные записи. Точная сумма кредита или дебетования может включать внешние стороны. Это делает его неудобным для передачи. Чтобы вызвать службу.
- Для простых объектов, таких как UserImage, значительная логика домена, которая может поместиться в самом объекте, может быть скудной, потому что это не так, насколько я могу судить, Агрегат. Я думаю, что агрегаторы представляют больше возможностей для размещения доменной логики. Пример учетной записи, скорее всего, является агрегатом.