Sollte die Verwendung von Dependency Injection und eines Inversion of Control-Containers alle Vorkommen des new
Schlüsselworts " " aus Ihrem Code entfernen ?
Mit anderen Worten, sollte jedes Objekt / jede Abhängigkeit, egal wie einfach oder kurzlebig, in Ihrem IoC-Container "registriert" und in die Methode / Klasse injiziert werden, die sie verwenden muss?
Wenn nein, wo ziehen Sie die Linie zwischen den Abhängigkeiten / Objekten, die im IoC-Container registriert werden, und dem, was "in-line" als konkrete Referenz über das new
Schlüsselwort erstellt wird?
.net
dependency-injection
ioc-containers
CraigTP
quelle
quelle
Antworten:
Vermeiden Sie Dogmen. Mach was sich richtig anfühlt.
Ich bevorzuge die Verwendung von "new" für Datenstrukturen, die kein Verhalten aufweisen.
Wenn die Klasse Verhalten hat, schaue ich auf den Umfang dieses Verhaltens. Wenn es staatenlos ist und keine Abhängigkeiten hat, neige ich zu "neu". Ich beginne die Umgestaltung in Richtung DI nur, wenn ich eine Abhängigkeit zu statusbehafteten Ressourcen (wie einer Datenbank oder einer Datei) oder zu anderen Klassen mit solchen Ressourcen hinzufügen muss.
quelle
new
Abhängigkeit in meinem eigenen Code aufwies , die meine Frage veranlasste. Es war eine einfache Klasse ohne Funktionalität oder "Verhalten" an sich, nur einfache Eigenschaften.In meinem Buch unterscheide ich zwischen stabilen und flüchtigen Abhängigkeiten . Es ist am wichtigsten, DI mit flüchtigen Abhängigkeiten zu verwenden, aber häufig können Sie eine noch lockerere Kopplung erzielen, indem Sie auch stabile Abhängigkeiten abstrahieren und injizieren.
Beachten Sie, dass sich die Anwendung von DI nicht auf einen DI-Container stützen sollte . In dem Fall, in dem Poor Man's DI verwendet wird, werden keine
new
Schlüsselwörter entfernt - sie werden nur in die Kompositionswurzel verschoben .Einige Leute bevorzugen tatsächlich Poor Man's DI gegenüber DI Containers. Die Wartungskosten sind zwar höher, dafür erhalten Sie jedoch Sicherheit bei der Kompilierung. Wie ich kürzlich von Dan North gehört habe: "
new
is the newnew
" :)Damit ist lediglich gemeint, dass der Composition Root nicht mit einem DI-Container implementiert wird, sondern nur eine ganze Reihe verschachtelter
new
Anweisungen enthält.quelle
"neu" ist kein verbotenes Schlüsselwort. Meine persönlichen Regeln:
Alle "Dienste" (ich bezeichne einen Dienst als eine Klasse, die eine oder mehrere Methoden für eine und nur eine Sache bereitstellt; zum Beispiel: Zugriff auf die Datenbank, Abrufen / Aktualisieren von Daten für eine bestimmte Domäne) sind im IOC-Container registriert. Keine Klasse sollte die Entscheidung treffen müssen, wie sie die Implementierung eines bestimmten Dienstes erhalten soll, den sie verwenden muss. Wenn Sie einen vorhandenen Dienst verwenden müssen, sollten Sie daher Ihre Klasse und den IOC-Container so konfigurieren, dass er Ihnen zur Verfügung steht. Stellen Sie sich vor, Sie wissen nicht, wie Ihre Implementierung funktioniert, es könnte sich um einen Webdienst handeln, der Ihnen egal ist.
Alle Beans oder Modelle müssen mit dem Schlüsselwort "new" oder mit einer vom IOC registrierten Factory erstellt werden, wenn für sie einige Standardeigenschaften aktiviert sein müssen. Es gibt auch den speziellen Fall von Dienstprogrammklassen, die nur statische Methoden enthalten (zum Beispiel: ein mathematischer Dienstprogrammdienst). Wenn sie völlig eigenständig sind und keine Datenbankverbindung oder einen anderen IOC-registrierten Dienst benötigen, lasse ich sie aus dem IOC aus und sie müssen statisch aufgerufen werden. Wenn eine solche Klasse jedoch einen vorhandenen IOC-registrierten Dienst verwenden muss, ändere ich ihn in eine Singleton-Klasse und registriere ihn im IOC.
quelle
Ich möchte nur die vorhandenen Antworten ergänzen, die früher angesprochen wurden,
new
ist völlig in Ordnung, um Objekte zu erstellen, die reine Wertobjekte sind (dh nur Eigenschaften / Getter / Setter haben). Weitere Informationen finden Sie im Google Testing-Blog .quelle
new
‚edKommt ganz klar auf die Sprache an, die du benutzt. Wenn Ihre Sprache Sie zwingt, Objekte zu verwenden, um sowohl tatsächliche Objekte als auch Datensätze (Wertobjekte, Strukturen) darzustellen, lautet die Antwort höchstwahrscheinlich Nein.
Wenn man nur von "echten" Objekten spricht, ist es nichts Falsches, eine Instanz explizit zu erstellen. Was Sie jedoch bedenken müssen, ist, dass alle Klassen dem Prinzip der Einzelverantwortung folgen sollten. Es sollte nicht die Verantwortung einer Klasse sein, den Implementierer eines Dienstes zu wählen, auf den sie sich verlässt. Es gibt jedoch Klassen, die genau diese Verantwortung haben, dh Implementierer bestimmter Dienste bereitzustellen. Eine IoC könnte eine solche Klasse sein. Tatsächlich ist jede Art von Fabrik eine solche Klasse.
Um es zusammenzufassen: Nur solche Klassen sollten Objekte direkt instanziieren, und es liegt in der Verantwortung, auszuwählen, welche Klassen instanziiert werden sollen.
Diese Kriterien könnten hilfreich sein: http://en.wikipedia.org/wiki/GRASP_(object-oriented_design)#Creator
quelle
Ein Wort: Nein.
Weitere Wörter: Die Abhängigkeitsinjektion ist genau das. Es ist ein Mittel, mit dem Sie Ressourcen einführen, von denen ein anderes Objekt abhängt, dessen komplizierte Details jedoch nicht aus einer anderen Quelle stammen sollten. Die Verwendung von DI bedeutet nicht, dass NICHTS in Ihrem Programm wissen sollte, wie ein anderes Objekt erstellt wird. Tatsächlich gehe ich davon aus, dass es für ein nicht triviales Programm höchst unmöglich ist, das "neue" Schlüsselwort (oder reflexionsbasierte Alternativen) vollständig zu vermeiden. DI bedeutet jedoch, dass Objekte, die nicht wissen MÜSSEN, wie komplexe Objekte zu erstellen sind, für die eine Vielzahl von Abhängigkeiten erforderlich sind, die dieses Objekt eng mit dem anderen koppeln, nicht über das gesamte Wissen zur engen Kopplung verfügen sollten.
Ich würde die beiden Haupttheorien des O / O-Softwaredesigns, GRASP und SOLID, studieren. GRASP fordert Sie auf, den Zweck des Objekts zu untersuchen und sich zu fragen: "Sollte dieses Objekt für die Erstellung neuer Objekte dieses anderen Typs verantwortlich sein? Ist dieser Teil der 'Jobbeschreibung' dieses Objekts?" SOLID geht einen Schritt weiter: Das "S" steht für das "Single Responsibility Principle", das eindeutig besagt, dass ein Objekt einen Job haben soll und dass es das einzige Objekt im Programm sein soll, das diesen speziellen Job ausführt.
GRASP empfiehlt Ihnen daher im Allgemeinen, Ihre vorhandenen Klassen zu durchsuchen, für die diese neuen Objekte erstellt werden, und eine zu finden, für die die Aufgabe zum Erstellen dieses Objekts mit der bereits durch das Objekt ausgeführten Aufgabe übereinstimmt, wobei der gewünschte Grad an "Kohäsion" beibehalten wird. SOLID wird Ihnen sagen, dass der Zusammenhalt der Schlüssel ist; Die Aufgabe, diese Objekte zu erstellen, sollte einer Fabrik übertragen werden, die in Ihre Klasse eingefügt werden soll. Ich denke, mit der zunehmenden Komplexität Ihres Programms werden Sie feststellen, dass die Einhaltung einer dieser Methoden mit der Bereitschaft zur Umgestaltung zu sehr ähnlichen Architekturen führen wird.
quelle