Як ін'єкційна залежність збільшує зв'язок?


32

На сторінці Вікіпедії про введення залежності, в розділі про недоліки йдеться про це:

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

із посиланням на статтю проти введення залежності .

Ін'єкційна залежність змушує клас використовувати інтерфейс замість конкретної реалізації. Це повинно призвести до зменшення зв'язку , ні?

Що я пропускаю? Як збільшується зв'язок ін'єкцій залежностей між класами?


2
Я не впевнений, хто написав цей список недоліків, але я б взяв його із зерном солі. Наприклад, я бачив, як DI зменшує розмір кодової бази на 2/3, усуваючи тону зайвого коду настройки.
Роб

@RobY Я в основному використовував фабрику для введення залежності, і мій досвід полягає в тому, що вона збільшує розмір коду, але спрощує тестування.
BЈоviћ

Спробуйте використовувати таку альтернативу, як Реєстр або Передача контексту;) Або інший код, який просто створює об'єкти, а потім витягує їх властивості з конфігурації. В основному я говорю про різницю між тепер і 15 роками тому.
Роб

Пов'язане: stackoverflow.com/a/9503612/264697 . Відповідь Марка Семана пояснює, як зменшується загальне з’єднання за допомогою введення залежностей.
Стівен

Відповіді:


42

Отже, чого я пропускаю?

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

Дуже часто це гарна торгівля. Клас не повинен знати подробиці про його залежності за межами інтерфейсу, і за програму повинно лежати зв'язок певних бітів коду.


Правильно, зв’язок зменшується в один бік, а збільшується іншим.
Пол Дрейпер

Але споживач не створює цього; це швидше справа.
Кейсі

@emodendroket - Так? Інверсія управління дозволяє споживачеві не створювати його. Ін'єкційна залежність є ортогональною для цього.
Теластин

Ну, ви робите відмінність, з якою я не знайомий, оскільки зазвичай терміни використовуються взаємозамінно.
Кейсі

22

Припустимо, у вас є підсистема, Sяка залежить від підключення до бази даних D. Без ін'єкцій залежностей існує відносно тісний зв'язок між Sі D, оскільки Sпотрібно знати як користуватися, так Dі як його створити. Решта системи, однак, можуть бути незрозуміло про цю залежність між Sта D.

Із введенням залежності залежність між Sі Dстає слабшою, тому що ви усуваєте Sзнання, як створити D. Sпросто потрібно знати, як ним користуватися. Збільшення загальної зв'язку пов'язане з тим, що зараз потрібно знати про інші частини системи Dта, як їх створити. Ступінь цього збільшення зв’язку залежить від того, як залежність від Dпотрапляння вводиться S:

  • За допомогою конструкторської інжекції творець Sпотребує залежності Dі, можливо, знань, як її створити.
  • За допомогою ін'єкцій на рівні методу кожен абонент методу, за Sдопомогою якого Dотримують ін'єкцію, потребує залежності Dта, можливо, знань, як її створити.

В будь-якому випадку кількість занять, що залежить від Dзбільшення, та знання, як створити Dнерухомість, повинні бути десь у системі. Це створює загальне збільшення зчеплення.


Гаразд, це має сенс для введення конструктора та сетера. Але якщо використовується заводський або стратегічний зразок, створення переміщується туди, а клас використовує лише введений об'єкт. Або це не введення залежності (лише інверсія контролю)?
BЈоviћ

Навіть при фабричному впорскуванні творець Sповинен постачати фабрику D, а це означає, що він повинен знати, що Sвикористовує D(або хоча б якийсь інтерфейс).
Ідан Ар'є

7

Я категорично не згоден, що це посилює зв'язок.

Без введення залежності ви маєте тісний зв'язок між підсистемою та конкретною реалізацією залежності.

За допомогою ін'єкції залежності ви від'єднали підсистему від впровадження залежності.

Аргументація того, що вона збільшує зв’язок між споживачем та цією підсистемою, ДУЖЕ сумнівна, оскільки це означає, що споживач зараз жорстко пов'язаний із залежністю, яка вимагається від підсистеми. Все це означає, що ви пишете щільно зв'язаний код, який з'єднує вашого споживача із залежністю. В ідеалі ВСЕ ваш код відокремлений.

Інжекція конструктора:

Дозвіл залежності обробляється контейнером для нагнітання залежності або фабрикою. Споживач може отримати конкретну реалізацію підсистеми з контейнера для нагнітання залежностей або заводу.

Споживачеві не потрібно знати, як виглядає конструктор підсистеми. Немає зв'язку з залежністю від підсистеми.

Спосіб ін'єкції:

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

TL; DR Найгіршим випадком введення залежності в підсистемі є те, що з'єднання переходить на споживчий код. НЕ ВІДКЛЮЧИТЬ ВІДПОВІДЕННЯ В СКЛАДУВАННІ.

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

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