На фоне своего увлеченного изучения DDD, я прочел статью Мартина Фаулера от 25 Ноября 2003 года Anemic Domain Model. Иногда для лучшего понимания материала я перевожу его на русский язык. Вот я и решил поделиться переводом.
Перевод авторский и местами очень смысловой.
Ссылка на оригинал.
В статье есть цитаты из уже опубликованной книги, которая была переведена на русский язык профессионалами, для того что бы улучшить понимание моего перевода я привел цитаты из книги под спойлерами.
Бледная Доменная Модель
Это один из тех анти-паттернов который долгое время окружал нас, а сейчас проявляется еще активнее. Я говорил о этом с Эриком Эвансом и мы оба отметили что он становится все популярнее. И я как сторонник правильной Доменной Модели, считаю что это не есть хорошо.
Первые симптомы Бледной Доменной Модели это то что она выглядит нормально, но только на первый взляд. Объекты именованны как существительные из предметной области, связанны между собой и имеют структуру как у нормальных доменных объектов. Понимание приходит при просмотре их содержимого, оно едва ли больше чем набор геттеров и сеттеров. Часто эти доменные объекты приходят с архитектурными правилами не размещать какую-либо доменную логику в них. Вместо этого есть набор сервисов (сервисных объектов) которые содержат всю доменную логику в себе. Эти сервисы находятся архитектурно уровнем выше доменной модели и используют ее как источник данных.
Весь ужас этого анти-паттерна в том, что он идет вразрез с базовой идеей Объектно Ориентированного Проектирования, который состоит а том, что бы совмещать данные и процесс (поведение). Бледная модель это что-то типа, процедурного проектирования, как раз то, с чем такие фанаты как я и Эрик, боролись с самых первых дней своей работы со Smalltalk.
В наши дни Объектно Ориентированный пуризм это хорошо, но я считаю что надо больше веских аргументов против этой «бледности» в модели. Проблема Бледной Доменной Модели в том, что она несет всю нагрузку Доменной Модели не привнося ее преимуществ. А расплачиваемся мы за это несуразностью маппинга базы данных, который обычно выливается в целый слой ORM. Это имеет смысл только тогда, когда используются мощные Объектно Ориенированные техники для организации сложной логики. Однако перемещая все поведение системы в сервисы, надо понимать, что все закончится
Также стоит отметить, что размещение поведения в Доменных Объектах не должно противоречить последовательному подходу использования слоев, для отделения доменной логики от слоя персистентности и представления. Логика которая должна быть в доменном объекте это и есть доменная логика, например: валидация, расчеты или все что вы называете «бизнес правила».
(Конечное есть случаи когда вы через параметр передаете в доменный объект источник данных или куски логики представления, но это ортогонально к моему представлению о «бледности».)
Одним из источников неверного толкования есть то, что многие Объектно Ориенированные эксперты рекомендуют размещать слой процедурных сервисов над доменной моделью, для того что бы сформировать сервисный слой. Но это не аргумент не размещать поведение в доменной модели, на самом деле сервисный слой подталкивает к использованию его в связке с доменной моделью содержащей поведение.
Отличная книга Эрика Эванса "Domain Driven Design" говорит следуйщее о этих слоях.
Слой приложения [так он называет Сервисный Слой]: определяет задачи которые предполагается, что приложение будет решать и направляет их выполнение на (богатую) доменную модель. Задачи этого слоя значимы для бизнеса (не бизнес логика) или являются просто взаимодействием с прикладным уровнем других систем. Этот слой должен оставаться тонким. Он не содержит бизнес логики или каких-либо знаний, он только координирует задачи и делегирует работу наборам доменных объектов уровнем ниже. Он не несет состояния которое отражало бы ситуацию в бизнес логике, но может знать о состоянии выполнения задачи для информирования пользователя и/или приложения вцелом.
Из книги
Определяет задачи, которые должна решить задача, и распределяет их между объектами, выражающими суть предметной области. Задания, выполняемые этим уровнем, имеют смысл для пользователя-специалиста или же необходимы для интерактивного взаимодействия с операционными уровнями других систем. Этот уровень не нужно «раздувать» в размерах. В нем не содержатся ни знания, ни деловые регламенты (business rules), а только выполняется координирование задач и распределение работы между совокупностями объектов предметной области на следующем, более низком уровне. В нем не отражается состояние объектов прикладной модели, но зато он может содержать состояние, информирующее пользователя о степени выполнения задачи для информирования пользователя.
Слой Домена (или Слой Модели): Отвечает за представление смысла бизнес процессов, несет информацию о бизнес ситуации и бизнес правилах (бизнес логике). Здесь контролируется и используется состояние которое отражает ситуацию в приложении (в его бизнес части), пускай даже технические детали хранения данных (персистентности) и делегируются инфраструктуре.
Этот слой сердце приложения.
Из книги
Отвечает за представление понятий прикладной предметной области, рабочие состояния, деловые регламенты. Именно здесь контролируется и используется текущее состояние прикладной модели, пусть даже технические подробности манипуляций данными делегируются инфраструктуре. Этот уровень является главной, алгоритмической частью программы.
Смысл тут в том что Сервисный Слой тонкий, а вся логика находится в Слое Домена. Он (Эрик) повторяет это в его сервисном шаблоне
Сейчас общая ошибка, сдаваться слишком рано при помещении поведения в соответствующий объект, постепенно скатываясь в процедурное программирование.
Из книги
В этом месте легко совершить распространенную ошибку: отказаться от попытки поместить операцию в подходящий для нее объект, и таким образом прийти к процедурному программированию.
Я не знаю почему этот анти-паттерн так часто встречается. Я подозреваю это от того, что так много людей которые не работали с правильной доменной моделью, особенно если они пришли из мира данных. Некоторые технологии поощряют этот анти-паттерн, такие как J2EE'шные Entity Beans, это одна из причин почему я предпочитаю POJO доменные модели.
В общем чем больше вашей логики в сервисах, тем больше похоже на то что, вы оставили себя без преимуществ Доменной Модели. А если вся ваша логика в сервисах, то вы тупо себя обобрали.
Спасибо за внимание.
На инвайт не претендую, так как он мне не нужен. Но если кто-то думает, что материал достоин инвайта, просто дайте знать в комментариях, мне будет приятно.