2010-03-26 4 views
23

Nur versucht, immer noch um IOC Prinzipien herumzukommen.IOC - Sollen util-Klassen mit statischen Hilfsmethoden mit IOC verdrahtet werden?

Q1: Statische Methoden - Sollen util-Klassen mit statischen Hilfsmethoden mit IOC verdrahtet werden?

Zum Beispiel, wenn ich eine HttpUtils-Klasse mit einer Reihe von statischen Methoden habe, sollte ich versuchen, es über IOC an andere Business-Logik-Klassen zu übergeben?

Folgen auf Fragen dafür könnte sein:

Q2: Singletons - Was über Dinge wie die Protokollierung, wo Sie in der Regel Zugriff auf sie über einen Logger.getInstance bekommen kann() -Aufruf eingeben. Würden Sie das normalerweise so lassen, wie es ist, und KEINEN IOC verwenden, um den Logger in Business-Klassen zu injizieren, die ihn brauchen?

Q3: Statische Klassen - Ich habe dieses Konzept nicht wirklich verwendet, aber gibt es Richtlinien dafür, wie Sie das normalerweise handhaben würden, wenn Sie zu einem IOC-basierten Ansatz wechseln würden.

Vielen Dank im Voraus.

Antwort

30

Das Komische an IoC ist, dass in diesem Stil geschriebene Objekte im Allgemeinen von diesen Details entkoppelt sind.

Lassen Sie uns die Utility-Klasse als Beispiel:

public class HttpUtils 
{ 
    public static void DoStuff(int someValue) 
    { 
     // ... 
    } 
} 

In einer nicht-IoC orientierte Anwendung, können Sie direkt diese Methode verwenden:

public class Foo 
{ 
    public int Value { get; set; } 

    public void DoStuff() 
    { 
     HttpUtils.DoStuff(Value); 
    } 
} 

jedoch, dass Paare die Definition von DoStuff direkt zu seiner Implementierung. IoC ist bestrebt, diese Art von Details zur Scheidung, so stattdessen definieren wir den Betrieb auf eigene:

public interface IDoesStuff 
{ 
    void DoStuff(int someValue); 
} 

Dann wir Zimmer in Foo für die Umsetzung lassen sich ändern:

public class Foo 
{ 
    private readonly IDoesStuff _doesStuff; 

    public Foo(IDoesStuff doesStuff) 
    { 
     _doesStuff = doesStuff; 
    } 

    public int Value { get; set; } 

    public void DoStuff() 
    { 
     _doesStuff.DoStuff(Value); 
    } 
} 

Diese abkoppelt Foo aus HttpUtils. Der Implementierer des Konzepts DoStuff ist jetzt ein Konfigurationsdetail und keine inhärente Abhängigkeit (wie bei der statischen Methode).

Beachten Sie, dass Foo keine Ahnung hat, ob IDoesStuff ein Singleton ist oder nicht. Diese Lebensdauer ist auch ein Konfigurationsdetail, und kein inhärentes Detail von Foo.

Zusammengefasst, IoC und static sind in der Regel uneins, da IoC fördert Änderung und static, per Definition, verhindert es. Deklarieren Sie Ihre Abhängigkeiten in Ihren Konstruktoren, und Sie werden feststellen, dass Sie fast nie die Funktionalität static verwenden.

+0

danke Bryan - Bedeutet das, dass es immer mehr Overhead von der IOC Konstruktion Dinge (z. B. Logger) jedes Mal sein könnte? Auch für die Klassen vom Typ utils wundere ich mich, dass das Refactoring schwieriger wird, wenn Sie Ihre Hilfsfunktionen in Ihren Hilfsklassen umgestalten? (Ich benutze ReSharper selbst) - danke – Greg

+0

Die meisten IoC-Container erlauben eine Art von Scoping. Damit meinen Sie, dass Ihr Objekt jedes Mal erstellt wird (Fabrik), einmal pro Kontext (Arbeitseinheit) oder einmal pro Anwendung (Singleton) erstellt wird. Dies bedeutet, dass Sie den Logger so registrieren können, dass er nur einmal erstellt wird. –

+2

Schließlich möchten Sie die Dienstprogrammklassen beseitigen. Jede Methode für jede dieser Klassen hat die gleichen Kopplungsprobleme wie die oben beschriebene Methode "HttpUtils.DoStuff". Aus diesem Grund möchten Sie nicht verlangen, dass * irgendein * Code direkt von 'statischen' Mitgliedern abhängt. Nimm stattdessen den Körper von 'HttpUtils.DoStuff', lege ihn hinter' IDoesStuff' und lösche die Methode vollständig aus 'HttpUtils'. Nun kann jede Klasse, die die statische Methode aufgerufen haben könnte, stattdessen "IDoesStuff" in ihrem Konstruktor akzeptieren. Viola: keine Notwendigkeit mehr für die Nutzungsklasse! –

6

Ein IoC-Container ist normalerweise nützlich, um Objekte mit Status zu injizieren. oder Klassen oder Schnittstellen, die mehr als eine Implementierung haben, selbst wenn die zweite Implementierung zu Testzwecken ein Mock ist. Wenn beides nicht wahr ist, gewinnen Sie nichts, indem Sie es injizieren.Das gebräuchlichste Idiom dieser Tage ist es, Ihre Klasse mit einer Schnittstelle zu konfrontieren, die sowohl die echte als auch die Scheinimplementierung implementieren können.

1) Statische Methoden auf Hilfsklassen - Nein, diese werden nicht oft von IoC injiziert. Normalerweise sind sie zustandslose Dienstprogramme. Um ein sehr einfaches Beispiel zu verwenden, benötigen Sie nicht zwei Versionen einer Hilfsmethode namens StringUtils.Reverse(). Sie brauchen nur einen, und Sie können leicht Tests um ihn herum schreiben, weil er keinen Status oder Abhängigkeiten hat, so dass es absolut keinen Vorteil hat, sich darüber lustig zu machen. Beispiel Test:

string reversedString = StringUtils.Reverse("input"); 
Assert.AreEqual("tupni", reversedString) 

Wenn das Dienstprogramm nicht wirklich staatenlos ist (zum Beispiel abhängig von HttpContext.Current), dann sollten Sie die Abhängigkeit explizit machen, indem sie die Injektion und nicht machte das Dienstprogramm statisch.

2) Singletons: Oft ja, Singletons werden injiziert. Aber eine gute Sache über IoC ist, dass Sie sich weniger Gedanken darüber machen, ob es nur etwas gibt oder nicht. Durch die Verwendung von IoC gewinnen Sie Flexibilität bei der Instanziierung. Die Entscheidung, einen bestimmten Typ jedes Mal als Singleton oder als neue Instanz zu definieren, wird Teil der Konfiguration des IoC-Containers, und nichts anderes im Code muss geändert werden.

So Singleton-Haube stoppt, ein separates Anliegen, das in die Klasse (und Klassen mit mehreren Bedenken, wenn sie nicht müssen, ist schlecht) codiert werden, und es wird das Anliegen des IoC-Container. Du schreibst die Klasse "as a Singleton" nicht mit etwas Speziellerem wie einem privaten Konstruktor und einer public static GetInstance() Methode, sondern kodierst sie nur für das Hauptproblem, während die Konfig des IoC Containers angibt, ob es ein Singleton ist oder nicht oder irgendwo dazwischen, wie eine Instanz pro Thread.

3) Statische Klassen - sind das natürliche Zuhause für statische Methoden. Ziehen Sie gegebenenfalls die Erweiterungsmethoden für statische Methoden in Betracht. Sie können diese Klassen nicht injizieren, da Sie sie nicht erstellen können. Die Verwendung von statischen Klassen sorgt für prozeduralen, nicht objektorientierten Code. Dies ist keine schlechte Sache für kleine Hilfsmethoden, aber wenn der Großteil des Codes so ist, dann verwenden Sie nicht die leistungsstarken OO-Funktionen der .Net-Plattform.

2

Statische Methoden per Definition benötigen keine Instanz. DI/IOC zielt darauf ab, Schnittstellen mit konkreten Klassen zu erfüllen und da Ihre statische Klasse zusammen mit ihren statischen Methoden definitionsgemäß keine Schnittstelle implementieren oder eine Klasse erweitern kann, macht die Frage keinen Sinn. Es gibt keinen Grund, die Hilfsklasse zu übergeben, da die Instanz nicht benötigt wird, um die statischen Methoden zu verwenden. Ihr Code wird immer die gleichen statischen Helper-Methoden ausführen, auch ohne eine Instanz.

In einer IOC/DI-basierten Anwendung würde man Schnittstellen definieren und mindestens eine Implementierung haben. Es geht darum, Instanzen und ihre Abhängigkeiten zu verwalten.

0

Das Dilemma entsteht, wenn die Utility-Klassen, sagen wir, Access-Datenbank benötigen. Während der db-Accessor Ioc benötigt, muss die Utility-Klasse Ioc as verwenden, damit sie nicht statisch sein kann.

Aber ich möchte wirklich Dienstprogramm-Klasse so statisch sein, so einfach zu konsumieren. Ich möchte nicht den Konstruktor jeder konsumierenden Klasse auffüllen, die Hilfsklassen benötigt.

Consume-Klassen selbst brauchen möglicherweise nicht einmal db-Zugriff selbst. Daher möchte ich den db-Accessor nicht einspeisen und ihn auch in Dienstklassen eingliedern.

Raten Sie, es gibt keine perfekte Lösung für jetzt.Eines Tages hoffe ich, dass wir einen Schritt weiter gehen, zusätzlich zur Konstruktor/Eigenschaft-Injektion, gibt es "globale Kontext-Injektion/Konfiguration", oder "statische Injektion", wenden Sie Ioc über die Objekterzeugung hinaus an.

Denken Sie darüber nach, warum nicht?

+0

Ist dies eine Antwort oder nur ein Kommentar zu der Frage? –