IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

C++ Discussion :

Question sur la conception d'une classe type Logger


Sujet :

C++

  1. #1
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Mai 2009
    Messages
    35
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2009
    Messages : 35
    Points : 31
    Points
    31
    Par défaut Question sur la conception d'une classe type Logger
    Bonjour à tous,
    Je suis sur un projet qui prend de l'ampleur. Il me faut commencer à développer des outils de débugging. Je suis en train de travailler sur la conception d'une classe de type logger, et je me pose surtout des questions sur la manière de l'implanter dans mon code.
    Cette classe devra tout bêtement recevoir des paramètres divers pour les afficher dans la console ou les enregistrer dans un unique fichier .log. Les informations qu'elles devra gérer serons surtout en rapport avec les différentes ressources chargées. Il s'agit d'un jeu 2D, les ressources serons principalement des fichiers de configuration, des images, des bibliothèques externes et des fichiers sonores.

    Je ne sais pas vraiment si la meilleur solution serait de créer un objet globale de la classe logger pour l'utiliser tout le long du programme, ou plutôt de créer un objet logger dans chaque classe de mon programme.

    Comment feriez-vous? Je n'ai pas vraiment plus de précision. C'est encore un peu confus dans ma tête. J'ai conscience qu'une classe globale est un peu une implantation à la sauvage, mais vu qu'elle ne gère qu'un seul fichier j'ai un peu de mal à voir ce que je pourrais gagner à créer plusieurs instances de cette classe (méthode plus propre mis part).

    Merci de votre aide.

  2. #2
    Membre régulier

    Inscrit en
    Octobre 2010
    Messages
    50
    Détails du profil
    Informations forums :
    Inscription : Octobre 2010
    Messages : 50
    Points : 70
    Points
    70
    Par défaut
    J'ai vu deux ou trois loggers dans des projets d'ampleur moyenne et il s'agissait toujours d'une classe avec une méthode statique Log() (ou un Singleton) et quelques overloads pour supporter différents "niveaux" de sévérité d'erreur. Si le programme est multi-threadé, il faut penser à protéger le stream derrière un mutex, mais à part je ne vois pas pourquoi on ferait plus complexe.

  3. #3
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 614
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 614
    Points : 30 626
    Points
    30 626
    Par défaut
    Salut,

    Un logger est, classiquement, le genre de ressource que l'on a très facilement tendance à rendre globale, voire pour laquelle on s'organise afin de pouvoir la désactiver sur simple demande (par exemple en fournissant un define quelconque à la compilation).

    Le pattern singleton est particulièrement adapté aux classes de logging, et, s'il ne devait servir qu'à une seule chose, ce serait sans doute pour elles.

    Tu pourrais donc créer une classe de base (template) singleton proche de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    template <typename T>
    class TSingleton
    {
        public:
            static T & instance()
            {
                static T inst;
                return inst;
            }
        protected:
            /* seules les classes dérivées ont accès au constructeur et au
             * destructeur
             */
            TSingleton(){}
            ~TSingleton(){}
        private:
             /* copie et affectation interdite (en attendant C++1x ) */
             TSingelton(TSingleton const &);
             TSingleton& operator=(TSingleton const &);
    };
    Tu remarquera que je ne lui donne pas de fonction "destroy" car il n'y a, à mon sens, aucune raison pour nous donner l'occasion de détruire le singleton une fois qu'il a été créé.

    Il sera, de toutes manières, correctement détruit au moment où l'application sera quittée

    Il est possible de diviser le logging en trois partie distinctes:
    1. L'exécution d'une action
    2. La survenue d'un événement (ex: clique de souris,...)
    3. Le résultat de l'action ou de l'événement

    Nous devrions donc retrouver ces trois possibilités dans l'interface de notre logger qui prendrait la forme de (logger "console")
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    #include <tsingleton.hpp> // pour la classe de base
    #include <iostream> // pour std::cerr
    /* on appelle cette technique le CRTP pour
     * Curriously Recuriing Template Pattern.
     *
     * On peut, en effet, être étonné du fait que l'on utilise une classe 
     * template avec une classe que l'on crée à peine, mais cela fonctionne
     * :D
     */
    class ConsoleLogger : public TSingleton<ConsoleLogger>
    {
        /* il faut rendre la classe de base amie de la classe logger 
         * de manière à lui donner l'accès au constructeur et au
         * destructeur
         */
        friend class TSingleton<ConsoleLogger>;
        public:
        /* les fonctions que l'on utilisera */
        /* logging du lancement d'une action */
        void logAction(std::string const & first, std::string const & second,
                     std::string const & file, int line)
        {
            std::cerr<<first<<second<<" in file "<<file<<" at line "<<line;
        }
        void logEvent(std::string const & first, std::string const & file, int line)
        {
            std::cerr<<"Event: "<<first<<" in file "<<file<<" at line "<<line;
        }
        void logResult(std::string const & res, std::string const & info)
        {
            std::cerr<<res<<std::endl;
            if(info!="")
                std::cerr<<info<<endl;
        }
        private:
            /* le constructeur et le destructeur sont privés et définis 
             * pour que seule la classe de base puisse les invoquer
             */
             ConsoleLogger(){}
             ~ConsoleLogger(){}
             /* le constructeur par copie et l'opérateur d'affectation sont
              * privés et non défini pour éviter toute duplication de l'objet
              * (en attendant C++1x)
              */
              ConsoleLogger(ConsoleLogger const &);
              ConsoleLogger & operator=(ConsoleLogger const &);
    };
    Mais cette classe ne sera pas facile à utiliser, car elle nécessiterait l'écriture d'un code proche de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    ConsoleLogger::instance().logAction("lecture du fichier",thefile,__FILE__,__LINE);
    if(myressource.read(thefile))
        ConsoleLogger::instance().logResult("success","");
    else
        ConsoleLogger::instance().logResult("error","unable to load the file");
    Si tu dois l'écrire de la sorte, tu en auras vite marre de logger tes différents événements

    De plus, écrit de la sorte, il devient impossible de désactiver le logging, ce qui n'est pas forcément des plus opportuns, étant donné qu'il s'agit de logger... des informations de débuggage, et que cela ne devrait donc pas avoir lieu en "production"

    Je te propose donc de passer par les macros préprocesseurs afin de gérer cela de manière plus facile.

    Nous ferons en sorte que le logging ne soit activé que si le symbole DEBUG est défini ( sous gcc, cela donnerait une ligne de compilation proche de gcc monfichier.cpp -DDEBUG), et de simplifier un peu l'utilisation.

    Nous allons donc créer un fichier d'en-tête séparé que nous veillerons simplement à inclure dans tout fichier dans lequel nous voulons logger des information.

    Il prendrait la forme de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    #ifndef DEBUG_MACRO_HPP // garde anti inclusion multiple
    #define DEBUG_MACRO_HPP
    #ifdef DEBUG // si le symbole DEBUG est defini
    #include <consolelogger.hpp>
    #include <cassert>
    #define DEBUGACTION(x1,x2) \
    ConsoleLogger::instance().logAction( x1 , x2 ,__FILE__,__LINE);
    #define DEBUGEVENT(x1)\
    ConsoleLogger::instance().logEvent( x1,__FILE__,__LINE);
    #define DEBUGSUCCESS \
    ConsoleLogger::instance().logResult("success","");
    #define DEBUGWARNING(x1) \
    ConsoleLogger::instance().logResult("warning", x1 );
    #define DEBUGERROR( a, x1) \
    ConsoleLogger::instance().logResult("error", x1 ); \
    assert(a);
    #else //si DEBUG n'est pas défini, on transforme tout en "no op"
    #define DEBUGACTION(x1,x2) ;
    #define DEBUGEVENT(x1) ;
    #define DEBUGSUCCESS  ;
    #define DEBUGWARNING(x1)  ;
    #define DEBUGERROR(x1)  ;
    #endif // symbole DEBUG
    #endif //DEBUG_MACRO_HPP
    Tu remarqueras que j'en ai profité pour lancer une assertion sur les erreurs... on pourrait faire pareil pour les avertissements, mais c'est à toi de juger

    Le code prenant le logging en compte pourrait alors ressembler à
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    DEBUGACTION("lecture du fichier",thefile);
    if(myressource.read(thefile))
        DEBUGSUCCESS
    else
        DEBUGERROR(myressource.loaded(),"unable to load the file")
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  4. #4
    Membre chevronné
    Avatar de Joel F
    Homme Profil pro
    Chercheur en informatique
    Inscrit en
    Septembre 2002
    Messages
    918
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Chercheur en informatique
    Secteur : Service public

    Informations forums :
    Inscription : Septembre 2002
    Messages : 918
    Points : 1 921
    Points
    1 921
    Par défaut
    Pourquoi tout le monde s'acharne a faire un singleton d'un logger ?
    Ca me parait mieux niveau flexibiltié et moins casse geule d'avoir des logegr qui s'instancie et qui sont passés au éléments que l'on veut logger.

    Ca permet aussi de pouvoir choisir qui logg comment ou vers quoi au niveau de l'instance et ca limite aussi les drames des singletons mal bouchonnés

  5. #5
    Membre chevronné Avatar de Astraya
    Homme Profil pro
    Consommateur de café
    Inscrit en
    Mai 2007
    Messages
    1 043
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France

    Informations professionnelles :
    Activité : Consommateur de café
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Mai 2007
    Messages : 1 043
    Points : 2 234
    Points
    2 234
    Par défaut
    Pourquoi tout le monde s'acharne a faire un singleton d'un logger ?
    je suis d'accord, un logger peut être aussi un RAII auquel on passe en paramètre le flux de sortie ostream.
    Homer J. Simpson


  6. #6
    gl
    gl est déconnecté
    Rédacteur

    Homme Profil pro
    Inscrit en
    Juin 2002
    Messages
    2 165
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : France, Isère (Rhône Alpes)

    Informations forums :
    Inscription : Juin 2002
    Messages : 2 165
    Points : 4 637
    Points
    4 637
    Par défaut
    Citation Envoyé par Joel F Voir le message
    Pourquoi tout le monde s'acharne a faire un singleton d'un logger ?
    Ca me parait mieux niveau flexibiltié et moins casse geule d'avoir des logegr qui s'instancie et qui sont passés au éléments que l'on veut logger.

    Ca permet aussi de pouvoir choisir qui logg comment ou vers quoi au niveau de l'instance et ca limite aussi les drames des singletons mal bouchonnés
    J'aurais plutôt tendance à dire "Pourquoi tout le monde s'acharne à développer son logger" alors qu'il en existe déjà, par exemple dans POCO. Il me semble aussi avoir vu un truc dans le sandbox boost.

    Sinon +1 sur le reste. Je ne vois pas en quoi il est avantageux d'avoir un logger singleton.

  7. #7
    Membre chevronné
    Avatar de Goten
    Profil pro
    Inscrit en
    Juillet 2008
    Messages
    1 580
    Détails du profil
    Informations personnelles :
    Âge : 33
    Localisation : France

    Informations forums :
    Inscription : Juillet 2008
    Messages : 1 580
    Points : 2 205
    Points
    2 205
    Par défaut
    Tout comme joel. Ou encore mieux comme gl .. Un logger c'est pas trivial autant évité le NIH.
    Par contre c'est pas dans la sandbox boost.log a été officiellement accepté dans boost .
    "Hardcoded types are to generic code what magic constants are to regular code." --A. Alexandrescu

  8. #8
    Membre chevronné
    Avatar de Joel F
    Homme Profil pro
    Chercheur en informatique
    Inscrit en
    Septembre 2002
    Messages
    918
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Chercheur en informatique
    Secteur : Service public

    Informations forums :
    Inscription : Septembre 2002
    Messages : 918
    Points : 1 921
    Points
    1 921
    Par défaut
    Citation Envoyé par gl Voir le message
    J'aurais plutôt tendance à dire "Pourquoi tout le monde s'acharne à développer son logger" alors qu'il en existe déjà, par exemple dans POCO. Il me semble aussi avoir vu un truc dans le sandbox boost.
    Boost.Log ets dispo dans le trunk de mémoire. Mais oui, pourquoi rerererefaire un logger :E

  9. #9
    gl
    gl est déconnecté
    Rédacteur

    Homme Profil pro
    Inscrit en
    Juin 2002
    Messages
    2 165
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : France, Isère (Rhône Alpes)

    Informations forums :
    Inscription : Juin 2002
    Messages : 2 165
    Points : 4 637
    Points
    4 637
    Par défaut
    Citation Envoyé par Goten Voir le message
    Par contre c'est pas dans la sandbox boost.log a été officiellement accepté dans boost .
    Il est déjà releasé ou il ne vient qu'avec la 1.45 ? Car je ne l'ai pas trouvé dans la 1.44.

  10. #10
    Membre chevronné
    Avatar de Goten
    Profil pro
    Inscrit en
    Juillet 2008
    Messages
    1 580
    Détails du profil
    Informations personnelles :
    Âge : 33
    Localisation : France

    Informations forums :
    Inscription : Juillet 2008
    Messages : 1 580
    Points : 2 205
    Points
    2 205
    Par défaut
    C'était une acceptation conditionelle donc je suis même pas sur que ça soit en 1.45 . Mais bon il est dans le trunk de toute façon.
    "Hardcoded types are to generic code what magic constants are to regular code." --A. Alexandrescu

  11. #11
    Responsable 2D/3D/Jeux


    Avatar de LittleWhite
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Mai 2008
    Messages
    26 860
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Mai 2008
    Messages : 26 860
    Points : 219 062
    Points
    219 062
    Billets dans le blog
    120
    Par défaut
    Bonjour,

    D'une part, si j'avais eu un Logger à faire, je l'aurais fait comme koala01 le décrit.

    Après il est tout aussi vrai que j'ai appris récemment, qu'il était plus que préférable d'éviter les Singleton (Problème en multithread, peu de possibilité d'évolution, variable globale déguisée, ...)

    Maintenant, ma question est:
    Je suis avec une gp2x (console portable, donc assez limitée), puis je utiliser boost sans craindre d'avoir des problème? (surtout que je dois compiler pour un ARM)
    Vous souhaitez participer à la rubrique 2D/3D/Jeux ? Contactez-moi

    Ma page sur DVP
    Mon Portfolio

    Qui connaît l'erreur, connaît la solution.

  12. #12
    Membre chevronné
    Avatar de Joel F
    Homme Profil pro
    Chercheur en informatique
    Inscrit en
    Septembre 2002
    Messages
    918
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Chercheur en informatique
    Secteur : Service public

    Informations forums :
    Inscription : Septembre 2002
    Messages : 918
    Points : 1 921
    Points
    1 921
    Par défaut
    boost compile sur ARM. LA vrai question est, cb de mémoire et y a t il un vrai compilo C++ sur ta plateforme;

  13. #13
    Responsable 2D/3D/Jeux


    Avatar de LittleWhite
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Mai 2008
    Messages
    26 860
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Mai 2008
    Messages : 26 860
    Points : 219 062
    Points
    219 062
    Billets dans le blog
    120
    Par défaut
    Citation Envoyé par Joel F Voir le message
    boost compile sur ARM. LA vrai question est, cb de mémoire et y a t il un vrai compilo C++ sur ta plateforme;
    On fait de la cross compilation, donc le compilo n'a pas de probleme. Apres, bah il faut que je me renseigne . 64Mo de memoire sur la plateforme (memoire vive)
    (J'ai trouve mon challenge de la semaine \o/ )
    Vous souhaitez participer à la rubrique 2D/3D/Jeux ? Contactez-moi

    Ma page sur DVP
    Mon Portfolio

    Qui connaît l'erreur, connaît la solution.

  14. #14
    Membre chevronné
    Avatar de Joel F
    Homme Profil pro
    Chercheur en informatique
    Inscrit en
    Septembre 2002
    Messages
    918
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Chercheur en informatique
    Secteur : Service public

    Informations forums :
    Inscription : Septembre 2002
    Messages : 918
    Points : 1 921
    Points
    1 921
    Par défaut
    64Mo : du luxe. Pour info, j'ai compilé du Boost sur du CELL à 256Ko par element de calcul :€

  15. #15
    Responsable 2D/3D/Jeux


    Avatar de LittleWhite
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Mai 2008
    Messages
    26 860
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Mai 2008
    Messages : 26 860
    Points : 219 062
    Points
    219 062
    Billets dans le blog
    120
    Par défaut
    Citation Envoyé par Joel F Voir le message
    64Mo : du luxe. Pour info, j'ai compilé du Boost sur du CELL à 256Ko par element de calcul :€
    Woah!
    Nous verrons comment je m'en sort. De toute facon, le compilateur est du cote des machines puissantes :p
    Vous souhaitez participer à la rubrique 2D/3D/Jeux ? Contactez-moi

    Ma page sur DVP
    Mon Portfolio

    Qui connaît l'erreur, connaît la solution.

Discussions similaires

  1. Question sur les propriétés d'une classe.
    Par Jean-Jacques Engels dans le forum Langage
    Réponses: 3
    Dernier message: 24/11/2013, 03h51
  2. Question de conception objet, une classe par table RDB
    Par callapa dans le forum Débuter avec Java
    Réponses: 0
    Dernier message: 14/01/2011, 10h55
  3. questions sur les "import" et une "class extends"
    Par miniRoshan dans le forum Général Java
    Réponses: 5
    Dernier message: 21/04/2010, 14h35
  4. Réponses: 6
    Dernier message: 31/08/2009, 17h41
  5. Réponses: 2
    Dernier message: 06/10/2008, 13h20

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo