Каковы преимущества использования Dependency Injection и IoC Containers?

62

Я планирую выступить с докладом о внедрении зависимостей и контейнерах IoC, и я ищу хорошие аргументы для его использования.

Каковы наиболее важные преимущества использования этой техники и этих инструментов?

Энди Лоури
источник
1
Смотрите здесь и здесь ответы на StackOverflow и здесь, чтобы получить хорошую полную статью по IoC. И если вы хотите аргументы против этого для сравнения, отправляйтесь сюда на SO.
Джесси С. Slicer
14
не для того, чтобы быть прикладом ... но если вы не знаете, почему следует использовать DI / IOC, почему вы об этом говорите? потерять ставку? ;-)
Стивен А. Лоу
2
@ Стивен, его босс мог попросить его сделать это.
1
@ Стивен, я уже использую DI все время (некоторые скажут слишком часто :-D), я просто ищу хорошие аргументы, чтобы другие люди могли его использовать.
Энди Лоури
2
Люди редко говорят о чрезмерном использовании DI. Если вы откладываете каждое отдельное решение, вы создадите ОО-эквивалент кода спагетти. Наличие согласованного дизайна требует, чтобы в какой-то момент было принято реальное решение.
Макнейл

Ответы:

47

Самое главное, для меня, это облегчить следование принципу единой ответственности .

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

Другим результатом этого является то, что мне намного легче увидеть мой путь к дизайну, который поддерживает принцип Open-Closed . Это один из самых вдохновляющих методов (второй после автоматизированного тестирования). Я сомневаюсь, что смог бы поддержать достоинства принципа Открыто-Закрыто.

DI / IoC - это одна из немногих вещей в моей карьере программиста, которая была «изменит правила игры». Существует огромный разрыв по качеству между кодом, который я написал до и после изучения DI / IoC. Позвольте мне подчеркнуть это еще немного. ОГРОМНОЕ улучшение качества кода.

Квентин-starin
источник
3
Почему принцип Открыто-Закрыто так важен? Если вы чувствуете, что вам нужно изменить API / интерфейс, почему бы не сделать это?
Арне Эвертссон
@ArneEvertsson Послушайте, как Роберт С. Мартин рассказывает о принципах Открыто-Закрыто. Вы будете просветлены.
Alternatex
@AmeEvertsson Open-Closed очень важен, когда ваш код предоставляется (например, в качестве коммерческого продукта) в качестве модуля для использования другими, так как он делает ваш код более адаптируемым в использовании, не обращаясь к вам за его изменением
Джеймс Эллис-Джонс
2
DI не упрощает управление зависимостями, поскольку это значительно сложнее, чем просто создание зависимости от конкретного класса. Это, однако, обеспечивает гибкость, но если вы не проводите «правильное» модульное тестирование, эта гибкость часто не требуется. Оба описанных ключевых преимущества также применимы к Service Locator, который проще.
Джеймс Эллис-Джонс
1
Я отклонил этот ответ несколько лет назад; Вот некоторые замечания: 1) На практике широкое использование DI имеет тенденцию работать против SRP, потому что программисты просто продолжают добавлять методы к своим внедренным «контроллерам», «сервисам», «DAO» и т. д. вместо создания новых классов для новый функционал. Это то, что обычно происходит в проектах Java и C # .NET, в которых используется некоторая DI-инфраструктура или контейнер. 2) Открыто-закрытый принцип был просто заблуждением Бертрана Мейера о полезности наследования класса (реализации); если вы найдете его в его книге на 1400 страниц, вы поймете, что я имею в виду - это действительно глупо.
Рожерио
9

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

Уинстон Эверт
источник
3

Преимущества инъекций зависимости:

  1. Ваш код чистый и более читаемый.
  2. Коды слабо связаны.
  3. Более пригодный для повторного использования, поскольку реализации сконфигурированы в файле XML, его можно использовать в другом контексте.
  4. Код может быть легко тестируемым с помощью другой фиктивной реализации.
Solaimani SA
источник
1

Я думаю, что фактические выгоды являются скорее политическими, чем техническими. DI - это просто альтернатива шаблону Service Locator , не более того. Само по себе это не облегчает соблюдение таких принципов, как SRP или OCP, или разделение слоев. Другие респонденты здесь путают разные концепции и методы, IMO.

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

Теперь я знаю, что многие не согласятся с этим мнением. Буду рад обсудить конкретные примеры.

Рожерио
источник
2
Но прямой вызов локатора службы или создание конкретной зависимости обычно жестко связывает ваши зависимости или, по крайней мере, откуда берутся ваши зависимости. Это, кажется, победить цель DI. Вы все еще должны ввести сервисный локатор тоже.
Мэтт H
Использование сервисного локатора не связывает ничего жестко, кроме использования самого класса сервисного локатора, который обычно не «внедряется». Создание конкретного класса реализации прекрасно в тех случаях, когда вам не нужна внешняя конфигурация (например, программисты обычно создают экземпляр класса ArrayList вместо использования DI - что было бы излишним).
Rogério
1
Вы упоминаете «слабую связь», а позже говорите, что указатель службы не влияет на уровень связи приложения. То же самое для создания экземпляров коллабораторов непосредственно в коде, я не могу придумать более совершенный способ связать объект с его зависимостями. Как тестировать оба сценария? Я, с уважением, полностью не согласен со всем, что вы сказали.
Клинт Иствуд
@Jonathan Вы должны прочитать статью о введении DI ; В заключение автор говорит, что DI и ServiceLocator являются «примерно эквивалентными», с «небольшим преимуществом» для последних. Связывание, которое имеет значение, находится между компонентом и другими компонентами, которые могут иметь несколько реализаций; ServiceLocator - это инфраструктурный сервис только с одной реализацией, так что все в порядке. Обратите внимание, что я написал «создание экземпляров зависимостей, когда это применимо »; конечно, если вам нужно отделить конфигурацию от использования, вы бы этого не сделали.
Рожерио
1
@Jonathan Что касается модульного тестирования, то существует миф о том, что создание коллабораторов препятствует созданию таких тестов; Существуют хорошо известные инструменты для проверки подлинности, которые выполняют функцию изоляции класса от реализаций зависимостей, независимо от того, внедрены они или нет.
Рожерио
-1

Когда DI используется, чтобы выставлять внутренние объекты с целью тестирования, шаблон использовался неправильно.

томас-питер
источник
1
что вы подразумеваете под "внутренними объектами"? в реальном ООП (обратите внимание, что, вероятно, только 1% программистов знают, что это на самом деле означает), существуют объекты, обменивающиеся друг с другом посредством отправки сообщений (то есть вызовов методов). В этом смысле каждый объект должен нести единоличную ответственность, нет более «важных» объектов, чем другие ... каждый имеет одну обязанность, и они сотрудничают для достижения функциональности, предоставляемой всей системой. Важно тестировать каждый объект изолированно, чтобы мы знали, что не пропустили ни одного случая, в этом DI действительно хорош.
Клинт Иствуд
Я забыл.
Томас-Питер