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 :

Exploitation du polymorphisme d'héritage lors d'une composition


Sujet :

C++

  1. #1
    Membre du Club
    Profil pro
    Inscrit en
    Mars 2012
    Messages
    99
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2012
    Messages : 99
    Points : 58
    Points
    58
    Par défaut Exploitation du polymorphisme d'héritage lors d'une composition
    Bonjour,

    J'ai l'architecture suivante :

    - classe ModelB et ModelC héritent d'une classe mère Model.
    - classe ControlerB et ControlerC héritent d'une class mère Controler.
    - classe ControlerB est composée d'un objet ModelB qu'elle contrôle.
    - classe ControlerC est composée d'un objet ModelC qu'elle contrôle.

    Est-il préfèrable de faire :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    class Controler {
      public :  
        Controler();  
        ~Controler();  
        void SetModel(Model*);  
     
     protected :  
       Model* model;  
    }
    et caster le model dés que nécessaire dans les classes filles ou faire :

    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
    class Controler {
      public :  
        Controler();  
        ~Controler();  
    }
     
    class ControlerB {
      public :  
        //...
        void SetModel(ModelB*);
     
      private :
        ModelB* _model; 
    }
     
    class ControlerC {
      public :  
        //...
        void SetModel(ModelC*);
     
      private :
        ModelC* _model; 
    }
    et ne pas exploiter le polymorphisme ?

    Pour information, les modèles ModelB et ModelC sont très éloignés (Model représente un haut degrés d'abstraction) et partagent donc très peu de méthodes communes (d'ou ma question car un ControlerB ne serait par exemple pas adapté pour gérer un ModelC d'un point de vue purement logique de conception... (d'un point de vue technique, les casts permettent de résoudre ce problème)).

    Merci

  2. #2
    Expert éminent sénior

    Femme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2007
    Messages
    5 189
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Essonne (Île de France)

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

    Informations forums :
    Inscription : Juin 2007
    Messages : 5 189
    Points : 17 141
    Points
    17 141
    Par défaut
    essaye de templater la classe Controleur.
    éventuellement, rend Controleur abstraite
    Mes principes de bases du codeur qui veut pouvoir dormir:
    • Une variable de moins est une source d'erreur en moins.
    • Un pointeur de moins est une montagne d'erreurs en moins.
    • Un copier-coller, ça doit se justifier... Deux, c'est un de trop.
    • jamais signifie "sauf si j'ai passé trois jours à prouver que je peux".
    • La plus sotte des questions est celle qu'on ne pose pas.
    Pour faire des graphes, essayez yEd.
    le ter nel est le titre porté par un de mes personnages de jeu de rôle

  3. #3
    Membre du Club
    Profil pro
    Inscrit en
    Mars 2012
    Messages
    99
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2012
    Messages : 99
    Points : 58
    Points
    58
    Par défaut
    Merci leternel de ton aide

    éventuellement, rend Controleur abstraite
    Oui je peux même définir une interface pour le Controler.

    essaye de templater la classe Controleur.
    Mais justement, est-il judicieux de rendre générique le Controler alors que les Controlers spécifiques auront des modèles très différents (voire trop justement) pour que la logique de factorisation n'ait pas de sens ici ?

  4. #4
    Expert éminent sénior

    Femme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2007
    Messages
    5 189
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Essonne (Île de France)

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

    Informations forums :
    Inscription : Juin 2007
    Messages : 5 189
    Points : 17 141
    Points
    17 141
    Par défaut
    Certainement, vu que tu as une interface de base.
    Qu'ils héritent de la même classe signifie qu'ils partagent la sémantique de cette classe.

    Cela se partage sûrement.
    Mes principes de bases du codeur qui veut pouvoir dormir:
    • Une variable de moins est une source d'erreur en moins.
    • Un pointeur de moins est une montagne d'erreurs en moins.
    • Un copier-coller, ça doit se justifier... Deux, c'est un de trop.
    • jamais signifie "sauf si j'ai passé trois jours à prouver que je peux".
    • La plus sotte des questions est celle qu'on ne pose pas.
    Pour faire des graphes, essayez yEd.
    le ter nel est le titre porté par un de mes personnages de jeu de rôle

  5. #5
    Membre du Club
    Profil pro
    Inscrit en
    Mars 2012
    Messages
    99
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2012
    Messages : 99
    Points : 58
    Points
    58
    Par défaut
    Tu me conseilles donc de faire par exemple :

    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
    template<class T>
    class Controler
    {
     
    };
     
    class ControlerB : public Controler<ModelB>
    {
     
    };
     
    class ControlerB : public Controler<ModelC>
    {
     
    };
    pour éviter les casts à répétition sur un Controler qui de base aurait en membre un type abstrait Model ?
    Après, comme les modèles sont utilisés pour deux choses très différentes, la notion de template ne sera pas beaucoup plus exploitable je pense .

    Je débute en template donc j'essaie de voir ce que ça peut m'apporter en plus dans mon cas!

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

    Informations professionnelles :
    Activité : aucun

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

    A priori, si tu décide de faire hériter différents modèles d'une classe de base, c'est que tu as sans doute une interface minimum commune.

    Si tu choisi de placer le modèle ("de base") dans la classe de base "controler", tu ne pourras profiter utiliser ton modèle au travers de ton contrôleur que... sous la forme sous laquelle le contrôleur le connais, à savoir : le modèle "de base".

    Maintenant, rien ne t'empêche de prévoir une fonction virtuelle (pure, dans le modèle de base) qui prenne un "indice" en argument et qui renvoie, d'une manière ou d'une autre, la valeur correspondant à cet indice. Tu pourrais donc, pour chaque modèle particulier, redéfinir cette fonction de manière à ce qu'elle fournisse une valeur "cohérente".

    Pour pouvoir travailler "facilement", la valeur renvoyée serait sans doute du genre de boost::any ou boost::variant

    Une autre solution pourrait consister à utiliser ce que l'on appelle le "retour co-variant".

    L'idée étant, dans la classe de base de contrôleur, de déclarer une fonction virtuelle pure renvoyant un pointeur sur le modèle de base, et de la redéfinir, dans les classes dérivées, de sorte à ce qu'elle renvoie un pointeur sur le modèle spécifique géré par ton contrôleur.

    Tu peux alors envisager les deux solutions : le fait de maintenir ce pointeur au niveau de la classe de base contrôleur, en redéfinissant la fonction sous la forme de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    ModeleDerive * ControleurDerive::model(){return dynamic_cast<ModeleDerive>(Controler::model());}
    tout comme tu pourrais tout aussi bien considérer que le modèle spécifique est une information qui ne doit pas être maintenue au niveau de la classe de base des contrôleurs, mais qui doit être maintenue au niveau de leurs classes dérivées.

    Il n'y a, à ce niveau, ni "bonne" ni "mauvaise" décision, dans le sens où elles seraient toutes les deux parfaitement cohérentes.

    Cependant, on dit souvent qu'un interface ne devrait disposer que des données strictement minimales pour fournir les comportements "immuables" (ceux qui n'ont en aucun cas vocation à être redéfinis ).

    Or, tous les comportements ayant trait à la gestion du modèle a, j'ai envide de dire forcément, vocation à être redéfinis.

    Il serait donc sans doute "de bon ton" de faire en sorte que le modèle particulier géré par un contrôleur particulier ne soit contenu que dans ce contrôleur particulier (mais ce n'est qu'un avis strictement personnel).

    Par contre, je ne crois sincèrement pas qu'il soit opportun de fournir un mutateur "setModel":

    D'abord, parce que le prototype de ce mutateur serait "figé" et prendrait d'office un Model * au lieu d'un ModelParticulier *

    Ensuite parce que l'idéal est à mon sens d'avoir un contrôleur directement utilisable dés la construction: une fois que tu as créé une instance de contrôleur, tu ne devrais avoir rien d'autre à faire pour pouvoir l'utiliser.

    De plus, il y a de fortes chances pour que, si tu veux travailler avec un autre modèle, il faille... travailler avec un autre contrôleur.

    Tout cela pour dire que, à mon sens, tu devrais sans doute t'orienter vers quelque chose qui serait proche de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    class Controler
    {
        /* les fonctions virtuelles pures "qui vont bien" */
    }
    class ControlerB : public Controler
    {
        public:
            ControlerB(ModelB* model):model_(model){}
            /* redéfinition des fonction qui vont bien */
        private:
            ModelB * model_;
    };
    NOTA: si tu prend cette direction, tu pourrais d'ailleurs tout à fait travailler avec des références (éventuellement constantes) plutôt qu'avec des pointeurs, ce qui devrait encore te faciliter la tâche
    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

  7. #7
    Expert éminent sénior

    Femme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2007
    Messages
    5 189
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Essonne (Île de France)

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

    Informations forums :
    Inscription : Juin 2007
    Messages : 5 189
    Points : 17 141
    Points
    17 141
    Par défaut
    [mode admiratif]
    Maître Koala01, où donc avez-vous appris à faire de tels discours?
    [/mode admiratif]
    Je suis totalement convaincu par cette approche. J'espère qu'il en sera de même pour sfarc!
    Mes principes de bases du codeur qui veut pouvoir dormir:
    • Une variable de moins est une source d'erreur en moins.
    • Un pointeur de moins est une montagne d'erreurs en moins.
    • Un copier-coller, ça doit se justifier... Deux, c'est un de trop.
    • jamais signifie "sauf si j'ai passé trois jours à prouver que je peux".
    • La plus sotte des questions est celle qu'on ne pose pas.
    Pour faire des graphes, essayez yEd.
    le ter nel est le titre porté par un de mes personnages de jeu de rôle

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

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 612
    Points : 30 612
    Points
    30 612
    Par défaut
    Citation Envoyé par leternel Voir le message
    [mode admiratif]
    Maître Koala01, où donc avez-vous appris à faire de tels discours?
    [/mode admiratif]
    Je suis totalement convaincu par cette approche. J'espère qu'il en sera de même pour sfarc!
    A vrai dire, c'est inné

    Plus sérieusement, il s'agit simplement d'une longue habitude de mise en oeuvre de ma signature
    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

  9. #9
    Membre du Club
    Profil pro
    Inscrit en
    Mars 2012
    Messages
    99
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2012
    Messages : 99
    Points : 58
    Points
    58
    Par défaut
    Bonjour et merci koala01 d'avoir pris le temps d'apporter tes lumières!

    L'idée étant, dans la classe de base de contrôleur, de déclarer une fonction virtuelle pure renvoyant un pointeur sur le modèle de base, et de la redéfinir, dans les classes dérivées, de sorte à ce qu'elle renvoie un pointeur sur le modèle spécifique géré par ton contrôleur.
    Oui mais j'aurais encore le modèle de base dans mon contrôleur de base donc pour une utilisation spécifique, je serais à chaque fois obliger de le "caster".

    Il serait donc sans doute "de bon ton" de faire en sorte que le modèle particulier géré par un contrôleur particulier ne soit contenu que dans ce contrôleur particulier (mais ce n'est qu'un avis strictement personnel).
    Je suis d'accord mais dans mon cas par exemple, le modèle est exploité par plusieurs contrôleur, d'où une définition du modèle qui se fait dans un autre contexte et qui est envoyé via un mutateur à l'objet concerné.

    Ce comportement peut vous paraître étrange (pourquoi ne pas avoir un seul contrôleur qui gère le même modèle ?). Si c'est le cas, c'est entièrement de ma faute . Je pense avoir mal choisi le terme de "contrôleur". Dans mon cas, les contrôleurs seraient en fait plutôt des objets qui exploitent un modèle, l'exploitation d'un même modèle pouvant être différente suivant les besoins du dit contrôleur.

    Tout cela pour dire que, à mon sens, tu devrais sans doute t'orienter vers quelque chose qui serait proche de

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    class Controler
    {
        /* les fonctions virtuelles pures "qui vont bien" */
    }
    class ControlerB : public Controler
    {
        public:
            ControlerB(ModelB* model):model_(model){}
            /* redéfinition des fonction qui vont bien */
        private:
            ModelB * model_;
    };
    C'est un peu l'idée vers laquelle je suis parti pour l'instant (avec le mutateur spécifique) même si je cherche encore à voir s'il existe une optimisation intéressante dans mon cas

    Merci beaucoup

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

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 612
    Points : 30 612
    Points
    30 612
    Par défaut
    Citation Envoyé par sfarc Voir le message
    Bonjour et merci koala01 d'avoir pris le temps d'apporter tes lumières!



    Oui mais j'aurais encore le modèle de base dans mon contrôleur de base donc pour une utilisation spécifique, je serais à chaque fois obliger de le "caster".
    Mais c'est KESKEJDI

    Disons que l'avantage, avec le retour co-variant, c'est que tu peux t'arranger pour le faire de manière totalement transparente pour l'utilisateur, et que le transtypage ne se fait qu'à un seul endroit bien déterminé
    Je suis d'accord mais dans mon cas par exemple, le modèle est exploité par plusieurs contrôleur, d'où une définition du modèle qui se fait dans un autre contexte et qui est envoyé via un mutateur à l'objet concerné.
    Mais pourquoi vouloir créer le contrôleur sans disposer du modèle qu'il est sensé manipuler

    A partir du moment où tu travailles, de toutes manières, avec un pointeur (ou une référence), il faut bien te dire que, quoi qu'il arrive, si tu décides de modifier le modèle "par ailleurs", le contrôleur travailleras sur le modèle "mis à jour"

    Il semble donc beaucoup plus logique, de commencer par créer / remplir le modèle et de ne créer le contrôleur qu'une fois que tu dois manipuler ton modèle, non
    Ce comportement peut vous paraître étrange (pourquoi ne pas avoir un seul contrôleur qui gère le même modèle ?). Si c'est le cas, c'est entièrement de ma faute . Je pense avoir mal choisi le terme de "contrôleur". Dans mon cas, les contrôleurs seraient en fait plutôt des objets qui exploitent un modèle, l'exploitation d'un même modèle pouvant être différente suivant les besoins du dit contrôleur.
    Selon le sacro saint principe de la responsabilité unique, il semble "logique" d'avoir plusieurs contrôleurs manipulant un modèle identique pour, simplement, permettre à ces différents contrôleurs d'avoir leurs propres responsabilités et les comportement y afférant
    C'est un peu l'idée vers laquelle je suis parti pour l'instant (avec le mutateur spécifique) même si je cherche encore à voir s'il existe une optimisation intéressante dans mon cas
    Déjà, tu ne pourras, de toutes manières, pas utiliser le polymorphisme sur ton mutateur car la solution que tu devrais utiliser est de déclarer un mutateur virtuel, prenant un Modele* en argument et de redéfinir le dit mutateur de manière à ce qu'il transtype le Modele* en ModeleParticulier *...

    tu seras sans doute d'accord avec moi pour dire que c'est tout, sauf efficace

    De plus, le fait de définir un simple accesseur mérite déjà d'être étudié avec le plus grand soin, car il ne faudrait décider de le faire que si l'accesseur correspond bel et bien à un service que l'on est en droit d'attendre de la part de la classe envisagée.

    Mais je suis encore plus circonspect vis à vis des mutateurs, qu'il faut vraiment, selon moi, éviter le plus possible.

    Enfin, on se rend compte de manière très récurrente, lorsqu'on en arrive à vouloir définir un accesseur et un mutateur, qu'il est souvent plus que temps de se poser la question de l'objectif que l'on poursuivait en déclarant le membre accédé /modifié dans une accessibilité restreinte

    Ceci étant dit, mettons que tu aies trois modèles concrets différents (faisons simple : ModeleA, ModeleB et ModeleC).

    Il se peut parfaitement que tu aies trois contrôleurs distincts que tu utiliseras dans des contextes différents pour chaque modèle (mettons : ControleurA1, ControleurA2 et ControleurA3, et pareil pour les autres modèles )

    A priori, ton modèle est déjà créé quand tu en arrive à savoir le contexte dans lequel tu te trouves:

    C'est parce que tu as un modèle de type ModeleA (et non un modèle de type ModeleB) et que tu te trouves dans le premier contexte (et non dans le troisième) que tu vas décider d'utiliser un contrôleur de type ControleurA1 et non un contrôleur de type ControleurA3, ni un contrôleur de type ControleurB2

    Tu peux donc partir d'un principe de double dispatch (faisons simple: fort similaire au patron de conception "visiteur" ) pour savoir quel est le type réel du modèle manipulé et pour créer le contrôleur "qui va bien" en fonction du contexte dans lequel tu te trouves.

    Comme, à ce moment là, la fonction qui sera appelée prendra d'office un pointeur (ou une référence) vers le type réel du modèle que tu veux manipuler, tu peux créer ton controleur en lui passant directement ce pointeur (ou cette référence) dans le constructeur, et tu n'as pas à t'inquiéter de pouvoir changer le modèle "en cours de route".

    Car il y a deux solutions :
    • Soit tu continues à manipuler le même modèle, mais dans un contexte différent, et, dans ce cas, tu dois créer une instance de contrôleur adaptée au nouveau contexte
    • Soit tu commences à manipuler un autre modèle, que ce soit dans le même contexte ou non, et, dans ce cas, tu devras AUSSI créer un autre contrôleur (adapté au type du "nouveau" modèle à manipuler)
    Finalement, il n'y a rien qui t'empêche d'envisager une fonction proche de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    void foo(/* ... */){
     
        ModeleA  temp(/*...*/);
        ControleurA1 first(temp);
        ControleurA2 second(temp);
        ControleurA3 third(temp);
        /* on exécute les trois contextes dans l'ordre défini */
        first.execute(/*...*/);
        second.execute(/*...*/);
        third.execute(/*...*/);
    }
    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

  11. #11
    Membre du Club
    Profil pro
    Inscrit en
    Mars 2012
    Messages
    99
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2012
    Messages : 99
    Points : 58
    Points
    58
    Par défaut
    Mais pourquoi vouloir créer le contrôleur sans disposer du modèle qu'il est sensé manipuler
    Comme, à ce moment là, la fonction qui sera appelée prendra d'office un pointeur (ou une référence) vers le type réel du modèle que tu veux manipuler, tu peux créer ton controleur en lui passant directement ce pointeur (ou cette référence) dans le constructeur, et tu n'as pas à t'inquiéter de pouvoir changer le modèle "en cours de route".
    Oui effectivement, c'est plus logique de passer un pointeur ou une référence en paramètre du constructeur de mon contrôleur

    (faisons simple: fort similaire au patron de conception "visiteur" )
    [...]

    Finalement, il n'y a rien qui t'empêche d'envisager une fonction proche de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    void foo(/* ... */){
     
        ModeleA  temp(/*...*/);
        ControleurA1 first(temp);
        ControleurA2 second(temp);
        ControleurA3 third(temp);
        /* on exécute les trois contextes dans l'ordre défini */
        first.execute(/*...*/);
        second.execute(/*...*/);
        third.execute(/*...*/);
    }
    Je pense que c'est la meilleure solution oui.
    Après, pour les contrôleurs exploitant des modèles distincts, il n'auront pas vraiment de traits communs (ControlerB et ControlerA par exemple ne partageront pas grand chose car chacun aura son modèle et ses comportements (très différents) qui en découlent).

    Merci encore une fois pour ton aide koala01

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

Discussions similaires

  1. Réponses: 1
    Dernier message: 19/12/2006, 14h08
  2. Mauvais noms de colonnes lors d'une requête
    Par nmathon dans le forum Bases de données
    Réponses: 2
    Dernier message: 09/04/2004, 07h27
  3. Combler les trous lors d'une suppression dans une table
    Par Billybongjoe dans le forum PostgreSQL
    Réponses: 5
    Dernier message: 08/04/2004, 14h02
  4. Erreur lors d'une requete INNER JOIN
    Par k-lendos dans le forum Langage SQL
    Réponses: 2
    Dernier message: 17/03/2004, 15h09
  5. Enlever la surbrillance lors d'une recherche avec vi
    Par sekiryou dans le forum Applications et environnements graphiques
    Réponses: 8
    Dernier message: 04/03/2004, 13h55

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