В шаблонах архитектуры корпоративных приложений Мартин Фаулер рассказывает о двух шаблонах для организации Domain Logic: Модель домена и Уровень обслуживания. Шаблон модели домена - это подход "чистого ООП", где модели (те объекты, которые, вероятно, просматриваются из базы данных с использованием ORM) содержат бизнес-логику (хотя, вероятно, только делегирование логики в другом классе).

Шаблон Service Layer похож на шаблон модели домена, но с тонким слоем перед ним, содержащим бизнес-операции, которые могут быть выполнены. В MVC контроллер будет в основном взаимодействовать с уровнем обслуживания. Я считаю, что большинство хорошо продуманных веб-приложений MVC используют этот шаблон.

Теперь, на мой вопрос. Мартин предполагает, что подход "Модель домена" является более объектно-ориентированным подходом и поэтому лучше. По моему опыту, это очень сложно (см.: Невозможно) реализовать на практике.
Возьмем пример, приведенный на первой диаграмме выше. Существует два "объекта" Contract и Product. Они сохраняются в базе данных с помощью mapper. В этом примере есть RecognitionStrategy. Мартин ставит методы делегирования этой стратегии, которая содержит фактическую бизнес-логику, в самих сущностях; клиент выполняет этот расчет с помощью contract.calculateRecognitions или contract.recognizedRevenue(someDate). При реализации подобных проектов я обычно пишу клиентский интерфейс как strategy.calculateRecognitions(contract) и strategy.recognizedRevenue(contract, someDate). Это делает уровень обслуживания необходимым для координации стратегии и контракта. Используемая конкретная стратегия вводится в службу.
Мартинский подход определенно более привлекателен с точки зрения дизайна, но работа вокруг настройки намного сложнее:
- Передача стратегии при создании экземпляра a
Productявляется болью. Вам нужно создатьProductс помощью factory, в котором используется конкретная служба, которая, в свою очередь, передаст ее в объект при его создании. - Менее мелкомасштабный контроль доступа к базе данных. В зависимости от настроек ORM делегирование
ContractнаProductможет выполнять запрос заProduct. Жесткая загрузкаProductв mapper (или ORM) может быть чрезмерной, когда мы загружаемContract, но не намереваемся называтьcontract.calculateRecognitions(). Мой подход дает нам более тонкий контроль, потому что служба имеет знания уровня абстракции базы данных, где, как сущности не должны.
Я уверен, что на практике больше болей, которые я не перечислял здесь.
Какие конкретные преимущества существуют в подходах Мартина, которые могут убедить меня использовать образец модели данных данных?