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


14

Минулого року я створив нову систему, використовуючи Dependency Injection та контейнер IOC. Це мене багато чого навчило щодо DI!

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

Мета звичайно - наблизити одиничні тести до бізнес-логіки!
Бізнес-логіка, що переплітається з тестовими викликами бази даних.

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

Запитання: Чи нормально використовувати DI Poor Man, щоб запровадити перевірку на застаріле додаток і розпочати прокатку кулі?

Окрім того, чи використання ІД бідного чоловіка як низового підходу до справжнього введення залежностей є цінним способом навчання необхідності та переваг цього принципу?

Чи можете ви рефакторувати метод, який має залежність від виклику бази даних та абстрактний, що викликає інтерфейс? Просто наявність цієї абстракції зробить те, що цей метод перевіряється, оскільки реалізація макету може бути передана через перевантаження конструктора.

Коли дороги наберуть прихильників, проект може бути оновлений для впровадження контейнера МОК, і там будуть конструктори, які беруть участь у абстракціях.



2
Просто записка. I consider it a challenge to decouple code and introduce an IOC container into a legacy applicationзвичайно, це так. Його називають технічним боргом. Ось чому перед будь-яким капітальним оновленням бажано малі та постійні рефактори. Зменшити основні вади дизайну і перехід до IoC було б менш складно.
Лаїв

Відповіді:


25

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

У статті вони констатують це

public class SearchController : Controller {

    IDinnerRepository dinnerRepository;

    public SearchController() : this(new DinnerRepository()) { }

    public SearchController(IDinnerRepository repository) {
        dinnerRepository = repository;
    }
}

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

Правильний засіб, звичайно, полягає не в тому, як пропонує Los Techies, додавати контейнер DI, а скоріше видалити порушник.

public class SearchController : Controller 
{
    IDinnerRepository dinnerRepository;

    public SearchController(IDinnerRepository repository) {
        dinnerRepository = repository;
    }
}

Тепер у класу, що залишився, свої залежності правильно інвертовані. Тепер ти можеш вводити ці залежності, як би то не хотілося.


Дякуємо за ваші думки! Я розумію "конструктора, що ображає", і як нам цього уникати. Я розумію, що наявність цієї залежності нічого не знімає, але це дає можливість проводити одиничні тести. Я з самого початку запроваджую ІП та якнайшвидше отримую одиничні тести на місці. Я намагаюся уникнути ускладнень контейнера або фабрики DI / IOC вже на початку гри. Як згадувалося, пізніше, коли зростає підтримка DI, ми можемо впровадити контейнер і видалити "конструкторів, що ображають".
Airn5475

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

2
@ Airn5475 бути обережним, щоб не більше абстрагування теж. Ці тести повинні перевірити змістовну поведінку - тестування того, що XServiceперехід параметра передається параметру XRepositoryі повертає те, що він отримує, не є надто корисним для кого-небудь, і не дає вам багато чого на шляху розширення. Напишіть свої тести на одиницю, щоб перевірити змістовну поведінку та переконайтесь, що ваші компоненти не такі вузькі, що ви фактично перекладаєте всю свою логіку на корінь композиції.
Ant Ant

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

@Rob: Це не так. Це просто зручний спосіб конструктору за замовчуванням відстояти дійсний об'єкт.
Роберт Харві

16

Ви робите помилкове припущення щодо того, що таке "DI DI бідолаха".

Створення класу, який має конструктор "ярликів", який все ще створює з'єднання , не є бідним чоловіком.

Якщо не використовувати контейнер, а створювати всі ін'єкції та карти вручну, це DI DI бідолахи.

Термін "бідний чоловік DI" звучить як погана справа. З цієї причини термін "чистий ДІ" заохочується в наші дні, оскільки він звучить більш позитивно і фактично більш точно описує процес.

Мало того, що користуватися бідними людьми / чистими ДІ не лише для введення ДІ в існуючу програму, але й правильним способом використання ДІ для багатьох нових програм. І як ви кажете, кожен повинен використовувати чистий DI принаймні в одному проекті, щоб дійсно зрозуміти, як працює DI, перш ніж передати відповідальність за "магію" контейнера IoC.


8
«Бідний чоловік» або «Чистий» DI, що б ви не хотіли, також пом'якшує багато проблем з контейнерами IoC. Я використовував контейнери IoC для всього, але чим більше часу проходить, тим більше я волію уникати їх.
Мураха П

7
@AntP, я з тобою: я на сьогодні на 100% чистої DI і активно уникаю контейнерів. Але я (ми) в меншості за цією оцінкою, наскільки я можу сказати.
Девід Арно

2
Здається так сумно - коли я віддаляюся від "чарівного" табору контейнерів IoC, знущаюся над бібліотеками тощо, і виявляю, що я охоплюю OOP, інкапсуляцію, ручний тест-подвійник та перевірку стану, здається, що тенденція до магії залишається на вгору +1 у будь-якому випадку
Ant Ant

3
@AntP & David: Добре чути, що я не один в таборі "Чистого DI". DI-контейнери були створені для усунення недоліків у мовах. Вони додають цінності в цьому сенсі. Але на мій погляд, справжня відповідь - це виправляти мови (або переходити на інші мови), а не будувати грубі над ними.
JimmyJames

1

Зміна парагідів у застарілих командах / базах кодів надзвичайно ризикована:

Щоразу, коли ви пропонуєте "вдосконалити" застарілий код і в команді є "застарілі" програмісти, ви просто говорите всім, що "вони зробили це неправильно", і ви стаєте Ворогом на весь час / час роботи з компанією.

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

Навіть у найбільш обмежених випадках, таких як просто так, що їх можна використовувати в тестових випадках, вони просто зроблять ті тестові випадки "нестандартним" та "іноземним" кодом, які в кращому випадку просто помітяться, @Ignoreколи вони порушуються або ще гірше будуть скаржитися постійно застарілі програмісти з найбільшою мірою керування та керуються переписом "правильно" при всьому цьому "витрачений час на одиничні тести", звинувачений виключно на вас.

Якщо впровадити рамку DI, або навіть концепцію "Чистого DI", у додаток для бізнесу, набагато менше величезної спадкової бази коду без відключення управління, команди та особливо спонсорства провідного розробника буде просто смертним колом для вас соціально та політично в команді / компанії. Робити подібні речі є надзвичайно ризикованим та може бути найгіршим політичним самогубством.

Ін'єкційна залежність - це рішення, яке шукає проблему.

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

Ін'єкційна залежність корисна лише в невеликих дозах для дуже вузького кола речей:

  • Речі, які сильно змінюються або мають багато альтернативних реалізацій, статично пов'язаних.

    • Драйвери JDBC - прекрасний приклад.
    • HTTP-клієнти, які можуть відрізнятися від платформи до платформи.
    • Системи лісозаготівлі залежать від платформи.
  • Системи плагінів, які мають настроювані плагіни, які можна визначити у коді конфігурації у вашій рамці та виявляти автоматично при запуску та динамічно завантажувати / перезавантажувати під час роботи програми.


10
Додаток-вбивця для DI - тестування одиниць. Як ви вже зазначали, більшості програмного забезпечення не потрібно багато DI самостійно. Але тести також є клієнтом цього коду, тому ми повинні розробити для перевірки. Зокрема, це означає розміщення швів у нашій конструкції, де тести можуть спостерігати поведінку. Для цього не потрібні химерні рамки DI, але це вимагає, щоб відповідні залежності стали явними та замінюваними.
amon

4
Якби ми, чорти, знали, якщо заздалегідь, що може змінитися, це була б половина битви. Я був на тривалих розробках, де багато нібито "виправлених" речей змінилося. Майбутнє доведення тут і там із використанням DI - це не погано. Використовуючи його скрізь, присмакує програмування культового культу.
Роббі Ді

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

4
@JarrodRoberson, це дійсно токсичне середовище. Однією з ключових ознак хорошого розробника є те, що вони озираються на код, про який писали в минулому, і думають, "так, я справді це написав? Це так неправильно!" Це тому, що вони виросли як розробник і дізналися нове. Хтось, хто дивиться на код, який він написав п'ять років тому і не бачить нічого поганого в цьому, нічого не навчився за ці п’ять років. Тож якщо казати людям, що вони робили неправильно, то в минулому роблять тебе ворогом, тоді швидко біжи з цієї компанії, бо вони - команда в глухий кут, яка стримує тебе і зводить тебе до їхнього бідного рівня.
Давид Арно

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