Чи є ін'єкція залежності від руки кращою альтернативою складу та поліморфізму?


13

По-перше, я програміст початкового рівня; Насправді я закінчую ступінь AS на кінцевому проекті, що завершується літом. На моїй новій роботі, коли для мене не існує якогось проекту (вони чекають, щоб заповнити команду ще новими наймами), мені дали книги читати і вчитися, поки я чекаю - деякі підручники, інші не так багато (як Code Complete). Переглянувши ці книги, я звернувся до Інтернету, щоб дізнатися якнайбільше, і почав дізнаватися про SOLID та DI (ми розповідали дещо про принцип заміни Ліскова, але не про інші ідеї SOLID). Отож, як я дізнався, я сів робити, щоб краще вчитися, і почав писати якийсь код, щоб використовувати DI вручну (на комп'ютерах розвитку немає ніяких рамок DI).

Справа в тому, що я це роблю, я помічаю, що це відчуває себе знайомим ... і, схоже, це дуже схоже на роботу, яку я робив у минулому, використовуючи композицію абстрактних класів з використанням поліморфізму. Чи пропускаю тут більшу картину? Чи є щось про DI (принаймні від руки), що виходить за рамки цього? Я розумію можливість наявності конфігурацій не в коді деяких фреймворків DI, які мають великі переваги, що стосується зміни речей без необхідності перекомпіляції, але, роблячи це вручну, я не впевнений, чи це щось інше, ніж зазначено вище ... Деяке розуміння цього було б дуже корисно!

Відповіді:


21

Фундаментальна ідея в DI полягає просто у просуванні залежностей в об'єкти, а не в тому, щоб дозволяти їм тягнути залежності ззовні. Це раніше називалося "інверсією управління". Це дозволяє контролювати залежності набагато краще, і - останнє, але не менш важливе - писати код, який легко перевірити.

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

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

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


1
Вприскування введення (DI) - це форма інверсії управління (IoC).
Меттью Флінн

@MatthewFlynn, справді. Довідково: martinfowler.com/articles/injection.html
Péter Török

1
Це моя довідка. Він розповідає про нові "легкі контейнери", які здійснюють інверсію управління, що було вже звичайним явищем, оскільки слухачі подій в інтерфейсі були формою IoC. Він дублює об'єкт, який зв'язує Spring і інші контейнери IoC, як впорскування залежностей, щоб відрізняти його від іншої форми інверсії управління.
Меттью Флінн

На жаль, я пропустив "справді". Я думав, ти мені суперечить ... Вибач.
Меттью Флінн

Ваш останній абзац змушує мене почуватися трохи краще; Весь час, коли я працював над своїм маленьким навчальним проектом, я постійно говорив собі: "Це відчувається як поліморфізм ..". На жаль, .Net та c # на моїй роботі жахливо застаріли, але, дивлячись на це, чи Unity є вбудованою рамкою c #, про яку ви говорите?
Дрейк Кларріс

22

Найкраща стаття, яку я коли-небудь читав на цю тему, - це Джеймс Шор . Я роблю " DI від руки " протягом століть, як частина абстракції та поліморфізму. Тож після того, як я потрапив у професійний світ і почув, що цей термін кидається, у мене був великий розрив між тим, що я вважав, що це слово повинно означати, і що воно насправді означає:

"Ін'єкційна залежність" - це термін, що становить 25 доларів, для концепції 5 центів.

Це з посади Шора, яка все зрозуміла для мене. Наприклад:

Дано

class Engine {public abstract void start()}
class V8 extends Engine {...}
class V6 extends Engine {...}

Замість написання:

class Car
{
    private Engine engine;
    public Car()
    {
        this.engine = new V6();
    }

    public void start()
    {
        this.engine.start();
    }
}

Ви пишете щось подібне:

class Car
{
    private Engine engine;
    public Car(Engine a)
    {
        this.engine = a;
    }

    public void start()
    {
        this.engine.start();
    }
}

...

Car F = new Car(new V8());

І це не дозволяє Carекземпляру обробляти конкретні Engineдеталі. Автомобіль просто потребує двигуна, неважливо, який з них, поки він реалізує основні функції двигуна. Тобто ваш Carклас не прив’язаний до конкретної залежності від реалізації; його "вводять" в інше місце, можливо, під час виконання.

У цьому конкретному прикладі автомобіля використовується підтип DI під назвою "Інжекція конструктора", що просто означає, що залежність передана як аргумент конструктора. Ви також можете використовувати setEngine(Engine a)метод для "ін'єкції сетера" тощо, але ці підтипи мені здаються педантичними.

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

Це воно.


0

Я не фахівець, тому що я тільки почав використовувати DI в останні пару років, але кілька корисних тем / функцій DI контейнерів, які я помітив, є (які я не вважаю продуктами композиції / поліморфізму (але я можу поправити це):

  • центральний вузол створення об'єктів
  • надайте одиночні кнопки на основі потоку
  • аспектно-орієнтовані методи, такі як перехоплення

0

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

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