Как правильно использовать Dependency Injection Container?

Умею создавать DIC (через Pimple).

Много где в интернете пишут что передавать во все классы целиком весь контейнер нехорошо, т.к. эти классы начинают зависеть сразу от всех элементов контейнера, неважно используют они их или нет. Ок, значит надо использовать правильно.

Правильно это надо передавать (например в конструкторе) только те элементы DIC которые будут нужны этому классу, ну ок
class First
{
    protected $elem1;
    protected $elem2;
    protected $elem3;

    public function __construct($elem1, $elem2, $elem3)
    {
        $this->elem1 = $elem1;
        $this->elem2 = $elem2;
        $this->elem3 = $elem3;
    }

    public function start()
    {
        return (new Second($this->elem1, $this->elem2, $this->elem3))->start();
    }
}

class Second
{
    protected $elem1;
    protected $elem2;
    protected $elem3;

    public function __construct($this->elem1, $this->elem2, $this->elem3)
    {
        $this->elem1 = $elem1;
        $this->elem2 = $elem2;
        $this->elem3 = $elem3;
    }

    public function start()
    {
        return (new Third($elem3))->start();
    }
}

class Third
{
    protected $elem3;

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

    public function start()
    {
        return 'Third';
    }
}


First сам что-то там делает и запускает Second
Second тоже что-то делает и использует только elem1 и elem2, а elem3 ему нужен чтобы использовать его в Third

И если вдруг понадобится третьему классу какой-то $elem4 то придется его протащить через классы Second и First (в этом плане когда мы тащим весь контейнер об этом можно не думать и просто добавить при инициализации контейнера новую зависимость), а так надо будет отрефакторить все классы (где они используются чтобы добавить нужные зависимости)

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

P.S. В интернете полно инструкций как инициировать DIC, а как его правильно использовать ни слова.

И так ли уж плохо тянуть весь DIC по классам?

Или мой гипотетический пример в принципе плох, возможно тем что логика слишком сложная и надо все переписать чтобы классы не вызывали друг из друга, а сделать их вызов в каком-то контроллере последовательно (передавая и получая необходимые для обработки данные)? Например если у нас есть большой массив данных и нам с ним надо провести разного рода обработки и чтобы не валить все в одном месте и делаются три класса, которые оперируют одним массивом данных и по разному его обрабатывают
  • Вопрос задан
  • 112 просмотров
Решения вопроса 2
bitniks
@bitniks
Go/PHP/Symfony developer
Сейчас First жестко зависит от Second, а Second от Third. Если руководствоваться DIC, то такого быть не должно. Second должен инжектиться в First, а Third в Second.

Например:
class First
{
    protected $elem1;
    protected $elem2;
    protected $elem3;
    protected $second;

    public function __construct($elem1, $elem2, $elem3, $second)
    {
        $this->elem1 = $elem1;
        $this->elem2 = $elem2;
        $this->elem3 = $elem3;
        $this->second = $second;
    }

    public function start()
    {
        return $this->second->start();
    }
}
Ответ написан
Комментировать
DIC - это некий механизм, который внедряет зависимости объекты.

Приведенный вами код не является примером использования DIC потому, что вы вручную передаете зависимости в объекты Second и Third.

Примером использования DIC будет внедрение в First, объекта Second, а в объект Second объекта Third:
class First
{
    protected $second;

    public function __construct(Second $second)
    {
        $this->second = $second;
    }

    public function start()
    {
        return $this->second->start();
    }
}


class Second
{
    protected $elem1;
    protected $elem2;
    protected $elem3;
    protected $third;

    public function __construct($this->elem1, $this->elem2, $this->elem3, Third $third)
    {
        $this->elem1 = $elem1;
        $this->elem2 = $elem2;
        $this->elem3 = $elem3;
        $this->third = $third;
    }

    public function start()
    {
        return $this->third->start();
    }
}


class Third
{
    protected $elem3;

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

    public function start()
    {
        return 'Third';
    }
}


При этом вы должны отдельно сконфигурировать каждый из контейнеров(объектов). Способ же будет зависить от выбора конкретного инструмента.
Ответ написан
Пригласить эксперта
Ответы на вопрос 1
dmitriylanets
@dmitriylanets
веб-разработчик
То что вы показали это не DIC а dependency injection . Используйте container.thephpleague.com/2.x/auto-wiring
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы