Я очень пытаюсь понять в чем отличие сервиса домена от сервиса приложения. Синяя книга ввела меня в ступор. В ней говорится, что доменный сервис появляется, если операцию нельзя применить к конкретной сущности (агрегату) и тогда эта логика переносится в сервис. Как следствие, доменный сервис работает исключительно с доменными сущностями, а не идентификаторами и примитивными типами. Получается, что доменный сервис не может зависить от [интерфейса] репозитория? Но мы же в основном пишем приложения в которых на вход приходят примитивы и есть необходимость работать с репозиториями. Получается, что эти примитивы обрабатывает сервис приложения и передает (если надо) в сервис домена?
для начала давай договоримся что если есть какое-то понятие (например доменный сервис, сервис уровня приложения) это не значит что тебе надо его вводить в рамках своей реализации. Все эти штуки - это опции. Твоя цель выбрать минимум а не все. То есть вполне возможно что у тебя нет кейсов для доменных сервисов и это нормально.
Затем... разницу надо уяснить не между доменными сервисами и сервисами уровня приложения а между "приложением" и "доменом". Домен - это твоя бизнес логика. Правила и ограничения. Приложение тут - это "оболочка" - считай интерфейс к домену. Может быть CLI, может быть HTTP. То есть это тот слой адаптеров который защищает твой домен от холодного и жестокого внешнего мира.
Дальше про "сервисы". Это такие вот "функции" которые не помещаются в рамках какого-то объекта. Клей между объектами. У сервисов нет своего стэйта, им остается лишь брать данные которые приходят на вход, какие-то еще данные и перенаправлять их другим.
Типичный пример сервиса уровня приложения это какой-нибудь HTTP контроллер или там консюмер в очереди. Чаще всего у тебя будут именно сервисы уровня приложения просто потому что без них сложно склеивать и перенаправлять операции.
Приложение задает границу бизнес операции. Мол что включает в себя какой-то http запрос. Мол вот захотелось тебе в рамках одного http запроса опубликовать сразу несколько айтемов в каталоге. В этом случае сервис уровня приложения дернет паблиш у нескольких айтемов.
Бизнес операция может быть представлена несколькими логическими транзакциями. Чаще всего одна логическая транзакция это вызов метода у доменного объекта который изменит его стэйт. Но есть ситуации когда тебе выгодно раздробить стэйт на несколько маленьких объектов и есть разные комбинации как с этими объектами работать. Эти комбинации можно объединить в доменный сервис который бует своего рода фасадом что бы жестко задать приложению что можно делать. Мол это бизнес-ограничение.
Есть еще забавные примеры с сервисами которые представляют собой какие-нибудь стратегии вычислений и должны использоваться только внутри домена (всякие вычисления скидок которые ты передаешь на вход объекту который владеет стэйтом).