Ich habe Dependency Injection (DI) für eine Weile verwendet und entweder in einen Konstruktor, eine Eigenschaft oder eine Methode injiziert. Ich hatte nie das Bedürfnis, einen IoC-Container ( Inversion of Control ) zu verwenden. Je mehr ich jedoch lese, desto mehr Druck verspüre ich von der Community, einen IoC-Container zu verwenden.
Ich habe mit .NET-Containern wie StructureMap , NInject , Unity und Funq gespielt . Ich sehe immer noch nicht, wie ein IoC-Container meinem Code zugute kommt / ihn verbessert.
Ich habe auch Angst, einen Container bei der Arbeit zu verwenden, weil viele meiner Mitarbeiter Code sehen, den sie nicht verstehen. Viele von ihnen zögern möglicherweise, neue Technologien zu erlernen.
Bitte überzeugen Sie mich, dass ich einen IoC-Container verwenden muss. Ich werde diese Argumente verwenden, wenn ich mit meinen Kollegen bei der Arbeit spreche.
Antworten:
Wow, ich kann nicht glauben, dass Joel dies befürworten würde:
darüber:
Viele Leute wissen nicht, dass Ihre Abhängigkeitskette verschachtelt werden kann, und es wird schnell unhandlich, sie manuell zu verkabeln. Selbst in Fabriken lohnt sich die Vervielfältigung Ihres Codes nicht.
IoC-Container können ja komplex sein. Aber für diesen einfachen Fall habe ich gezeigt, dass es unglaublich einfach ist.
Okay, lassen Sie uns das noch mehr rechtfertigen. Angenommen, Sie haben einige Entitäten oder Modellobjekte, die Sie an eine intelligente Benutzeroberfläche binden möchten. Diese intelligente Benutzeroberfläche (wir nennen sie Shindows Morms) möchte, dass Sie INotifyPropertyChanged implementieren, damit sie die Nachverfolgung von Änderungen vornehmen und die Benutzeroberfläche entsprechend aktualisieren kann.
"OK, das klingt nicht so schwer", also fängst du an zu schreiben.
Sie beginnen damit:
..und am Ende mit diesem :
Das ist ekelhafter Installationscode, und ich behaupte, wenn Sie solchen Code von Hand schreiben, stehlen Sie von Ihrem Kunden . Es gibt bessere und intelligentere Arbeitsweisen.
Hören Sie jemals diesen Begriff, arbeiten Sie klüger, nicht härter?
Stellen Sie sich vor, ein kluger Kerl in Ihrem Team kam und sagte: "Hier ist ein einfacher Weg."
Wenn Sie Ihre Eigenschaften virtuelle machen ( zu beruhigen, ist es nicht so große Sache) , dann können wir weben automatisch in dieser Eigenschaft Verhalten. (Dies nennt man AOP, aber mach dir keine Sorgen um den Namen, konzentriere dich darauf, was es für dich tun wird)
Je nachdem, welches IoC-Tool Sie verwenden, können Sie Folgendes tun:
Poof! Das gesamte manuelle INotifyPropertyChanged BS wird jetzt automatisch für Sie auf jedem virtuellen Eigenschaftssetzer des betreffenden Objekts generiert.
Ist das Magie? JA ! Wenn Sie der Tatsache vertrauen können, dass dieser Code seine Aufgabe erfüllt, können Sie die gesamte Eigenschaft, die mumbo-jumbo umschließt, sicher überspringen. Sie müssen geschäftliche Probleme lösen.
Einige andere interessante Anwendungen eines IoC-Tools für AOP:
quelle
Ich bin bei dir, Vadim. IoC-Container haben ein einfaches, elegantes und nützliches Konzept und müssen mit einem 200-seitigen Handbuch zwei Tage lang studiert werden.
Ich persönlich bin ratlos darüber, wie die IoC-Community einen schönen, eleganten Artikel von Martin Fowler in eine Reihe komplexer Frameworks umgewandelt hat, die normalerweise Handbücher mit 200 bis 300 Seiten enthalten.
Ich versuche nicht zu urteilen (HAHA!), Aber ich denke, dass Leute, die IoC-Container verwenden, (A) sehr klug sind und (B) kein Einfühlungsvermögen für Leute haben, die nicht so klug sind wie sie. Alles macht für sie vollkommen Sinn, so dass sie Schwierigkeiten haben zu verstehen, dass viele gewöhnliche Programmierer die Konzepte verwirrend finden. Es ist der Fluch des Wissens . Die Leute, die IoC-Container verstehen, haben Probleme zu glauben, dass es Leute gibt, die das nicht verstehen.
Der wertvollste Vorteil der Verwendung eines IoC-Containers besteht darin, dass Sie einen Konfigurationsschalter an einem Ort haben können, mit dem Sie beispielsweise zwischen Testmodus und Produktionsmodus wechseln können. Angenommen, Sie haben zwei Versionen Ihrer Datenbankzugriffsklassen ... eine Version, die aggressiv protokolliert und viele Überprüfungen durchgeführt hat, die Sie während der Entwicklung verwendet haben, und eine andere Version ohne Protokollierung oder Überprüfung, die für die Produktion schreiend schnell war. Es ist schön, an einem Ort zwischen ihnen wechseln zu können. Auf der anderen Seite ist dies ein ziemlich triviales Problem, das ohne die Komplexität von IoC-Containern auf einfachere Weise einfach zu handhaben ist.
Ich glaube, wenn Sie IoC-Container verwenden, wird Ihr Code ehrlich gesagt viel schwieriger zu lesen. Die Anzahl der Stellen, an denen Sie suchen müssen, um herauszufinden, was der Code versucht, steigt um mindestens eine. Und irgendwo im Himmel schreit ein Engel.
quelle
Vermutlich zwingt Sie niemand, ein DI-Container-Framework zu verwenden. Sie verwenden DI bereits, um Ihre Klassen zu entkoppeln und die Testbarkeit zu verbessern, sodass Sie viele der Vorteile erhalten. Kurz gesagt, Sie bevorzugen die Einfachheit, was im Allgemeinen eine gute Sache ist.
Wenn Ihr System einen Komplexitätsgrad erreicht, bei dem manuelle DI zur lästigen Pflicht wird (dh die Wartung erhöht), wägen Sie dies gegen die Team-Lernkurve eines DI-Container-Frameworks ab.
Wenn Sie mehr Kontrolle über die Verwaltung der Abhängigkeitslebensdauer benötigen (dh wenn Sie das Singleton-Muster implementieren möchten), sehen Sie sich DI-Container an.
Wenn Sie einen DI-Container verwenden, verwenden Sie nur die Funktionen, die Sie benötigen. Überspringen Sie die XML-Konfigurationsdatei und konfigurieren Sie sie im Code, wenn dies ausreicht. Halten Sie sich an die Konstruktorinjektion. Die Grundlagen von Unity oder StructureMap können auf einige Seiten reduziert werden.
Es gibt einen großartigen Blog-Beitrag von Mark Seemann dazu: Wann man einen DI-Container benutzt
quelle
Meiner Meinung nach ist der Hauptvorteil eines IoC die Möglichkeit, die Konfiguration Ihrer Abhängigkeiten zu zentralisieren.
Wenn Sie derzeit die Abhängigkeitsinjektion verwenden, sieht Ihr Code möglicherweise so aus
Wenn Sie eine statische IoC-Klasse verwenden, im Gegensatz zu den meiner Meinung nach verwirrenderen Konfigurationsdateien, könnten Sie Folgendes haben:
Dann würde Ihre statische IoC-Klasse so aussehen, ich verwende hier Unity.
quelle
IoC-Container eignen sich auch zum Laden tief verschachtelter Klassenabhängigkeiten. Zum Beispiel, wenn Sie den folgenden Code mit Depedency Injection hatten.
Wenn Sie alle diese Abhängigkeiten in einen IoC-Container geladen haben, können Sie den CustomerService auflösen, und alle untergeordneten Abhängigkeiten werden automatisch aufgelöst.
Zum Beispiel:
quelle
Ich bin ein Fan von deklarativer Programmierung (sehen Sie sich an, wie viele SQL-Fragen ich beantworte), aber die IoC-Container, die ich mir angesehen habe, scheinen zu geheimnisvoll für ihr eigenes Wohl zu sein.
... oder vielleicht sind die Entwickler von IoC-Containern nicht in der Lage, klare Dokumentationen zu schreiben.
... oder beides ist bis zu dem einen oder anderen Grad wahr.
Ich denke nicht, dass das Konzept eines IoC-Containers schlecht ist. Die Implementierung muss jedoch sowohl leistungsstark (dh flexibel) genug sein, um in einer Vielzahl von Anwendungen nützlich zu sein, als auch einfach und leicht verständlich.
Es ist wahrscheinlich sechs von anderthalb Dutzend der anderen. Eine echte Anwendung (kein Spielzeug oder eine Demo) ist zwangsläufig komplex und berücksichtigt viele Eckfälle und Ausnahmen von den Regeln. Entweder kapseln Sie diese Komplexität in imperativen Code oder in deklarativen Code. Aber du musst es irgendwo darstellen.
quelle
Bei der Verwendung eines Containers geht es hauptsächlich darum, von einem imperativen / skriptbasierten Initialisierungs- und Konfigurationsstil zu einem deklarativen zu wechseln . Dies kann verschiedene positive Auswirkungen haben:
Natürlich kann es Schwierigkeiten geben:
quelle
Für mich klingt es so, als hätten Sie bereits Ihren eigenen IoC-Container erstellt (unter Verwendung der verschiedenen von Martin Fowler beschriebenen Muster) und fragen, warum die Implementierung eines anderen besser ist als Ihre.
Sie haben also eine Menge Code, der bereits funktioniert. Und fragen sich, warum Sie es durch die Implementierung eines anderen ersetzen möchten.
Vorteile für die Prüfung eines IoC-Containers eines Drittanbieters
Nachteile
Wägen Sie also Ihre Vorteile gegen Ihre Nachteile ab und treffen Sie eine Entscheidung.
quelle
Ich denke, der größte Teil des Werts eines IoC wird durch die Verwendung von DI erzielt. Da Sie dies bereits tun, ist der Rest des Vorteils inkrementell.
Der Wert, den Sie erhalten, hängt von der Art der Anwendung ab, an der Sie arbeiten:
Bei mehreren Mandanten kann der IoC-Container einen Teil des Infrastrukturcodes zum Laden verschiedener Clientressourcen übernehmen. Wenn Sie eine Komponente benötigen, die für den Client spezifisch ist, verwenden Sie einen benutzerdefinierten Selektor, um die Logik zu verarbeiten, und sorgen Sie sich nicht um sie aus Ihrem Client-Code. Sie können dies sicherlich selbst erstellen, aber hier ist ein Beispiel dafür, wie ein IoC helfen kann.
Mit vielen Erweiterungspunkten kann der IoC zum Laden von Komponenten aus der Konfiguration verwendet werden. Dies ist eine übliche Sache, aber Werkzeuge werden vom Container bereitgestellt.
Wenn Sie AOP für einige Querschnittsthemen verwenden möchten, bietet das IoC Hooks zum Abfangen von Methodenaufrufen. Dies wird bei Projekten seltener ad-hoc durchgeführt, aber das IoC erleichtert es.
Ich habe bereits solche Funktionen geschrieben, aber wenn ich jetzt eine dieser Funktionen benötige, würde ich lieber ein vorgefertigtes und getestetes Tool verwenden, wenn es zu meiner Architektur passt.
Wie von anderen erwähnt, können Sie auch zentral konfigurieren, welche Klassen Sie verwenden möchten. Dies kann zwar eine gute Sache sein, ist jedoch mit Fehlleitung und Komplikationen verbunden. Die Kernkomponenten für die meisten Anwendungen werden nicht viel ersetzt, so dass der Kompromiss etwas schwieriger ist.
Ich verwende einen IoC-Container und schätze die Funktionalität, muss aber zugeben, dass ich den Kompromiss bemerkt habe: Mein Code wird auf Klassenebene klarer und auf Anwendungsebene weniger klar (dh Visualisierung des Kontrollflusses).
quelle
Ich bin ein genesender IOC-Süchtiger. Ich finde es heutzutage in den meisten Fällen schwierig, die Verwendung von IOC für DI zu rechtfertigen. IOC-Container opfern die Überprüfung der Kompilierungszeit und bieten Ihnen im Gegenzug eine "einfache" Einrichtung, eine komplexe Lebensdauerverwaltung und die sofortige Erkennung von Abhängigkeiten zur Laufzeit. Ich finde, dass der Verlust der Überprüfung der Kompilierungszeit und die daraus resultierenden Laufzeitmagien / Ausnahmen in den allermeisten Fällen die Schnickschnack nicht wert sind. In großen Unternehmensanwendungen können sie es sehr schwierig machen, den Vorgängen zu folgen.
Ich kaufe das Zentralisierungsargument nicht, weil Sie das statische Setup auch sehr einfach zentralisieren können, indem Sie eine abstrakte Factory für Ihre Anwendung verwenden und die Objekterstellung religiös auf die abstrakte Factory verschieben, dh die richtige DI ausführen.
Warum nicht statische magiefreie DI so machen:
Ihre Containerkonfiguration ist Ihre abstrakte Factory-Implementierung. Ihre Registrierungen sind Implementierungen von abstrakten Mitgliedern. Wenn Sie eine neue Singleton-Abhängigkeit benötigen, fügen Sie der abstrakten Factory einfach eine weitere abstrakte Eigenschaft hinzu. Wenn Sie eine vorübergehende Abhängigkeit benötigen, fügen Sie einfach eine andere Methode hinzu und fügen Sie sie als Func <> ein.
Vorteile:
Ich empfehle Skeptikern, das nächste Green Field-Projekt auszuprobieren und sich ehrlich zu fragen, an welchem Punkt Sie den Container benötigen. Es ist einfach, einen IOC-Container später zu berücksichtigen, da Sie lediglich eine Factory-Implementierung durch ein IOC-Container-Konfigurationsmodul ersetzen.
quelle
Der größte Vorteil der Verwendung von IoC-Containern für mich (ich persönlich verwende Ninject) bestand darin, das Weitergeben von Einstellungen und anderen Arten von globalen Statusobjekten zu vermeiden.
Ich programmiere nicht für das Web, meine ist eine Konsolenanwendung und an vielen Stellen tief im Objektbaum muss ich Zugriff auf die vom Benutzer angegebenen Einstellungen oder Metadaten haben, die in einem vollständig separaten Zweig des Objektbaums erstellt werden. Mit IoC fordere ich Ninject einfach auf, die Einstellungen als Singleton zu behandeln (da es immer nur eine Instanz von ihnen gibt), die Einstellungen oder das Wörterbuch im Konstruktor anzufordern und vorab ... sie erscheinen magisch, wenn ich sie brauche!
Ohne Verwendung eines IoC-Containers müsste ich die Einstellungen und / oder Metadaten über 2, 3, ..., n Objekte weitergeben, bevor sie tatsächlich von dem Objekt verwendet werden, das sie benötigt.
DI / IoC-Container bieten viele weitere Vorteile, wie andere hier ausführlich beschrieben haben. Der Übergang von der Idee zum Erstellen von Objekten zum Anfordern von Objekten kann umwerfend sein. Die Verwendung von DI war jedoch für mich und mein Team sehr hilfreich, sodass Sie sie möglicherweise hinzufügen können zu deinem Arsenal!
quelle
IoC-Frameworks eignen sich hervorragend, wenn Sie ...
... Sicherheit wegwerfen. Viele (alle?) IoC-Frameworks zwingen Sie, den Code auszuführen, wenn Sie sicher sein möchten, dass alles korrekt angeschlossen ist. "Hey! Ich hoffe, ich habe alles eingerichtet, damit meine Initialisierungen dieser 100 Klassen in der Produktion nicht fehlschlagen und Nullzeiger-Ausnahmen auslösen!"
... Wurf Code mit Globals (IoC Frameworks sind alle globalen Zustände zu ändern).
... beschissenen Code mit unklaren Abhängigkeiten schreiben, der schwer zu überarbeiten ist, da Sie nie wissen, was von was abhängt.
Das Problem mit IoC ist, dass die Leute, die sie verwenden, Code wie diesen geschrieben haben
Das ist offensichtlich fehlerhaft, da die Abhängigkeit zwischen Foo und Bar fest verdrahtet ist. Dann erkannten sie, dass es besser wäre, Code wie zu schreiben
das ist auch fehlerhaft, aber weniger offensichtlich. In Haskell wäre die Art von
Foo()
,IO Foo
aber Sie wollen dasIO
-part wirklich nicht und es sollte ein Warnzeichen sein, dass etwas mit Ihrem Design nicht stimmt, wenn Sie es haben.Um es loszuwerden (den IO-Teil), nutzen Sie alle Vorteile von IoC-Frameworks und keinen seiner Nachteile. Sie könnten stattdessen eine abstrakte Factory verwenden.
Die richtige Lösung wäre so etwas wie
oder vielleicht
und injizieren (aber ich würde es nicht injizieren nennen) Bar.
Außerdem: Sehen Sie sich dieses Video mit Erik Meijer (Erfinder von LINQ) an, in dem er sagt, dass DI für Leute ist, die keine Mathematikkenntnisse haben (und ich könnte nicht mehr zustimmen): http://www.youtube.com/watch?v = 8Mttjyf-8P4
Im Gegensatz zu Mr. Spolsky glaube ich nicht, dass Leute, die IoC-Frameworks verwenden, sehr klug sind - ich glaube einfach, dass sie keine Mathematikkenntnisse haben.
quelle
IBar
es tatsächlich nichtIO IBar
). Und ja, im Haskell-Beispiel Ich kann keine Nullreferenz bekommen.Ich habe festgestellt, dass die korrekte Implementierung von Dependency Injection Programmierer dazu zwingt, eine Vielzahl anderer Programmierpraktiken zu verwenden, die dazu beitragen, die Testbarkeit, Flexibilität, Wartbarkeit und Skalierbarkeit von Code zu verbessern: Praktiken wie das Prinzip der Einzelverantwortung, Trennung von Bedenken und Codierung gegen APIs. Es fühlt sich so an, als ob ich gezwungen wäre, modularere Klassen und Methoden in Bissgröße zu schreiben, was das Lesen des Codes erleichtert, da er in mundgerechten Blöcken aufgenommen werden kann.
Es werden jedoch auch ziemlich große Abhängigkeitsbäume erstellt, die über ein Framework (insbesondere wenn Sie Konventionen verwenden) viel einfacher verwaltet werden können als von Hand. Heute wollte ich etwas sehr schnell in LINQPad testen, und ich dachte, es wäre zu mühsam, einen Kernel zu erstellen und meine Module zu laden, und am Ende schrieb ich dies von Hand:
Rückblickend wäre es schneller gewesen, das IoC-Framework zu verwenden, da die Module so ziemlich alles durch Konvention definieren.
Nachdem ich einige Zeit damit verbracht habe, die Antworten und Kommentare zu dieser Frage zu studieren, bin ich überzeugt, dass die Leute, die gegen die Verwendung eines IoC-Containers sind, keine echte Abhängigkeitsinjektion praktizieren. Die Beispiele, die ich gesehen habe, beziehen sich auf Praktiken, die häufig mit der Abhängigkeitsinjektion verwechselt werden. Einige Leute beschweren sich über Schwierigkeiten beim "Lesen" des Codes. Bei korrekter Ausführung sollte der überwiegende Teil Ihres Codes bei Verwendung von DI von Hand identisch sein wie bei Verwendung eines IoC-Containers. Der Unterschied sollte vollständig in einigen "Startpunkten" innerhalb der Anwendung liegen.
Mit anderen Worten, wenn Sie IoC-Container nicht mögen, führen Sie Dependency Injection wahrscheinlich nicht so durch, wie es gemacht werden soll.
Ein weiterer Punkt: Die Abhängigkeitsinjektion kann wirklich nicht von Hand durchgeführt werden, wenn Sie irgendwo Reflexion verwenden. Ich hasse es zwar, was Reflexion für die Code-Navigation bedeutet, aber Sie müssen erkennen, dass es bestimmte Bereiche gibt, in denen dies wirklich nicht vermieden werden kann. ASP.NET MVC versucht beispielsweise, den Controller bei jeder Anforderung durch Reflektion zu instanziieren. Um die Abhängigkeitsinjektion von Hand durchzuführen, müssten Sie jeden Controller wie folgt zu einem "Kontextstamm" machen:
Vergleichen Sie dies nun damit, dass ein DI-Framework dies für Sie tun kann:
Beachten Sie bei Verwendung eines DI-Frameworks Folgendes:
ISimpleWorkflowInstanceMerger
kann ich testen, ob es wie erwartet verwendet wird, ohne dass eine Datenbankverbindung oder ähnliches erforderlich ist.ISimpleWorkflowInstanceMerger
Schnittstelle enthält. Auf diese Weise kann ich die Anwendung in separate Module aufteilen und eine echte mehrschichtige Architektur beibehalten, was wiederum die Flexibilität der Dinge erheblich erhöht.Eine typische Webanwendung verfügt über einige Controller. Der ganze Schmerz, DI von Hand in jedem Controller auszuführen, wird sich wirklich summieren, wenn Ihre Anwendung wächst. Wenn Sie eine Anwendung mit nur einem Kontextstamm haben, die niemals versucht, einen Dienst durch Reflektion zu instanziieren, ist dies kein so großes Problem. Trotzdem wird die Verwaltung von Anwendungen, die Dependency Injection verwenden, ab Erreichen einer bestimmten Größe extrem teuer, es sei denn, Sie verwenden ein Framework zum Verwalten des Abhängigkeitsdiagramms.
quelle
Immer wenn Sie das Schlüsselwort "new" verwenden, erstellen Sie eine konkrete Klassenabhängigkeit, und in Ihrem Kopf sollte eine kleine Alarmglocke ertönen. Es wird schwieriger, dieses Objekt isoliert zu testen. Die Lösung besteht darin, auf Schnittstellen zu programmieren und die Abhängigkeit zu injizieren, damit das Objekt mit allem, was diese Schnittstelle implementiert (z. B. Mocks), einem Unit-Test unterzogen werden kann.
Das Problem ist, dass Sie irgendwo Objekte konstruieren müssen. Ein Factory-Muster ist eine Möglichkeit, die Kopplung aus Ihren POXOs zu verschieben (Plain Old-Objekte "Fügen Sie hier Ihre OO-Sprache ein"). Wenn Sie und Ihre Mitarbeiter alle Code wie diesen schreiben, ist ein IoC-Container die nächste "inkrementelle Verbesserung", die Sie an Ihrer Codebasis vornehmen können. Es wird all diesen fiesen Factory-Boilerplate-Code aus Ihren sauberen Objekten und Ihrer Geschäftslogik herausschieben. Sie werden es bekommen und lieben. Geben Sie einem Unternehmen einen Vortrag darüber, warum Sie es lieben, und begeistern Sie alle.
Wenn Ihre Mitarbeiter noch keine DI durchführen, sollten Sie sich zuerst darauf konzentrieren. Verbreiten Sie das Wort darüber, wie man sauberen Code schreibt, der leicht zu testen ist. Sauberer DI-Code ist der schwierige Teil. Wenn Sie dort sind, sollte es relativ trivial sein, die Objektverdrahtungslogik von Factory-Klassen in einen IoC-Container zu verschieben.
quelle
Da alle Abhängigkeiten deutlich sichtbar sind, werden Komponenten erstellt, die lose miteinander verbunden und gleichzeitig für die gesamte Anwendung leicht zugänglich und wiederverwendbar sind.
quelle
Sie nicht brauchen einen IoC - Container.
Wenn Sie jedoch konsequent einem DI-Muster folgen, werden Sie feststellen, dass mit einem solchen eine Menge redundanten, langweiligen Codes entfernt werden.
Dies ist ohnehin oft die beste Zeit, um eine Bibliothek / ein Framework zu verwenden - wenn Sie verstehen, was es tut und es ohne die Bibliothek tun könnten.
quelle
Ich bin gerade dabei, selbst entwickelten DI-Code herauszuziehen und durch ein IOC zu ersetzen. Ich habe wahrscheinlich weit über 200 Codezeilen entfernt und durch etwa 10 ersetzt. Ja, ich musste ein wenig lernen, wie man den Container verwendet (Winsor), aber ich bin Ingenieur und arbeite an Internet-Technologien in der 21. Jahrhundert, also bin ich daran gewöhnt. Ich habe wahrscheinlich ungefähr 20 Minuten damit verbracht, mir die Anleitungen anzusehen. Das war meine Zeit wert.
quelle
Während Sie Ihre Klassen weiter entkoppeln und Ihre Abhängigkeiten invertieren, bleiben die Klassen weiterhin klein und das "Abhängigkeitsdiagramm" wird immer größer. (Dies ist nicht schlecht.) Die Verwendung der Grundfunktionen eines IoC-Containers macht die Verkabelung all dieser Objekte trivial, aber die manuelle Ausführung kann sehr mühsam werden. Was ist zum Beispiel, wenn ich eine neue Instanz von "Foo" erstellen möchte, aber eine "Leiste" benötigt? Und ein "Balken" braucht ein "A", "B" und "C". Und jeder von ihnen braucht 3 andere Dinge usw. usw. (ja, ich kann mir keine guten falschen Namen einfallen lassen :)).
Die Verwendung eines IoC-Containers zum Erstellen Ihres Objektdiagramms für Sie reduziert die Komplexität um eine Tonne und überträgt es in eine einmalige Konfiguration. Ich sage einfach "Erstelle mir ein 'Foo'" und es findet heraus, was benötigt wird, um eines zu bauen.
Einige Leute verwenden die IoC-Container für viel mehr Infrastruktur, was für fortgeschrittene Szenarien in Ordnung ist, aber in diesen Fällen stimme ich zu, dass sie Code verschleiern und das Lesen und Debuggen für neue Entwickler erschweren können.
quelle
Das Gleiche gilt für die Einheit. Wenn Sie zu groß werden, können Sie das Knarren in den Sparren hören.
Es überrascht mich nie, wenn Leute anfangen darüber zu reden, wie sauber IoC-Code aussieht, wie die gleichen Leute, die einmal darüber gesprochen haben, wie Vorlagen in C ++ in den 90er Jahren der elegante Weg waren, sie heutzutage als arkan zu entschlüsseln . Bah!
quelle
In der .NET-Welt ist AOP nicht allzu beliebt, daher ist für DI ein Framework Ihre einzige echte Option, unabhängig davon, ob Sie eines selbst schreiben oder ein anderes Framework verwenden.
Wenn Sie AOP verwendet haben, können Sie diese beim Kompilieren Ihrer Anwendung injizieren, was in Java häufiger vorkommt.
DI bietet viele Vorteile, z. B. eine reduzierte Kopplung, sodass das Testen von Einheiten einfacher ist. Wie werden Sie es jedoch implementieren? Möchten Sie Reflexion verwenden, um es selbst zu tun?
quelle
Es sind also fast 3 Jahre vergangen, oder?
50% derjenigen, die sich für IoC-Frameworks ausgesprochen haben, verstehen den Unterschied zwischen IoC- und IoC-Frameworks nicht. Ich bezweifle, dass sie wissen, dass Sie Code schreiben können, ohne auf einem App-Server bereitgestellt zu werden
Wenn wir das beliebteste Java Spring-Framework verwenden, wird die IoC-Konfiguration von XMl in den Code verschoben und sieht nun so aus
`@Configuration öffentliche Klasse AppConfig {
} `Und wir brauchen einen Rahmen, um dies zu tun, warum genau?
quelle
Ehrlich gesagt finde ich nicht, dass es viele Fälle gibt, in denen IoC-Container benötigt werden, und meistens fügen sie nur unnötige Komplexität hinzu.
Wenn Sie es nur verwenden, um die Konstruktion eines Objekts zu vereinfachen, muss ich fragen, ob Sie dieses Objekt an mehr als einer Stelle instanziieren. Würde ein Singleton nicht Ihren Bedürfnissen entsprechen? Ändern Sie die Konfiguration zur Laufzeit? (Wechseln der Datenquellentypen usw.).
Wenn ja, benötigen Sie möglicherweise einen IoC-Container. Wenn nicht, verschieben Sie die Initialisierung nur von der Stelle, an der der Entwickler sie leicht sehen kann.
Wer hat gesagt, dass eine Schnittstelle sowieso besser ist als Vererbung? Angenommen, Sie testen einen Dienst. Warum nicht den Konstruktor DI verwenden und mithilfe der Vererbung Verspottungen der Abhängigkeiten erstellen? Die meisten Dienste, die ich benutze, haben nur wenige Abhängigkeiten. Doing Unit - Tests auf diese Weise verhindert , dass eine Tonne nutzlos Schnittstellen beibehalten und bedeutet , dass Sie nicht haben zu ReSharper verwenden , um schnell die Deklaration einer Methode zu finden.
Ich glaube, dass es für die meisten Implementierungen ein Mythos ist, zu sagen, dass IoC-Container nicht benötigten Code entfernen.
Zuerst wird der Container eingerichtet. Dann müssen Sie noch jedes Objekt definieren, das initialisiert werden muss. Sie speichern also keinen Code bei der Initialisierung, sondern verschieben ihn (es sei denn, Ihr Objekt wird mehrmals verwendet. Ist es besser als Singleton?). Anschließend müssen Sie für jedes Objekt, das Sie auf diese Weise initialisiert haben, eine Schnittstelle erstellen und verwalten.
Hat jemand irgendwelche Gedanken dazu?
quelle
ShippingCostCalculator
oderProductUIPresentation
eine andere Strategie / Implementierung innerhalb genau derselben Codebasis konfigurieren oder austauschen , indem Sie nur eine geänderte XML-Datei bereitstellen.Sie benötigen einen IoC-Container, wenn Sie die Konfiguration Ihrer Abhängigkeiten zentralisieren müssen, damit sie problemlos in großen Mengen ausgetauscht werden können. Dies ist am sinnvollsten bei TDD, wo viele Abhängigkeiten ausgetauscht werden, die Abhängigkeiten jedoch nur wenig voneinander abhängig sind. Dies geschieht auf Kosten einer Verschleierung des Kontrollflusses der Objektkonstruktion bis zu einem gewissen Grad. Daher ist eine gut organisierte und angemessen dokumentierte Konfiguration wichtig. Es ist auch gut, einen Grund dafür zu haben, sonst ist es nur eine Vergoldung der Abstraktion . Ich habe gesehen, dass es so schlecht gemacht wurde, dass es heruntergezogen wurde, um einer goto-Anweisung für Konstruktoren zu entsprechen.
quelle
Hier ist warum. Das Projekt heißt IOC-with-Ninject. Sie können es mit Visual Studio herunterladen und ausführen. In diesem Beispiel wird Ninject verwendet, aber ALLE 'neuen' Anweisungen befinden sich an einem Speicherort. Sie können die Ausführung Ihrer Anwendung vollständig ändern, indem Sie das zu verwendende Bindungsmodul ändern. Das Beispiel ist so eingerichtet, dass Sie an eine verspottete Version der Dienste oder an die reale Version binden können. Bei kleinen Projekten spielt das vielleicht keine Rolle, aber bei großen Projekten ist es eine große Sache.
Um ganz klar zu sein, Vorteile, wie ich sie sehe: 1) ALLE neuen Anweisungen an einer Stelle im Stammverzeichnis des Codes. 2) Code mit einer Änderung komplett neu faktorisieren. 3) Extrapunkte für 'Cool Factor', weil es ... gut: cool ist. : p
quelle
Ich werde versuchen herauszufinden, warum das IOC aus meiner Sicht möglicherweise nicht gut ist.
Wie bei allem anderen ist der IOC-Container (oder wie Einstein es ausdrücken würde, I = OC ^ 2) ein Konzept, das Sie selbst entscheiden müssen, ob Sie es in Ihrem Code benötigen oder nicht. Der jüngste Aufschrei der Mode über IOC ist nur das, Mode. Verlieben Sie sich nicht in Mode, das ist das Erste. Es gibt unzählige Konzepte, die Sie in Ihren Code implementieren können. Zunächst verwende ich die Abhängigkeitsinjektion, seit ich mit dem Programmieren begonnen habe, und habe den Begriff selbst gelernt, als er unter diesem Namen populär gemacht wurde. Die Abhängigkeitskontrolle ist ein sehr altes Thema und wurde bisher auf Billionen von Wegen behandelt, je nachdem, was von was entkoppelt wurde. Alles von allem zu entkoppeln ist ein Unsinn. Das Problem mit dem IOC-Container besteht darin, dass er versucht, genauso nützlich zu sein wie Entity Framework oder NHibernate. Während das Schreiben eines objektrelationalen Mappers einfach ein Muss ist, sobald Sie eine Datenbank mit Ihrem System koppeln müssen, ist ein IOC-Container nicht immer erforderlich. Also, wenn IOC-Container nützlich ist:
1: Es kommt nicht so oft vor, dass Sie so viele Abhängigkeiten in Ihrem Code haben oder dass Sie diese schon früh im Design kennen. Abstraktes Denken ist nützlich, wenn abstraktes Denken fällig ist.
2: Das Koppeln Ihres Codes mit Code von Drittanbietern ist ein HuGe-Problem. Ich habe mit Code gearbeitet, der mehr als 10 Jahre alt ist und der damals ausgefallenen und fortgeschrittenen Konzepten wie ATL, COM, COM + und so weiter folgte. Mit diesem Code können Sie jetzt nichts mehr tun. Was ich damit sagen will ist, dass ein fortschrittliches Konzept einen offensichtlichen Vorteil bietet, der jedoch langfristig mit dem veralteten Vorteil selbst aufgehoben wird. Es hatte einfach alles teurer gemacht.
3: Softwareentwicklung ist schwer genug. Sie können es auf nicht erkennbare Ebenen erweitern, wenn Sie zulassen, dass ein erweitertes Konzept in Ihren Code eingefügt wird. Es gibt ein Problem mit IOC2. Obwohl es Abhängigkeiten entkoppelt, entkoppelt es auch den Logikfluss. Stellen Sie sich vor, Sie haben einen Fehler gefunden und müssen eine Pause einlegen, um die Situation zu untersuchen. IOC2 macht dies wie jedes andere fortschrittliche Konzept schwieriger. Das Beheben eines Fehlers innerhalb eines Konzepts ist schwieriger als das Beheben eines Fehlers in einem einfacheren Code, da beim Beheben eines Fehlers ein Konzept erneut befolgt werden muss. (Um nur ein Beispiel zu nennen: C ++ .NET ändert die Syntax ständig so stark, dass Sie gründlich überlegen müssen, bevor Sie eine ältere Version von .NET überarbeiten.) Wo liegt also das Problem mit IOC? Das Problem besteht in der Lösung von Abhängigkeiten. Die Logik zum Auflösen ist üblicherweise im IOC2 selbst verborgen. geschrieben vielleicht auf ungewöhnliche Weise, die Sie lernen und pflegen müssen. Wird Ihr Drittanbieterprodukt in 5 Jahren verfügbar sein? Microsoft war nicht.
Das "Wir wissen wie" -Syndrom ist in Bezug auf IOC2 allgegenwärtig. Dies ähnelt dem Testen der Automatisierung. Ausgefallene Laufzeit und perfekte Lösung auf den ersten Blick: Sie lassen einfach alle Ihre Tests über Nacht ausführen und sehen die Ergebnisse am Morgen. Es ist wirklich schmerzhaft, Unternehmen für Unternehmen zu erklären, was automatisierte Tests wirklich bedeuten. Automatisierte Tests sind definitiv kein schneller Weg, um die Anzahl der Fehler zu reduzieren, die Sie über Nacht einführen können, um die Qualität Ihres Produkts zu verbessern. Aber die Mode macht diesen Begriff ärgerlich dominant. IOC2 leidet unter dem gleichen Syndrom. Es wird angenommen, dass Sie es implementieren müssen, damit Ihre Software gut ist. Jedes kürzlich geführte Interview wurde mich gefragt, ob ich IOC2 und Automatisierung implementiere. Das ist ein Zeichen der Mode: Das Unternehmen hat einen Teil des Codes in MFC geschrieben, den sie nicht aufgeben werden.
Sie müssen IOC2 wie jedes andere Konzept in Software lernen. Die Entscheidung, ob IOC2 verwendet werden muss, liegt im Team und im Unternehmen. Mindestens ALLE oben genannten Argumente müssen jedoch erwähnt werden, bevor die Entscheidung getroffen wird. Nur wenn Sie sehen, dass die Plus-Seite die negative Seite überwiegt, können Sie eine positive Entscheidung treffen.
An IOC2 ist nichts auszusetzen, außer dass es nur die Probleme löst, die es löst, und die Probleme einführt, die es einführt. Nichts anderes. Es ist jedoch sehr schwierig, gegen die Mode vorzugehen, sie haben einen schweißtreibenden Mund, die Anhänger von allem. Es ist seltsam, wie keiner von ihnen da ist, wenn das Problem mit ihrer Phantasie offensichtlich wird. Viele Konzepte in der Softwareindustrie wurden verteidigt, weil sie Gewinn bringen, Bücher geschrieben, Konferenzen abgehalten und neue Produkte hergestellt werden. Das ist Mode, normalerweise von kurzer Dauer. Sobald Menschen etwas anderes finden, geben sie es vollständig auf. IOC2 ist nützlich, zeigt aber die gleichen Anzeichen wie viele andere verschwundene Konzepte, die ich gesehen habe. Ich weiß nicht, ob es überleben wird. Dafür gibt es keine Regel. Sie denken, wenn es nützlich ist, wird es überleben. Nein, so geht es nicht. Ein großes, reiches Unternehmen reicht aus und das Konzept kann innerhalb weniger Wochen sterben. Wir werden sehen. NHibernate überlebte, EF wurde Zweiter. Vielleicht überlebt IOC2 auch. Vergessen Sie nicht, dass die meisten Konzepte in der Softwareentwicklung nichts Besonderes sind, sie sind sehr logisch, einfach und offensichtlich, und manchmal ist es schwieriger, sich an die aktuelle Namenskonvention zu erinnern, als das Konzept selbst zu verstehen. Macht das Wissen über IOC2 einen Entwickler zu einem besseren Entwickler? Nein, denn wenn ein Entwickler nicht in der Lage war, ein Konzept zu entwickeln, das IOC2 ähnelt, ist es für ihn schwierig zu verstehen, welches Problem IOC2 löst. Die Verwendung sieht künstlich aus und er oder sie beginnt möglicherweise damit um politisch korrekt zu sein. Vergessen Sie nicht, dass die meisten Konzepte in der Softwareentwicklung nichts Besonderes sind, sie sind sehr logisch, einfach und offensichtlich, und manchmal ist es schwieriger, sich an die aktuelle Namenskonvention zu erinnern, als das Konzept selbst zu verstehen. Macht das Wissen über IOC2 einen Entwickler zu einem besseren Entwickler? Nein, denn wenn ein Entwickler nicht in der Lage war, ein Konzept zu entwickeln, das IOC2 ähnelt, ist es für ihn schwierig zu verstehen, welches Problem IOC2 löst. Die Verwendung sieht künstlich aus und er oder sie beginnt möglicherweise damit um politisch korrekt zu sein. Vergessen Sie nicht, dass die meisten Konzepte in der Softwareentwicklung nichts Besonderes sind, sie sind sehr logisch, einfach und offensichtlich, und manchmal ist es schwieriger, sich an die aktuelle Namenskonvention zu erinnern, als das Konzept selbst zu verstehen. Macht das Wissen über IOC2 einen Entwickler zu einem besseren Entwickler? Nein, denn wenn ein Entwickler nicht in der Lage war, ein Konzept zu entwickeln, das IOC2 ähnelt, ist es für ihn schwierig zu verstehen, welches Problem IOC2 löst. Die Verwendung sieht künstlich aus und er oder sie beginnt möglicherweise damit um politisch korrekt zu sein. Macht das Wissen über IOC2 einen Entwickler zu einem besseren Entwickler? Nein, denn wenn ein Entwickler nicht in der Lage war, ein Konzept zu entwickeln, das IOC2 ähnelt, ist es für ihn schwierig zu verstehen, welches Problem IOC2 löst. Die Verwendung sieht künstlich aus und er oder sie beginnt möglicherweise damit um politisch korrekt zu sein. Macht das Wissen über IOC2 einen Entwickler zu einem besseren Entwickler? Nein, denn wenn ein Entwickler nicht in der Lage war, ein Konzept zu entwickeln, das IOC2 ähnelt, ist es für ihn schwierig zu verstehen, welches Problem IOC2 löst. Die Verwendung sieht künstlich aus und er oder sie beginnt möglicherweise damit um politisch korrekt zu sein.
quelle
Persönlich verwende ich IoC als eine Art Strukturkarte meiner Anwendung (Ja, ich bevorzuge auch StructureMap;)). Es macht es einfach, meine üblichen Schnittstellenimplementierungen während der Tests durch Moq-Implementierungen zu ersetzen. Das Erstellen eines Test-Setups kann so einfach sein wie ein neuer Init-Aufruf meines IoC-Frameworks, bei dem die Klasse, die meine Testgrenze ist, durch ein Mock ersetzt wird.
Dies ist wahrscheinlich nicht das, wofür IoC da ist, aber es ist das, wofür ich es am meisten benutze.
quelle
IOC CONTAINER LÖST EIN PROBLEM, DAS SIE möglicherweise NICHT HABEN, ABER ES IST EIN SCHÖNES PROBLEM
http://kozmic.net/2012/10/23/ioc-container-solves-a-problem-you-might-not-have-but-its-a-nice-problem-to-have/
quelle
Sie benötigen kein Framework, um eine Abhängigkeitsinjektion zu erreichen. Sie können dies auch mit Java-Kernkonzepten tun. http://en.wikipedia.org/wiki/Dependency_injection#Code_illustration_using_Java
quelle
Mir ist klar, dass dies ein ziemlich alter Beitrag ist, aber er scheint immer noch einigermaßen aktiv zu sein, und ich dachte, ich würde ein paar Punkte beisteuern, die in anderen Antworten noch nicht erwähnt wurden.
Ich werde sagen, dass ich mit den Vorteilen der Abhängigkeitsinjektion einverstanden bin, aber ich ziehe es vor, die Objekte selbst zu konstruieren und zu verwalten, wobei ich ein Muster verwende, das dem von Maxm007 in seiner Antwort beschriebenen nicht unähnlich ist. Ich habe zwei Hauptprobleme bei der Verwendung von Containern von Drittanbietern festgestellt:
1) Wenn eine Bibliothek eines Drittanbieters die Lebensdauer Ihrer Objekte "automatisch" verwaltet, kann dies zu unerwarteten Ergebnissen führen. Wir haben festgestellt, dass Sie insbesondere in großen Projekten erheblich mehr Kopien eines Objekts haben können, als Sie erwarten, und mehr als wenn Sie die Lebenszyklen manuell verwalten würden. Ich bin sicher, dass dies je nach verwendetem Framework unterschiedlich ist, aber das Problem besteht trotzdem. Dies kann auch problematisch sein, wenn Ihr Objekt Ressourcen, Datenverbindungen usw. enthält, da das Objekt manchmal länger als erwartet leben kann. Daher erhöhen IoC-Container zwangsläufig die Ressourcennutzung und den Speicherbedarf einer Anwendung.
2) IoC-Container sind meiner Meinung nach eine Form der "Black-Box-Programmierung". Ich habe festgestellt, dass insbesondere unsere weniger erfahrenen Entwickler dazu neigen, sie zu missbrauchen. Es ermöglicht dem Programmierer, nicht darüber nachdenken zu müssen, wie Objekte zueinander in Beziehung stehen sollen oder wie sie entkoppelt werden sollen, da es ihnen einen Mechanismus bietet, mit dem sie einfach jedes gewünschte Objekt aus der Luft greifen können. Beispielsweise kann es einen guten Entwurfsgrund geben, dass ObjectA niemals direkt über ObjectB Bescheid wissen sollte, aber anstatt eine Fabrik, eine Brücke oder einen Service-Locator zu erstellen, sagt ein unerfahrener Programmierer einfach: "Kein Problem, ich hole ObjectB einfach aus dem IoC-Container." ". Dies kann tatsächlich zu einer erhöhten Objektkopplung führen, was IoC verhindern soll.
quelle
Die Abhängigkeitsinjektion in einem ASP.NET-Projekt kann mit wenigen Codezeilen durchgeführt werden. Ich nehme an, dass die Verwendung eines Containers einen gewissen Vorteil hat, wenn Sie eine App haben, die mehrere Frontends verwendet und Unit-Tests benötigt.
quelle