#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, доступному только для чтения.