Abhängigkeitsinjektion: Soll ich ein Framework verwenden?

24

Ich habe kürzlich an einem Python-Projekt gearbeitet, in dem wir eine starke Abhängigkeitsinjektion durchgeführt haben (weil wir dies tun müssen, damit die App testbar ist), aber wir haben kein Framework verwendet. Manchmal war es etwas mühsam, alle Abhängigkeiten manuell zu verbinden, aber insgesamt hat es super funktioniert.

Wenn ein Objekt an mehreren Stellen erstellt werden musste, hatten wir einfach eine Funktion (manchmal eine Klassenmethode dieses Objekts), um eine Produktionsinstanz zu erstellen. Diese Funktion wurde aufgerufen, wann immer wir das Objekt brauchten.

In den Tests haben wir dasselbe getan: Wenn wir mehrere Male eine 'Testversion' eines Objekts (dh eine von Scheinobjekten gesicherte reale Instanz) erstellen mussten, hatten wir eine Funktion, um diese 'Testversion' zu erstellen. einer Klasse, die in Tests verwendet werden soll.

Wie gesagt, im Allgemeinen hat das gut funktioniert.

Ich betrete jetzt ein neues Java-Projekt und wir entscheiden, ob wir ein DI-Framework verwenden oder DI manuell ausführen (wie im vorherigen Projekt).

Bitte erläutern Sie, wie sich die Arbeit mit einem DI-Framework unterscheidet und wie sie besser oder schlechter ist als die manuelle 'Vanille'-Abhängigkeitsinjektion.

Bearbeiten: Ich möchte auch zu der Frage hinzufügen: Haben Sie ein professionelles Projekt erlebt, das DI manuell ohne Rahmen ausführt?

Aviv Cohn
quelle
Neben meiner Antwort. Beide Wege sind kompatibel. Sie können Soft-Dependency-Injection dem Framework überlassen und Ihre Fabriken für kritische Komponenten behalten. Komponenten, die sich auf das Modell oder Geschäft beziehen.
Laiv
4
Ich denke, Sie haben es bereits überprüft, nur für den Fall, dass Sie es nicht tun. Warum benötigen wir Frameworks für DI?
Laiv

Antworten:

19

Der Schlüssel von DI-Containern ist die Abstraktion . DI-Behälter abstrahieren dieses Designanliegen für Sie. Wie Sie sich vorstellen können, hat dies spürbare Auswirkungen auf den Code, der häufig in weniger Konstrukteure, Setter, Fabriken und Builder übersetzt wird. Infolgedessen wird Ihr Code (aufgrund der zugrunde liegenden IoC ) lockerer , sauberer und einfacher gekoppelt . Obwohl nicht ohne Kosten.

Hintergründe

Vor Jahren mussten wir für eine solche Abstraktion verschiedene Konfigurationsdateien schreiben ( deklarative Programmierung ). Es war fantastisch zu sehen, wie sich die Anzahl der LOCs erheblich verringerte, aber während die LOCSs abnahmen, stieg die Anzahl der Konfigurationsdateien leicht an. Für mittlere oder kleine Projekte war es überhaupt kein Problem, aber für größere Projekte wurde das Problem, dass die "Assemblierung des Codes" zu 50% zwischen Code- und XML-Deskriptoren verstreut war, zu einem ... Das Hauptproblem war jedoch das Paradigma selbst. Es war ziemlich unflexibel, weil die Deskriptoren wenig Platz für Anpassungen ließen.

Das Paradigma verlagerte sich zunehmend in Richtung Konvention über Konfiguration , bei der Konfigurationsdateien gegen Anmerkungen oder Attribute ausgetauscht werden. Es hält unseren Code sauberer und einfacher und bietet uns gleichzeitig die Flexibilität, die XML nicht bieten konnte.

Dies ist wahrscheinlich der bedeutendste Unterschied in Bezug auf Ihre bisherige Arbeitsweise. Weniger Code und mehr Magie.

Auf der Unterseite...

Konvention über Konfiguration macht die Abstraktion so schwer, dass Sie kaum wissen, wie es funktioniert. Manchmal magisch und hier kommt noch ein Nachteil. Sobald es funktioniert, kümmern sich viele Entwickler nicht mehr darum, wie es funktioniert.

Dies ist ein Handicap für diejenigen, die DI mit DI-Containern gelernt haben. Sie verstehen die Relevanz der Entwurfsmuster, der bewährten Verfahren und der Prinzipien, die vom Container abstrahiert wurden, nicht vollständig. Ich habe Entwickler gefragt, ob sie mit DI und seinen Vorteilen vertraut sind, und sie haben geantwortet: - Ja, ich habe Spring IoC verwendet -. (Was zur Hölle heißt das?!?)

Man kann jedem dieser "Nachteile" zustimmen oder nicht. Meiner bescheidenen Meinung nach ist es ein Muss zu wissen, was in Ihrem Projekt vor sich geht. Ansonsten haben wir kein vollständiges Verständnis davon. Es ist auch von Vorteil, zu wissen, wofür DI ist, und eine Vorstellung davon zu haben, wie es implementiert werden soll.

Auf der positiven Seite...

Ein Wort Produktivität . Mit Frameworks können wir uns auf das konzentrieren, was wirklich wichtig ist. Das Geschäft der Anwendung.

Trotz der bemerkten Mängel sind diese Tools für viele von uns (welcher Job durch Termine und Kosten bedingt ist) eine unschätzbare Ressource. Meiner Meinung nach sollte dies unser Hauptargument für die Implementierung eines DI-Containers sein. Produktivität .

Testen

Unabhängig davon, ob wir reine DI oder Container implementieren, ist das Testen kein Problem. Ganz im Gegenteil. Die gleichen Behälter liefern uns oft die Mocks für Unit-Tests aus der Box. Im Laufe der Jahre habe ich meine Tests als Thermometer verwendet. Sie sagen mir, ob ich mich stark auf die Containereinrichtungen verlassen habe. Ich sage das, weil diese Container private Attribute ohne Setter oder Konstruktoren initialisieren können. Sie können Bauteile fast überall einspritzen!

Klingt verlockend, oder? Achtung! Fallen Sie nicht in die Falle !!

Vorschläge

Wenn Sie sich für die Implementierung von Containern entscheiden, empfehle ich dringend, sich an die bewährten Methoden zu halten. Implementieren Sie weiterhin Konstruktoren, Setter und Interfaces. Erzwingen Sie die Verwendung des Frameworks / Containers . Dies erleichtert die Migration in ein anderes Framework oder das Entfernen des eigentlichen Frameworks. Dies kann die Abhängigkeit vom Container erheblich verringern.

In Bezug auf diese Praktiken:

Wann sind DI-Container zu verwenden?

Meine Antwort wird durch die eigenen Erfahrungen verzerrt sein, die hauptsächlich für DI-Container sprechen (wie ich bemerkte, konzentriere ich mich stark auf Produktivität, so dass ich nie die Notwendigkeit einer reinen DI hatte. Ganz im Gegenteil).

Ich denke, Sie werden einen interessanten Artikel von Mark Seeman zu diesem Thema finden, der auch die Frage beantwortet, wie man reine DI implementiert .

Wenn wir schließlich von Java sprechen, würde ich zunächst einen Blick auf JSR330 - Dependency Injection werfen .

Zusammenfassend

Vorteile :

  • Kostensenkung und Zeitersparnis. Produktivität.
  • Eine kleinere Anzahl von Komponenten.
  • Der Code wird einfacher und sauberer.

Nachteile :

  • DI wird an Drittanbieter-Bibliotheken delegiert. Wir sollten uns ihrer Kompromisse, Stärken und Schwächen bewusst sein.
  • Lernkurve.
  • Sie lassen Sie schnell einige gute Gewohnheiten vergessen.
  • Erhöhung der Projektabhängigkeiten (mehr Bibliotheken)
  • Auf Reflexion basierende Container benötigen mehr Ressourcen (Speicher). Dies ist wichtig, wenn wir durch die Ressourcen eingeschränkt werden.

Unterschiede zu reinem DI :

  • Weniger Code und mehr Konfigurationsdateien oder Anmerkungen.
Laiv
quelle
1
"Diese Frameworks sind nicht für Sie privat, um Komponententests oder Integritätstests durchzuführen. Machen Sie sich also keine Gedanken über Tests." Was genau bedeutet das? Die Formulierung lässt mich denken, dass es ein Tippfehler ist, aber ich habe Probleme, ihn zu dekodieren.
candied_orange
Dies bedeutet, dass das zeitaufwändige Debuggen oder die Verwendung der Frameworks zum Testen keine ausreichenden Nachteile darstellen, um diese Frameworks zu verwenden. Denn auch wenn Sie sie nicht mögen, haben sie doch Vorteile, die einen Versuch wert sind. Die großen Nachteile sind keine Frameworks für sich. So benutzt du sie. Einige bewährte Methoden wie Schnittstellen und Setter sind weiterhin erforderlich, auch wenn Ihr Framework dies nicht tut. Schließlich gibt es gute Bibliotheken zum Testen, die sich leicht in diese Art von Frameworks (DI) integrieren lassen
Laiv,
Wenn Sie das meinen,
denken
Srry. Ich versuche zu sagen, dass er seinen Code auch mit diesen Frameworks testen kann. Trotz der Abstraktion können Tests durchgeführt werden. Fühlen Sie sich frei, meine Antwort zu bearbeiten. Wie Sie sehen, ist mein Englisch noch weit davon entfernt, anständig zu sein :-)
Laiv,
1
Beachten Sie, dass Dolch2 DI etwas anders macht. Der Glue-Code wird zur Kompilierungszeit wie normale, lesbare Java-Quellen generiert, sodass es viel einfacher ist zu verfolgen, wie die Dinge zusammengeklebt werden, als sich mit Laufzeitmagie zu befassen.
Thorbjørn Ravn Andersen
10

Nach meiner Erfahrung führt ein Abhängigkeitsinjektionsframework zu einer Reihe von Problemen. Einige der Probleme hängen vom Framework und den Tools ab. Möglicherweise gibt es Vorgehensweisen, die die Probleme lindern. Aber das sind die Probleme, die ich getroffen habe.

Nicht globale Objekte

In einigen Fällen möchten Sie ein globales Objekt einfügen: Ein Objekt, das nur eine Instanz in Ihrer ausgeführten Anwendung enthält. Dies könnte eine seinMarkdownToHtmlRendererer , a DatabaseConnectionPool, die Adresse für Ihren API-Server usw. sein. In diesen Fällen funktionieren Abhängigkeitsinjektions-Frameworks sehr einfach. Fügen Sie einfach die erforderliche Abhängigkeit zu Ihrem Konstruktor hinzu, und Sie haben sie.

Aber was ist mit Objekten, die nicht global sind? Was ist, wenn Sie den Benutzer für die aktuelle Anforderung benötigen? Was ist, wenn Sie die aktuell aktive Datenbanktransaktion benötigen? Was ist, wenn Sie das HTML-Element für das div benötigen, das eine Form enthält, in der sich ein Textfeld befindet, das gerade ein Ereignis ausgelöst hat?

Die Lösung, die ich bei DI-Frameworks gesehen habe, sind hierarchische Injektoren. Dies macht das Einspritzmodell jedoch komplizierter. Es wird schwieriger, herauszufinden, was aus welcher Hierarchieebene injiziert wird. Es wird schwierig zu sagen, ob ein bestimmtes Objekt pro Anwendung, pro Benutzer, pro Anforderung usw. vorhanden ist. Sie können nicht mehr nur Ihre Abhängigkeiten hinzufügen und es funktionieren lassen.

Bibliotheken

Oft möchten Sie eine Bibliothek mit wiederverwendbarem Code haben. Dies enthält auch Anweisungen zum Erstellen von Objekten aus diesem Code. Wenn Sie ein Abhängigkeitsinjektionsframework verwenden, enthält dieses normalerweise Bindungsregeln. Wenn Sie die Bibliothek verwenden möchten, fügen Sie deren Bindungsregeln zu Ihren hinzu.

Es können sich jedoch verschiedene Probleme ergeben. Möglicherweise wird dieselbe Klasse an verschiedene Implementierungen gebunden. Die Bibliothek erwartet möglicherweise bestimmte Bindungen. Die Bibliothek überschreibt möglicherweise einige Standardbindungen, was dazu führt, dass Ihr Code seltsame Dinge tut. Ihr Code überschreibt möglicherweise eine Standardbindung, wodurch der Bibliothekscode seltsame Dinge tut.

Versteckte Komplexität

Wenn Sie Fabriken manuell schreiben, haben Sie ein Gefühl dafür, wie die Abhängigkeiten der Anwendung zusammenpassen. Wenn Sie ein Abhängigkeitsinjektionsframework verwenden, wird dies nicht angezeigt. Stattdessen neigen Objekte dazu, immer mehr Abhängigkeiten zu entwickeln, bis früher oder später alles von so ziemlich allem abhängt.

IDE-Unterstützung

Ihre IDE wird das Framework für die Abhängigkeitsinjektion wahrscheinlich nicht verstehen. In manuellen Fabriken finden Sie alle Aufrufer eines Konstruktors, um alle Stellen herauszufinden, an denen das Objekt möglicherweise erstellt wird. Die vom DI-Framework generierten Aufrufe werden jedoch nicht gefunden.

Fazit

Was erhalten wir von einem Abhängigkeitsinjektionsframework? Wir müssen ein einfaches Boilerplate vermeiden, das zum Instanziieren von Objekten benötigt wird. Ich bin alles dafür, einfältige Kesselplatten zu eliminieren. Es ist jedoch einfach, eine einfache Kesselplatte zu warten. Wenn wir diese Heizplatte ersetzen wollen, sollten wir darauf bestehen, sie durch etwas einfacheres zu ersetzen. Aufgrund der verschiedenen Probleme, die ich oben besprochen habe, glaube ich nicht, dass Frameworks (zumindest so wie sie sind) der Rechnung entsprechen.

Winston Ewert
quelle
Dies ist eine sehr gute Antwort, aber ich kann mir nicht vorstellen, einen IoC-Container für eine Klassenbibliothek zu verwenden. Das fühlt sich für mich nach schlechtem Design an. Ich würde von einer Bibliothek erwarten, dass sie mir explizit alle erforderlichen Abhängigkeiten gibt.
RubberDuck
@RubberDuck, in meinem Fall habe ich für ein großes Unternehmen mit einer großen Anzahl von Java-Projekten gearbeitet, die alle auf demselben Framework für die Abhängigkeitsinjektion standardisiert sind. An diesem Punkt wird es für einige Teams verlockend, eine Bibliothek zu exportieren, die vom DI-Framework zusammengestellt werden soll, anstatt eine sinnvolle externe Schnittstelle bereitzustellen.
Winston Ewert
Das ist leider @WinstonEwert. Vielen Dank, dass Sie den Kontext für mich ausgefüllt haben.
RubberDuck
Es wäre toll, IDE-Teil, mit der Laufzeitbindung von Injektionen Framework im Gegensatz zu Design-Time-Typ-Bindung von manuellen Injektionen. Der Compiler verhindert vergessene Injektionen, wenn sie manuell sind.
Basilevs
IntelliJ versteht CDI (Java EE Standard DI)
Thorbjørn Ravn Andersen
3

Ist Java + Dependency Injection = Framework erforderlich?

Nein.

Was bringt mir ein DI-Framework?

Die Objektkonstruktion erfolgt in einer Sprache, die nicht Java ist.


Wenn die Factory-Methoden für Ihre Anforderungen gut genug sind, können Sie DI in Java vollständig ohne Framework in 100% authentischem Pojo Java ausführen. Wenn Ihre Bedürfnisse darüber hinausgehen, haben Sie andere Möglichkeiten.

Die Designmuster der Gang of Four bringen viele großartige Dinge zustande, hatten aber immer Schwächen, wenn es um die Kreationsmuster ging. Java selbst hat hier einige Schwächen. DI-Frameworks helfen bei dieser kreativen Schwäche mehr als bei den eigentlichen Injektionen. Sie wissen schon, wie man das ohne sie macht. Wie viel Gutes sie tun, hängt davon ab, wie viel Hilfe Sie bei der Objektkonstruktion benötigen.

Es gibt viele Schöpfungsmuster, die nach der Viererbande herauskamen. Der Josh Bloch Builder ist ein wunderbarer Hack um Javas Mangel an benannten Parametern. Darüber hinaus gibt es iDSL-Builder, die viel Flexibilität bieten. Aber jedes von diesen stellt bedeutende Arbeit und Boilerplate dar.

Frameworks können Sie vor etwas Langeweile bewahren. Sie sind nicht ohne Nachteile. Wenn Sie nicht aufpassen, sind Sie möglicherweise auf das Framework angewiesen. Versuchen Sie, das Framework nach der Verwendung zu wechseln, und überzeugen Sie sich selbst. Selbst wenn Sie die generische XML- oder Annotations-Version beibehalten, werden möglicherweise zwei Sprachen unterstützt, die Sie bei der Bewerbung von Programmieraufträgen nebeneinander erwähnen müssen.

Bevor Sie sich zu sehr in die Leistungsfähigkeit von DI-Frameworks verlieben, nehmen Sie sich etwas Zeit und untersuchen Sie andere Frameworks, die Ihnen Funktionen bieten, für die Sie möglicherweise andernfalls ein DI-Framework benötigen. Viele haben sich über die einfache DI hinaus verzweigt . Bedenken Sie: Lombok , AspectJ und slf4J . Jedes überlappt sich mit einigen DI-Frameworks, aber jedes funktioniert für sich.

Wenn das Testen wirklich die treibende Kraft dahinter ist, schauen Sie sich Folgendes an : jUnit (jedes xUnit wirklich) und Mockito (jedes Mock wirklich), bevor Sie überlegen, ob ein DI-Framework Ihr Leben übernehmen sollte.

Sie können tun, was Sie wollen, aber für ernsthafte Arbeiten bevorzuge ich einen gut gefüllten Werkzeugkasten einem Schweizer Taschenmesser. Ich wünschte, es wäre einfacher, diese Linien zu zeichnen, aber einige haben hart gearbeitet, um sie zu verwischen. Daran ist nichts auszusetzen, aber es kann diese Entscheidungen schwierig machen.

CandiedOrange
quelle
PowerMock hat einige dieser Fälle gelöst. Zumindest ließ es Sie Statik nachahmen
Laiv
Meh. Wenn Sie DI ordnungsgemäß ausführen, sollte es relativ einfach sein, ein IoC-Container-Framework gegen ein anderes auszutauschen. Halten Sie diese Anmerkungen aus Ihrem Code und Sie werden in Ordnung sein. Verwenden Sie für DI grundsätzlich den IoC-Container, anstatt den Container als Service-Locator zu verwenden.
RubberDuck
@RubberDuck richtig. Wenn Sie Ihre Codebasis nicht ständig in mehreren DI-Frameworks testen und warten, können Sie auf einfache und zuverlässige Weise überprüfen, ob Sie DI ordnungsgemäß ausführen. Auch wenn ich in Java nichts anderes als Pojo verwende, ist es, wenn erhebliche Anstrengungen unternommen wurden, um das XML zu erstellen, immer noch kein einfacher Austausch, wenn das XML vom IoC-Container abhängig ist.
candied_orange
@CandiedOrange Ich verwende "einfach" als relativen Begriff. Nach dem großen Schema der Dinge ist es keine allzu schwierige Aufgabe, eine Kompositionswurzel durch eine andere zu ersetzen. Ein paar Tage arbeiten Tops. Um sicherzustellen, dass Sie DI richtig ausführen, sind Code Reviews genau dafür gedacht.
RubberDuck
2
@RubberDuck Die meisten "Kompositionswurzeln", die ich gesehen habe, sind etwa 5 Codezeilen in main. Also nein. keine allzu schwierige Aufgabe. Es ist das proprietäre Material, das sich jenen Zeilen entzieht, vor denen ich warne. Sie nennen es "DI richtig machen". Ich frage Sie, was Sie verwenden würden, um ein Problem in einer Codeüberprüfung zu beweisen. Oder würdest du einfach "Meh" sagen?
candied_orange
2

Das Erstellen von Klassen und das Zuweisen von Abhängigkeiten ist Teil des Modellierungsprozesses, der unterhaltsamen Teile. Dies ist der Grund, warum die meisten Programmierer gerne programmieren.

Zu entscheiden, welche Implementierung verwendet wird und wie Klassen aufgebaut sind, muss auf irgendeine Weise implementiert werden und ist Teil der Anwendungskonfiguration.

Manuelles Schreiben von Fabriken ist eine mühsame Arbeit. DI-Frameworks vereinfachen dies, indem Abhängigkeiten, die möglicherweise aufgelöst werden, automatisch aufgelöst werden und für diejenigen, die dies nicht tun, eine Konfiguration erforderlich ist.

Mit modernen IDEs können Sie durch Methoden und deren Verwendung navigieren. Manuell geschriebene Fabriken sind sehr gut, da Sie einfach den Konstruktor einer Klasse markieren, seine Verwendung anzeigen und alle Stellen anzeigen können, an denen und wie die bestimmte Klasse erstellt wird.

Aber auch mit DI-Framework können Sie eine zentrale Stelle einnehmen, z. B. die Konfiguration der Objektdiagrammkonstruktion (ab sofort OGCC). Wenn eine Klasse von mehrdeutigen Abhängigkeiten abhängt, können Sie einfach in OGCC nachsehen, wie eine bestimmte Klasse konstruiert wird genau da.

Sie könnten einwenden, dass Sie persönlich der Meinung sind, dass es ein großes Plus ist, die Verwendung eines bestimmten Konstruktors zu sehen. Ich würde sagen, was für Sie besser herauskommt, ist nicht nur subjektiv, sondern kommt hauptsächlich aus persönlicher Erfahrung.

Wenn Sie immer an Projekten gearbeitet hätten, die sich auf DI-Frameworks stützten, würden Sie nur das wirklich wissen, und wenn Sie eine Konfiguration einer Klasse sehen wollten, würden Sie sich immer mit OGCC befassen und würden nicht einmal versuchen, zu sehen, wie die Konstruktoren verwendet werden , weil Sie wissen würden, dass die Abhängigkeiten sowieso alle automatisch verkabelt werden.

Natürlich können DI-Frameworks nicht für alles verwendet werden, und ab und zu müssen Sie eine oder zwei Factory-Methoden schreiben. Ein sehr häufiger Fall ist das Erstellen einer Abhängigkeit während der Iteration über eine Auflistung, wobei jede Iteration ein anderes Flag liefert, das eine andere Implementierung einer ansonsten gemeinsamen Schnittstelle erzeugen sollte.

Am Ende wird es höchstwahrscheinlich darauf ankommen, was Sie bevorzugen und was Sie opfern wollen (entweder wenn Sie Fabriken schreiben oder Transparenz).


Persönliche Erfahrung (Warnung: subjektiv)

Ich spreche als PHP-Entwickler, obwohl ich die Idee hinter DI-Frameworks mag, habe ich sie immer nur einmal verwendet. Damals sollte ein Team, mit dem ich zusammengearbeitet habe, eine Anwendung sehr schnell bereitstellen, und wir konnten keine Zeit verlieren, Fabriken zu schreiben. Also haben wir einfach ein DI-Framework ausgewählt, es konfiguriert und es hat irgendwie funktioniert .

Für die meisten Projekte lasse ich die Fabriken gerne manuell schreiben, weil mir die schwarze Magie in DI-Frameworks nicht gefällt. Ich war für die Modellierung einer Klasse und ihrer Abhängigkeiten verantwortlich. Ich war derjenige, der entschieden hat, warum das Design so aussieht, wie es aussieht. Also werde ich derjenige sein, der die Klasse richtig konstruiert (auch wenn die Klasse harte Abhängigkeiten hat, wie z. B. konkrete Klassen anstelle von Schnittstellen).

Andy
quelle
2

Persönlich benutze ich keine DI-Container und mag sie nicht. Ich habe noch ein paar Gründe dafür.

Normalerweise ist es eine statische Abhängigkeit. Es ist also nur ein Service-Finder mit all seinen Nachteilen. Aufgrund der Art der statischen Abhängigkeiten werden sie dann ausgeblendet. Sie müssen sich nicht mit ihnen auseinandersetzen, sie sind irgendwie schon da und es ist gefährlich, weil Sie aufhören, sie zu kontrollieren.

Es verstößt gegen OOP-Prinzipien wie Kohäsion und David Wests Lego-Brick-Objektmetapher.

Wenn Sie also das gesamte Objekt so nah wie möglich am Einstiegspunkt des Programms erstellen, ist dies der richtige Weg.


quelle
1

Wie Sie bereits bemerkt haben: Abhängig von der Sprache, die Sie verwenden, gibt es unterschiedliche Sichtweisen, und unterschiedliche Anforderungen an den Umgang mit ähnlichen Problemen.

In Bezug auf die Abhängigkeitsinjektion kommt es auf Folgendes an: Die Abhängigkeitsinjektion ist, wie der Begriff sagt, nichts anderes, als die Abhängigkeiten, die ein Objekt benötigt, in dieses Objekt einzufügen. Sie entkoppeln Objekterstellung und Objektverbrauch um mehr Flexibilität zu gewinnen.

Wenn Ihr Design gut strukturiert ist, gibt es in der Regel nur wenige Klassen mit vielen Abhängigkeiten. Daher sollte die Verkabelung von Abhängigkeiten - entweder von Hand oder durch ein Framework - relativ einfach sein und die Anzahl der zu schreibenden Testkessel sollte leicht zu handhaben sein.

Es ist jedoch kein DI-Framework erforderlich.

Aber warum wollen Sie trotzdem ein Framework verwenden?

I) Vermeiden Sie Boilerplate-Codes

Wenn Ihr Projekt eine Größe erreicht, bei der Sie immer wieder den Schmerz verspüren, Fabriken (und Instatiationen) zu schreiben, sollten Sie ein DI-Framework verwenden

II) Deklakrativer Programmieransatz

Als Java einmal mit XML programmierte , ist es jetzt: Mit Anmerkungen übergießen und die Magie geschieht .

Aber im Ernst: Ich sehe einen klaren Vorteil . Sie kommunizieren Ihre Absicht klar damit, zu sagen, was benötigt wird, anstatt wo es zu finden und wie es zu bauen ist.


tl; dr

DI-Frameworks verbessern Ihre Codebasis nicht auf magische Weise, aber sie sorgen dafür, dass gut aussehender Code wirklich klar aussieht . Verwenden Sie es, wenn Sie das Gefühl haben, es zu brauchen. Ab einem bestimmten Punkt in Ihrem Projekt sparen Sie Zeit und vermeiden Übelkeit.

Thomas Junk
quelle
1
Sie haben Recht! Ich mache mir zu viele Gedanken darüber, wie die Dinge unter der Haube funktionieren. Ich habe schreckliche Erfahrungen mit Frameworks gemacht, die ich kaum verstanden habe. Ich plädiere nicht dafür, die Frameworks zu testen, sondern verstehe nur, was sie tun und wie sie es tun (wenn möglich). Aber es hängt von Ihren eigenen Interessen ab. Ich denke, wenn Sie verstehen, wie sie funktionieren, können Sie besser entscheiden, ob sie für Sie geeignet sind. So würden Sie beispielsweise verschiedene ORMs vergleichen.
Laiv
1
Ich denke, es ist immer richtig zu wissen, wie Dinge unter der Haube funktionieren. Aber es sollte dich nicht ärgern, wenn du es nicht weißt. Ich denke das Verkaufsargument für Spring ist zB, dass es einfach funktioniert. Und ja, Sie haben absolut Recht, um eine fundierte Entscheidung über die Verwendung eines Frameworks zu treffen, müssen Sie über ein gewisses Maß an Wissen verfügen. Aber ich sehe zu oft ein Muster von Misstrauen gegenüber Menschen, die nicht die gleichen Narben wie sich selbst haben, obwohl es in Ihrem Fall nicht der Glaube ist, dass nur derjenige, der manuelle Jagd erlebt hat, in den Supermarkt gehen darf.
Thomas Junk
Glücklicherweise benötigen wir heutzutage nicht einmal Spring- oder DI-Frameworks für Java. Wir haben bereits den JSR330 erhalten, der leider ignoriert wird (zumindest habe ich kein Projekt gesehen, das ihn implementiert). Also, die Leute haben noch Zeit, ihre Narben zu gewinnen :-)
Laiv
Ich habe meine Antwort bearbeitet und Ihre Kommentare berücksichtigt. Ich habe die mit dem Debuggen verbundenen "Nachteile" beseitigt. Ich bin zu dem Schluss gekommen, dass Sie damit Recht hatten. Schauen Sie sich das an und überlegen Sie, ob Sie Ihre Antwort ebenfalls aktualisieren sollten, da Sie im Moment Teile zitieren würden, die ich aus meiner Antwort entfernt habe.
Laiv,
1
Die Antwort hat sich so wenig geändert !!! Nichts, das dich beunruhigen sollte :-). Die Nachricht und die Argumente bleiben gleich. Ich wollte nur, dass Ihre Antwort so bleibt, wie sie ist. Ich denke, Sie haben gerade eine der Anführungszeichen entfernt.
Laiv,
0

Ja. Sie sollten wahrscheinlich Mark Seemanns Buch "Dependency Injection" lesen. Er skizziert einige gute Praktiken. Basierend auf einigen Ihrer Aussagen könnten Sie davon profitieren. Sie sollten eine Kompositionswurzel oder eine Kompositionswurzel pro Arbeitseinheit anstreben (z. B. Webanforderung). Ich mag seine Art zu denken, dass jedes Objekt, das Sie erstellen, als Abhängigkeit betrachtet wird (wie jeder Parameter einer Methode / eines Konstruktors), daher sollten Sie wirklich darauf achten, wo und wie Sie Objekte erstellen. Ein Framework hilft Ihnen dabei, diese Konzepte klar zu halten. Wenn Sie Marks Buch lesen, finden Sie mehr als nur die Antwort auf Ihre Frage.

Keith
quelle
0

Ja, wenn Sie in Java arbeiten, würde ich ein DI-Framework empfehlen. Dafür gibt es einige Gründe:

  • Java verfügt über mehrere äußerst gute DI-Pakete, die eine automatische Abhängigkeitsinjektion bieten, und in der Regel zusätzliche Funktionen enthalten, die schwerer manuell zu schreiben sind als einfache DI-Pakete (z. B. Abhängigkeiten mit Gültigkeitsbereichen, die eine automatische Verbindung zwischen Gültigkeitsbereichen ermöglichen, indem Code generiert wird, um nachzuschlagen, in welchem ​​Gültigkeitsbereich sie sich befinden sollen) Verwenden Sie ein d, um die richtige Version der Abhängigkeit für diesen Bereich zu finden (z. B. können Objekte mit Anwendungsbereich auf Objekte mit Anforderungsbereich verweisen).

  • Java-Anmerkungen sind äußerst nützlich und bieten eine hervorragende Möglichkeit zum Konfigurieren von Abhängigkeiten

  • Die Java-Objektkonstruktion ist im Vergleich zu dem, was Sie in Python gewohnt sind, überaus ausführlich. Die Verwendung eines Frameworks spart hier mehr Arbeit als in einer dynamischen Sprache.

  • Java DI-Frameworks können nützliche Dinge tun, z. B. das automatische Generieren von Proxys und Dekoratoren, die in Java mehr funktionieren als eine dynamische Sprache.

Jules
quelle
0

Wenn Ihr Projekt klein genug ist und Sie nicht viel Erfahrung mit dem DI-Framework haben, würde ich empfehlen, das Framework nicht zu verwenden und dies manuell zu tun.

Grund: Ich habe einmal in einem Projekt gearbeitet, in dem zwei Bibliotheken verwendet wurden, die direkte Abhängigkeiten zu verschiedenen Di-Frameworks hatten. Beide hatten einen Framework-spezifischen Code wie di-give-me-an-instance-of-XYZ. Soweit ich weiß, können Sie immer nur eine aktive Framework-Implementierung gleichzeitig haben.

Mit Code wie diesem können Sie mehr Schaden anrichten als profitieren.

Wenn Sie mehr Erfahrung haben, würden Sie wahrscheinlich die Verzerrung durch eine Schnittstelle (Fabrik oder Servicelocator) entfernen, so dass dieses Problem nicht mehr besteht und das di-Framework diesem Schaden mehr Nutzen bringt.

k3b
quelle