Singleton, Protokollierung und globale Einstellungen - Gute oder schlechte Implementierung?

8

Ich habe eine Protokollierungsklasse, die von fast überall in der Anwendung aufgerufen werden muss.

Allerdings muss am Anfang der Anwendung mit "welcher Pfad zum Schreiben", "Protokollierungsstufe" und wenn "aktiviert" ist oder nicht aktiviert werden.

Ich möchte diese Parameter nicht jedes Mal angeben oder die Logging-Klasse als Parameter an jedes einzelne Objekt in meiner Anwendung übergeben. Daher verwende ich das Singleton-Muster für die Protokollierung.

In letzter Zeit habe ich viel von eng gekoppelten Klassen gelitten. Ich möchte nicht noch einmal denselben Fehler machen, aber nachdem ich darüber nachgedacht habe, ist das die einzige gute Lösung.

UPDATE:

Ich interessiere mich nicht dafür, dass ich ähnliche Designprobleme aufzeichnen würde. Ich habe das gleiche Dilemma mit einem anderen globalen Einstellungsobjekt, das aus so vielen Klassen verwendet werden muss. Aber es in jeden einzelnen von ihnen zu injizieren macht nur einen schrecklichen Overhead und weniger lesbaren Code.

Was halten Sie von dieser Implementierung und was tun Sie, wenn Sie ähnliche Designentscheidungen treffen?

P.S. Bitte schlagen Sie nicht etwas wie "Log4X-Bibliothek verwenden" usw. vor.

    
dr. evil 28.04.2009, 07:14
quelle

9 Antworten

4

Erstens - könnten Sie den Protokollschreiber als Trace-Listener schreiben und Trace.Write etc von den Methoden verwenden?

Brauchen Sie hier tatsächlich eine Instanz? Das wäre zum Beispiel nützlich, wenn Sie es als TextWriter oder ähnlich abstrahieren möchten - aber wenn es sich um einen eigenständigen Singleton handelt, können die Methoden nicht direkt statische Methoden verwenden, zB Log.Write(...) (anstatt zu übergeben in einer Protokollinstanz)?

Das allgemeine Problem - es hängt von den Typen ab, die die Protokollierung durchführen. Für "manager" (etc) -Klassen könnten Sie die Injection von Abhängigkeiten (Unity, StructureMap usw.) in Betracht ziehen, um dies zu automatisieren. Ich würde normalerweise keine Injektion mit DTOs verwenden.

    
Marc Gravell 28.04.2009, 07:18
quelle
3

Auch wenn Sie keine Vorschläge für "log4X verwenden" möchten (obwohl Sie nicht genau sagen, warum Sie das Rad neu erfinden wollen), erscheint es sinnvoll, die getroffenen Entscheidungen zu prüfen durch verschiedene Logging-Bibliotheken.

Nach meiner Erfahrung sind die Probleme der engen Kopplung bei der Protokollierung nicht so relevant - insbesondere möchte ich die Protokollierungsseite meiner App nur selten testen und es macht mir nichts aus, wenn sie sich während der Einheit an der Konsole anmeldet Testen.

Kurz gesagt, das "normale" Muster von:

%Vor%

(mit entsprechenden Namensänderungen usw.) ist in seiner Verwendung von statischen Methoden ästhetisch nicht ansprechend, funktioniert aber in der Praxis ziemlich gut. Zumindest war das meine Erfahrung.

    
Jon Skeet 28.04.2009 07:21
quelle
2

Sie können hier wahrscheinlich ein Singleton verwenden. Sie haben eine enge Kopplung zwischen jeder Klasse in der Anwendung und der Logger-Klasse, aber wenn die Logger-Klasse und die globale Einstellungen-Klasse wirklich in jeder Klasse benötigt werden, kann dies akzeptabel sein.

    
J W 28.04.2009 07:30
quelle
1

Ich persönlich benutze in diesem Fall die statische Klasse. Die Klasse verfügt über statische Konfigurationsfelder (für das manuelle Experimentieren) und einige Funktionen, um sie mithilfe der Konfiguration aus dem entsprechenden CONFIG-Dateiabschnitt zu füllen.

Dies ist in der Tat sehr ähnlich wie bei DI, da Sie eine neue Konfiguration "injizieren" können. Um die Konfiguration auf das neue Modell zu ändern, ändere ich einfach im .config Dateifeld, das den "aktiven" Konfigurationsabschnitt enthält.

Dies ist einfach zu bedienen, einfach zu warten, und jeder versteht es ... Ich sehe keinen besonderen Nachteil davon ...

    
majkinetor 28.04.2009 08:23
quelle
0

Die Protokollierung und Einstellungen werden auf zwei verschiedene Arten gehandhabt. Wenn ich also richtig verstanden habe, war Ihre eigentliche Frage eher mit der Handhabung globaler Einstellungen zwischen Assemblies zu tun.

Im Hinblick auf die Protokollierung sind die Dinge ziemlich klar - die Verwendung eines globalen Singleton ist üblich, obwohl es Ihre Bibliotheken eng an die Protokollbibliothek koppelt. Trace-Listener zu verwenden ist eine noch bessere Lösung IMHO.

Wenn Sie jedoch über Anwendungseinstellungen sprechen, sollten Sie vermeiden . Behalten Sie alle anwendungsbezogenen Einstellungen nur an einer Stelle (diejenigen, die beibehalten werden sollen), aber nicht statisch für andere Bibliotheken verfügbar. Daher muss die Übergabe der entsprechenden Einstellungen an andere Assemblies die Verantwortung des Anrufers sein, nicht umgekehrt.

    
Groo 28.04.2009 07:51
quelle
0

Ist das ASP.Net? In diesem Fall können Sie das Fehlerereignis in Global.asax verwenden.

Haben Sie für Ihre vielen Abhängigkeiten in Betracht gezogen, ein Abhängigkeits-Injection-Framework zu verwenden?

Aktualisieren

Ich bin mir nicht sicher, welche Auswirkungen die Leistung hat und wie relevant die Leistung für Ihre App ist, aber dieses Framework sieht interessant aus: PostSharp , < a href="http://johnnycoder.com/blog/2009/01/16/caching-with-c-aop-and-postsharp/"> Ein Blogpost darüber .

Möglicherweise können Sie auch das bedingte Attribut nutzen.

Wenn Sie PostSharp verwenden, würde mich interessieren, wie es funktioniert.

    
Chuck Conway 28.04.2009 07:22
quelle
0

Eine Sache, die Sie untersuchen könnten, ist Paket-für-Funktion. Es wird behauptet, dass das Folgen dieser Technik einige Probleme annimmt, die zu einer hohen Kopplung zwischen Klassen führen. Genauer gesagt würde es bedeuten, dass es in jeder Anwendung in Ihrer Anwendung nur eine Klasse gibt, die für die Kommunikation mit dem Konfigurationsanbieter verantwortlich ist (was durchaus Teil einer Konfigurations- / Setup- / Installationsfunktion selbst sein könnte). Das Kopplungsniveau ist immer noch auf der hohen Seite, aber da es gut definiert ist, sollte es managbar sein.

    
CurtainDog 28.04.2009 10:15
quelle
0

Ähnliches:

%Vor%     
Yordan Georgiev 20.05.2009 07:42
quelle
0

Wenn Sie immer in dieselbe Quelle schreiben, können Sie das Singleton-Muster verwenden.

Wenn Sie jedoch Informationen zu verschiedenen Quellen protokollieren, z. B. in einer Datei oder einem Ereignisprotokoll, erstellen Sie eine andere Instanz der Protokollierungsklasse für eine andere Konfiguration.

    
Trilok 11.09.2012 21:09
quelle