Зависимость Ад - как передать зависимости глубоко глубоко вложенным объектам?
Вот общий мнимый пример, составленный для этого сообщения. Рассмотрим 6 классов
TableFactory, TableData, TableCRUD, TableSchema, DBConnect, Logger.
TableFactory
- это внешний класс, предположим, что он содержит объект TableData
для таблицы БД.
В этом TableFactory
нет вызовов TableSchema
или DBConnect
или logger
. Я нацелен на пример внутренних объектов, которые не нужны во внешней области.
TableData
- это внутренние выборки и работает с данными, поэтому ему нужны TableCrud
, DBConnect
и logger
.
TableCrud
содержит TableSchema
и нуждается в DBConnect
и logger
.
DBConnect
itseld, чтобы сделать что-то интересное, нужен Logger. Мой пример теперь имеет 3 области.
Мой вопрос довольно прост, если у вас есть объект 3 (или более) областей, которые не вызываются объектами на внешней области, как отправлять объекты из внешнего в внутреннее пространство без нарушения интерфейса Принцип сегрегации → TableFactory не должен иметь дело с DBConnect или Logger, необходимыми для внутренних объектов.
Если кто-то уважает основные принципы ООП и стремится к простоте проверки → у вас будут внешние объекты, нуждающиеся в инъекции 5 объектов, а затем есть методы геттера, которые пропускают объекты, необходимые дальше по цепочке. И внутренние объекты с областью, в свою очередь, требуют инъекции зависимостей их внутренних объектов с 3-кратным областью, а также для геттеров. Это делает объекты с наружной областью, требующие многих зависимостей, и геттеры, чтобы передать их.
Есть ли альтернатива этой методологии прохождения объектов, что я пропустил по пути? Поделись, пожалуйста! Любые ссылки/комментарии оценены.
Ответы
Ответ 1
Это распространенное заблуждение, что зависимости нужно передавать через граф объектов. Чтобы обобщить пример, Miško Hevery дает в "Чистый код: не ищите вещи" , "Дом, которому нужна дверь" , не нужно знать о Заблокировать дверь:
class HouseBuilder
{
public function buildHouse()
{
$lock = new Lock;
$door = new Door($lock);
$house = new House($door);
return $house;
}
}
Как вы можете видеть, Хаус полностью забывает о том, что дверь в нем требует блокировки. Это обязанность HouseBuilder создавать все необходимые зависимости и складывать их вместе по мере необходимости. Изнутри.
Следовательно, в вашем сценарии вы должны определить, какие объекты должны работать над зависимостями (cf Закон Деметры). Затем ваш строитель должен создать всех соавторов и убедиться, что зависимости вставляются в соответствующие объекты.
Также см. Как думать о "новом" операторе в отношении модульного тестирования
Ответ 2
Если вы спотыкаетесь на тот же вопрос, проверьте статью Херви, которая попадает в глаз быков.
http://misko.hevery.com/2008/10/21/dependency-injection-myth-reference-passing/
В случае, если в дальнейшем статья исчезнет, вы найдете фрагмент
"Каждый объект просто знает об объектах, с которыми он непосредственно взаимодействует. Ссылка на объекты не передается, чтобы получить их в нужном месте, где они необходимы".
Итак, что нужно сделать, вместо того, чтобы создавать глубокий вложенный графический объект с передачей зависимостей сверху вниз, идти горизонтально и управлять зависимостями в другом месте.