Введення залежності: У який момент мені дозволено створити новий об’єкт?


13

Я переробляю PHP- додаток, і я намагаюся зробити якомога більше ін'єкцій залежності (DI).

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

Я рефакторинг, щоб я міг ввести залежність, а не створити новий об’єкт у класі, але в якийсь момент мені доведеться створити деякі об’єкти, тобто використовувати жахливе newключове слово.

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

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

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



Я рекомендую IoC для послуг та політики. Для моделей чи допоміжних класів я б просто використовував new. Звичайно, є кілька точок входу, куди потрібно зателефонувати в контейнер IoC, але їх не повинно бути багато. Зазвичай ви конфігуруєте IoC один раз, а потім просите вирішити один клас за запитом. У випадку MVC, як правило, це контролер.
CodesInChaos

Клас вищого рівня, який ви згадуєте, є частиною композиційного кореня. Це далеко не неправильно.
Facio Ratio

Відповіді:


12

Після цього трохи покрутившись для цього, схоже, (як згадувалося в коментарі вище) клас вищого рівня, про який я говорив, називається складом кореня .

Дійсно, це прийняте рішення додати створення всіх об'єктів в цьому кореневому складі (або посилання на контейнер IoC звідси).

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

Клас верхнього рівня може бути трохи брудним, завалений newі , set_property()але я повинен сказати , що я на самом деле вважаю за краще мати весь цей код в одному місці, а не розкиданий по всіх інших класів

Ще одна корисна сторінка, де обговорюються хіти ефективності цього методу тут


1
+1, оскільки я ніколи раніше не чув про "Склад Корінь".
c_maker

2

Клас «Фабрика» розповсюдиться newпо всьому. Це буде створення будь-якого об'єкта, який ви запитуєте, і, ймовірно, залежності цього об'єкта. Оскільки завданням фабрик є присвоєння правильного об'єкта для вас, що мають newу цьому класі, це не погано.

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

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


-2

Мої два центи тут:

Я переробляю PHP-додаток, і я намагаюся зробити якомога більше ін'єкцій залежності

Ви не заявляєте, якщо використовуєте рамку введення залежності. Я думаю, що ти обов'язково повинен. Використовуйте щось, що надає потрібні вам функції: /programming/9348376/guice-like-dependency-injection-frameworks-in-php .

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

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

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

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

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

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

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

Ви також налаштовуєте свій IoC-фреймворк для використання Factory, коли ви використовуєте сторонній ліб, який вже вимагає використання Factory. У цьому випадку у вас немає контролю над цим, і вам потрібно сказати своєму контейнеру IoC: "Ей, коли я запитую один з цих інтерфейсів, ви повинні використовувати цю фабрику, щоб надати мені відповідний екземпляр".

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

У цьому випадку здається, що вам не потрібно використовувати заводські зразки для цих об’єктів / служб / контролерів / будь-що, і ви можете просто налаштувати свій IoC для створення «нового» відповідного класу та введення всього іншого.

Я сподіваюся, що це допомагає.


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

4
doing DI manually beats the whole purpose of using an Inversion of Control container- Якщо ви маєте на увазі "... що централізує ваші залежності у конфігураційному файлі", то ви маєте рацію, тому що це все контейнер IoC. Справжня мета DI - це роз'єднання, і ви можете це зробити, поставляючи свої залежності методом конструктора. Для цього вам взагалі не потрібна рамка DI.
Роберт Харві

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

1
Я погодився б, що вам потрібна рамка для дуже великих додатків. Багато додатків не такі великі, і не отримують користі від додаткової складності використання рамки DI.
Роберт Харві

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