Які переваги використання залежної ін'єкції та контейнерів IoC?


62

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

Які найважливіші переваги використання цієї техніки та цих інструментів?


1
Дивіться тут і тут, щоб отримати відповіді на StackOverflow, і тут - хороша повна стаття про IoC. І якщо ви хочете аргументи проти цього для порівняння, головуйте тут .
Джессі К. Слікер

14
не бути прикладом ... але якщо ви не знаєте, чому слід вживати DI / IOC, то чому ви про це говорите? програти ставку? ;-)
Стівен А. Лоу

2
@Steven, його начальник, можливо, попросив би це зробити.

1
@Steven, я вже весь час використовую DI (дехто би казав занадто часто :-D), я просто шукаю якісь хороші аргументи, щоб змусити інших людей використовувати його.
Енді Лоурі

2
Люди рідко говорять про надмірне використання DI. Якщо ви затягуєте кожне окреме рішення, ви створите OO еквівалент коду спагетті. Наявність узгодженої конструкції вимагає, щоб у якийсь момент було прийнято реальне рішення.
Macneil

Відповіді:


47

Найголовніше для мене - це спрощення слідування принципу єдиної відповідальності .

DI / IoC спрощує мене для управління залежностями між об'єктами. У свою чергу, це полегшує мені виведення когерентної функціональності на власний контракт (інтерфейс). Як результат, мій код був набагато більш модульованим з часу, коли я дізнався про DI / IoC.

Іншим результатом цього є те, що я набагато легше бачу свій шлях до дизайну, який підтримує принцип відкритого типу . Це одна з найнадійніших методик натхнення (поступається лише автоматизованому тестуванню). Я сумніваюся, що міг би достатньо підтримувати чесноти принципу відкритого закриття.

DI / IoC - одна з небагатьох речей у моїй програмістській кар’єрі, яка була "зміною ігор". Існує величезна різниця в якості між кодом, який я писав до і після вивчення DI / IoC. Дозвольте підкреслити, що ще кілька. ВЕЛИЧЕЗНЕ поліпшення якості коду.


3
Чому принцип відкритого закриття настільки великий? Якщо ви вважаєте, що вам потрібно змінити API / інтерфейс, чому б вам не зробити це?
Арне Евертссон

@ArneEvertsson Слухайте, як Роберт К. Мартін розповідає про відкритий принцип. Ви будете освічені.
Альтернатекс

@AmeEvertsson Open-Closed дуже важливий, коли ваш код постачається (наприклад, як комерційний продукт) як модуль для використання іншими, оскільки він робить ваш код більш пристосованим у використанні, не повертаючись до вас, щоб змінити його
Джеймс Елліс-Джонс

2
DI не спрощує управління залежностями, а значно складнішими, ніж просто створення залежності до конкретного класу. Однак це забезпечує гнучкість, але якщо ви не робите «належне» тестування, ця гнучкість часто не знадобиться. Обидві ключові переваги, що описуються, стосуються також Локатора послуг, що є простішим.
Джеймс Елліс-Джонс

1
Я відповів на цю відповідь років тому; ось деякі зауваження: 1) На практиці широко використання DI має тенденцію працювати проти SRP, оскільки програмісти просто продовжують додавати методи до своїх ін'єкційних «контролерів», «служб», «DAO» тощо, замість того, щоб створювати нові класи для нова функціональність. Це те, що ви зазвичай бачите в Java та C # .NET проектах, які використовують деяку структуру DI або контейнер. 2) Принцип відкритого закриття був лише оманою Бертрана Мейєра щодо корисності спадкового класу (реалізації); якщо ви будете шукати в його книзі на 1400+ сторінках, ви побачите, що я маю на увазі - це справді нерозумно.
Rogério

9

На прикладах, які справді відкривали мені очі, було бачити, як це дало змогу легко контролювати об'єкти, створені таким чином. До цього у мене виникли проблеми при спробі виділити об'єкти для одиничного тесту. Я часто писав би тести для взаємодії зі значно більшою системою. Це було дійсно важко, оскільки система в цілому була набагато менш передбачуваною та набагато більш схильною до зміни окремих компонентів.


3

Перевагами ін'єкцій залежностей є:

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

1

Я думаю, що фактичні вигоди є більш політичними, ніж технічними. DI - це просто альтернатива шаблону пошуку локальних служб , не більше того. Саме по собі це не полегшує дотримання таких принципів, як SRP або OCP, або декупаж шарів. Інших респондентів тут плутають різні поняття та методи, ІМО.

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

Тепер я знаю, що багато хто не погодиться з цією думкою. Я буду радий обговорити конкретні приклади.


2
Але безпосередньо виклик локатора послуг або встановлення конкретної залежності, як правило, важко залучає ваші залежності, або, принаймні, звідки беруться ваші залежності. Це, здається, переможе мета Д.І. Ви все ще повинні ввести сервіс-локатор.
Метт H

Використання Locator-сервісу нічого не вимагає, крім використання класу Service Locator, який зазвичай не "вводиться". Моменталізація конкретного класу реалізації є прекрасним у випадках, коли вам не потрібна зовнішня конфігурація (наприклад, програмісти зазвичай інстанціюють безпосередньо клас ArrayList замість використання DI - що було б надмірним).
Rogério

1
Ви згадуєте "низьке з'єднання", а пізніше ви говорите, що локатор сервісу не впливає на рівень з'єднання програми. Те ж саме для екземпляра співпрацівників безпосередньо на коді, я не можу придумати більш досконалий спосіб з’єднати об'єкт із його залежностями. Як ви перевіряєте обидва сценарії? Я, з повагою, повністю не згоден з усім, що ви сказали.
Клінт Іствуд

@Jonathan Ви повинні прочитати статтю, яка тоді представила DI ; автор підсумовує, кажучи, що DI та ServiceLocator є "приблизно еквівалентними", з "незначним краєм" для останнього. Важливе з'єднання полягає між компонентом та іншими компонентами, які можуть мати кілька реалізацій; a ServiceLocator - це інфраструктурна послуга, яка має лише одну реалізацію, тож це нормально. Зауважте, що я писав "миттєві залежності, коли це можливо "; Звичайно, якщо вам потрібно відокремити конфігурацію від використання, ви б цього не робили.
Rogério

1
@Jonathan Що стосується тестування одиниць, це міф про те, що примірник співпрацівників перешкоджає створенню таких тестів; є добре відомі глузуючі інструменти, які виконують завдання ізолювати клас від реалізацій залежностей, вводяться вони чи ні.
Rogério

-1

Коли DI використовується для викриття внутрішніх предметів з метою тестування, зразок зловживається.


1
що ви маєте на увазі під "внутрішніми об'єктами" ?. в реальному OOP (зауважте, що, ймовірно, лише 1% програмістів знають, що це насправді), є об'єкти, що спілкуються один з одним за допомогою надсилання повідомлень (тобто методів викликів). У цьому сенсі кожен об'єкт повинен мати єдину відповідальність, немає "важливіших" об'єктів, ніж інші ... кожен має єдиний обов'язок, і вони співпрацюють для досягнення функціональності, що надається всією системою. Важливо тестувати кожен об'єкт ізольовано, щоб ми знали, що ми не пропустили жодного випадку, саме в цьому DI справді добре.
Клінт Іствуд

Я забув.
томас-петер
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.