Ад зависимостей - как передать зависимости глубоко вложенным объектам? - PullRequest
25 голосов
/ 23 мая 2011

Вот общий воображаемый пример, составленный для этого поста.Рассмотрим 6 классов

TableFactory, TableData, TableCRUD, TableSchema, DBConnect, Logger. 

TableFactory - это внешний класс, допустим, он содержит объект TableData для таблицы БД.

В этом TableFactory нет вызововдо TableSchema или DBConnect или logger.Я нацеливаюсь на пример внутренних объектов, которые не нужны во внешней области.

TableData - это внутренняя выборка, которая работает с данными, поэтому для нее нужны TableCrud, DBConnect и Logger.

TableCrud содержит TableSchema и нуждается в DBConnect и Logger.

DbConnect для того, чтобы все было весело, нужен регистратор.Мой пример теперь имеет 3 области видимости.

Мой вопрос довольно прост: если у вас есть объект 3 (или более) областей действия, которые не вызываются объектами во внешней области видимости, как можно отправитьэти объекты из внешней во внутреннюю область видимости, не нарушая принцип разделения интерфейса -> TableFactory не должен иметь дело с DBConnect или Logger, необходимыми внутренним объектам.

Если уважать основные принципы ООП и стремиться к легкомуtestability -> у вас будут внешние объекты, нуждающиеся в инжекции 5 объектов, а затем есть методы получения, которые будут передавать объекты, необходимые дальше по цепочке.В свою очередь, объекты внутренней области видимости потребуют внедрения зависимостей их внутренних объектов глубиной в 3 области, с получателями для них тоже.Это делает для объектов с внешней областью видимости, требующих многих зависимостей, и получателей просто для их передачи.

Есть ли альтернатива этой методологии передачи объектов, которую я пропустил по пути?Поделись, пожалуйста!Любые ссылки / комментарии приветствуются.

Ответы [ 2 ]

47 голосов
/ 23 мая 2011

Это распространенное заблуждение, что зависимости должны передаваться через граф объектов.Чтобы обобщить пример, Мишко Хевери дает Чистый код: не ищите вещи , Дом, которому нужна дверь, не должен знать о Замке в двери:

class HouseBuilder
{
    public function buildHouse()
    {
        $lock  = new Lock;
        $door  = new Door($lock);
        $house = new House($door);

        return $house;
    }
}

Как видите, Хаус совершенно не замечает того факта, что Дверь в нем требует замка.HouseBuilder отвечает за создание всех необходимых зависимостей и их объединение по мере необходимости.Изнутри.

Следовательно, в вашем сценарии вы должны определить, какие объекты должны работать с какими зависимостями (см. Закон Деметры ).Затем ваш Builder должен создать всех соавторов и убедиться, что зависимости внедрены в соответствующие объекты.

Также см. Как думать о «новом» операторе в отношении модульного тестирования

1 голос
/ 03 августа 2017

Если вы наткнулись на тот же вопрос, проверьте статью Херви, которая попадает в глаза быка

http://misko.hevery.com/2008/10/21/dependency-injection-myth-reference-passing/

В случае, если статья исчезнет в будущем, вот выдержка

«Каждый объект просто знает об объектах, с которыми он непосредственно взаимодействует. Нет ссылки на объекты просто для того, чтобы привести их в нужное место, где они необходимы».

Так что нужно сделать вместосоздание глубокого вложенного графа объектов с передачей зависимостей сверху вниз, горизонтали и управлением зависимостями в другом месте.

...