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 new
Schlü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 new
fü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?
quelle
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.Antworten:
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
new
undset_property()
aber ich muss sagen , dass ich alle diesen Code an einem Ort mit eigentlich lieber, anstatt verstreut über alle über die anderen KlassenEine weitere nützliche Seite, auf der die Leistungstreffer dieser Methode erläutert werden
quelle
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 Sienew
in 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
new
oder statischen Aufrufen geben, um Objekte zu instanziieren, die für Ihre Anwendung erforderlich sind. Dort würde das hingehören.quelle
Meine zwei Cent hier:
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 .
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.
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."
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.
quelle
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.