Сервисы

Сервис - PHP объект объявленный определенным образом.

По своей сути, сервисы, это самые обычные PHP объекты, но также зарегистрированные в системе в специальном *.services.yml файле. Объекты, зарегистрированные в виде сервисов, в некоторых случаях могут вызываться напрямую, как обычные объекты, но зачастую, это становится проблематичным из-за поддержки зависимостей.

Сервисы могут описывать зависимости, которые им необходимы. Данные зависимости передаются в конструктор объекта сервиса, и объект использует их по назначению. Если зависимость имеет свои зависимости, они также будут загружены, и переданы в нужный конструктор, нужного объекта. За подобное поведение отвечает Service Container, который хранит всю информацию о сервисах, и собирает из них объекты, готовые к использованию.

Преимущества и недостатки

Как и у всех подходов, есть всегда как плюсы, так и недостатки.

Плюсы от объявления объектов в виде сервисов:

  • Позволяет использовать Dependency Injection.
  • Конечный пользователь (разработчик) работает с сервисами через единый API.
  • Так как разработчики обращаются к объектам через сервисы, это позволяет заменять частично или целиком объекты сервисов, не нарушая целостность системы и не требует никаких изменений в кодовой базе где уже используются сервисы.
  • Это позволяет изменять, дорабатывать или полностью заменять объекты сервисов в собственных проектах, опять же, не нарушая целостность системы и не беспокоиться о том, что код, обращающийся к сервису сломается. До тех пор пока вы следуете интерфейсу оригинального сервиса, проект будет продолжать работать бесперебойно, не зависимо, какое название у объекта и неймспейс.
  • Обращение к объекту при помощи сервиса, инициализирует объект сервиса единожды, при первом обращении (по умолчанию, самый распространенный вариант), а при всех последующих, отдает уже инициализированный экземпляр. Это очень положительно сказывается на производительности и потреблении ресурсов.
  • Сервисы могут иметь метки, а другой код, находить все сервисы с определенной меткой и использовать их в нужный момент. Таким образом, сервисы могут быть частью какой-то коллекции, которые одновременно вызываются при определенных условиях. Вам, как разработчику, не придётся думать, как найти все объекты на проекте, которые отвечают каким-то признакам.

Недостатки от объявления объектов в виде сервисов:

  • Если ваш объект, нуждается в инициализации на каждое обращение, то использование сервисов в данном случае, может сделать обратный эффект, и снизить производительность. Но такие случаи крайне редкие.
  • Из-за возможности указывать зависимости, которые поступают в объект через конструктор, у вас может возникнуть проблема, что в объект поступает слишком много других объектов, которые могут понадобиться, а могут не понадобиться. Это усложняет поддержку подобных объектов, и может негативно сказаться на производительности.

Когда использовать сервисы

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

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

В общем случае, рекомендации будут следующие:

  • Если ваш объект, нуждается в функционале, который предоставляется сторонним сервисом — используйте сервис и указывайте необходимый(е) как зависимость вашего.
  • Если ваш объект самодостаточен, или вовсе состоит из статических методов (утилитарный класс, например Drupal\Component\Utility\Crypt), и не нуждается в других сервисах, то лучше не объявлять его в качестве сервиса.
  • Если ваш объект нуждается в инициализации каждый раз, когда он вызывается (например Value Object), то сервисы лучше избегать. Хоть они и поддерживают возможность создания экземпляра на каждое обращение к сервису, эта операция намного затратнее по ресурсам, нежели простое создание экземпляра объекта.

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

Рекомендации выше, лишь рекомендации, в каждой из них можно сделать наоборот и это тоже будет правильно, но делайте это только в том случае, если вы понимаете последствия, и не забывайте производить тестирование до и после.

Ссылки

💝 Помогите нам сделать документацию лучше!

Вся документация Druki с отрытым исходным кодом. Нашли ошибку или неточность? Создайте pull request.

Редактировать текущий документ Обсудить улучшение

Или узнайте как контрибутить.

🤔 По-прежнему нужна помощь?

Не нашли ответа на свой вопрос? Попросите помощи у сообщества!

Задайте вопрос на GitHub Смотрите другие ресурсы сообщества