ZF Doctrine 2: тяжелые классы моделей или облегченная модель сервисный уровень?

#php #zend-framework #architecture #doctrine-orm #service-layer

#php #zend-framework #архитектура #doctrine-orm #сервисный уровень

Вопрос:

Я интегрирую Zend Framework и Doctrine 2, и я открываю для себя сервисный уровень.

Теперь я понимаю (я ошибаюсь?) что у меня есть 2 возможные архитектуры :

  • Модель, в которой классы содержат логику предметной области, т.е. свойства средства получения / установки сложные методы
  • Облегченная модель, где классы содержат свойства средства получения / установки и уровень сервиса, содержащий логику домена и модифицирующий классы моделей

Каковы плюсы / минусы каждого из них?

Мне кажется странным терять ООП, помещая логику домена как внешнюю по отношению к модели, поэтому я не понимаю, зачем использовать сервисный уровень.

Комментарии:

1. Всегда возможны более двух архитектур

Ответ №1:

Что заставляет вас думать, что ваш сервисный уровень является внешним по отношению к вашей модели? Это не так. Фактически, это центральная часть вашей модели, наряду с сущностями, репозиториями и т.д.

Если вы используете Doctine2, вам понадобится сервисный уровень. Одна из причин заключается в том, что вы не хотите, чтобы ваши сущности знали о EntityManager (ухудшает тестируемость). Другое дело, что вы также не хотите, чтобы ваши контроллеры управляли EM (это не работа контроллеров — знать о постоянстве).

Обычно я использую архитектуру, в которой уровень обслуживания является интерфейсом контроллера к модели. Уровень обслуживания предоставляет функции, которые работают с объектами (либо принимая их в качестве параметров, либо возвращая их, либо и то, и другое). Сохранение объектов скрыто уровнем обслуживания. Либо класс service сам управляет EM и репозиториями, либо делегирует его какому-то другому коду, о существовании которого контроллер никогда не узнает.

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

Комментарии:

1. Отличный и ясный ответ, спасибо, хотя мне трудно понять, почему теряется ООП… Я имею в виду, что я думаю, что $user->generatePassword() это лучше , чем $userService->generatePassword($user) поскольку метод применяется к пользователю, это не «функция», применяемая к параметру… Это то, что я подразумеваю под «внешним». Для меня это похоже на разницу между ООП (объектами и методами на объектах) и функциональным программированием. На уровне обслуживания объект является просто контейнером данных…

2. @matthieu если ваш generatedPassword() метод генерирует только случайную строку, тогда вполне нормально иметь этот метод в вашей сущности; он не создает никаких внешних зависимостей, связанных с сохраняемостью.

3. @matthieu — Объекты являются контейнерами данных — они просто «навороченные» (потому что у них могут быть методы для манипулирования или отчета об их внутреннем состоянии). GeneratePassword () может быть прекрасным — при условии, что он не зависит от какой-либо внешней вещи. Например, если GeneratePassword () просто генерирует 8 случайных символов и присваивает эту строку $this-> password (или передает ее в $ this-> SetPassword(), который затем соответствующим образом хэширует ее), это нормально. Это нормально, потому что это влияет только на пароль пользователя, и больше ни на что. Теперь, если вы хотите отправить пользователю по электронной почте его новый пароль, вы бы захотели это сделать

4. Или пост во внешнем блоге с комментариями, чтобы другие — такие, как я, hint, подсказка — могли извлечь выгоду из обмена. Мне очень интересно это обсуждение. 😉

5. @Cobby — Точно. В частности, это нормально, потому что эти функции не имеют внешних побочных эффектов. По крайней мере, в моих проектах я не разрешаю сущностям делать такие вещи, как отправка электронной почты. На самом деле, я, вероятно, не разрешил бы им напрямую обращаться к внешнему API, доступному только для чтения.