Yii DI - фреймворконезависимый контейнер и инжектор
- samdark
- Администратор
- Сообщения: 9489
- Зарегистрирован: 2009.04.02, 13:46
- Откуда: Воронеж
- Контактная информация:
Yii DI - фреймворконезависимый контейнер и инжектор
Выложил альфа-версию. Возможно, запилим на ней Yii 3.0 когда-нибудь:
https://github.com/yiisoft/di
Какие мысли? Что можно улучшить?
https://github.com/yiisoft/di
Какие мысли? Что можно улучшить?
Нравится Yii? Давайте сделаем его лучше!.
Re: Yii DI - фреймворконезависимый контейнер и инжектор
Движение в правильном направлении.
Но почему не взять готовое, и при необходимости декорировать, подмешав функциональности?
Опять какая-то магия https://github.com/yiisoft/di/blob/mast ... r.php#L220
По-моему создание должно быть максимально простым - фабрики анонимками или invokable-классами для lazy load, готовые инстансы, и в последнюю очередь рефлексия (но я бы рефлексию вообще не включал - более явно самому фабрику прописать, тем более анонимкой это пара строк). Функциональность, как мне кажется, уже вся есть.
Но почему не взять готовое, и при необходимости декорировать, подмешав функциональности?
Опять какая-то магия https://github.com/yiisoft/di/blob/mast ... r.php#L220
По-моему создание должно быть максимально простым - фабрики анонимками или invokable-классами для lazy load, готовые инстансы, и в последнюю очередь рефлексия (но я бы рефлексию вообще не включал - более явно самому фабрику прописать, тем более анонимкой это пара строк). Функциональность, как мне кажется, уже вся есть.
- samdark
- Администратор
- Сообщения: 9489
- Зарегистрирован: 2009.04.02, 13:46
- Откуда: Воронеж
- Контактная информация:
Re: Yii DI - фреймворконезависимый контейнер и инжектор
Так и взято готовое. Просто зависимости убраны, инжектор выкинут в отдельный класс и чуть причёсано.
Анонимки тоже поддерживаются, но для большинства случае ими очень неудобно описывать зависимости. Много букв получается и конфиги невозможно описать не в PHP.
Анонимки тоже поддерживаются, но для большинства случае ими очень неудобно описывать зависимости. Много букв получается и конфиги невозможно описать не в PHP.
Нравится Yii? Давайте сделаем его лучше!.
- samdark
- Администратор
- Сообщения: 9489
- Зарегистрирован: 2009.04.02, 13:46
- Откуда: Воронеж
- Контактная информация:
Re: Yii DI - фреймворконезависимый контейнер и инжектор
Так да, есть два подхода как описывать зависимости в контейнерах:
1. Явно по id в анонимках их вынимать.
2. Менее явно, используя интерфейсы как id.
Часто встречается в остальных реализациях и то и то. У нас можно и так и так.
1. Явно по id в анонимках их вынимать.
2. Менее явно, используя интерфейсы как id.
Часто встречается в остальных реализациях и то и то. У нас можно и так и так.
Нравится Yii? Давайте сделаем его лучше!.
Re: Yii DI - фреймворконезависимый контейнер и инжектор
в итоге получается жирный сложный компонент, который можно упростить, до приема только анонимок, а все остальное вынести в бутстрапирование приложения. Получаем конфиг, из конфига в рантайме собираем контейнер, оборачивая определения сервисов в анонимки. В итоге убираем сложный компонент, навязывающий свой флоу, а получаем простой компонент, 10-20 строк копипасты для бутстрапа плюс возможность копипасту расширить до чего угодно.
Код: Выделить всё
$config = ...;
$container = new Container();
if (isset($config['dependencies']['factories'])) {
foreach ($config['dependencies']['factories'] as $id => $factoryName) {
$container->addLazy($id, function (Container $container) use ($id, $factoryName) {
if ($container->has($factoryName)) {
$factory = $container->get($factoryName);
} else {
$factory = new $factoryName();
$container->add($factoryName, $factory);
}
return $factory($container, $id);
});
}
}
if (isset($config['dependencies']['invokables'])) {
foreach ($config['dependencies']['invokables'] as $id => $className) {
$container->addLazy($id, function (Container $container) use ($className) {
return new $className();
});
}
}
if (isset($config['dependencies']['aliases'])) {
foreach ($config['dependencies']['aliases'] as $aliasId => $targetId) {
$container->addLazy($aliasId, function (Container $container) use ($targetId) {
return $container->get($targetId);
});
}
}
// что-то еще откуда угодно
return $container;
$ontainer = \yii\di\buildFromConfig($config);
Re: Yii DI - фреймворконезависимый контейнер и инжектор
я не разделяю эти два варианта. Id может быть какой угодно строкой - хоть смысловым id ('articleRepo') хоть именем интерфейса (\yii\ArticleRepositoryInterface::class, 'yii\\ArticleRepositoryInterface').
То есть не об этом говорил.
PS на самом деле многие не понимают, что вызывая $container->get(\yii\ArticleRepository::class) мы вызываем не реализацию интерфейса, а объект класса, который мы для удобства пометили именем интерфейса. Тонкая грань, но она есть - это просто идентификатор.
- samdark
- Администратор
- Сообщения: 9489
- Зарегистрирован: 2009.04.02, 13:46
- Откуда: Воронеж
- Контактная информация:
Re: Yii DI - фреймворконезависимый контейнер и инжектор
Ох, боюсь даже представить, насколько не быстро это всё будет работать с анонимками. Это центральный компонент и обязан быть максимально шустрым, но, в то же время, простым. Но так да, с анонимками красиво.из конфига в рантайме собираем контейнер, оборачивая определения сервисов в анонимки
Нравится Yii? Давайте сделаем его лучше!.
- samdark
- Администратор
- Сообщения: 9489
- Зарегистрирован: 2009.04.02, 13:46
- Откуда: Воронеж
- Контактная информация:
Re: Yii DI - фреймворконезависимый контейнер и инжектор
Это я про автовайринг. Вайрить можно или по именам интерфейсов из сигнатуры конструктора или метода или по каким-то аннотациям. Имена переменных использовать категорически нехорошо, рефакторинг пострадает очень сильно.я не разделяю эти два варианта. Id может быть какой угодно строкой - хоть смысловым id ('articleRepo') хоть именем интерфейса (\yii\ArticleRepositoryInterface::class, 'yii\\ArticleRepositoryInterface').
То есть не об этом говорил.
Нравится Yii? Давайте сделаем его лучше!.
Re: Yii DI - фреймворконезависимый контейнер и инжектор
да нет, быстро. плюс такой вариант очень удобно можно закэшировать в продакшн-режиме, формируя класс с методами вида public function getArticleRepository(), хотя не вижу смысла - контейнер будет билдиться миллисекунды.samdark писал(а): ↑2017.11.25, 22:56Ох, боюсь даже представить, насколько не быстро это всё будет работать с анонимками. Это центральный компонент и обязан быть максимально шустрым, но, в то же время, простым. Но так да, с анонимками красиво.из конфига в рантайме собираем контейнер, оборачивая определения сервисов в анонимки
Еще раз: я за то, чтобы сам контейнер был максимально простым, чуть ли не реестром, а все остальное бы шло дополнительными классами.
Re: Yii DI - фреймворконезависимый контейнер и инжектор
но иногда необходимо - в проекте например может быть несколько разных сериалайзеров для разных кейсов. Но так да, если выдерживается соотношение один интерфейс - одна реализация, но называть лучше интерфейсом.
Re: Yii DI - фреймворконезависимый контейнер и инжектор
Данному yiisoft/di для полной декларативности стоит добавить поддержку ссылок вроде [42, new Reference('otherService')].
Пока он уступает приведённому подходу из zend/service-manager с factories, invokables и aliases в паре с ReflectionBasedAbstractFactory и другим PSR- контейнерам тем, что всё рассматривает как фабрику, не позволяя хранить скалярные параметры не оборачивая их в анонимку.
Пока он уступает приведённому подходу из zend/service-manager с factories, invokables и aliases в паре с ReflectionBasedAbstractFactory и другим PSR- контейнерам тем, что всё рассматривает как фабрику, не позволяя хранить скалярные параметры не оборачивая их в анонимку.
Re: Yii DI - фреймворконезависимый контейнер и инжектор
надо исходить из того, что нужно создать гибкую абстракцию. А гибкая она будет только если будет минималистична. Часть абстракции на себя взял psr-11 (get/has).
Сформулируем оставшиеся пункты: очевидно мы должны уметь в контейнер что-то засеттить, и очевидно, контейнер должен поддерживать lazy load. Вот все что должен уметь конкретный контейнер. Все остальное имеет место быть, но дополнительно.
Сформулируем оставшиеся пункты: очевидно мы должны уметь в контейнер что-то засеттить, и очевидно, контейнер должен поддерживать lazy load. Вот все что должен уметь конкретный контейнер. Все остальное имеет место быть, но дополнительно.
- samdark
- Администратор
- Сообщения: 9489
- Зарегистрирован: 2009.04.02, 13:46
- Откуда: Воронеж
- Контактная информация:
Re: Yii DI - фреймворконезависимый контейнер и инжектор
Ссылки есть и поддерживаются. Наверное, забыл их в readme описать...
Нравится Yii? Давайте сделаем его лучше!.
- samdark
- Администратор
- Сообщения: 9489
- Зарегистрирован: 2009.04.02, 13:46
- Откуда: Воронеж
- Контактная информация:
Re: Yii DI - фреймворконезависимый контейнер и инжектор
На тему скалярных параметров думал, но что-то не нашёл им нормального применения.
Автоматически вайрить их по имени переменной — это, опять же, убить возможность простейшего рефакторинга типа rename. Да и конфликты возможны.
Аннотации не хочется потому что мы начинаем знать про наш контейнер там, где не должны, хоть формально это и не код.
Автоматически вайрить их по имени переменной — это, опять же, убить возможность простейшего рефакторинга типа rename. Да и конфликты возможны.
Аннотации не хочется потому что мы начинаем знать про наш контейнер там, где не должны, хоть формально это и не код.
Нравится Yii? Давайте сделаем его лучше!.
- samdark
- Администратор
- Сообщения: 9489
- Зарегистрирован: 2009.04.02, 13:46
- Откуда: Воронеж
- Контактная информация:
Re: Yii DI - фреймворконезависимый контейнер и инжектор
На тему сделать основу только на анонимках надо попробовать. Подозреваю, что всё-таки выйдет значительная просадка производительности.
Нравится Yii? Давайте сделаем его лучше!.
Re: Yii DI - фреймворконезависимый контейнер и инжектор
https://gist.github.com/xtreamwayz/b8d7 ... ry-php-L18
"ну давай, расскажи мне про рефакторинг". Мы же про контейнер или про рефакторинг?
Re: Yii DI - фреймворконезависимый контейнер и инжектор
https://rawgit.com/kocsismate/php-di-co ... hmark.html
pimple для примера работает на анонимках. Может еще что-то. Но если посмотреть тхолодные тесты даже на хороших объемах, то видим, что время незначительно мало (можно принебречь), а потребление памяти у всех плюс минус одинаково.
- samdark
- Администратор
- Сообщения: 9489
- Зарегистрирован: 2009.04.02, 13:46
- Откуда: Воронеж
- Контактная информация:
Re: Yii DI - фреймворконезависимый контейнер и инжектор
В примере по ссылке на тему конфига не ясно, почему конфиг должен быть именно в DI-контейнере. По идее, это не его задача и тот же DoctrineFactory мог бы его затягивать себе или в конструктор или брать из отдельного компонента с конфигом.
Нравится Yii? Давайте сделаем его лучше!.
- samdark
- Администратор
- Сообщения: 9489
- Зарегистрирован: 2009.04.02, 13:46
- Откуда: Воронеж
- Контактная информация:
Re: Yii DI - фреймворконезависимый контейнер и инжектор
Одно влияет на другое."ну давай, расскажи мне про рефакторинг". Мы же про контейнер или про рефакторинг?
Нравится Yii? Давайте сделаем его лучше!.
Re: Yii DI - фреймворконезависимый контейнер и инжектор
di-контейнер - это контейнер зависимостей. Зависимость - это не объект, а некая сущность, от которой зависит зависимое. Фабрика БД-коннекшна например зависит от параметров соединения с базой.
можно зассеттить параметры, прописанные в DbConnectionConfig, можно прописанные в обычном массиве в конфиге. Без разницы. Первый вариант даже лучше, но это не значит что не может существовать второй.DoctrineFactory мог бы его затягивать себе или в конструктор или брать из отдельного компонента с конфигом.