Контейнер DI и адаптированный MVC

Я создал внутреннюю структуру MVC PHP, и теперь я изо всех сил пытаюсь внедрить контейнер DI. Я принял Pimple в качестве DiC, я прочитал книгу Криса Хартьеса "The Grumpy Programmer's Guide To Создание тестируемых PHP-приложений" (очень хорошее и вдохновляющее чтение, очень рекомендую!), благодаря которым я больше понял о TDD. В любом случае, если я получу DI в ядре фреймворка, как мне заполнить определения и как мне его передать.

  1. Внедрение контейнера (внедрение в объект приложения вплоть до созданного пользователем контроллера). - НЕПРАВИЛЬНО
  2. Заставлять пользователя-разработчика «заполнять» его в Bootstrap — НЕПРАВИЛЬНО
  3. Синглтон – ОЧЕНЬ НЕПРАВИЛЬНО
  4. Шаблон наблюдателя (DiC прикреплен к наблюдателю. Наблюдатель как внешний интерфейс к DiC) - ?(Вероятно, худшая идея: D)

Затем, как сделать ядро ​​DiC доступным во всей структуре (скажем, для внедрения объекта конфигурации), без создания каких-либо зависимостей, ненужного принуждения пользователя к его кодированию или добавления накладных расходов на создание XML/JSON или любого другого.

PS: ** Я верю, что увижу много ответов о Inversion-of-Control (IoC) и Service Locator. Что я не могу понять, как именно их реализовать. Ссылайтесь на простое/базовое руководство.


person DaGhostman Dimitrov    schedule 18.10.2013    source источник
comment
Pimple — это локатор службы (прославленный реестр), а не контейнер внедрения зависимостей. Кроме того, вам не нужен контейнер внедрения зависимостей для использования внедрения зависимостей в ваш код.   -  person tereško    schedule 19.10.2013
comment
Я запутался, везде, где я читал (даже на основном сайте), написано, что это Simple DiC, не могли бы вы оценить?   -  person DaGhostman Dimitrov    schedule 19.10.2013
comment
Контейнер DI позволяет собрать обязанности класса, которые необходимо внедрить в конструктор. Он либо выполнит полную сборку, либо просто предоставит список зависимостей, связанных с классом. Контейнеры DI обычно находятся на фабриках/строителях. Локатор службы — это зависимость класса, экземпляр которого затем будет использовать вытягивать зависимости, которые ему действительно нужны.   -  person tereško    schedule 19.10.2013
comment
Хорошо, если контейнер DI должен находиться (быть доступным) внутри фабрики, это означает, что он создает зависимость между фабрикой и контейнером? или я что-то пропустил здесь   -  person DaGhostman Dimitrov    schedule 19.10.2013
comment
Что мешает вам $myFactory = new FooFactory( new DIContainer );. Я надеюсь, что когда вы слышите factory, у вас не возникает ассоциации со статическим методом factory, потому что последний ИМХО - довольно плохая практика.   -  person tereško    schedule 19.10.2013
comment
Я понимаю фабричный шаблон, но то, что я читал в эти дни, заключалось в том, что внедрение контейнера DI - не очень хорошая идея, это то, что я упомянул в пункте 1.? Если бы вы могли сформулировать простой ответ, резюмируя комментарии, которые вы дали, и объяснить немного больше, я верю, что это могло бы кому-то помочь.   -  person DaGhostman Dimitrov    schedule 19.10.2013
comment
Ваш пункт № 1 говорит о внедрении контейнера DI в экземпляр. Это приводит к тому, что класс берет на себя обязанности извне. Фабрика создает экземпляр. Factory может зависеть от контейнера DI, потому что он предоставляет фабрике детали для сборки указанного экземпляра. Эхх... Наверное, мне придется написать реальный ответ. Просто на их написание уходит слишком много времени.   -  person tereško    schedule 19.10.2013


Ответы (1)


(отказ от ответственности, я разработчик PHP-DI)

Я не очень понимаю ваш вопрос, мне кажется, что если у вас есть полный контроль над инфраструктурой MVC, то использование DI и DIC должно быть довольно простым. Вот копия введения в DI на домашней странице PHP-DI:

  • Приложению нужен FooController, поэтому:
  • Application gets FooController from the Container, so:
    • Container creates SomeRepository
    • Контейнер создает BarService и предоставляет ему SomeRepository.
    • Контейнер создает FooController и предоставляет ему BarService
  • Application calls FooController
    • FooController calls BarService
      • BarService calls SomeDependency
        • SomeRepository does something

Контейнер отвечает за создание всех объектов (графа объектов), а затем нефреймворковый код (контроллеры, службы и т. д.) работает без НИКОГДА вызова Контейнера.

Тогда как сделать ядро ​​DiC доступным во всей структуре?

Не делайте его доступным во всей структуре.

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


Пример: вы хотите внедрить объект конфигурации в контроллер:

class MyController {
    private $configuration;

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

Поскольку роль DIC заключается в создании этого контроллера, он будет внедрять объект конфигурации.

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

А также, если у вас есть вопросы о том, как писать свои контроллеры, возможно, вам следует прочитать это: Контроллеры как сервисы? .

person Matthieu Napoli    schedule 19.10.2013