Модели модели домена и уровня обслуживания в P EAA

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

A sample Domain Model

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

A sample Service Layer

Теперь, на мой вопрос. Мартин предполагает, что подход "Модель домена" является более объектно-ориентированным подходом и поэтому лучше. По моему опыту, это очень сложно (см.: Невозможно) реализовать на практике.

Возьмем пример, приведенный на первой диаграмме выше. Существует два "объекта" 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(). Мой подход дает нам более тонкий контроль, потому что служба имеет знания уровня абстракции базы данных, где, как сущности не должны.

Я уверен, что на практике больше болей, которые я не перечислял здесь.

Какие конкретные преимущества существуют в подходах Мартина, которые могут убедить меня использовать образец модели данных данных?

Ответ 1

Что касается вашего первого момента, вы должны использовать инъекцию зависимостей при создании экземпляра объекта Product. Конструкция графа объекта является полнофункциональной ответственностью и не должна смешиваться с вашей бизнес-логикой (принцип единой ответственности).

Что касается второго момента, то особенности вашего поставщика должны быть скрыты за вашим уровнем доступа к данным, а ваш DAO или репозиторий должны возвращать объекты в соответствии с вашими потребностями.

Альтернатива для вашей озабоченности по поводу жадной загрузки продукта s (при ситуации, в которой отношения друг к другу) заключается в том, чтобы Продукт DAO вводился в объект Контракт. При таком подходе вы можете получить связанный с контрактом продукт, связанный с контрактом, когда это необходимо (возможно, на геттере, который также можно использовать внутри).

Конечно, идеального решения не существует, и всегда будут компромиссы. Ваша работа в качестве архитектора для оценки подхода, который лучше подходит для вашего приложения.

В моем личном опыте я заметил, что слишком много полагаться на классы обслуживания, как правило, порождает гигантские классы, которые не имеют четко определенной ответственности и обычно слишком трудны для тестирования.

Таким образом, преимущества использования подхода "Модель домена" - четкое разделение проблем и повышенная тестируемость.

Наконец, вам не нужно использовать "чистый" подход к модели домена. Предполагается, что модель домена и уровень обслуживания будут использоваться вместе. Объекты модели домена охватывают поведение, попадающее в их границы, и логика покрытия уровня обслуживания не принадлежит ни одному объекту домена.

Некоторые дополнительные ссылки вы можете найти интересными

Разработка и развитие домена на практике - интересная статья о DDD

Инъекция зависимостей, шаблоны проектирования с использованием Spring и Guice - отличная книга по инъекции зависимостей

Привет,

Эммануэль Луис Ларигет Бельтрам

Ответ 2

Модель домена представляет собой объект, а также поведение лучше, чем анемичное. Потому что поведение связано с ним. Основным примером является dog может bark, breathe и eat. В слое "Сервис" модель расширяется с помощью BarkHandler и BreatheHandler.

Доменный подход к модели основан на шаблоне проектирования UML. Мой предыдущий ответ здесь. Для подхода к моделированию аномальных доменов (уровень обслуживания) сложно сделать UML-диаграмму (диаграмму классов), и даже если вы смогли ее создать, она официально не принимается, поэтому люди будут иметь другую интерпретацию.

С точки зрения дизайна, уровень обслуживания слишком "independent" или разделен. Если посмотреть на модель анемичного домена class, вы не можете найти поведение (например, сохранение), связанное с моделью домена. Вам нужно найти весь проект, чтобы найти конкретное поведение для модели домена. Пока в богатой доменной модели вы знаете следы поведения внутри самой модели домена.

Богатая модель домена имеет улучшенный модификатор доступа (открытый, закрытый, защищенный) для своих свойств. А также видимость собственности. Например, если вы хотите изменить статус после отправки, вы можете заставить свойство получить доступ к public, но установить доступ к protected. На уровне обслуживания вам необходимо сделать доступ к набору public или обмануть его с помощью internal protected и заставить отправителя напрямую изменить свойство с помощью internal access. Но это сложная задача.

Но богатая модель домена не обладает гибкостью, поскольку anemic domain model имеет. Вы не можете добавлять поведение к модели без изменения класса модели домена, если вы не используете наследование. Хотя в модели анемичного домена вы даже можете менять ее на уровне времени выполнения.