Pull to refresh

Comments 21

UFO just landed and posted this here
1) Объясню на примере Pimple, поскольку он довольно популярный:

  • Интерфейс ArrayAccess, прост в использование но выглядит криво в ООПшном коде.
  • Настраивается извне, что как я уже писал выше мне не нравится. Я хочу чтобы контейнер инкапсулировал свою логику
  • Нет статического интерфейса. Как по мне, кому-то то это тоже понадобится
  • Нет доступа к глубоким значением по точке, что выглядит не так красиво как с ней
  • Поскольку для вложенности надо создавать несколько контейнеров, то в случае если сервиса нет, вы получите только имя последнего ключа (например просто repository) вместо полного (user.repository).
  • Нет аналога $this->instance()


Если сдается примитивным, пишите которые фичи вам надо, может и появляться =)

2. Я всегда сначала пишу статью на хабр, смотрю фидбек, перевожу на англ и тогда уже ставлю в доку. Так что статья это бета тест доков ))

3. Спасибо, на самом деле у меня PHPStorm, но вот как раз эту либу писал в Атоме

UFO just landed and posted this here
> А почему не на примере symfony/dependency-injection?

как я писал в самом начале статьи, совсем не люблю конфигурацию зависимостей в конфиг файлах, а настройка его через PHP более громоздка, e.g.:

$container
    ->register('newsletter_manager', 'NewsletterManager')
    ->addArgument(new Reference('mailer'));

// вместо
$this->instance('newsletter_manager', NesletterManager::class, ['@mailer']);


> Поясните, что вы конкретно имеете ввиду, используя устоявшуюся терминологию.

Настраивать PHPixie DI можно только изнутри самого класса во время создания екземпляра через protected методы. То нельзя просто так взять и добавить новое значение где-то потом в рантайме, как с Pimple:

// может случится где угодно
$container['session_storage'] = function ($c) {
    return new SessionStorage('SESSION_ID');
};


> Это ухудшает взаимодействие и опускает DI до уровня Service Locator или синглтонофасадов Laravel.

Как я уже писал вначале статьи, я считаю что контейнеры сильно проигрывают стандартным классам фабрик, и этот компонент написан на случай «если кому-то очень хочется контейнер». Если разработчик сам вправе решать использовать контейнер или нет, он также должен иметь право использовать синглофасады если захочет. Конечно же никто не мешает просто их не использовать если не хочется.

Я не спорю конечно что компонент симфони в совсем другой лиге. PHPixie DI больше создает конкуренцию легковесным контейнерам типа Пимпл и Аура
UFO just landed and posted this here
Лучше рассматривать PHP-Di как пример чем symfony/dependency-injection.
он то как раз слишком много умеет, ему нужен кеш, он допускает возможность создавать новый инстанс сервисов через make(), в то время как в пикси это конфигурация решает будет ли возвращаться новый инстанс. Сам по себе PHPixie DI более строгий. Как я уже писал в другом комменте, выбор контейнера дело вкуса, этот DI достаточно отличается от других чтобы не быть клоном, а уже каким пользоваться зависит только от того какой стиль конфигурации и интерфейса вам больше нравится.
Мне очен нравится ларавеловская импелементация Illuminate/Container
Не вижу никаких плюсов по сравнение с ним
Посмотрите на https://github.com/auraphp/Aura.Di — много полезных фишек можно взять на вооружение. С кучей зависимостей приложение есть не более 2мб памяти из-за ленивой загрузки, можно настроить авто-разруливание зависимостей через контроль типов и не париться. В случае Pimple style — контейнеров не имеет значения, нужен Вам сервис сейчас или нет, он все равно будет инициализирован и будет висеть и есть ресурсы.
В PHPixie DI и так все работает как lazy в Aura, даже ->instance(). А вот авто разруливание сомнительная фича имхо, к тому же в случае если конструкторы принимвют интерфейсы, то настараивать какой сервис использовать вместо интерфейса все равно надо вручную. К тому же аура использует подход с ArrayAccess как и Pimpl.

На самом деле все это дело вкуса, так как самое важное это насколько вам нравится работа с контйнером. Я думаю phpixie di достаточно отличается своим интерфейсом от других чтобы не быть велосипедом, а вот какой интерфейс работы нравится больше уже решать вам.
А вот авто разруливание сомнительная фича имхо, к тому же в случае если конструкторы принимвют интерфейсы, то настараивать какой сервис использовать вместо интерфейса все равно надо вручную

Так сложно задать мэпу соответствий интерфейс => реализация, прям уж никак. Что до автосвязывания — это на самом деле очень мощная штука, в том плане что разработчики обычно ленивы, а так вся эта "магия" не будет им мешать делать больше объектов вместо пары жирных "что бы не конфигурить ничего".


К тому же аура использует подход с ArrayAccess как и Pimpl.

мы точно про dependency injection? ну мол я к тому что какая разница если в нашем коде контейнер использоваться не должен.

Ну у меня тут явно комплексный вариант, как хочешь так и используй, хоть как и статический локатор. Автоваиринг еще не нравится тем что можно инжекнуть как я писал в начале статьи: совсем далекое из совсем другого концы системы. Именно поэтому у меня фабрики, каждой доступно только то к чему у нее есть доступ, то есть нельзя так просто взять и всунуть в класс валидации какой-то сервис с другого бандла. Как по мне тогда нарушается модулярность кода. То есть если вот у меня есть ОРМкак то только ее или ее репозитории можно куда-то инжектить, а не какой-то внутренний ее сервис.

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

А если не делать этот же разработчик будет меньше дробить систему, потому что лень делать фабрики. Проходили.


Я эту проблему решил при помощи deptrac который просто не даст закоммитить такой код.

За deptrac спасибо, не знал такое :)
UFO just landed and posted this here
В целом контейнер неплохой, идея конфигурации только изнутри мне тоже нравится, за это плюс.

Но как мне кажется, подойдёт для не очень больших проектов, расскажу почему.

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

class SomeController
{

    /**
     * @var SomeLogicService $service
     */
    private $service;
    
    public function __construct(SomeLogicService $service)
    {
        $this->service = $service;
    }
}

class SomeLogicService
{
    /**
     * @var AnotherLogicService $service
     */
    private $service;

    public function __construct(AnotherLogicService $service)
    {
        $this->service = $service;
    }
}


Без auto-wiring мне придётся все 50 классов описывать в контейнере, в том числе и контроллер. А это несколько неудобно.
С auto-wiring остаточно описать контроллер в контейнере.
Так это работает в Laravel и Symfony (по крайней мере я так это использую)
На самом деле во всех своих проектах я использую фабрики, так что мне все равно приходится руками описывать как строить контроллеры. Автоваиринг конечно удобно, но тогда надо еще рефлексию парсить и как-то кешировать метаданные. Если будете использовать ->instance() метод, то это только одна строчка конфигурации на контроллер, что не так уж и много, чтобы ради этого тянуть парсер и кеш. К тому же этот кеш еще надо читать и парсить на каждом запросе, а такой контейнер как в PHPixie DI закешируеться самим opcache PHP.

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

А зачем если эти фабрики можно сгенерировать (так собственно симфони и делает). Ну то есть я понимаю, все явно, все круто, но мне это не интересно как потенциальному пользователю.


но тогда надо еще рефлексию парсить и как-то кешировать метаданные.

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

Ну если кодогенерация то да, с ней спорить трудно
С auto-wiring остаточно описать контроллер в контейнере.

https://github.com/Symplify/ControllerAutowire — прошу, можно и контроллеры не описывать. Нужно будет только для интерфейсов имплементации обозначить и если декорацией увликаетесь.

ну библиотека ведь всё равно вместо нас их описывает ;) https://github.com/Symplify/ControllerAutowire/blob/master/src/DependencyInjection/Compiler/RegisterControllersPass.php#L40

в Laravel 5 такие контроллеры например из коробки идут.
суть в общем в том была, что так или иначе контроллеры описать придётся при такой схеме, а вот всё остальное уже «автовайриться» будет
Sign up to leave a comment.

Articles