Hallo,
Ich erfrage hier mal Eure Meinung zum Thema API einer Lib-Assembly.
Ich nutze in meinen Klassen einen Logging Provider. Dieser wird injiziert oder kann injiziert werden.
D.h. in einigen Klassen ist er als nullable ausprogrammiert. In anderen Klassen hingegen ist der ILogger nicht nullable. Insbesondere, weil dort durch das Log wichtige Information im Fehlerfall ausgegeben werden. In den Klassen mit nullable kommen ausschließlich optionale Informationen, die nicht zur angeforderten Schnittstellenfunktion beitragen.
Der Sinn beim nullable Typ ist hier, eine Nutzung der Klasse auch zu ermöglichen, wenn kein Logging-Provider für die nutzende App definiert ist.
Jetzt zum Kern meiner Frage:
Macht es mehr Sinn die nullable ILogger rauszuschmeissen und den Anwender der Klasse zum Liefern eines Logging Provider zu zwingen? Er könnte den Logger ja schließlich auch mocken, wenn er keinen Logging-Provider liefern möchte...
Bin gespannt auf Eure Meinungen.
Viele Grüße Sprotti
heut debug ich, morgen browse ich, übermorgen cast ich die Königin auf int...
Wenn du die Lib verteilst, dann sollte der User der Lib entscheiden wann er etwas loggt.
I.d.R. machen das auch alle mit bekannten Libs so, dass dort der User einen entsprechenden Logger mitgeben muss um Ausgaben zu bekommen.
Ein Beispiel dafür ist z.B. StackExchange.Redis wo über Injection dann die Nullable ILogger Instanz mitgegben wird.
Wenn diese nicht gesetzt ist, dann wird auch nichts geloggt.
Da du auch nicht wissen kannst in welchen Umgebungen deine Lib verwendet wird, wäre es fatal wenn du dort Vorgaben mit nötigen Logging hast.
Ggf. läuft deine Lib in einer Anwendung im Embedded Bereich, dann wäre auch Logging ggf. gar nicht möglich oder nur im kleinen Bereich.
T-Virus
Developer, Developer, Developer, Developer....
99 little bugs in the code, 99 little bugs. Take one down, patch it around, 117 little bugs in the code.
Logging oder andere Metriken sind Dinge, die einen massiven, negativen Impact auf die Runtime-Performance ausüben kann - vor allem wenn man Best Practises wie Compile-Time Logging nicht anwendet.
Wenn Deine Logging-Dinge innerhalb Deines Providers mich 20% Runtime-Performance kostet, weil Du es erzwingst, dann fliegt die Lib halt wieder raus. Das muss niemanden aufgebürdet werden.
Daher gilt es auch als Recommendation, dass eine "neutrale" Lib kein Logging-Parameter erzwingt. Unterliegt im Endeffekt der generellen Regel: nur den Code ausführen, den man auch ausführen muss.
Weil aber es doch ab und zu Libs gibt, die das ignorieren, hab auch ich mir einen solchen Mock geschrieben: https://github.com/BenjaminAbt/ThrowAwayLogger
Nachhaltig ist es nicht. Es wird Code ausgeführt, der nicht ausgeführt werden muss.
Zitat von T-Virus
Da du auch nicht wissen kannst in welchen Umgebungen deine Lib verwendet wird, wäre es fatal wenn du dort Vorgaben mit nötigen Logging hast.
Deswegen ist es ja prinzipiell ein Interface, sodass Dir nichts aufgezwungen wird. Mit der Umgebung hat das nichts zutun.
Zitat von T-Virus
Ggf. läuft deine Lib in einer Anwendung im Embedded Bereich, dann wäre auch Logging ggf. gar nicht möglich oder nur im kleinen Bereich.
Warum nicht? Ich verwende ILogger auch im Embedded-Bereich problemlos im gleichen Maße wie in ASP.NET Core.
Was unterscheidet sich da? Ehrliche Frage: vielleicht kenn ichs nicht.
- performance is a feature -
Microsoft MVP - @Website - @AzureStuttgart - github.com/BenjaminAbt - Sustainable Code
Die embedded Geräte mit denen ich gearbeitet habe, hatten im worst case 128MB RAM und 512MB Speicher.
Da hat ein Log(-file) schnell den Platz belegt, wenn man nicht aufgepasst hat. Daher habe ich immer offline als Ringspeicher geloggt und sofern eine Netzwerkverbindung bestand, an eine Datenbank übertragen.
BTT: Persönlich finde ich es am Besten einmal im Konstruktor einen Logger mitzugeben. Ist dieser null, greift eine standard implementierung. Im Zweifel Abt´s ThrowAwayLogger, der nix tut.
So kann ich eine Library ohne viel Aufwand testen und ein Gefühl dafür bekommen ob sie das macht was ich brauche. Entspricht sie meiner Erwartung, programmiere ich den Logger aus.
Das senkt die Einstiegshürde. Es gibt nix nervigeres als erstmal 10 Klassen schreiben zu müssen um dann zu merken, dass die Library gar nicht tut was man sucht!
Zitat von trib
Die embedded Geräte mit denen ich gearbeitet habe, hatten im worst case 128MB RAM und 512MB Speicher.
Da hat ein Log(-file) schnell den Platz belegt, wenn man nicht aufgepasst hat.
Das ist aber ja nur eine Hardware-Limitierung, sofern Du direkt auf die Hardware loggst. Du kannst aber ohne Probleme auch von Embedded auf extern loggen, sofern die Hardware in einem Netz ist. Das ist aber alles dann situationsbedingt und fällt für mich nicht unter den generellen Fall "Embedded".
Hab ne Software, die im Embedded-Bereich läuft und sowohl auf ne SD-Card sowie auch gegen ein HTTP Endpunkt loggen kann.
Ist dieser null, greift eine standard implementierung.
Wo wir wieder beim Fall wären: es wird Zeug ausgeführt, das nicht sein muss. Im dümmsten Fall ist die Standard-Implementierung inkompatibel. Kostet einfach Ressourcen, das man vermeiden kann.
PS: .NET hat mittlerweile auch einen NullLogger.
- performance is a feature -
Microsoft MVP - @Website - @AzureStuttgart - github.com/BenjaminAbt - Sustainable Code
Hi,
habt vielen Dank für Eure Antworten. Ich werde die Lib-API so aufbauen, dass alle Logger optional angegeben werden können. Auch wenn es inzwischen einen NullLogger gibt, ist stets mehr Aufwand mit einer erzwungenen Abhängigkeit generiert.
Mich haben aber besonders die Argumente zum Thema Performance und zusätzlicher Implementierungsaufwand überzeugt.
heut debug ich, morgen browse ich, übermorgen cast ich die Königin auf int...