В Symfony появился Service Locator
- samdark
- Администратор
- Сообщения: 9489
- Зарегистрирован: 2009.04.02, 13:46
- Откуда: Воронеж
- Контактная информация:
В Symfony появился Service Locator
http://symfony.com/blog/new-in-symfony- ... e-locators
Что думаете? Мода в очередной раз меняется?
https://www.youtube.com/watch?v=Ks75ep-Ztdg
Что думаете? Мода в очередной раз меняется?
https://www.youtube.com/watch?v=Ks75ep-Ztdg
Нравится Yii? Давайте сделаем его лучше!.
Re: В Symfony появился Service Locator
Так такой однозначный резолв хэндлеров для команд всегда реализовывался инъекцией самого контейнера и дёрганием его как локатора:
чтобы не инстанцировать по тегам сотни хэндлеров через CompillerPass при извлечении шины.
А более продвинутые программисты спокойно делали SFHandlerResolver implements HandlerResolverInterface для сторонних библиотек вроде SimpleBus, чтобы использовать new SFHandlerResolver($container, $map), реализующий метод resolve:
который внутри себя уже делал:
или:
Но нерадивые программисты по примеру Yii (или нечаянно) могли так из него не только обработчики дёрнуть, но и любой другой сервис из контейнера достать.
Чтобы такие резолверы с префиксами для своих маппингов не писать (хардкод) и чтобы весь основной контейнер не инъектить (риск говнокода) там придумали возможность создать лёгкую прокси-копию контейнера, в которую можно передать только нужный список сервисов из основного контейнера по новым именам:
и инъектить уже этот безопасный контейнер-песочницу вместо основного и из него по новым ключам дёргать только его содержимое:
Такой хитрый вспомогательный объект и назвали здесь именем ServiceLocator.
И от утечки глобального доступа ко всей куче сервисов защитились, и проблему резолва по простым ключам без префиксов решили, и основной контейнер как локатор теперь можно в шинах не использовать.
Про это и говорится в описании.
Код: Выделить всё
$handler = $this->container->get('app.handler.' . $commandName);
А более продвинутые программисты спокойно делали SFHandlerResolver implements HandlerResolverInterface для сторонних библиотек вроде SimpleBus, чтобы использовать new SFHandlerResolver($container, $map), реализующий метод resolve:
Код: Выделить всё
$handler = $this->handlerResolver->resolve($command);
Код: Выделить всё
public function resolve($command) {
return $this->container->get($this->map[get_class($command)]);
}
Код: Выделить всё
return $this->container->get($this->prefix . '.' . get_class($command));
Чтобы такие резолверы с префиксами для своих маппингов не писать (хардкод) и чтобы весь основной контейнер не инъектить (риск говнокода) там придумали возможность создать лёгкую прокси-копию контейнера, в которую можно передать только нужный список сервисов из основного контейнера по новым именам:
Код: Выделить всё
services:
app.command_handler_locator:
class: Symfony\Component\DependencyInjection\ServiceLocator
tags: ['container.service_locator']
arguments:
-
AppBundle\FooCommand: '@app.command_handler.foo'
AppBundle\BarCommand: '@app.command_handler.bar'
Код: Выделить всё
$handler = $this->handlerLocator->get($commandName);
И от утечки глобального доступа ко всей куче сервисов защитились, и проблему резолва по простым ключам без префиксов решили, и основной контейнер как локатор теперь можно в шинах не использовать.
Про это и говорится в описании.
Нет, это не про "тот самый" ServiceLocator.
- samdark
- Администратор
- Сообщения: 9489
- Зарегистрирован: 2009.04.02, 13:46
- Откуда: Воронеж
- Контактная информация:
Re: В Symfony появился Service Locator
Ну как не тот самый, когда тот? Если контейнер инъектится, он автоматически превращается в локатор.
Нравится Yii? Давайте сделаем его лучше!.
- samdark
- Администратор
- Сообщения: 9489
- Зарегистрирован: 2009.04.02, 13:46
- Откуда: Воронеж
- Контактная информация:
Re: В Symfony появился Service Locator
Явно назвали локатор локатором и по сути поощрили явную зависимость от него.
Нравится Yii? Давайте сделаем его лучше!.
Re: В Symfony появился Service Locator
Поощрили для единственного примера-исключения с CommandBus, где использование контейнера как локатора для runtime-получения объекта обработчика по имени команды было необходимо. Сделали возможность создания по требованию легковесных отдельных локаторов-коллекций для группировки однородного белого списка обработчиков для шин, чтобы не использовать не по назначению оригинальный контейнер. Больше никаких кейсов для использования контейнера как локатора в приложении не вижу.
Этот ServiceLocator в Symfony - именно вещь для организации коллекций однородных объектов с доступом по индексу вроде:
Код: Выделить всё
$handler = $handlerLocator->get($commandName);
$db = $dbLocator->get($connectionId);
Последний раз редактировалось ElisDN 2017.05.05, 07:47, всего редактировалось 2 раза.
- samdark
- Администратор
- Сообщения: 9489
- Зарегистрирован: 2009.04.02, 13:46
- Откуда: Воронеж
- Контактная информация:
Re: В Symfony появился Service Locator
Ну не знаю... я прокидывание контейнера в том или ином случае встречал в каждом проекте на Symfony, с которым приходилось работать.
Нравится Yii? Давайте сделаем его лучше!.
Re: В Symfony появился Service Locator
Это реально необходимо только в Twig_Extension для получения $this->container->get('templating.helper.assets'), чтобы не зациклить граф. Хотя это решается прокидыванием Lazy Load Proxy. В остальных случаях прокидывание не особо нужно.
Последний раз редактировалось ElisDN 2019.03.18, 13:11, всего редактировалось 2 раза.
- samdark
- Администратор
- Сообщения: 9489
- Зарегистрирован: 2009.04.02, 13:46
- Откуда: Воронеж
- Контактная информация:
Re: В Symfony появился Service Locator
Да я-то понимаю, что прокидывание само по себе убивает всю идею DI, но что есть то есть...
Нравится Yii? Давайте сделаем его лучше!.
Re: В Symfony появился Service Locator
Плохие архитектурные решения в симфони есть (стандартный DiC, например) как и везде, но локатор, описанный в заметке к ним не относится.
Заметка показывает, как можно удобно использовать psr-11 для создания шины. DI это не убивает - командная шина сама по себе локатор обработчиков и то что туда заинжектили пср контейнер да еще со списком команд, это правильное использование контейнера.
Почему нельзя инжектить контейнер:
1. Зависимость от контейнера.
2. Неявная зависимость от всех сервисов, имеющихся в контейнере - не поймешь по API класса, что он использует. Программирование по контракту сломано.
Принятие psr-11 фактически сняло первую проблему - зависеть от тоненького psr интерфейса не страшно, а наоборот - есть куча реализаций, и адаптеры писать не надо, как на свои интерфейсы.
Вторая проблема в представленном кейсе не имеет смысла - шина все равно зависит от всех обработчиков и команд. Так что DI здесь не нарушен и SL здесь не антипаттерн. Все разумно.
Заметка показывает, как можно удобно использовать psr-11 для создания шины. DI это не убивает - командная шина сама по себе локатор обработчиков и то что туда заинжектили пср контейнер да еще со списком команд, это правильное использование контейнера.
Почему нельзя инжектить контейнер:
1. Зависимость от контейнера.
2. Неявная зависимость от всех сервисов, имеющихся в контейнере - не поймешь по API класса, что он использует. Программирование по контракту сломано.
Принятие psr-11 фактически сняло первую проблему - зависеть от тоненького psr интерфейса не страшно, а наоборот - есть куча реализаций, и адаптеры писать не надо, как на свои интерфейсы.
Вторая проблема в представленном кейсе не имеет смысла - шина все равно зависит от всех обработчиков и команд. Так что DI здесь не нарушен и SL здесь не антипаттерн. Все разумно.
- samdark
- Администратор
- Сообщения: 9489
- Зарегистрирован: 2009.04.02, 13:46
- Откуда: Воронеж
- Контактная информация:
Re: В Symfony появился Service Locator
PSR-11 проблему явной зависимости от контейнера не снял ни в коем случае. Как была, так и осталась. Он вообще для того, чтобы можно было подменять реализацию контейнера, а не для чего-то ещё.
По второму пункту на тему частного случая согласен, но ведь все мы знаем, что примеры из документации применяют по поводу и без...
По второму пункту на тему частного случая согласен, но ведь все мы знаем, что примеры из документации применяют по поводу и без...
Нравится Yii? Давайте сделаем его лучше!.
Re: В Symfony появился Service Locator
Как раз он снял эту проблему. Принцип инверсии зависимостей говорит, что мы должны зависеть от абстракций. ContainerInterface - абстракция, делающая зависимость от реализации контейнера неявной.
- samdark
- Администратор
- Сообщения: 9489
- Зарегистрирован: 2009.04.02, 13:46
- Откуда: Воронеж
- Контактная информация:
Re: В Symfony появился Service Locator
Именно что мы должны зависеть от абстракций. То есть на вход требовать конкретные интерфейсы, а не контейнер, из которого можно достать что угодно.
Нравится Yii? Давайте сделаем его лучше!.
- slavcodev
- Сообщения: 3134
- Зарегистрирован: 2009.04.02, 21:42
- Откуда: Valencia
- Контактная информация:
Re: В Symfony появился Service Locator
Саша, а как же "Фреймворк дает возможности, как их применят на совести программиста"?
Жду Yii 3!
- samdark
- Администратор
- Сообщения: 9489
- Зарегистрирован: 2009.04.02, 13:46
- Откуда: Воронеж
- Контактная информация:
Re: В Symfony появился Service Locator
Я за то, чтобы фреймворк давал осознанно срезать углы. Просто раньше Symfony ставил более жёсткие рамки и его за это хвалили, а тут, получается, рамки расширяются.
Нравится Yii? Давайте сделаем его лучше!.