Das einzige legitime Anti-Pattern für die Abhängigkeitsinjektion, das mir bekannt ist, ist das Service Locator- Pattern, bei dem es sich um ein Anti-Pattern handelt, wenn ein DI-Framework dafür verwendet wird.
Alle anderen so genannten DI-Anti-Patterns, von denen ich hier oder anderswo gehört habe, sind nur etwas spezifischere Fälle von allgemeinen OO / Software-Design-Anti-Patterns. Zum Beispiel:
Die Überinjektion von Konstruktoren ist eine Verletzung des Single-Responsibility-Prinzips . Zu viele Konstruktorargumente weisen auf zu viele Abhängigkeiten hin. Zu viele Abhängigkeiten deuten darauf hin, dass die Klasse versucht, zu viel zu tun. Normalerweise korreliert dieser Fehler mit anderen Code-Gerüchen, wie ungewöhnlich langen oder mehrdeutigen Klassennamen ("Manager"). Statische Analysewerkzeuge können leicht übermäßige afferente / efferente Kopplung erkennen.
Das Injizieren von Daten ist im Gegensatz zum Verhalten ein Subtyp des poltergeistischen Anti-Musters, wobei der Geist in diesem Fall der Container ist. Wenn eine Klasse das aktuelle Datum und die aktuelle Uhrzeit kennen muss, injizieren Sie keine DateTime
Daten. Stattdessen injizieren Sie eine Abstraktion über die Systemuhr (normalerweise nenne ich meine ISystemClock
, obwohl ich denke, dass es eine allgemeinere im SystemWrappers- Projekt gibt). Dies gilt nicht nur für DI; Dies ist für die Testbarkeit unbedingt erforderlich, damit Sie zeitlich veränderliche Funktionen testen können, ohne darauf warten zu müssen.
Jeden Lebenszyklus als Singleton zu deklarieren, ist für mich ein perfektes Beispiel für Frachtkultprogrammierung und in geringerem Maße die umgangssprachliche Bezeichnung " Objekt-Senkgrube ". Ich habe mehr Missbrauch von Singletons gesehen, als mir einfällt, und nur sehr wenig davon betrifft DI.
Ein weiterer häufiger Fehler sind implementierungsspezifische Schnittstellentypen (mit seltsamen Namen wie IOracleRepository
), die nur ausgeführt werden, um sie im Container registrieren zu können. Dies ist an und für sich ein Verstoß gegen das Prinzip der Inversion von Abhängigkeiten (nur weil es sich um eine Schnittstelle handelt, bedeutet dies nicht, dass es wirklich abstrakt ist) und beinhaltet häufig auch ein Aufblähen der Schnittstelle, das das Prinzip der Schnittstellentrennung verletzt .
Der letzte Fehler, den ich normalerweise sehe, ist die "optionale Abhängigkeit", die sie in NerdDinner gemacht haben . Mit anderen Worten, es gibt einen Konstruktor, der die Abhängigkeitsinjektion akzeptiert, aber auch einen anderen Konstruktor, der eine "Standard" -Implementierung verwendet. Dies auch verletzt die DIP und neigt zu führen LSP als Entwickler Verletzungen als auch, im Laufe der Zeit beginnen Annahmen um die Default - Implementierung zu machen und / oder starten neu-ing up Instanzen des Standardkonstruktors verwenden.
Wie das alte Sprichwort sagt, können Sie FORTRAN in jeder Sprache schreiben . Dependency Injection ist kein Allheilmittel , die ihr Abhängigkeitsmanagement verhindern werden die Entwickler von vermasseln, aber es tut verhindert eine Reihe von gemeinsamen Fehlern / anti-Muster:
...und so weiter.
Natürlich möchten Sie kein Framework entwerfen, das von einer bestimmten IoC-Container- Implementierung wie Unity oder AutoFac abhängt. Dies verstößt erneut gegen das DIP. Wenn Sie jedoch einmal darüber nachdenken, müssen Sie bereits einige Entwurfsfehler gemacht haben, da die Abhängigkeitsinjektion eine allgemeine Abhängigkeitsverwaltungstechnik ist und nicht an das Konzept eines IoC-Containers gebunden ist.
Jeder kann einen Abhängigkeitsbaum erstellen. Vielleicht ist es ein IoC-Container, vielleicht ist es ein Unit-Test mit einer Reihe von Mocks, vielleicht ist es ein Testtreiber, der Dummy-Daten liefert. Ihr Framework sollte sich nicht darum kümmern, und die meisten Frameworks, die ich gesehen habe, interessieren sich nicht dafür, nutzen jedoch die Abhängigkeitsinjektion in hohem Maße, damit sie problemlos in den IoC-Container der Wahl des Endbenutzers integriert werden kann.
DI ist keine Raketenwissenschaft. Versuchen Sie nur zu vermeiden new
und es sei static
denn, es gibt einen zwingenden Grund, sie zu verwenden, z. B. eine Utility - Methode, die keine externen Abhängigkeiten aufweist, oder eine Utility - Klasse, die möglicherweise keinen Zweck außerhalb des Frameworks hat (Interop - Wrapper und Dictionary - Schlüssel sind häufige Beispiele dafür) Dies).
Viele Probleme mit IoC-Frameworks treten auf, wenn Entwickler erst lernen, wie sie verwendet werden, und anstatt die Art und Weise, wie sie mit Abhängigkeiten und Abstraktionen umgehen, an das IoC-Modell anzupassen, versuchen Sie stattdessen, den IoC-Container so zu manipulieren, dass er den Erwartungen der Entwickler entspricht alter Codierungsstil, der häufig eine hohe Kopplung und eine geringe Kohäsion beinhaltet. Schlechter Code ist schlechter Code, unabhängig davon, ob DI-Techniken verwendet werden oder nicht.