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 :

[conception] paramètre d'une commande


Sujet :

C++

  1. #1
    r0d
    r0d est déconnecté
    Expert éminent

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2004
    Messages
    4 264
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ain (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Août 2004
    Messages : 4 264
    Points : 6 683
    Points
    6 683
    Billets dans le blog
    2
    Par défaut [conception] paramètre d'une commande
    Bonsoir,

    sur le petit jeu que je suis en train de programmer, je me trouve confronté à un petit problème que je pensais classique mais sur lequel je ne parviens pas à trouver de réponse satisfaisante. Il se trouve que je me suis rendu compte que je vais avoir besoin d'un séquenceur (pour les animations et quelques effets que je voudrais ajouter, entres autres). Donc j'ai implémenté un séquenceur super simple, dont l'unité de temps est la frame (je suis en frame rate constant), qui n'est rien d'autre qu'une queue d'événements finalement.

    Et donc mon problème est le suivant:
    J'ai implémenté mes évènements comme des Command classique: une "interface" IEvent avec une fonction Execute(). Ce que j'ai fais, c'est que cette fonction Execute() je l'ai déclarée comme une boost::function, mais je ne pense pas que ce soit important.

    Le soucis, c'est que ces événement vont être de nature très variée. Et donc, je vais avoir besoin de passer des paramètres à cette fonction Execute. Et des paramètres de types très variés. Et donc mon problème c'est ça: trouver une façon propre et robuste (la robustesse de mon code est primordiale car c'est un projet voué à la collaboration) pour gérer les paramètres de mes événements.

    Dans un premier temps, j'avais pensé à déclarer une "interface" IEventParam, totalement vide, qui me permet, en passant par un pointeur, de downcaster le paramètre à la réception. Quelque chose comme ça:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    struct IEventParam(){}
     
    struct IEvent
    {
       virtual void Execute( IEventParam * ) = 0;
    };
    avec un exemple d'utilisation:
    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
    struct MoveUnitParam
    {
       Unit* unit; // unité à déplacer
       float vitesse; // en pixel par frame
       unsigned int direction;
    };
     
    struct MoveUnit: public IEvent //cet événement déplace une unité sur la carte
    {
       void Execute( IEventParam * param )
       {
          MoveUnitParam * muParam = (MoveUnitParam *) param;
          muParam ->unit->Move( muParam ->vitesse, muParam ->direction );
       }
    };
    Bon, en vérité, j'ai fais plus simple, parce que à la place d'une structure héritant de IEvent, je passe par une boost::function<IEventParam*> et ça m'évite de passer par une structe IEvent et j'appelle directement les fonctions souhaitées sans passer par Ivent::Execute(). Mais ça ne change rien au problème et c'est plus clair comme ça.

    Donc, comme on peut le voir dans cet exemple, il y a des choses assez moches dans cette méthode, et je cherche un moyen plus propre, et surtout plus robuste pour le faire. Là par exemple, le downcast me parait dangereux. Autre chose qui ne me plait pas, c'est que j'ai tout un tas d'évenements qui n'ont pas besoin de paramètres, mais il faut tout de même que je les déclare avec un IEventParam* en paramètre. Ca ne me parait pas logique, je pense donc que ce n'est pas un modèle valide.

    Donc voilà, si vous avez compris ce que je raconte (c'est que ça à l'air de rien, mais c'est pas facile à expliquer! ), je cherche une solution propre et robuste pour gérer les paramètres de mes événements.

  2. #2
    Membre régulier Avatar de cynique
    Profil pro
    Inscrit en
    Septembre 2007
    Messages
    60
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2007
    Messages : 60
    Points : 72
    Points
    72
    Par défaut
    Pour moi, il n'y a pas besoin de paramètre sur la fonction Execute(). Les paramètres devraient être stockées dans l'objet de commande:

    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
     
    struct IEvent
    {
       virtual ~IEvent() {}; // n'oublie pas les déstructeurs virtuel dans les classes de base!
       virtual void Execute() = 0;
    };
     
    struct MoveUnit: public IEvent //cet événement déplace une unité sur la carte
    {
       Unit* unit; // unité à déplacer
       float vitesse; // en pixel par frame
       unsigned int direction;
     
       void Execute()
       {
          unit->Move( vitesse, direction );
       }
    };
    Maintenant, tu peux créer une list<IEvent *> et l'utiliser comme un FIFO, et le code qui consomme les événements n'a aucun besoin de savoir les paramètres. Si tu as une classe sans besoin de paramètres:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    struct FlashScreen: public IEvent // on allume l'écran
    {
       void Execute()
       {
          ...
       }
    };
    Parfait!


  3. #3
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Points : 13 017
    Points
    13 017
    Par défaut
    Bonjour,
    J'aurais de base tendance à penser comme cynique que le paramètre de l'exécution fait parti du contexte IEvent. Donc, si tu passes par boost, se serait un boost::function<void()> avec un bind sur le bon contexte.
    Cependant, j'ai l'impression que c'est le cas où Boost.Any peut t'être utile d'autant si je lis les premières phrases de la doc (c'est moi qui souligne) :
    The following base class demonstrates one approach to runtime polymorphism based callbacks that also require arbitrary argument types. The absence of virtual member templates requires that different solutions have different trade-offs in terms of efficiency, safety, and generality. Using a checked variant type offers one approach:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    class consumer
    {
    public:
        virtual void notify(const any &) = 0;
        ...
    };

  4. #4
    Alp
    Alp est déconnecté
    Expert éminent sénior

    Avatar de Alp
    Homme Profil pro
    Inscrit en
    Juin 2005
    Messages
    8 575
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations forums :
    Inscription : Juin 2005
    Messages : 8 575
    Points : 11 861
    Points
    11 861
    Par défaut
    +1, il faut que tu te débrouilles pour faire disparaître les paramètres de Execute, car sinon tu te retrouves avec un design bancal : tu stockerais une liste d'évènements, mais tu n'agirais pas pareil selon l'évènement courant (au niveau du code de traitement de la liste) ? Pas bon.

    Je suppose que tu as tout ce qu'il faut pour construire une fonction Execute au moment ou tu rajoutes un évènement donné dans la liste ? Dans ce cas, boost::bind est une solution pas trop mal je pense. Une alternative étant ce qui est proposé par 3DArchi.

  5. #5
    Membre chevronné
    Homme Profil pro
    edi
    Inscrit en
    Juin 2007
    Messages
    905
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Gironde (Aquitaine)

    Informations professionnelles :
    Activité : edi

    Informations forums :
    Inscription : Juin 2007
    Messages : 905
    Points : 1 923
    Points
    1 923
    Par défaut
    Est-ce-que tu as au moment où tu génères l'événement toutes les informations dont tu as besoin pour cet événement ? Ou est-ce-qu'il te faut ajouter des info au moment où tu le traites ?

  6. #6
    r0d
    r0d est déconnecté
    Expert éminent

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2004
    Messages
    4 264
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ain (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Août 2004
    Messages : 4 264
    Points : 6 683
    Points
    6 683
    Billets dans le blog
    2
    Par défaut
    Bonjour à tous, et merci pour vos réponses,

    Après réflexion, je pense effectivement faire comme propose cynique. J'aurais aimé me passer d'une classe IEvent (et des ses fils), mais ça me parait difficile finalement. C'est que j'essaie d'éviter la prolifération des classes, et malgré cela, j'en ai déjà beaucoup trop à mon goût (j'ai déjà plus de 50 en-têtes).

    Pour l'instant j'appelle directement des fonctions membres de mes classes (grâce à bosst:bind effectivement), mais ce n'est pas assez souple. Passer par des IEvent résoudra le problème.


  7. #7
    Alp
    Alp est déconnecté
    Expert éminent sénior

    Avatar de Alp
    Homme Profil pro
    Inscrit en
    Juin 2005
    Messages
    8 575
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations forums :
    Inscription : Juin 2005
    Messages : 8 575
    Points : 11 861
    Points
    11 861
    Par défaut
    Tu es obligé d'avoir IEvent si tu veux stocker des évènements de natures différentes quelque part et les traiter de manière uniforme, malgré que cela se passe différemment selon la vraie nature de l'évènement.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Réponses: 4
    Dernier message: 14/03/2011, 14h44
  2. [SHELL] ajouter des paramètres pour une commande shell
    Par anissben dans le forum Shell et commandes GNU
    Réponses: 5
    Dernier message: 11/12/2010, 13h36
  3. Paramètres d'une commande
    Par nurgle1 dans le forum LabVIEW
    Réponses: 1
    Dernier message: 16/07/2010, 11h53
  4. Réponses: 2
    Dernier message: 29/09/2009, 10h07
  5. Paramètre d'une commande et viewer crystal report
    Par nanouille56 dans le forum SAP Crystal Reports
    Réponses: 0
    Dernier message: 03/04/2008, 15h58

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