Konstruktorinjektion (DI) vs. statische Fabriken für Querschnittsaufgaben?

8

In den meisten beliebigen Anwendungen gibt es viele übergreifende Bedenken, die unter allen verfügbaren Schichten angegangen werden müssen, z. Protokollierung, Nachrichtenbus, Konfiguration. Was ich festgestellt habe, ist, dass sie in manchen Klassen dazu neigen, den Konstruktor komplett zu sprengen, wenn die Module mit einem IoC injiziert werden.

%Vor%

Bei üblichen Fällen von Überinjektionen von Konstrukteuren tendiere ich dazu, die Bedenken in Bausteine ​​zu zerlegen, die eng zusammengehören, so dass ich in einer Klasse weniger Abhängigkeiten erhalte. Dies ist jedoch bei Querschneidkonzepten nicht möglich.

Unter den Protokollierungs-Frameworks scheinen statische Fabriken / Dienste sehr beliebt zu sein, z.B.

%Vor%

Meine Frage ist: Ist diese Herangehensweise eine gute, für alle Arten von cross cutting Zeug? Was sind die Nachteile, wenn der Code am Ende so aussieht:

%Vor%     
xvdiff 11.08.2014, 11:10
quelle

2 Antworten

6

Wenn Sie mehr auf TDD haben, können Sie leicht erraten, welcher Ansatz besser ist.

Mit Dependency-Injection wird Ihr Code mehr (unit) testable . Sie können Abhängigkeiten über ein spöttisches Framework injizieren und Ihre Komponententests ohne große Kopfschmerzen erstellen.

Aber im Fall von statischen Fabriken, da Ihre Fabrikklassen (hart) in Ihre Klasse verdrahtet sind, gibt es während der Unit-Tests keinen Ausweg, wie Sie sie von außerhalb Ihrer Klasse injizieren können.

Vorteile von DI gegenüber statischen Fabriken -

  1. Parallele Entwicklung - Stellen Sie sich einen Protokollierungsdienst vor, den Sie gerade verwenden, der von jemand anderem erstellt wird, und Sie werden Ihren Code testen (und Sie kümmern sich nicht um die Einheit) Testen des Logging-Dienstes, da Sie davon ausgehen, dass es bei der Verwendung getestet werden sollte. Du tötest mit DI, sprichst die Abhängigkeit mit einem Mock-Objekt ein und schaffst es.

  2. Geschwindigkeit - Während der Unit-Tests sollten Sie nicht möchten, dass sie lange dauern (so dass Sie mit jeder einzelnen Änderung Ihrer Hauptklasse eine Kaffeepause einlegen; )). Sie möchten auf jeden Fall möchten, dass der Komponententest im Handumdrehen ausgeführt wird und einen Fehler meldet. Statische Factory, die von externen Ressourcen (z. B. Netzwerk / DB, FileSystem) abhängt, wird Zeit brauchen. Sie verwenden besser DI, verwenden ein Mock-Objekt und fertig.

  3. Testbarkeit - DI hilft, den Client von seinen Abhängigkeiten zu isolieren (fördert die Verwendung von Interfaces) und verbessert somit die Testbarkeit (durch Verwendung von Mocks).

Rabi 11.08.2014, 11:33
quelle
5

Das Verschieben der Abhängigkeiten aus dem Konstruktor löst das Problem nicht, da Sie die Anzahl der Abhängigkeiten einer Klasse nicht verringern und die Wahrscheinlichkeit groß ist, dass Sie immer noch gegen Single-Responsibility-Prinzip und das Open / Close-Prinzip , das verursacht Ihr Code ist schwer zu testen, schwer zu ändern und schwer zu pflegen.

Stattdessen ist es oft eine gute Lösung, diese übergreifenden Bedenken aus Ihren Komponenten herauszuziehen und sie in Komponenten zu platzieren, die speziell auf diesen Querschnittsbegriff zugeschnitten sind und diese Komponente die ursprüngliche Komponente umhüllen. Mit anderen Worten: Erstellen Sie Dekorierer .

Dies zwingt Sie wahrscheinlich dazu, das Design Ihrer Klassen zu ändern, da Sie, wenn Sie keine generischen Abstraktionen zum Definieren von Gruppen verwandter Services haben, einen Decorator pro Abstraktion definieren müssen, was eine Menge Codeverdopplung verursachen würde , die in fast allen Fällen schlecht ist.

Also modellieren Sie Ihr System stattdessen um command / handlers und Abfrage/Handler und Sie werden an einem viel besseren Ort sein. Sie können jedes Stück Geschäftslogik mit einem generischen Dekorator dekorieren, den Sie einmal definieren und überall wiederverwenden. Dies hält Ihr System sauber, aber immer noch sehr flexibel.

    
Steven 11.08.2014 15:34
quelle