Abhängigkeitsinjektion: Ab wann darf ich ein neues Objekt erstellen?

13

Ich überarbeite eine PHP- Anwendung und versuche, so viel Abhängigkeitsinjektion (DI) wie möglich zu machen.

Ich habe das Gefühl, dass ich ein gutes Verständnis dafür habe, wie es funktioniert, und ich kann sicher sehen, dass meine Klassen viel schlanker und robuster werden.

Ich überarbeite, damit ich eine Abhängigkeit einfügen kann, anstatt ein neues Objekt innerhalb der Klasse zu erstellen, aber irgendwann muss ich einige Objekte erstellen, dh das gefürchtete newSchlüsselwort verwenden.

Das Problem, auf das ich jetzt gestoßen bin, ist, an welchem ​​Punkt kann ich tatsächlich neue Objekte erstellen? Es sieht so aus, als würde ich in einer Klasse der obersten Ebene landen und viele neue Objekte erstellen, da es keinen anderen Ort gibt, an den ich gehen kann. Das fühlt sich falsch an.

Ich habe einige Blogs gelesen, die Factory-Klassen verwenden , um alle Objekte zu erstellen, und dann fügen Sie die Factory in andere Klassen ein. Sie können dann die Factory-Methoden aufrufen, und die Factory erstellt das neue Objekt für Sie.

Mein Anliegen dabei ist jetzt, dass meine Fabrikklassen newfür alle kostenlos sein werden! Ich denke, das mag in Ordnung sein, da es sich um Fabrikklassen handelt, aber gibt es einige Regeln, an die man sich halten muss, wenn man ein Fabrikmuster und DI verwendet, oder gehe ich hier weit von der Marke ab?

Gaz_Edge
quelle
Verwandte: Warum heißt Inversion of Control so?
Robert Harvey
Ich empfehle IoC für Dienste und Richtlinien. Für Modell- oder Hilfsklassen würde ich einfach verwenden new. Natürlich gibt es einige Einstiegspunkte, an denen Sie den IoC-Container aufrufen müssen, aber es sollten nicht viele vorhanden sein. Normalerweise konfigurieren Sie das IoC einmal und fordern dann an, dass eine Klasse pro Anforderung aufgelöst wird. Im Fall von MVC ist dies normalerweise der Controller.
CodesInChaos
Die von Ihnen erwähnte Klasse der obersten Ebene ist Teil der Kompositionswurzel. Es ist alles andere als falsch.
Facio Ratio

Antworten:

12

Nach einigem googeln scheint es (wie in einem Kommentar oben erwähnt), dass die Klasse der obersten Ebene, über die ich gesprochen habe, die Kompositionswurzel heißt .

Es scheint in der Tat die akzeptierte Lösung zu sein, die Erstellung aller Objekte in diesem Kompositionsstamm hinzuzufügen (oder von hier aus auf einen IoC-Container zu verweisen).

Meine ursprüngliche Sorge dabei war, dass diese Klasse der Spitzenklasse ein bisschen chaotisch werden würde. Dies ist bis zu einem gewissen Grad wahr, aber die Vorteile wägen die Nachteile ab. Zum Beispiel kann ich sehen, dass sich die Lesbarkeit, Testbarkeit und Wartbarkeit aller meiner anderen Klassen verbessert hat.

Die Top-Level - Klasse kann ein bisschen chaotisch sein, übersät mit newund set_property()aber ich muss sagen , dass ich alle diesen Code an einem Ort mit eigentlich lieber, anstatt verstreut über alle über die anderen Klassen

Eine weitere nützliche Seite, auf der die Leistungstreffer dieser Methode erläutert werden

Gaz_Edge
quelle
1
+1, weil ich noch nie von 'Composition Root' gehört habe.
c_maker
2

Eine Factory-Klasse wird newüberall verteilt sein. Es würde jedes Objekt erstellen, das Sie anfordern, und wahrscheinlich die Abhängigkeiten dieses Objekts. Da es die Aufgabe der Fabriken ist, das richtige Objekt für Sie newin dieser Klasse zu instanziieren, ist das keine schlechte Sache.

DI ist so, dass Sie ein lose gekoppeltes Design haben. Sie können Änderungen an Ihrer Anwendung vornehmen, indem Sie die Abhängigkeit ändern, die für jedes Objekt bereitgestellt wird. Machen Sie Ihre Anwendung flexibel, erweiterbar und einfach zu testen.

Auf der obersten Ebene verfügen Sie über Code, der einige Fabriken instanziiert, Verbindungen zu Diensten herstellt und eine Antwort sendet. Es wird eine ganze Reihe von newoder statischen Aufrufen geben, um Objekte zu instanziieren, die für Ihre Anwendung erforderlich sind. Dort würde das hingehören.

Schleis
quelle
-2

Meine zwei Cent hier:

Ich überarbeite eine PHP-Anwendung und versuche, so viel Abhängigkeitsinjektion wie möglich zu machen

Sie geben nicht an, ob Sie ein Abhängigkeitsinjektionsframework verwenden. Ich denke du solltest es definitiv. Verwenden Sie etwas, das Ihnen die Funktionen bietet, die Sie benötigen: /programming/9348376/guice-like-dependency-injection-frameworks-in-php .

Das Problem, auf das ich jetzt gestoßen bin, ist, an welchem ​​Punkt kann ich tatsächlich neue Objekte erstellen? Es sieht so aus, als würde ich in einer Klasse der obersten Ebene landen und viele neue Objekte erstellen, da es keinen anderen Ort gibt, an den ich gehen kann. Das fühlt sich falsch an.

Normalerweise verwenden Sie die Konfiguration oder einen zentralen Punkt für die Instanziierung der ursprünglichen Objekte, aus denen Ihre Anwendung besteht. Der Container erstellt die Objekte für Sie.

Anschließend greifen Sie über den IoC-Container auf Objekte (Dienste, Anbieter, Controller ...) zu. Bei Bedarf wird transparent ein Objekt für Sie erstellt oder Sie erhalten einen Verweis auf die entsprechende vorhandene Instanz.

Natürlich können Sie innerhalb Ihrer speziellen Implementierung von Objekten andere Objekte instanziieren, für die Sie kein DI benötigen (Datenstrukturen, benutzerdefinierte Typen usw.), aber das ist normale Programmierung.

Ich habe einige Blogs gelesen, die Factory-Klassen verwenden, um alle Objekte zu erstellen, und dann fügen Sie die Factory in andere Klassen ein. Sie können dann die Factory-Methoden aufrufen, und die Factory erstellt das neue Objekt für Sie.

Normalerweise verwenden Sie eine Factory, wenn das IoC-Framework einige IoC-Objekte über Ihre Fabriken instanziieren soll (dies ist erforderlich, wenn das Instanziieren eines bestimmten Objekts zusätzliche Arbeit erfordert). Wenn Sie Ihre Objekte einfach mit "new Object ()" erstellen und einige Eigenschaften festlegen können, möchten Sie nicht unbedingt ein Factory-Muster verwenden.

Mit anderen Worten, ich würde sagen, dass die Verwendung eines Factory-Musters für eine Klasse oder eine Gruppe von Klassen davon abhängt, wie Sie diese Klassen modellieren möchten, und nicht davon, ob Sie DI verwenden (es sei denn, Ihre DI-Implementierung erfordert ausdrücklich Fabriken, was ungewöhnlich ist).

Sie konfigurieren Ihr IoC-Framework auch für die Verwendung einer Factory, wenn Sie eine Drittanbieter-Bibliothek verwenden, für die bereits eine Factory erforderlich ist. In diesem Fall haben Sie keine Kontrolle darüber und müssen Ihrem IoC-Container mitteilen: "Hey, wenn ich nach einer dieser Schnittstellen frage, müssen Sie diese Factory verwenden, um mir eine geeignete Instanz bereitzustellen."

Mein Anliegen dabei ist jetzt, dass meine Fabrikklassen ein neuer Alleskönner werden! Ich denke, das mag in Ordnung sein, da es sich um Fabrikklassen handelt, aber gibt es einige Regeln, an die man sich halten muss, wenn man Fabrikmuster und DI verwendet, oder gehe ich hier weit von der Marke ab.

In diesem Fall klingt es so, als müssten Sie für diese Objekte / Dienste / Controller / was auch immer keine Factory-Muster verwenden, und Sie können Ihren IoC einfach so konfigurieren, dass die entsprechende Klasse mit "new" instanziiert und alles andere eingefügt wird.

Ich hoffe, es hilft.

jjmontes
quelle
Vielen Dank für die Antwort, aber sicherlich ist der IoC-Container die 'Top-Level-Klasse', auf die ich mich bezog. Wenn ich dort nur Objekte erstellen kann, wird es ein richtiges Durcheinander sein.
Gaz_Edge
4
doing DI manually beats the whole purpose of using an Inversion of Control container- Wenn Sie damit "... was Ihre Abhängigkeiten in einer Konfigurationsdatei zentralisiert" meinen, dann haben Sie Recht, denn das ist alles, was ein IoC-Container wirklich tut. Das eigentliche Ziel von DI ist die Entkopplung. Sie können dies tun, indem Sie Ihre Abhängigkeiten in einer Konstruktormethode angeben. Sie benötigen dazu überhaupt kein DI-Framework.
Robert Harvey
mmm Sie erstellen keine Objekte, Sie fragen den IoC-Container nach ihnen (von jedem Ort aus, den Sie benötigen), oder Sie verwenden die Feld- / Argumentinjektion, damit Ihren Klassen automatisch die entsprechenden Klassen injiziert werden, die immer vom IoC-Container erstellt werden.
Jjmontes
1
Ich würde zustimmen, dass Sie ein Framework für sehr große Anwendungen benötigen . Viele Anwendungen sind nicht so groß und profitieren nicht von der zusätzlichen Komplexität der Verwendung eines DI-Frameworks.
Robert Harvey
2
Ich habe nicht gesagt, dass es war. Ich habe einfach gesagt, dass Sie dafür keinen DI-Container benötigen.
Robert Harvey