Was ist der Zweck von IOC-Containern? Die kombinierten Gründe dafür können auf das Folgende vereinfacht werden:
Bei Verwendung der OOP / SOLID-Entwicklungsprinzipien wird die Abhängigkeitsinjektion unordentlich. Entweder haben Sie die obersten Einstiegspunkte, die Abhängigkeiten für mehrere Ebenen unter sich verwalten und Abhängigkeiten rekursiv durch die Konstruktion leiten, oder Sie haben etwas doppelten Code in Factory- / Builder-Mustern und -Schnittstellen, mit denen Abhängigkeiten nach Bedarf erstellt werden.
Es gibt keine OOP / SOLID-Methode, um dies durchzuführen, UND es gibt einen super hübschen Code.
Wenn diese vorherige Aussage wahr ist, wie machen es IOC-Container? Soweit ich weiß, wenden sie keine unbekannte Technik an, die mit manueller DI nicht möglich ist. Daher besteht die einzige Erklärung darin, dass IOC-Container die OOP / SOLID-Prinzipien durch die Verwendung von privaten Zugriffsmethoden für statische Objekte brechen.
Brechen IOC-Container die folgenden Prinzipien hinter den Kulissen? Dies ist die eigentliche Frage, da ich ein gutes Verständnis habe, aber das Gefühl habe, dass jemand anderes ein besseres Verständnis hat:
- Umfangskontrolle . Der Umfang ist der Grund für fast jede Entscheidung, die ich für mein Code-Design treffe. Block, Lokal, Modul, Statisch / Global. Der Geltungsbereich sollte sehr eindeutig sein, so viel wie möglich auf Blockebene und so wenig wie möglich auf statischer Ebene. Sie sollten Deklarationen, Instantiierungen und Lebenszyklusenden sehen. Ich vertraue darauf, dass die Sprache und GC den Umfang verwalten, solange ich ausdrücklich damit einverstanden bin. Bei meinen Recherchen habe ich festgestellt, dass IOC-Container die meisten oder alle Abhängigkeiten als statisch einrichten und sie durch eine AOP-Implementierung im Hintergrund steuern. Also nichts ist transparent.
- Verkapselung . Was ist der Zweck der Einkapselung? Warum sollten wir so private Mitglieder behalten? Aus praktischen Gründen können Implementierer unserer API die Implementierung nicht durch Ändern des Status (der von der Eigentümerklasse verwaltet werden sollte) unterbrechen. Aus Sicherheitsgründen kann es jedoch nicht zu Injektionen kommen, die unsere Mitgliedstaaten überholen und die Validierung und Klassenkontrolle umgehen. Alles (spöttische Frameworks oder IOC-Frameworks), das Code vor der Kompilierung einfügt, um privaten Mitgliedern externen Zugriff zu ermöglichen, ist ziemlich umfangreich.
- Grundsatz der einheitlichen Verantwortung . An der Oberfläche scheinen IOC-Container die Dinge sauberer zu machen. Aber stellen Sie sich vor, wie Sie dasselbe ohne die Helfer-Frameworks erreichen würden. Es würden Konstruktoren mit etwa einem Dutzend Abhängigkeiten übergeben. Das bedeutet nicht, dass Sie es mit IOC-Containern verschleiern müssen, es ist eine gute Sache! Es ist ein Zeichen, Ihren Code neu zu faktorisieren und SRP zu folgen.
Offen / Geschlossen . Genauso wie SRP nicht nur für Klassen gedacht ist (ich wende SRP nur für Einzelverantwortliche an, geschweige denn für Methoden). Open / Closed ist nicht nur eine übergeordnete Theorie, um den Code einer Klasse nicht zu ändern. Es ist eine Übung, die Konfiguration Ihres Programms zu verstehen und die Kontrolle darüber zu haben, was geändert und was erweitert wird. IOC-Container können die Funktionsweise Ihrer Klassen teilweise ändern, weil:
ein. Der Hauptcode bestimmt nicht das Auswechseln von Abhängigkeiten, sondern die Framework-Konfiguration.
b. Der Gültigkeitsbereich kann zu einem Zeitpunkt geändert werden, der nicht von den aufrufenden Mitgliedern gesteuert wird. Er wird stattdessen extern von einem statischen Framework festgelegt.
Die Konfiguration der Klasse ist also nicht wirklich abgeschlossen, sondern ändert sich basierend auf der Konfiguration eines Tools eines Drittanbieters.
Der Grund, warum dies eine Frage ist, ist, dass ich nicht unbedingt ein Meister aller IOC-Container bin. Und obwohl die Idee eines IOC-Containers schön ist, scheinen sie nur eine Fassade zu sein, die eine schlechte Implementierung verdeckt. Um jedoch eine externe Bereichskontrolle, den Zugriff privater Mitglieder und das langsame Laden zu erreichen, müssen viele nicht triviale, fragwürdige Dinge weitergehen. AOP ist großartig, aber die Art und Weise, wie es durch IOC-Container erreicht wird, ist auch fraglich.
Ich kann darauf vertrauen, dass C # und der .NET GC das tun, was ich von ihm erwarte. Aber ich kann nicht das gleiche Vertrauen in ein Drittanbieter-Tool setzen, das meinen kompilierten Code ändert, um Problemumgehungen für Dinge durchzuführen, die ich nicht manuell ausführen könnte.
EG: Entity Framework und andere ORMs erstellen stark typisierte Objekte und ordnen sie Datenbankentitäten zu. Außerdem bieten sie grundlegende Funktionen für die Ausführung von CRUD. Jeder kann sein eigenes ORM erstellen und die OOP / SOLID-Prinzipien weiterhin manuell befolgen. Aber diese Rahmenbedingungen helfen uns, damit wir das Rad nicht jedes Mal neu erfinden müssen. Während IOC-Container uns anscheinend dabei helfen, die OOP / SOLID-Prinzipien gezielt zu umgehen und zu vertuschen.
IOC
undExplicitness of code
ist genau das, womit ich Probleme habe. Manuelles DI kann leicht zur Pflicht werden, bringt aber zumindest den eigenständigen expliziten Programmfluss an einen Ort - "Sie bekommen, was Sie sehen, Sie sehen, was Sie bekommen". Während die Bindungen und Deklarationen von IOC-Containern leicht selbst zu einem versteckten Parallelprogramm werden können.