2009-06-04 11 views
41

Ich habe jetzt manuelle Konstruktoreinspritzung DI für ein kleines bisschen benutzt. Eine Sache, die ich bemerke, ist, dass meine Konstruktoren anfangen, ziemlich lang zu werden.Konstruktorinjektion: Wie viele Abhängigkeiten sind zu viele?

Ich habe eine Klasse, die auf eine Reihe kleiner Objekte angewiesen ist - irgendwo zwischen 6 und 10 manchmal. Als ich fortfuhr, meine Anwendung in kleinere Stücke zu brechen, konnte ich diese Zahl im Laufe der Zeit wachsen sehen. Ist das ein häufiges Problem?

Offensichtlich hängt dies sehr von dem Projekt ab. Die grundlegende Frage ist jedoch:

Wann fängst du an, mit der Anzahl der Abhängigkeiten, die eine Klasse hat, unbehaglich zu werden? Mit welchen Strategien reduzieren Sie diese Abhängigkeiten?

Antwort

10

Dies kann ein Zeichen dafür sein, dass die Klasse mit den 6-10 Abhängigkeiten selbst refaktoriert werden muss.

+1

Was ist, wenn Sie keine logische Möglichkeit finden, sie in mehrere Klassen wie WW zu gruppieren? erwähnt? Stimmen Sie zu, dass es dann in Ordnung ist, viele Abhängigkeiten zu haben? Ich meine, sagen wir Abhängigkeiten sind Automarken: BMW, OPEL, VW usw. Sie sind alle Autos. Vielleicht nicht das beste Beispiel, aber ich hoffe, Sie bekommen die Idee. –

+1

@ Darius.V - Wenn Sie eine 'Cars' Klasse haben, die 50 Markenabhängigkeiten hat, dann haben Sie eindeutig die SRP verletzt. Sie müssen sie in gemeinsame Merkmale gruppieren (z. B. 'ElectricCars',' HybridCars', 'DieselCars',' GasolineCars'), sodass Ihre Top-Level-Klasse 'Cars' nur einige Abhängigkeiten hat, die jeweils gemeinsame Eigenschaften und Methoden haben. Darunter können Sie das [Strategie-Muster] (https://stackoverflow.com/a/31971691) verwenden, um mehrere ähnliche Autos zu einer einzigen Abhängigkeit zu vereinfachen (zum Beispiel haben Sie nur eine einzige "BenzinCarsStrategy", die in Ihre Autos eingespritzt wird) Klasse, die alle Gasautos verwaltet). – NightOwl888

4

Ich würde nicht mehr als drei oder vier denken. Wenn Sie mehr als das bekommen, würde ich darüber nachdenken, wie gut Sie Ihre concerns abstrahieren. Ein einzelnes repository-Objekt zum Beispiel sollte alle Ihre Datenbeschaffungsanforderungen innerhalb der betreffenden Klasse erfüllen.

+3

Vermutlich, wenn ein Objekt Zugriff auf eine Datenbank und eine Art der externen Kommunikation benötigt (zB Repository und IO), ist das bereits 2 Abhängigkeiten aus den zugewiesenen 4. Neben - ist nicht eine der Nebenwirkungen sicherzustellen, dass jeder Klasse hat eine einzige Verantwortung (single concern), die zu mehr Klassen führen wird als zu weniger? Letztendlich muss es eine Klasse geben, die all diese kleineren Teile orchestrieren kann ... und diese Klasse wird viele Abhängigkeiten haben, um zu funktionieren. – Runcible

+0

@Runcible, ganz richtig. Und wenn die von Ihnen beschriebene Konsolidierung stattfindet, haben Sie tatsächlich weniger Dinge in den Konstruktor zu injizieren. Was Sie beschreiben, BTW ist ein Inversion Control Container (wie Windsor, zum Beispiel). –

+1

@Runcible, Ich habe in letzter Zeit mit diesem Problem der Abhängigkeit über die Injektion gekämpft. Ich habe zwei Beiträge gefunden, die sehr hilfreich waren. http://blog.ploeh.dk/2010/01/20/RebuttalConstructorover-injectionanti-pattern/ & http://blog.ploeh.dk/2010/02/02/RefactoringtoAggregateServices/ Eine andere Anmerkung, ich glaube die Absicht von SRP soll keine Klasse haben, die eine Sache macht, aber einen Grund hat, sich aus der geschäftlichen Perspektive zu ändern. – GetFuzzy

0

Sie sollten auch sehen, ob einer der Parameter Ihres Konstruktors auch in einer einzelnen Klasse zusammengefasst werden soll (vorausgesetzt, die Parameter sind als Klasse sinnvoll).

Möglicherweise möchten Sie auch das ServiceLocator-Muster für einige Ihrer Abhängigkeiten verwenden. Dies gilt insbesondere, wenn Sie die Abhängigkeiten in einer langen Kette von Konstruktoren übergeben müssen.

+4

Das Service Locator-Muster steht im Gegensatz zu den Dependency-Injection-Prinzipien. Service Locator verletzt das Demeter-Gesetz: http://www.youtube.com/watch?v=RlfLCWKxHJ0 – Runcible

+0

Sehr schönes Video, Runcible. Sehr verständliche Erklärung von DI, IOC, Service Locator. – Alexanderius

9

Ich würde mir keine Sorgen machen.

Stattdessen würde ich mir Sorgen machen, dass die Klasse zu komplex ist.

Eine Klasse mit vielen Abhängigkeiten, die sie alle verwendet, aber keine Schleifen oder wenn Anweisungen in Ordnung ist. In einem Code, an dem ich gerade gearbeitet habe, gab es ungefähr 14 Abhängigkeiten in einer Klasse. Es gab jedoch nur einen Pfad durch den Code und keine logische Möglichkeit, die Abhängigkeiten in bessere Klassen zu gruppieren.

Eine Klasse mit einer kleinen Anzahl von Abhängigkeiten, die viele Verzweigungsanweisungen oder komplexe Schleifenbedingungen enthält, sollte vereinfacht werden.

1

Eine Klasse mit 6-10 Abhängigkeiten ist ein Code-Geruch. Es ist ein deutlicher Hinweis darauf, dass die Klasse die Single Responsibility Principle verletzt.

Welche Strategien werden verwendet, um diese Abhängigkeiten zu reduzieren?

Mark Seemann hat diese Aufgabe klar in seinem Amt Refactoring to Aggregate Services und moreso in seinem Buch Dependency Injection in .NET gemacht. Die Tatsache, dass Ihre Klasse so viele Abhängigkeiten aufweist, weist darauf hin, dass es innerhalb der Klasse mehr als eine Verantwortlichkeit gibt. Oft gibt es ein implizites Domain-Konzept, das darauf wartet, gemacht zu werden explicit, indem es identifiziert und es in seinen eigenen Service macht. Im Allgemeinen sollten die meisten Klassen niemals mehr als 4-5 Abhängigkeiten benötigen.