Logging von Klassen



  • Ich Habe folgendes Konstrukt:

    class Modul
    {
      public: setzeZustand(int);
      private: int internerZustand;
    }
    

    Davon erstelle ich eine Instanz. Der interne Zustand wird immer wieder verändert, das Objekt ändert sich also. Es hat sehr viele weitere Variablen und ich möchte nun die Veränderung loggen, also eine Art Historie erstellen (am liebsten mit boost/serialize).

    Ich könnte nun natürlich eine weitere Klasse Modul_Snapshot oder so erstellen und eine Methode am Objekt aufrufen, welche mir die Daten in ein Objekt von Modul_Snapshot kopiert. Dann müsste ich aber alle Zustände doppelt pflegen, einmal in Modul und dann auch in Modul_Snapshot sowie die Funktion welche selbiges erstellt.

    Gibt es eine einfach Möglichkeit das alles automatisch nur aus der Klasseninformation von Modul zu erledigen? Sodass ich weitere Attribute zu Modul hinzufügen kann und diese dann automatisch mitgespeichert werden?



  • C++ hat kein Reflection, daher wird da "automatisch" nichts gehen. Die Aufgbae klingt ein wenige nach dem Entwurfstmuster Memento. Wobei bei Dir der eigentlich Zweck nicht das Wiederherstellen, sondern das Serialisieren des Zustandes ist. Ich vermute mal, dass dein Hauptproblem ist, dass die Klasse Modul "sehr viele Variablen" hat, was ansich schon nach einem Designfehler riecht.
    Davon mal abgesegehn kannst Du aber die Daten, die den Modulzustand ausmachen in eine Klasse auslagern, die dann am Stück in ein Memento geschrieben werden. Das heißt, bekommst Du dort neue Attribute, wird die Memento Klasse nicht geändert und auch nicht die Methode, die den Zustand in ein Memento schreibt.



  • Ich fürchte, bevor ich Dir sagen kann, wie Du es nicht machen sollst, muß ich Dir erst das Warum ausreden.

    "sehr viele Variablen" wird schlechterdings zu einer std::map<string,boost::any>, na wenigstens kannste jetzt loggen und neue Attribute zufügen.



  • Ich verstehe nicht ganz, warum du beides pflegen musst. Entweder du machst die Arbeit in der "MachMirSnapshot"-Funktion selbst, oder halt in der Klasse.

    class Modul
    {
      friend class ModulSnapshot;
      int internal_state;
    public:
    };
    
    class ModulSnapshot
    {
      int internal_state;
    public:
      ModulSnapshot(const Modul &modul)
        : internal_state(modul.internal_state)
      {}
      ModulSnapshot &operator >> (std::ostream &stream)
      {
        stream << "Modul state snapshot:\n";
        stream << "Internal state: " << internal_state << "\n";
        return *this;
      }
    };
    
    int main()
    {
      Modul modul;
      std::ofstream log("log.txt");
      ModulSnapshot(modul) >> log;
    }
    


  • Erstmal vielen Dank für eure Antworten, das Pattern gefällt mir, aber ich erkenne leider bei euch beiden nicht wo sich da Aufwand einsparen lässt.

    Sowohl in diesem Pattern als auch im Code von cooky451 wird "int _state" (resp. "int _value") bzw. bei cooky451 "int internal_state" sowohl in der Klasse des Originators als auch im Momento deklariert. Also zwei mal! Hinzu kommen noch die Funktionen zum Setzen und die Konstruktoren, das ist mir ein bisschen zu viel Aufwand für meine Modulersteller.

    Im Prinzip habe ich schon gefunden was ich möchte, boost/serialize. Da genügt eine einfache Zeile in der Methode serialize und schon wird das ganze Modul archiviert. Das Problem ist nur, der macht das ganze nur einmal und beachtet keine Zustände 😞

    Wenn alles nichts Hilft muss ich wohl solche Memento verwenden und diese dann serialisieren.


Log in to reply