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.Antworten:
Ich werde Ihre Punkte numerisch durchgehen, aber zuerst sollten Sie Folgendes beachten: Verwechseln Sie nicht, wie ein Verbraucher eine Bibliothek verwendet, mit der Art und Weise, wie die Bibliothek implementiert wird . Gute Beispiele hierfür sind Entity Framework (das Sie selbst als gute Bibliothek zitieren) und ASP.NETs MVC. Beide machen eine Menge unter der Haube, zum Beispiel mit Reflektion, was absolut nicht als gutes Design angesehen werden würde, wenn Sie es durch den alltäglichen Code verbreiten würden.
Diese Bibliotheken sind absolut nicht "transparent" in ihrer Funktionsweise oder was sie hinter den Kulissen tun. Dies ist jedoch kein Nachteil, da sie gute Programmierungsprinzipien bei ihren Verbrauchern unterstützen . Wenn Sie also über eine Bibliothek wie diese sprechen, denken Sie daran, dass es für Sie als Benutzer einer Bibliothek keine Aufgabe ist, sich um deren Implementierung oder Wartung zu kümmern. Sie sollten sich nur Gedanken darüber machen, wie es dem Code hilft oder behindert, den Sie schreiben und der die Bibliothek verwendet. Kombiniere diese Konzepte nicht!
Also, um nach Punkten durchzugehen:
Sofort erreichen wir, was ich nur annehmen kann, ist ein Beispiel von oben. Sie sagen, dass IOC-Container die meisten Abhängigkeiten als statisch einrichten. Nun, vielleicht gehören zu den Implementierungsdetails, wie sie funktionieren, statische Speicher
IKernel
. Aber das ist nicht dein Anliegen!Tatsächlich ist ein IoC-Container genauso explizit wie die Abhängigkeitsinjektion eines armen Mannes. (Ich werde weiterhin IoC-Container mit dem DI eines armen Mannes vergleichen, da es unfair und verwirrend wäre, sie mit keinem DI zu vergleichen. Um klar zu sein, ich verwende den DI eines armen Mannes nicht als Abwertungsmaßnahme.)
In der DI eines armen Mannes würden Sie eine Abhängigkeit manuell instanziieren und sie dann in die Klasse einfügen, die sie benötigt. An dem Punkt, an dem Sie die Abhängigkeit erstellen, wählen Sie, was Sie damit tun möchten. Speichern Sie sie in einer Variablen mit lokalem Gültigkeitsbereich, einer Klassenvariablen oder einer statischen Variablen. Speichern Sie sie überhaupt nicht. Sie können dieselbe Instanz an viele Klassen übergeben oder für jede Klasse eine neue erstellen. Wie auch immer. Der Punkt ist, um zu sehen, was passiert, Sie schauen auf den Punkt, wahrscheinlich in der Nähe des Anwendungsstamms, an dem die Abhängigkeit erstellt wird.
Was ist nun mit einem IoC-Container? Nun, du machst genau das gleiche! Wieder von Ninject Terminologie geht, schauen Sie auf , wo die Bindung eingerichtet ist, und ob es so etwas wie sagt
InTransientScope
,InSingletonScope
oder was auch immer. Wenn überhaupt, ist dies möglicherweise klarer, weil Sie den Code genau dort haben, der seinen Gültigkeitsbereich deklariert, anstatt eine Methode durchsehen zu müssen, um zu verfolgen, was mit einem Objekt passiert (ein Objekt kann auf einen Block beschränkt sein, wird aber darin mehrmals verwendet) Block oder nur einmal, zum Beispiel). Vielleicht stößt du also auf die Idee, eine Funktion im IoC-Container anstelle einer unformatierten Sprachfunktion zu verwenden, um den Umfang zu bestimmen, aber solange du deiner IoC-Bibliothek vertraust - was du auch tun solltest -, gibt es keinen wirklichen Nachteil .Ich weiß immer noch nicht genau, wovon du hier sprichst. Betrachten IoC-Container private Eigenschaften als Teil ihrer internen Implementierung? Ich weiß nicht, warum sie das tun würden, aber es ist auch nicht Ihre Aufgabe, wie eine Bibliothek, die Sie verwenden, implementiert wird.
Oder stellen sie vielleicht eine Funktion wie das Injizieren in private Setter zur Verfügung? Ehrlich gesagt bin ich noch nie darauf gestoßen, und ich bin zweifelhaft, ob dies wirklich ein gemeinsames Merkmal ist. Aber selbst wenn es da ist, ist es ein einfacher Fall eines Werkzeugs, das missbraucht werden kann. Denken Sie daran, dass es auch ohne IoC-Container nur ein paar Zeilen Reflection-Code sind, um auf eine private Eigenschaft zuzugreifen und diese zu ändern. Es ist etwas, was Sie so gut wie nie tun sollten, aber das bedeutet nicht, dass .NET schlecht ist, um die Fähigkeit verfügbar zu machen. Wenn jemand ein Werkzeug so offensichtlich und wild missbraucht, ist es die Schuld der Person, nicht die des Werkzeugs.
Der letzte Punkt ist hier ähnlich wie bei 2. In den meisten Fällen verwenden IoC-Container den Konstruktor. Die Setter-Injektion wird unter ganz bestimmten Umständen angeboten, unter denen aus bestimmten Gründen die Konstruktor-Injektion nicht verwendet werden kann. Wer ständig Setter-Injection einsetzt, um zu verbergen, wie viele Abhängigkeiten übergeben werden, verschwindet massiv aus dem Werkzeug. Das ist NICHT die Schuld des Werkzeugs, sondern ihre.
Wenn dies ein wirklich einfacher Fehler war, den ich unschuldig begangen habe und den IoC-Container ermutigen, dann haben Sie vielleicht Recht. Es wäre, als würde man jedes Mitglied meiner Klasse öffentlich machen und dann anderen die Schuld geben, wenn sie Dinge ändern, die sie nicht sollten, oder? Wer jedoch Verstöße gegen die SRP mit Setter Injection vertuscht, ignoriert die grundlegenden Designprinzipien absichtlich oder kennt sie überhaupt nicht. Es ist unvernünftig, den IoC-Container dafür verantwortlich zu machen.
Dies gilt insbesondere , da dies auch mit dem DI eines armen Mannes genauso einfach möglich ist:
Diese Sorge scheint also völlig orthogonal zu sein, ob ein IoC-Container verwendet wird oder nicht.
Ändern, wie Ihre Klassen zusammenarbeiten, ist kein Verstoß gegen OCP. Wenn dies der Fall wäre, würde jede Abhängigkeitsinversion eine Verletzung von OCP fördern. Wenn dies der Fall wäre, würden sie nicht beide das gleiche SOLID-Akronym haben!
Außerdem haben weder a) noch b) etwas mit OCP zu tun. Ich weiß nicht einmal, wie ich dies in Bezug auf OCP beantworten soll.
Das einzige, was ich vermuten kann, ist, dass Sie glauben, OCP habe etwas damit zu tun, dass das Verhalten zur Laufzeit nicht geändert wird oder von wo aus im Code der Lebenszyklus von Abhängigkeiten gesteuert wird. Es ist nicht. Bei OCP muss kein vorhandener Code geändert werden, wenn Anforderungen hinzugefügt oder geändert werden. Es geht nur darum , Code zu schreiben , nicht darum, wie der Code, den Sie bereits geschrieben haben, zusammengeklebt ist (obwohl lose Kopplung natürlich ein wichtiger Teil des Erreichens von OCP ist).
Und eine letzte Sache, die Sie sagen:
Ja, das kannst du . Es gibt absolut keinen Grund zu der Annahme, dass diese Tools, auf die sich eine Vielzahl von Projekten stützt, fehlerhafter sind oder unerwartetem Verhalten unterliegen als jede andere Bibliothek von Drittanbietern.
Nachtrag
Ich habe gerade bemerkt, dass Ihre Intro-Absätze auch eine Adressierung gebrauchen könnten. Sie sagen sardonisch, dass IoC-Container "keine geheime Technik verwenden, von der wir noch nie gehört haben", um chaotischen, duplikationsanfälligen Code zum Erstellen eines Abhängigkeitsdiagramms zu vermeiden. Und Sie haben vollkommen recht, sie gehen diese Dinge tatsächlich mit denselben grundlegenden Techniken an, wie wir Programmierer es immer tun.
Lassen Sie mich Ihnen ein hypothetisches Szenario erläutern. Als Programmierer stellen Sie eine große Anwendung zusammen, und an dem Einstiegspunkt, an dem Sie Ihr Objektdiagramm erstellen, stellen Sie fest, dass Sie einen ziemlich unordentlichen Code haben. Es gibt eine ganze Reihe von Klassen, die immer wieder verwendet werden, und jedes Mal, wenn Sie eine dieser Klassen erstellen, müssen Sie die gesamte Kette von Abhängigkeiten unter ihnen erneut erstellen. Außerdem haben Sie keine aussagekräftige Möglichkeit, den Lebenszyklus von Abhängigkeiten zu deklarieren oder zu steuern, außer mit benutzerdefiniertem Code für jede Abhängigkeit. Ihr Code ist unstrukturiert und voller Wiederholungen. Dies ist die Unordnung, über die Sie in Ihrem Intro-Absatz sprechen.
Also fangen Sie zuerst an, ein Bit umzugestalten, bei dem ein wiederholter Code so strukturiert ist, dass Sie ihn in Hilfsmethoden auslagern und so weiter. Aber dann fangen Sie an zu überlegen - ist dies ein Problem, das ich vielleicht allgemein angehen könnte , das nicht spezifisch für dieses bestimmte Projekt ist, das Ihnen aber bei all Ihren zukünftigen Projekten helfen könnte?
Sie setzen sich also hin und überlegen, ob es eine Klasse geben soll, die Abhängigkeiten auflöst. Und Sie skizzieren, welche öffentlichen Methoden benötigt werden:
Bind
"Wenn Sie ein Konstruktorargument vom Typ seheninterfaceType
, übergeben Sie eine Instanz vonconcreteType
". Der zusätzlichesingleton
Parameter gibt an, obconcreteType
jedes Mal dieselbe Instanz verwendet oder immer eine neue erstellt werden soll.Resolve
Ich werde einfach versuchen,T
mit jedem Konstruktor zu konstruieren, den es finden kann, dessen Argumente alle Typen sind, die zuvor gebunden wurden. Es kann sich auch rekursiv aufrufen, um die Abhängigkeiten vollständig aufzulösen. Wenn eine Instanz nicht aufgelöst werden kann, weil nicht alles gebunden wurde, wird eine Ausnahme ausgelöst.Sie können versuchen, dies selbst zu implementieren, und Sie werden feststellen, dass Sie ein wenig Nachdenken und Zwischenspeichern für die Bindungen benötigen, wenn dies
singleton
zutrifft, aber auf keinen Fall drastisch oder schrecklich. Und wenn Sie fertig sind , haben Sie den Kern Ihres eigenen IoC-Containers! Ist es wirklich so beängstigend? Der einzige wirkliche Unterschied zwischen diesem und Ninject oder StructureMap oder Castle Windsor oder was auch immer Sie bevorzugen, ist, dass diese viel mehr Funktionen haben, um die (vielen!) Anwendungsfälle abzudecken, in denen diese Basisversion nicht ausreicht. Was Sie jedoch im Herzen haben, ist die Essenz eines IoC-Containers.quelle
In der Theorie? Nein, IoC-Container sind nur ein Werkzeug. Sie können Objekte haben, die eine einzige Verantwortung haben, gut getrennte Schnittstellen, deren Verhalten nach dem Schreiben nicht mehr geändert werden kann usw.
In der Praxis? Absolut.
Ich meine, ich habe nicht wenige Programmierer gehört, die sagen, dass sie IoC-Container speziell verwenden , um Ihnen die Verwendung einer bestimmten Konfiguration zu ermöglichen, um das Verhalten des Systems zu ändern - was gegen das Open / Closed-Prinzip verstößt. Früher gab es Witze über das Codieren in XML, weil 90% ihrer Arbeit darin bestand, die Spring-Konfiguration zu reparieren. Und Sie haben sicherlich Recht, dass das Ausblenden der Abhängigkeiten (was zugegebenermaßen nicht bei allen IoC-Containern der Fall ist) eine schnelle und einfache Möglichkeit ist, hochgradig gekoppelten und sehr fragilen Code zu erstellen.
Schauen wir es uns anders an. Betrachten wir eine sehr einfache Klasse mit einer einzigen grundlegenden Abhängigkeit. Es hängt von einem
Action
, einem Delegaten oder einem Funktor ab, der keine Parameter akzeptiert und zurückgibtvoid
. Was ist die Verantwortung dieser Klasse? Das kannst du nicht sagen. Ich könnte diese Abhängigkeit so klar benennen, dassCleanUpAction
man denkt, sie macht das, was man will. Sobald IoC ins Spiel kommt, wird es alles . Jeder kann in die Konfiguration gehen und Ihre Software modifizieren, um so ziemlich beliebige Dinge zu tun."Wie unterscheidet sich das von der Übergabe
Action
an den Konstruktor?" du fragst. Dies ist anders, da Sie nicht ändern können, was nach der Bereitstellung der Software (oder zur Laufzeit!) An den Konstruktor übergeben wird. Dies ist anders, da Ihre Komponententests (oder die Komponententests Ihrer Kunden) die Szenarien abgedeckt haben, in denen der Delegat an den Konstruktor übergeben wird."Aber das ist ein falsches Beispiel! Meine Sachen erlauben keine Verhaltensänderungen!" du rufst aus Tut mir leid, dass ich es dir sage, aber es tut mir leid. Es sei denn, die Schnittstelle, die Sie injizieren, besteht nur aus Daten. Und Ihre Schnittstelle ist nicht nur Daten, denn wenn es nur Daten wären, würden Sie ein einfaches Objekt erstellen und dieses verwenden. Sobald Sie eine virtuelle Methode in Ihrem Injektionspunkt haben, lautet der Vertrag Ihrer Klasse mit IoC "Ich kann alles ".
"Wie unterscheidet sich das von der Verwendung von Skripten, um Dinge voranzutreiben? Das ist vollkommen in Ordnung." einige von euch fragen. Es ist nicht anders. Aus Sicht der Programmgestaltung gibt es keinen Unterschied. Sie verlassen Ihr Programm, um beliebigen Code auszuführen. Und sicher, das wird schon seit Ewigkeiten in Spielen gemacht. Es ist in Tonnen von Systemadministrationstools getan. Ist es OOP? Nicht wirklich.
Es gibt keine Entschuldigung für ihre gegenwärtige Allgegenwart. IoC-Container haben einen festen Zweck: Ihre Abhängigkeiten zusammenzufügen, wenn Sie über so viele Kombinationen verfügen, oder wenn sie sich so schnell verschieben, dass es unpraktisch ist, diese Abhängigkeiten explizit anzugeben. Daher passen nur sehr wenige Unternehmen in dieses Szenario.
quelle
Verstößt die Verwendung eines IoC-Containers notwendigerweise gegen die OOP / SOLID-Prinzipien? Nein .
Können Sie IoC-Container so verwenden, dass sie gegen die OOP / SOLID-Prinzipien verstoßen? Ja .
IoC-Container sind nur Frameworks zum Verwalten von Abhängigkeiten in Ihrer Anwendung.
Sie sagten Lazy Injection, Property Setter und einige andere Funktionen, die ich noch nicht nutzen wollte, und denen ich zustimme, können Ihnen ein weniger als optimales Design verleihen. Die Verwendung dieser spezifischen Funktionen ist jedoch auf Einschränkungen in der Technologie zurückzuführen, in der Sie IoC-Container implementieren.
Bei ASP.NET-WebForms müssen Sie beispielsweise die Eigenschaftsinjektion verwenden, da es nicht möglich ist, eine Instanz zu erstellen
Page
. Dies ist verständlich, da WebForms niemals unter Berücksichtigung strenger OOP-Paradigmen entwickelt wurde.ASP.NET MVC andererseits ist es durchaus möglich, einen IoC-Container mit der sehr OOP / SOLID-freundlichen Konstruktorinjektion zu verwenden.
In diesem Szenario (mithilfe der Konstruktorinjektion) werden meines Erachtens aus den folgenden Gründen die SOLID-Prinzipien gefördert:
Prinzip der Einzelverantwortung - Mit vielen kleineren Klassen können diese Klassen sehr spezifisch sein und einen Grund für die Existenz haben. Die Verwendung eines IoC-Containers erleichtert die Organisation erheblich.
Offen / Geschlossen - Hier können Sie die Funktionalität einer Klasse erweitern, indem Sie verschiedene Abhängigkeiten einfügen. Mit Abhängigkeiten, die Sie einfügen, können Sie das Verhalten dieser Klasse ändern. Ein gutes Beispiel ist das Ändern der Klasse, die Sie injizieren, indem Sie einen Decorator schreiben, der Caching oder Protokollierung hinzufügt. Sie können die Implementierungen Ihrer Abhängigkeiten vollständig ändern, wenn Sie sie in einer geeigneten Abstraktionsebene schreiben.
Liskov-Substitutionsprinzip - Nicht wirklich relevant
Prinzip der Schnittstellentrennung - Wenn Sie möchten, können Sie einer konkreten Zeit mehrere Schnittstellen zuweisen. Jeder IoC-Behälter, der ein Körnchen Salz enthält, kann dies problemlos tun.
Abhängigkeitsinversion - Mit IoC-Containern können Sie die Abhängigkeitsinversion auf einfache Weise durchführen.
Es ist sowohl explizit als auch transparent. Sie müssen Ihrem IoC-Container mitteilen, wie Abhängigkeiten verkabelt und die Lebensdauer von Objekten verwaltet werden sollen. Dies kann entweder durch Konvention, durch Konfigurationsdateien oder durch Code geschehen, der in den Hauptanwendungen Ihres Systems geschrieben wurde.
Dies ist der ganze Grund für OOP / SOLID, um Systeme verwaltbar zu machen. Die Verwendung eines IoC-Containers entspricht diesem Ziel.
Eine Klasse mit 12 Abhängigkeiten ist wahrscheinlich eine SRP-Verletzung, egal in welchem Kontext Sie sie verwenden.
quelle
Mit dem
static
Schlüsselwort in C # können Entwickler viele OOP / SOLID-Prinzipien brechen, aber es ist unter den richtigen Umständen immer noch ein gültiges Werkzeug.IoC-Container ermöglichen gut strukturierten Code und verringern die kognitive Belastung für Entwickler. Ein IoC-Container kann verwendet werden, um das Befolgen der SOLID-Prinzipien erheblich zu vereinfachen. Es kann zwar missbraucht werden, aber wenn wir die Verwendung eines missbräuchlichen Tools ausschließen würden, müssten wir die Programmierung ganz aufgeben.
Während dieser Vorwurf einige gültige Punkte über schlecht geschriebenen Code aufwirft, ist dies nicht unbedingt eine Frage und auch nicht besonders nützlich.
quelle
Ich sehe mehrere Fehler und Missverständnisse in Ihrer Frage. Der erste wichtige Punkt ist, dass Ihnen die Unterscheidung zwischen Eigenschafts- / Feldinjektion, Konstruktorinjektion und Service-Locator fehlt. Es gab viele Diskussionen (z. B. Flammenkrieg) darüber, wie man etwas richtig macht. In Ihrer Frage scheinen Sie nur die Eigenschaftsinjektion anzunehmen und die Konstruktorinjektion zu ignorieren.
Zweitens gehen Sie davon aus, dass sich IoC-Container auf die Gestaltung Ihres Codes auswirken. Sie müssen nicht oder zumindest nicht das Design Ihres Codes ändern, wenn Sie IoC verwenden. Ihre Probleme mit Klassen mit vielen Konstruktoren sind darauf zurückzuführen, dass IoC echte Probleme mit Ihrem Code versteckt (möglicherweise eine Klasse, die die SRP unterbricht), und dass versteckte Abhängigkeiten einer der Gründe sind, warum Leute von der Verwendung der Eigenschaftsinjektion und des Service-Locators abraten.
Ich verstehe nicht, wo das Problem mit dem Open-Closed-Prinzip liegt, also werde ich es nicht kommentieren. Ihnen fehlt jedoch ein Teil von SOLID, der großen Einfluss darauf hat: das Prinzip der Abhängigkeitsinversion. Wenn Sie DIP folgen, werden Sie feststellen, dass das Invertieren einer Abhängigkeit eine Abstraktion einführt, deren Implementierung aufgelöst werden muss, wenn eine Instanz einer Klasse erstellt wird. Mit diesem Ansatz werden Sie am Ende viele Klassen haben, für deren ordnungsgemäße Funktion mehrere Schnittstellen realisiert und bei der Erstellung bereitgestellt werden müssen. Wenn Sie diese Abhängigkeiten dann manuell bereitstellen würden, müssten Sie viel zusätzliche Arbeit leisten. IoC-Container erleichtern diese Arbeit und ermöglichen es Ihnen, sie zu ändern, ohne das Programm neu kompilieren zu müssen.
Die Antwort auf Ihre Frage lautet also nein. IoC-Container verstoßen nicht gegen die OOP-Designprinzipien. Ganz im Gegenteil, sie lösen Probleme, die durch das Befolgen der SOLID-Prinzipien (insbesondere des Dependency-Inversion-Prinzips) verursacht werden.
quelle