PHP Profi

Неймспейсы и организация сервисов бизнес-логики в Symfony Перевод

php symfony service

Я хочу поговорить о пространствах имен для сервисов в Symfony, специфичное для Symfony3.

Это захватывающие времена, Symfony 4 уже на подходе — выходит 30-го ноября — так что этот пост может стать неактуальным в ближайшее время! Тем не менее концепт всё тот же, так что давайте взглянем на него!

В последнее время, общаясь со своей командой в SlowCode, мы определили общий способ создания сервисов.

Первое правило: использовать папку для логических сервисов

Любой сервис, который обеспечивает логику приложения, будет находиться в папке App\Service. Таким образом, все аккуратно, и все разработчики в команде знают, где их найти.

Второе правило: использовать папку для домена

Следующий слой — это доменное имя. Это опять же, чтобы обеспечить порядок. Возможно, вы так не думаете, но когда вы в конечном итоге работаете с 8-ю доменными именами, в каждом из которых по 2-3 сервиса, то всё может стать запутано, если оно не аккуратно :)

Например, если у нас есть сервис, который имеет отношение к остаткам (Stock) под названием StockAvailability, то её название вместе с пространством имен будет AppBundle\Service\Stock\StockAvailability.

Третье правило: использовать '.' для разделения папок и '_' для разделения слов

Идентификатор сервиса должен быть разделён точкой ('.') по названию папок и подчёркиванием ('_'), если в названии — папки или сервиса — больше, чем одно слово.

Так, в предыдущем примере, мы задали бы все это дело вот так:

services:

    app.service.stock.stock_availability:
        class: AppBundle\Service\Stock\StockAvailability
        arguments:
            - '@doctrine.orm.entity_manager'
            ...

В последнее время в Symfony 3.3, был принят новый способ определения сервиса.

Теперь лучше задать идентификатор сервиса через FQCN (полное название класса с пространством имён). Итак, вместо того, как задавали мы его раньше, мы можем это сделать так:

services:

    AppBundle\Service\Stock\StockAvailability:
    	public: true
        arguments:
            - '@doctrine.orm.entity_manager'
            ...

Задав его таким способом, вы по-прежнему можете достать сервис из сервис-контейнера (с новым идентификатором, конечно, – с полным имением класса):

use AppBundle\Service\Stock\StockAvailability

public function fooAction(Request $request)
{

    // до Symfony 3.3 вы получали бы её так
    // $stockService = $this->get('app.service.stock.stock_availability');

    // В Symfony 3.3 вы можете получить сервис так
    // (Это возможно, только если вы объявлили свой сервис как публичный)
    $stockService = $this->get(StockAvailability::class);

}

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

use AppBundle\Service\Stock\StockAvailability

public function fooAction(Request $request, StockAvailability $stockService)
{
	// now we have it injected into our variable $stockService
	// so we don't need to get it from the container
}

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

О приватных/публичных сервисах. Я понимаю, куда Symfony "клонит", и я думаю, что ограничение использовать ‘инъекции’ вместо ‘получения’ делает код более надежным, и, вероятно, более читаемым, в конце концов. Однако, я все же думаю, есть и плюсы у подхода, использовавшегося до 3.3 версии. Получение сервисов из контейнера является очень полезным, и обеспечивает гибкость и скорость.

Я думаю, что, поскольку по-прежнему можно объявить сервис публичным, это я и буду делать... что вы будете делать?

Подробнее здесь:
Symfony service container
Symfony 3.3 best practices
Symfony class for service id

2017-11-29 alek13 оригинал
General Food

Комментарии

авторизуйтесь, чтобы оставить комментарий