Что оборотные стороны к использованию Внедрения зависимости? [закрытый]

333
задан Epaga 10 February 2011 в 21:38
поделиться

12 ответов

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

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


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

Предположим, вы хотите спроектировать кампус колледжа. Вы должны передать часть дизайна студентам и профессорам, иначе физический корпус не подойдет физикам. Ни один архитектор не знает достаточно о том, что нужно физическим людям, чтобы делать все самостоятельно. Но вы не можете делегировать дизайн каждой комнаты ее жильцам, потому что тогда вы получите гигантскую груду щебня.

Как можно распределить ответственность за дизайн по всем уровням большой иерархии, сохраняя при этом согласованность и гармонию общего дизайна? Это проблема архитектурного дизайна, которую пытается решить Александр, но это также фундаментальная проблема разработки компьютерных систем.

Решает ли DI эту проблему? . Но это действительно помогает вам ясно увидеть, пытаетесь ли вы делегировать ответственность за проектирование каждой комнаты ее обитателям.

13
ответ дан 23 November 2019 в 00:43
поделиться

Читаемость кода. Вы не сможете легко понять поток кода, поскольку зависимости скрыты в файлах XML.

3
ответ дан 23 November 2019 в 00:43
поделиться

Пара моментов:

  • DI увеличивает сложность, обычно за счет увеличения количества классов, поскольку обязанности разделяются больше, что не всегда выгодно
  • Ваш код будет (в некоторой степени) связан с используемой вами структурой внедрения зависимостей (или, в более общем смысле, с тем, как вы решите реализовать шаблон DI)
  • Контейнеры DI или подходы, которые выполняют определение типов, обычно влекут за собой небольшие потери времени выполнения (очень незначительные, но он есть)

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

206
ответ дан 23 November 2019 в 00:43
поделиться

DI - это метод или шаблон, не связанный с какой-либо структурой. Вы можете подключить свои зависимости вручную. DI помогает вам с SR (единственная ответственность) и SoC (разделение ответственности). DI приводит к лучшему дизайну. С моей точки зрения и опыта минусов нет . Как и в случае с любым другим шаблоном, вы можете ошибиться или неправильно использовать его (но что в случае с DI довольно сложно).

Если вы вводите DI в качестве принципа для унаследованного приложения, используя фреймворк, то единственная самая большая ошибка, которую вы можете сделать, - это неправильно использовать его в качестве Service-Locater. DI + Framework сам по себе великолепен и просто улучшал ситуацию везде, где я его видел! С организационной точки зрения, есть общие проблемы с каждым новым процессом, техникой, шаблоном, ...:

  • Вы должны обучить свою команду
  • Вы должны изменить свое приложение (которое включает риски)

В целом Вы должны инвестировать время и деньги , да и минусов нет, правда!

5
ответ дан 23 November 2019 в 00:43
поделиться

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

1
ответ дан 23 November 2019 в 00:43
поделиться

Если вы используете DI без контейнера IOC, самым большим недостатком является то, что вы быстро видите, сколько зависимостей на самом деле имеет ваш код и насколько тесно все связано на самом деле. («Но я думал, что это хороший дизайн!») Естественная прогрессия заключается в том, чтобы перейти к контейнеру МОК, который может занять немного времени для изучения и реализации (не так плохо, как кривая обучения WPF, но это также не бесплатно).Последний недостаток заключается в том, что некоторые разработчики начнут писать честные до добра модульные тесты, и им потребуется время, чтобы понять это. Разработчики, которые раньше могли что-то провернуть за полдня, внезапно потратят два дня, пытаясь понять, как высмеять все свои зависимости.

Подобно ответу Марка Симанна, суть в том, что вы тратите время на то, чтобы стать лучшим разработчиком, а не взламывать биты кода вместе и выкладывать их за дверь / в производство. Что бы предпочел ваш бизнес? Только вы можете ответить на это.

8
ответ дан 23 November 2019 в 00:43
поделиться

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

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

(в качестве примечания, я нахожу всю эту тему довольно "религиозной", но ваш пробег зависит от уровня технического фанатизма в вашей команде разработчиков!)

.
9
ответ дан 23 November 2019 в 00:43
поделиться

Вот моя собственная первоначальная реакция: Практически те же недостатки у любого паттерна.

  • требуется время, чтобы научиться
  • , если его неправильно понять, это может принести больше вреда, чем пользы
  • , если довести до крайности, это может быть больше работы, чем оправдывает выгоду
75
ответ дан 23 November 2019 в 00:43
поделиться

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

45
ответ дан 23 November 2019 в 00:43
поделиться

Это скорее придирка. Но одним из недостатков внедрения зависимостей является то, что оно немного усложняет инструментам разработки рассуждение о коде и навигацию по нему.

В частности, если вы укажете нажатой кнопкой Control/Command-Click на вызов метода в коде, это привести вас к объявлению метода на интерфейсе, а не к конкретной реализации.

Это действительно скорее обратная сторона слабосвязанный код (код, разработанный интерфейсом) и применяется, даже если вы не используете внедрение зависимостей (т. Е.даже если вы просто используете фабрики). Но появление внедрения зависимостей — это то, что действительно поощряло слабо связанный код в массах, поэтому я подумал, что упомяну об этом.

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

На самом деле, я рискну предположить, что для каждого «недостатка», который вы можете найти для инъекции зависимости, вы найдете много преимуществ, которые намного перевешивают его.

11
ответ дан 23 November 2019 в 00:43
поделиться

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

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

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

Соответствующие ссылки

http://thedailywtf.com/Articles/The_Inner-Platform_Effect.aspx

http://www.joelonsoftware.com/articles/fog0000000018.html


Вероятно, самая простая форма зависимости инъекция (не смейтесь) - это параметр. Зависимый код зависит от данных, и эти данные вводятся посредством передачи параметра.

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

Давайте возьмем эту простую традиционную функцию - синтаксис C ++ здесь не важен, но я должен как-то его записать ...

void Say_Hello_World ()
{
  std::cout << "Hello World" << std::endl;
}

У меня есть зависимость, которую я хочу извлечь и вставить - текст «Hello World». Достаточно просто ...

void Say_Something (const char *p_text)
{
  std::cout << p_text << std::endl;
}

Почему это более негибкое, чем оригинал? Что ж, если я решу, что вывод должен быть в юникоде. Я, наверное, хочу переключиться с std :: cout на std :: wcout. Но это означает, что мои строки должны быть wchar_t, а не char. Либо необходимо изменить каждого вызывающего абонента, либо (что более разумно) старая реализация заменяется адаптером, который переводит строку и вызывает новую реализацию.

Это ремонтные работы, которые не понадобились бы, если бы мы сохранили оригинал.

И если это покажется тривиальным, взгляните на эту реальную функцию из Win32 API ...

http://msdn.microsoft.com/en-us/library/ms632680%28v=vs. 85% 29.aspx

Это 12 "зависимостей", с которыми нужно разобраться. Например, если разрешение экрана становится действительно огромным, возможно, нам понадобятся 64-битные значения координат - и другая версия CreateWindowEx. И да, уже существует более старая версия, которая, предположительно, негласно отображается на новую версию ...

http://msdn.microsoft.com/en-us/library/ms632679%28v=vs .85% 29.aspx

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

Объектно-ориентированное внедрение зависимостей в принципе ничем не отличается.Написание класса - это накладные расходы, как в тексте исходного кода, так и во время разработчика, и если этот класс написан для предоставления зависимостей в соответствии с некоторыми спецификациями зависимых объектов, тогда зависимый объект заблокирован для поддержки этого интерфейса, даже если есть необходимость чтобы заменить реализацию этого объекта.

Ничто из этого не следует понимать как утверждение, что внедрение зависимостей - это плохо - это далеко не так. Но любую хорошую технику можно применить чрезмерно и не в том месте. Так же, как не каждую строку нужно извлекать и превращать в параметр, не каждое низкоуровневое поведение нужно извлекать из высокоуровневых объектов и превращать во инъекционную зависимость.

181
ответ дан 23 November 2019 в 00:43
поделиться
Другие вопросы по тегам:

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