Saubere Lösung für einen Ereignis-Log



  • blub² schrieb:

    Ich benutze immer eine Klasse in der ich alles static mache die einmalig initialisiert wird (Pfad) und dann ein Interface zur Verfügung stellt (z.B. auch string + int hinten drangehängt also etwa log(string, int)).

    Was für Vorteile hast du hier gegenüber einem Singleton? Ich sehe nur Nachteile.

    Davon abgesehen fände ich operator<< ein intuitiveres Interface.



  • blub² schrieb:

    drakon schrieb:

    Entweder so, oder mit einem Singleton. Was besser ist, musst du wohl selbst entscheiden.

    Wieso ein Singleton?!

    Ich benutze immer eine Klasse in der ich alles static mache die einmalig initialisiert wird (Pfad) und dann ein Interface zur Verfügung stellt (z.B. auch string + int hinten drangehängt also etwa log(string, int)).

    Das ist prinzipiell ebenfalls ein Singleton. Eine eher schlechte Implementierung (Gültigkeiten z.B), aber es ist eine.



  • Nexus schrieb:

    blub² schrieb:

    Ich benutze immer eine Klasse in der ich alles static mache die einmalig initialisiert wird (Pfad) und dann ein Interface zur Verfügung stellt (z.B. auch string + int hinten drangehängt also etwa log(string, int)).

    Was für Vorteile hast du hier gegenüber einem Singleton? Ich sehe nur Nachteile.

    Davon abgesehen fände ich operator<< ein intuitiveres Interface.

    1. @operator<< Stimmt, wäre eine Möglichkeit. Ist würde ich sagen Geschmackssache.

    blub² schrieb:

    Wieso ein Singleton?!



  • blub² schrieb:

    1. @operator<< Stimmt, wäre eine Möglichkeit. Ist würde ich sagen Geschmackssache.

    Aber auch Flexibilitätssache. Mit log() -Memberfunktionen kannst du zum Beispiel nie alle möglichen Kombinationen von Eingabeargumenten behandeln. Selbst mit Templates müsstest du für jede Argumentzahl eine neue Überladung bereitstellen.

    blub² schrieb:

    blub² schrieb:

    Wieso ein Singleton?!

    Was willst du damit sagen? Ich habe ja gefragt, warum du deine Variante einem herkömmlichen Singleton vorziehst.



  • Nexus schrieb:

    blub² schrieb:

    blub² schrieb:

    Wieso ein Singleton?!

    Was willst du damit sagen? Ich habe ja gefragt, warum du deine Variante einem herkömmlichen Singleton vorziehst.

    Sorry, ich sags mal (ein bisschen) ausführlicher:
    Warum überhaupt einen Singleton verwenden?

    War wohl etwas zu kurz formuliert, aber ich bin halt auch noch nicht der "Ober-Checker" und wüsste gerne wie / wo / was / warum ;).
    Ich bin nämlich bis jetzt noch überhaupt garnicht auf die Idee gekommen einen Singleton zu verwenden.

    Wenn ich jetzt mal ein bisschen rate ohne recherchiert zu haben tippe ich darauf dass es darum geht eine Log Klasse als Singleton zu entwerfen und von dieser dann ein Objekt (noch in der Headerdatei?) zu erzeugen welches dann verwendet werden kann, praktisch im Stil von cerr / cout.
    Was bringt mir das für Vorteile?

    #edit: Das mit cerr / cout war irgendwie nur mittelmäßig gut als Vergleich...



  • Aha, okay. Ich habe dein "?!" als Abneigung gegenüber Singletons interpretiert, sorry für das Missverständnis. 🙂

    Singletons sind ein Design Pattern für global zugängliche, einzigartige Objekte, wie hier zum Beispiel ein Logger. Ein kurzes Beispiel, wie sowas aussehen kann (hier das Meyers-Singleton):

    class Singleton
    {
        public:
            static Singleton& Instance()
            {
                static Singleton instance; // Beim ersten Aufruf Objekt erzeugen
                return instance; // Referenz auf das einzige Objekt zurückgeben
            }
        private:
            // Konstruktoren, andere Daten und Funktionen
    };
    

    Das Objekt wird also nicht direkt im globalen Namensraum, sondern innerhalb der Methode als static deklariert. Aber die Verwendung von static als Speicherklasse für das Objekt ist nur eine mögliche Implementierung, man kann beispielsweise auch new und delete einsetzen.

    Gegenüber einer Klasse, die nur aus static -Membern besteht, ist man hier freier. Zum Beispiel wird das Objekt nur erstellt, falls Instance() überhaupt aufgerufen wird. Oder falls bei der Zerstörung eine spezielle Aufräumsemantik hinzukommen soll, die man als Programmierer beeinflussen will, hat man mehr Möglichkeiten. Bei static -Daten hast du wenig Macht über die Lebensdauer und Speicherverwaltung.

    Allerdings sei noch erwähnt, dass globale Variablen einige Probleme mit sich bringen und Singletons diese nur teilweise beheben können. Man sollte nicht in Versuchung geraten: Trotz der scheinbaren Einfachheit auf den ersten Blick (globaler Zugriff von überall her) können langfristig komplexe, schwer wartbare Abhängigkeiten entstehen. In vielen Fällen rät es sich, Klassen und deren Objekte so lokal wie möglich zu halten und allenfalls Zeiger oder Referenzen zur Weitergabe verwenden.



  • Danke für die Ausführliche Erklärung!

    Ich sehe schon, es gibt noch viel zu lernen 🙄.



  • Ich danke ebenfalls.
    So wie ich das verstanden habe löst ein Singleton nur das Problem der Einzigartigkeit.
    Wenn ich jetzt z.B. mehrere Threads habe in denen zu loggende Ereignisse (u.A Fehler) auftreten können und das dem main-Thread melden möchte habe ich ja wieder nichts davon, weil die Log-Klasse erst recht wieder einen Funktionszeiger auf die Funktion die die Nachricht bearbeitet braucht (Das habe ich in der ersten Frage vermutlich nicht gut angedeutet). Was ist die sauberste Lösung dafür?

    LG



  • Ich habe für logs-eigtl immer cout, clog und cerr verwendet und die streams nur "umgebogen" - bisher bin ich damit immer recht gut gefahren...
    allerdings ist es hier nicht möglich, logging-filter zu erstellen(außer die abstufung cout, clog). die meisten libs haben da ja so was wie logging-level etc - und natürlich geht das auch nur, so lang man keine eigene lib programmiert.

    bb


  • Mod

    unskilled schrieb:

    Ich habe für logs-eigtl immer cout, clog und cerr verwendet und die streams nur "umgebogen" - bisher bin ich damit immer recht gut gefahren...
    allerdings ist es hier nicht möglich, logging-filter zu erstellen(außer die abstufung cout, clog). die meisten libs haben da ja so was wie logging-level etc - und natürlich geht das auch nur, so lang man keine eigene lib programmiert.

    bb

    Die Funktionsweise der ostreams kann man, wenn man möchte, ziemlich verbiegen. Man würde dazu den darunterliegenden streambuf verändern. Das ist eigentlich genau das richtige, wenn nicht die paar Stunden Einarbeitung in das Thema nötig wären, bevor man das richtig kann.


Anmelden zum Antworten