Abhängigkeitsinjektion vs. Service-Standort
Ich bin derzeit auf der Abwägung der vor-und Nachteile zwischen DI und SL. Allerdings habe ich mich in den folgenden catch-22, das bedeutet, dass ich sollte nur die Verwendung SL für alles und Spritzen nur ein IoC-container in jeder Klasse.
DI Catch-22:
Einige Abhängigkeiten, wie Log4Net, einfach nicht passen DI. Ich nenne diese meta-Abhängigkeiten und das Gefühl, Sie sollte blickdicht sein zum aufrufenden code. Meine Begründung ist, dass, wenn Sie eine einfache Klasse " D " wurde ursprünglich eingeführt, ohne Anmeldung, und wächst dann zu verlangen, Protokollierung, dann abhängige Klassen 'A', 'B' und 'C' muss jetzt irgendwie erhalten diese Abhängigkeit und übergeben Sie es nach unten von 'A' bis 'D' (vorausgesetzt 'A' komponiert 'B', 'B' komponiert 'C', und so weiter). Wir haben jetzt deutliche änderungen im code, nur weil wir verlangen die Protokollierung in eine Klasse.
Wir benötigen daher eine undurchsichtige Mechanismus für die Erlangung der meta-Abhängigkeiten. Zwei in den Sinn kommen: Singleton und SL. Die ehemalige bekannte Einschränkungen, vor allem im Hinblick auf starre scoping-Fähigkeiten: am besten ein Singleton wird die Verwendung einer Abstrakten Fabrik, die gespeichert ist im Gültigkeitsbereich der Anwendung (ie. in einer statischen Variablen). Dies ermöglicht einige Flexibilität, aber ist nicht perfekt.
Eine bessere Lösung wäre, um zu injizieren, ein IoC-container in solche Klassen, und verwenden Sie dann SL, innerhalb der Klasse zu lösen, diese meta-Abhängigkeiten vom container.
Daher catch-22: denn die Klasse ist jetzt injiziert werden, mit einem IoC-container, dann warum nicht verwenden Sie es zu beheben, alle anderen Abhängigkeiten auch?
Ich würde mich sehr über Eure Gedanken 🙂
InformationsquelleAutor der Frage Lawrence Wagerfield | 2011-02-13
Du musst angemeldet sein, um einen Kommentar abzugeben.
Verwendung des service-locator-Muster völlig untergräbt einen der wichtigsten Punkte der dependency injection. Der Punkt von dependency injection, um die Abhängigkeiten explizit. Sobald Sie verstecken sich diese Abhängigkeiten nicht durch die Ihnen explizite Parameter im Konstruktor, du bist nicht mehr tun vollwertige dependency injection.
Diese sind alle Konstruktoren für eine Klasse namens
Foo
(gesetzt, um das Thema der Johnny-Cash-song):Falsch:
Falsch:
Falsch:
Rechts:
Nur letzteres macht die Abhängigkeit von
Bar
explicit.Als für die Protokollierung gibt es eine richtige Weg, es zu tun, ohne es durchdringt in Ihren domain-code (es sollte nicht, aber wenn es dann funktioniert, die Sie verwenden, dependency injection period). Erstaunlich, IoC-Container kann helfen, mit diesem Problem. Start hier.
InformationsquelleAutor der Antwort jason
Service Locator ist ein anti-pattern, aus Gründen hervorragend beschrieben http://blog.ploeh.dk/2010/02/03/ServiceLocatorIsAnAntiPattern.aspx. In Bezug auf die Protokollierung zu aktivieren, können Sie entweder zu behandeln, wie eine Abhängigkeit wie jede andere, und injizieren eine Abstraktion, die per Konstruktor oder property-injection.
Der einzige Unterschied mit log4net, ist, dass es erfordert die Art der Aufrufer, der den Dienst nutzt. Mit Ninject (oder einem anderen container) Wie kann ich herausfinden, die Art, die Anforderung des service? beschreibt, wie Sie dieses Problem lösen (es verwendet, Ninject, sondern gilt für alle IoC-container).
Alternativ könnte man denken, dass die Protokollierung als ein cross-cutting concern, die nicht angemessen ist, zu mischen und mit der business-Logik-code, in diesem Fall können Sie das abfangen, die von vielen IoC-Container. http://msdn.microsoft.com/en-us/library/ff647107.aspx beschreibt die Verwendung abfangen mit Unity.
InformationsquelleAutor der Antwort devdigital
Meine Meinung ist, dass es hängt. Man ist manchmal besser und manchmal der andere. Aber ich würde sagen, generell bevorzuge ich DI. Es gibt nur wenige Gründe für diese.
Wenn Abhängigkeit injiziert wird irgendwie in eine Komponente behandelt werden kann Sie als Teil seiner Schnittstelle. So ist es einfacher für die Komponente Benutzer zu liefern, diese Abhängigkeiten, die dazu führen, dass Sie sichtbar sind. Im Falle von injizierten SL oder Statische SL, Abhängigkeiten ausgeblendet sind, und die Verwendung von Komponenten ist etwas schwieriger.
Injiziert Abhängigkeiten sind besser für unit-Tests verursachen, können Sie einfach verspotten. Bei SL haben Sie, um das setup-Locator - + mock-Abhängigkeiten wieder. So ist es mehr Arbeit.
InformationsquelleAutor der Antwort Oleg Rudckivsky
Manchmal logging implementiert werden kann, mit AOPso dass Sie nicht mischen Sie mit business-Logik.
Ansonsten sind die Optionen :
http://aabs.wordpress.com/2007/12/31/the-ambient-context-design-pattern-in-net/
Natürlich in diesem Kontext muss konfigurierbar sein, so dass Sie verwenden können stub/mock für unit-Tests.
Andere vorgeschlagene Verwendung von AmbientContext, um das aktuelle Datum/Zeit Anbieter gibt , so dass Sie können die stub es während unit-test, und beschleunigt die Zeit, wenn Sie wollen.
InformationsquelleAutor der Antwort frecil
Wenn das Beispiel nimmt nur log4net als Abhängigkeit, dann brauchen Sie nur das zu tun:
Gibt es keinen Punkt, um zu injizieren, die Abhängigkeit als log4net bietet granulare Protokollierung, indem Sie die Art (oder einen string) als parameter.
Auch, DI ist nicht korreliert mit SL. IMHO der Zweck der ServiceLocator ist für die Lösung optionale Abhängigkeiten.
ZB: Wenn der SL bietet ein interface ILog, ich Schreibe Protokollierung daa.
InformationsquelleAutor der Antwort Rafael Diego Nicoletti
Habe ich mit der Google Guice DI-framework im Java-und entdeckt, dass es noch viel mehr als das testen einfacher. Zum Beispiel brauchte ich eine separate log-pro Anwendung (nicht Klasse), mit der weiteren Voraussetzung, dass alle meine common library code verwenden Sie die logger in der aktuellen call-Kontext. Die Injektion der logger dies möglich gemacht. Zugegeben, alle die Bibliothek-code geändert werden muss: der logger injiziert wurde in der Konstrukteurswertung. Auf den ersten, ich wehrte dieser Methode, da Sie alle coding-änderungen erforderlich; schließlich merkte ich, dass die änderungen hatte viele Vorteile:
Unnötig zu sagen, ich bin jetzt ein großer fan von DI, und verwenden Sie es für alle aber die trivialsten Anwendungen.
InformationsquelleAutor der Antwort sabra
Wir haben landete auf einem Kompromiss: verwenden Sie DI aber bundle-top-level-Abhängigkeiten in ein Objekt vermeidet refactoring Hölle sollten diese Abhängigkeiten ändern.
Im Beispiel unten, können wir hinzufügen 'ServiceDependencies' zimmerreserviereung, ohne das Sie umgestalten alle abgeleiteten Abhängigkeiten.
Beispiel:
InformationsquelleAutor der Antwort BlackjacketMack
Weiß ich, dass die Leute wirklich sagen DI ist das nur gut IOC-Muster, aber ich bekomme nicht diese. Ich werde versuchen, Sie zu verkaufen SL ein bisschen. Ich werde mit der neuen MVC-Core-framework, Ihnen zu zeigen, was ich meine. Ersten DI-Motoren sind wirklich Komplex. Was die Menschen wirklich meinen, wenn Sie sagen, DI, ist die Verwendung einiger Frameworks wie Unity, Ninject, Autofac... , alles tun, die schweres heben für Sie, wo SL kann so einfach sein, wie eine Fabrik-Klasse. Für eine kleine schnelle Projekt-dies ist eine einfache Möglichkeit zu tun, IOC, ohne zu lernen ein ganzes framework für die ordnungsgemäße DI, könnten Sie nicht so schwer zu lernen, aber immer noch.
Nun zu dem problem, dass DI werden können. Ich verwende ein Zitat von MVC-Core-docs.
"ASP.NET Kern ist entworfen vom Boden oben zu unterstützen und zu nutzen dependency injection." Die meisten Leute sagen, dass über DI "99% der code-Basis haben sollte, keine Kenntnis von Ihren IoC-container." Also, warum würden Sie brauchen, zu entwerfen von Grund auf, wenn nur 1% der code sollte sich dessen bewusst sein, nicht alt MVC-Unterstützung der DI? Gut, das ist das große problem der DI-es hängt davon ab DI. Alles macht Arbeit", WIE ES GETAN WERDEN SOLLTE" wird eine Menge Arbeit. Wenn Sie einen Blick auf das neue Action-Injection ist das nicht, je nach DI, wenn Sie
[FromServices]
Attribut. Jetzt DI Leute werden NICHT sagen, Sie nehme an, Sie gehen mit Fabriken nicht dieses Zeug, aber wie Sie sehen können, nicht einmal die Leute, die MVC war es Recht. Das problem der DI ist sichtbar in den Filter und schauen Sie, was Sie tun müssen, um zu bekommen, DI in einem filterWo, wenn Sie verwendet SL könnten Sie dies getan haben, mit var _logger = Locator.Get();. Und dann kommen wir zu den Ansichten. Mit allen gibt es guten Willen in Bezug auf DI Sie hatte die Verwendung SL für die Ansichten. die neue syntax
@inject StatisticsService StatsService
ist das gleiche wievar StatsService = Locator.Get<StatisticsService>();
.Die meisten beworbenen Teil der DI ist das unit testing. Aber was die Leute und das zu tun, ist nur die Prüfung dort mock-Dienste ohne Zweck, oder mit Draht, gibt es DI-Motor zu tun, real-tests. Und ich weiß, dass Sie alles tun können, was schwer aber die Menschen am Ende macht ein SL-locator, auch wenn Sie nicht wissen, was es ist. Wo nicht viel Menschen machen, DI, ohne jemals zu Lesen auf es zuerst.
Mein größtes problem mit DI ist, dass der Benutzer der Klasse muss sich bewusst sein, die innere Funktionsweise der Klasse in der anderen, es zu benutzen.
SL kann verwendet werden, in einem guten Weg und hat einige Vorteile die meisten alle seine Einfachheit.
InformationsquelleAutor der Antwort Filip Cordas
Dies ist in Bezug auf die "Service Locator ist ein Anti-Pattern" von Mark Seemann.
Ich könnte hier falsch sein. Aber ich dachte nur, ich sollte meine Gedanken zu teilen, zu.
Die Process () - Methode für OrderProcessor nicht wirklich Folgen dem "Inversion of Control" - Prinzip. Es bricht auch das Single-Responsibility-Prinzip auf der methodenebene. Warum sollte eine Methode sein, die sich mit der Instanziierung des
Objekte(via new oder jede S. L.-Klasse), die es braucht, um etwas zu erreichen.
Anstatt die Process () - Methode erstellen, die die Objekte der Konstruktor kann tatsächlich haben sich die Parameter für die jeweiligen Objekte(Lesen, Abhängigkeiten), wie unten gezeigt. WIE kann dann ein Service-Locator anders sein, von einem IOC -
container. UND es wird Hilfe bei der Unit-Tests als gut.
InformationsquelleAutor der Antwort Aniket Bhoyar
Ich weiß, diese Frage ist ein wenig alt, ich dachte nur, ich würde meine Eingabe.
In der Realität, 9 mal out of 10, dass Sie wirklich nicht müssen SL und sollte sich auf DI. Es gibt jedoch einige Fälle, wo Sie verwenden sollten, SL. Eine Gegend, in der ich mich mit SL (oder eine variation davon) in die Spiele-Entwicklung.
Ein weiterer Vorteil der SL (in meiner Meinung) ist die Fähigkeit, sich zu übergeben um
internal
Klassen.Unten ist ein Beispiel:
Wie Sie sehen können, hat der Benutzer der Bibliothek hat keine Ahnung, was diese Methode aufgerufen wurde, weil wir nicht DI, nicht, dass wir in der Lage wären, sowieso.
InformationsquelleAutor der Antwort Mathew O'Dwyer