Яке найкраще визначення для ін'єкції залежності?


10

Кожен раз, коли хтось звертається до мене і просить мене визначити введення залежності в концептуальний спосіб і пояснити реальні плюси і мінуси використання DI в розробці програмного забезпечення. Зізнаюся, у мене є певні труднощі з поясненням понять DI. Щоразу мені потрібно розповідати їм історію про принцип єдиної відповідальності, склад над спадщиною тощо.

Хтось може допомогти мені пояснити найкращий спосіб описати DI для розробників?


2
Проблема тут полягає в тому, що існує стільки суперечливих визначень DI. Я приймаю позицію "чистого DI": якщо у мене є функція, яка спирається на її параметри, щоб надати всі стан, дані тощо, то ця функція використовує DI. З іншого боку, деякі запевнятимуть, що без рамки DI не існує ін'єкції залежності (хоча вони, звичайно, неправильні;)). Тож якщо ви не зможете визначити визначення, ви не можете почати пояснювати, що це таке ...
Девід Арно,

Отже, як я розумію, це не лише моя проблема.
Тіаго Сампайо



Все зводиться до цього: введення залежності є однією з методик, що застосовуються для досягнення інверсії залежності; все інше - це лише додаткові речі, побудовані на цьому. Зауважимо, що в цих двох термінах слово "залежність" має дещо різні значення. В ін'єкційній залежності вказується на компонент, від якого залежить код. Під інверсією залежності це означає саме (спрямоване) відношення - те, яке ми хочемо перевернути. Останнє - мета, тому основні плюси і мінуси однакові; плюс деякі додаткові занепокоєння, пов'язані з реальною реалізацією, як-от управління життєвим ресурсом об'єкта.
Філіп Мілованович

Відповіді:


22

Ін'єкція залежностей - жахлива назва (ІМО) 1 для досить прямого поняття. Ось приклад:

  1. У вас є метод (або клас з методами), який робить X (наприклад, отримання даних з бази даних)
  2. У рамках виконання X, зазначений метод створює та керує внутрішнім ресурсом (наприклад, a DbContext). Цей внутрішній ресурс називається залежністю
  3. Ви вилучаєте створення та керування ресурсом (тобто DbContext) з методу і покладаєте на нього відповідальність за надання користувачеві надання цього ресурсу (як параметр методу або при інстанціюванні класу)
  4. Тепер ви робите ін'єкцію залежності.


[1] : Я походжу з нижчого рівня, і мені знадобилося кілька місяців, щоб сісти і вивчити ін'єкцію залежності, оскільки назва означає, що це було б щось набагато складніше, як, наприклад, введення DLL . Той факт, що Visual Studio (а ми розробники взагалі) посилається на бібліотеки .NET (DLL або збірки ), від яких залежить проект. залежності, зовсім не допомагає. Існує навіть таке поняття, як ходунок залежностей (залежно.exe) .


[Редагувати] Я вважав, що деякий демо-код стане для деяких корисним, тож ось один (у C #).

Без введення залежності:

public class Repository : IDisposable
{
    protected DbContext Context { get; }

    public Repository()
    {
        Context = new DbContext("name=MyEntities");
    }

    public void Dispose()
    {
        Context.Dispose();
    }
}

Тоді ваш споживач зробить щось на кшталт:

using ( var repository = new Repository() )
{
    // work
}

Той самий клас, реалізований із схемою введення залежності, буде таким:

public class RepositoryWithDI
{
    protected DbContext Context { get; }

    public RepositoryWithDI(DbContext context)
    {
        Context = context;
    }
}

Тепер відповідальність, що викликає абонент, може створити DbContextі передати (помилка, ввести ) його своєму класу:

using ( var context = new DbContext("name=MyEntities") )
{
    var repository = new RepositoryWithDI(context);

    // work
}

3
Це слід додати до Вікіпедії.
Еворлор

2
Тепер відповідальність абонента за створення екземпляра DbContext - я думаю, це буде відповідальністю точки входу програми для встановлення всіх необхідних залежностей. Тому споживачеві потрібно лише ввести необхідний тип як залежність у власному договорі.
Фабіо

@Fabio Це могло бути. (У такому випадку відповідальність абонента повинна надавати ресурс, який був створений при запуску програми, до методу / класу, що викликається.) У моєму прикладі це не так, тому що це не є вимогою пояснювати поняття введення залежності .
Марк.2377,

5

Абстрактні поняття часто краще пояснити за допомогою реальної світової аналогії. Це моя аналогія:

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

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

Тож ви запроваджуєте нове правило: клієнти приносять свій хліб. Ви більше не забезпечуєте собі хліба. Це безпрограшна ситуація: клієнти отримують точний хліб, який вони хочуть, і вам більше не доведеться турбуватися про закупівлю хліба, який вам не цікавий. Зрештою, ви виробник сендвічів, а не пекар.

О, і щоб розмістити тих клієнтів, які не хочуть купувати власний хліб, ви відкриваєте другий сусідній магазин, в якому продаються ваші оригінальні м'які білі хліби. Клієнти, які не принесли власного хліба, просто повинні отримати за замовчуванням, а потім прийти до вас, щоб зробити з ним бутерброд.

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


1
Мені це подобається, але ОП шукає пояснення для розробників . Початкова абстракція хороша, але рано чи пізно вона потребує прикладу реального життя.
Роббі Ді

1
@RobbieDee: Коли мета шаблону зрозуміла, його реалізація також стає зрозумілою. Наприклад, відповідь Марка абсолютно правильна, але я відчуваю, що пояснення замикає складний характер прикладу ситуації, яку він використовує. Це зводиться до "Якщо ви хочете побудувати корабель, не барабаняйте людей збирати деревину і не привласнюйте їм завдання та роботу, а навчіть їх прагнути до нескінченної величини моря". . Замість того, щоб пояснювати, що робити, я вважаю за краще пояснювати, чому це робити.
Flater

2
Ви, звичайно, маєте рацію, але я не можу не допомогти, але думаю, що мені потрібен відчутний приклад - наприклад, немає справжньої файлової системи чи бази даних, щоб зірвати апетит, але, можливо, це лише мій погляд на розробника :)
Роббі Ді

1

Проста відповідь на це:

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

.Net Core - це досить хороший приклад, який ви можете надати, оскільки в цій структурі використовується велика кількість ін'єкцій залежностей. Як правило, послуги, які ви хочете зробити ін'єкційними, знаходяться на сайтіstartup.cs файлі.

Звичайно, студент повинен знати про такі поняття, як поліморфізм, інтерфейси та принципи проектування OOP.


0

Навколо багато пуху та банку, що є, по суті, простою концепцією.

Також дуже легко заграти " яким фреймворком я повинен користуватися ", коли це можна зробити просто в коді.

Це визначення, яке я особисто використовую:

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

Деякі приклади можуть бути, коли Y - це файлова система або з'єднання з базою даних.

Такі рамки, як moq, дозволяють визначати парні версії (прикидаються версії Y) за допомогою інтерфейсу тому можливо вводити в екземпляр Y, де Y, наприклад, з'єднання з базою даних.

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


0

Ми надаємо поведінку функції під час виконання методом вставки цієї функції у функцію через параметр.

Модель стратегії - відмінний приклад введення залежності.


0

Щоб зробити це правильно, спершу треба визначити залежності та ін'єкцію.

  • Залежність: будь-який ресурс, необхідний операції.
  • Ін'єкція: передача цього ресурсу в операцію, як правило, як аргумент методу.

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

Припустимо, ви замість цього використовуєте властивості та називаєте їх A і B. Якщо змінити імена на Op1 та Op2, ви порушите метод Add. Або ваш IDE оновив би всі назви для вас, справа в тому, що метод потребує оновлення, оскільки він має залежність від зовнішніх ресурсів.

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

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

Переваги: оскільки залежності від середовища методу були усунені, зміни методу не впливатимуть на навколишнє середовище та навпаки. => Додаток стає простішим у обслуговуванні (зміні).

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