Чи має використання DI / IoC видаляти всі виникнення "нового" ключового слова?


21

Чи повинні використання введення залежностей та інверсія контейнера управління видалити всі випадки newключового слова з вашого коду?

Іншими словами, чи повинен кожен об'єкт / залежність, незалежно від того, наскільки простий чи короткочасний, "бути зареєстрований" у вашому контейнері IoC та введений у метод / клас, який потребує їх використання?

Якщо ні, то де ви намалюєте лінію, між якою залежність / об’єкти реєструються в контейнері IoC, порівняно з тим, що створюється "in-line" як конкретна довідка за допомогою newключового слова?


У мене була така ж думка, відповідно до "нове" слово з 4 літер? "
Майкл Пасха

Відповіді:


27

Уникайте догм. Роби те, що відчуваєш правильно.

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

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


15
+1 за "уникнути догми". Занадто легко потрапити в пастку просто слідувати рухам, не розуміючи, що відбувається або де його слід правильно використовувати.
Уейн Моліна

@Alex Мені це подобається. Дуже прагматичний підхід. Як ні дивно, я збирався додати якийсь код у своєму запитанні, показуючи new'ed залежність у власному коді, який підштовхнув моє запитання. Це був простий клас без функціональності або "поведінки" сам по собі, лише прості властивості.
CraigTP

11

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

Майте на увазі, що застосування DI не повинно покладатися на контейнер DI . У випадку, коли ІД бідного чоловіка використовується, newключові слова не видаляються - вони просто переміщуються до кореня композиції .

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

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


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

3
Переповнення стека містить 2000+ питань у тезі залежності-введення, і багато з них подібні до цього. Програмісти мають 23 запитання в одному тезі. Виходячи з цих цифр, де розробник має найбільший шанс отримати відповідь на таке питання?
Марк Семанн

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

3

"new" - це не заборонене ключове слово. Мої особисті правила:

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

Усі боби або моделі повинні бути створені за допомогою «нового» ключового слова або з фабрикою, зареєстрованою МОК, коли мені потрібні деякі властивості за замовчуванням. Існує також окремий випадок класів корисних програм, що містять лише статичні методи (наприклад, математична послуга служби). Якщо вони повністю автономні і не потребують підключення до бази даних чи іншої послуги, зареєстрованої МОК, я залишаю їх поза МОК, і вони повинні стати статично викликані. Однак якщо одному такому класу потрібно використовувати існуючу послугу, зареєстровану МОК, я змінюю його на однотонний клас і реєструю його в МОК.


2

Я просто хотів би додати до існуючих відповідей, які виховував вулер, newцілком чудово створювати об'єкти, які є об'єктами чистого значення (тобто мають лише властивості / геттери / сеттери). Докладніше див. Блог тестування Google .


+1 для посилання. Пункт 9 у цій публікації щоденника відповідає на запитання та надає прагматичну відмінність між тим, що слід, а що не слід new- ed
CraigTP

1

Ясно залежить від мови, якою ви користуєтесь. Якщо ваша мова змушує вас використовувати об’єкти для представлення як фактичного об'єкта, так і записів (об'єкт значення, структури), то відповідь, швидше за все, "ні".

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

Отже, підводячи підсумок: Тільки такі класи повинні безпосередньо створювати об'єкти, на кого покладено обов'язок вибирати, які класи інстанціювати.
Ці критерії можуть вам бути корисними: http://en.wikipedia.org/wiki/GRASP_(object-oriented_design)#Creator


1

Одне слово: Ні.

Більше слів: Введення залежності в це саме те. Це засіб, за допомогою якого ви вводите ресурси, від яких залежить інший об'єкт, але не повинні знати складні деталі з іншого джерела. Використання DI не означає, що НІЧОГО у вашій програмі не повинно знати, як створити будь-який інший об’єкт; Насправді я вважаю, що нетривіальній програмі дуже неможливо повністю уникати "нового" ключового слова (або на основі рефлексії). Однак, DI означає, що об'єкти, які не повинні знати, як створювати складні об'єкти, які потребують безлічі залежностей, які тісно з'єднають цей об'єкт з іншим, не повинні мати усі ці знання про тісне з'єднання.

Я вивчив би дві основні теорії дизайну програмного забезпечення для O / O, GRASP та SOLID. GRASP скаже вам вивчити призначення об'єкта і запитаєте себе: "Чи повинен цей об'єкт нести відповідальність за створення нових об'єктів такого типу? Чи це частина" опису завдання "цього об'єкта?" SOLID йде на крок далі: "S" означає "Принцип єдиної відповідальності", який однозначно стверджує, що об'єкт повинен мати одну роботу, і він повинен бути єдиним об'єктом в програмі, який виконує цю конкретну роботу.

Отже, GRASP, як правило, спонукає вас переглянути ваші існуючі класи, для яких створюються ці нові об’єкти, і знайти той, для якого завдання створення цього об'єкта відповідає тому, що об’єкт вже робить, зберігаючи бажаний рівень "згуртованості". SOLID скаже вам, що єдність є ключовою; завдання по створенню цих об'єктів має бути надано якійсь фабриці, яку слід вводити у ваш клас. Я думаю, ви побачите, оскільки складність вашої програми продовжує зростати, що дотримання будь-якої з цих методологій із готовністю до рефакторації призведе до дуже подібних архітектур.

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