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 :

L'encapsulation des données? à tout prix?


Sujet :

C++

  1. #1
    Expert éminent
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 641
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 641
    Par défaut L'encapsulation des données? à tout prix?
    Salut,

    Soit une classe ayant comme membre quatre ou cinq vector ou map différents.

    Evidemment, une grosse majorité des fonctions membres des vector et des maps est intéressante au niveau de la classe elle-même.

    En plus, pour corser le tout, il n'est pas impossible que deux membres distincts soient des map contenant le meme type de données...

    Pour respecter l'esprit de l'encapsulation des données, il faudrait déclarer ces membres privés et coder pour chaque membre les fonctions qui vont bien, c'est à dire surement cinq ou six fonctions par membres afin de pouvoir les manipuler...

    Le résultat serait une classe comprenant une grosse trentaine de fonctions membres (si pas plus) qui... se contenteront de reproduire le comportement des vector et des map, selon les membres de la classe

    Dans une telle situation, quels sont ceux d'entre vous qui décideraient de se faciliter la vie (quitte à rendre le maintien du code plus difficile) en déclarant les membres public et ceux qui préféreraient respecter en tous points le principe d'encapsulation en les déclarant privé, quitte à ce que cette classe ne soit pas sensée évoluer par la suite, sachant que le patern "facade" sera vraissemblablement utilié pour la gestion réelle de cette classe

    Autant prévenir tout de suite, je n'ai absolument pas besoin des interventions qui auraient pour but de me convaincre de l'intérêt d'encapsuler les données...

    Merci, je connais les avantages de l'encapsulation, et j'en suis bien conscient

    Simplement, je n'ai pas de position précise sur la question, ma logique tendant à me faire choisir l'encapsulation, ma fainéantise naturelle tendant à me faire choisir les membres publiques...

    Si je pose la question, c'est que, à tord ou à raison, j'envisage de m'allier à l'avis le plus souvent exprimé
    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

  2. #2
    Membre Expert

    Profil pro
    Inscrit en
    Juin 2006
    Messages
    1 294
    Détails du profil
    Informations personnelles :
    Localisation : Royaume-Uni

    Informations forums :
    Inscription : Juin 2006
    Messages : 1 294
    Par défaut
    Salut,

    Citation Envoyé par koala01
    Soit une classe ayant comme membre quatre ou cinq vector ou map différents.
    Fichtre ! Y'a vraiment pas moyen de découper un peu plus ?

    Pour répondre à la question : j'encapsule à tout prix.
    Néanmoins je ne me souviens pas m'être retrouvé dans ce genre de situation.
    D'expérience j'aurais tendance à dire que les interfaces de type conteneurs (sur lesquels on fait des 'get') sont incompatibles avec les interfaces de type orienté objet (qui sont supposé recevoir des demandes de traitements).
    Du coup les endroits où des conteneurs sont utilisés sont normalement facilement encapsulables.

    Y'a un moment où il faut mettre un frein à l'entropie des accesseurs sinon ça devient vraiment beaucoup plus difficile d'encapsuler des données derrière des demandes de traitement...

    Tu parles de 'pattern' facade mais j'ai plus l'impression qu'il s'agit là d'une classe de type 'manager' qui ne propose aucun traitement ?
    Ces données ont vraiment besoin de se trouver toutes dans la même classe ?

    Je ne suis pas sûr que ça réponde à la question finalement

    MAT.

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

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 641
    Par défaut
    Pour mon malheur, la classe dont je présente les caractéristiques est réellement à considérer comme une classe à part entière, et tous les membres doivent se trouver dans cette classe, meme si, de fait, elle prend réellement l'apparence d'un manager...
    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 émérite Avatar de mchk0123
    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    816
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Janvier 2007
    Messages : 816
    Par défaut
    Si j'était toi, j'essayerais de trouver une solution qui satisfasse tes 2 demandes : conserver l'encapsulation, et être fainéant.

    Les puristes du C++ trouverons que c'est une hérésie, mais dans la pratique tu peux t'en sortir en utilisant une macro :

    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
    #define DECLARE_MAP_VAR(varname) std::map<T,U> varname;
    #define DECLARE_MAP_ACCESSORS(varname) \
      U get_##varname(const T &key); \
      void set_##varname(const T &key, u &value); \
    ...
    class ma_classe {
      public:
        DECLARE_MAP_ACESSORS(var1);
        DECLARE_MAP_ACESSORS(var2);
        ...
      protected:
        DECLARE_MAP_VAR(var1);
        DECLARE_MAP_VAR(var2);
        ...
    };
    ...
    ma_classe<string, string> c;
     
    c.set_var1("clef1", "val1");
    c.set_var2("clef1", "val1");
    ...
    Je penses qu'il doit aussi exister une solution à base de template, mais personnellement je n'en ai jamais mis en oeuvre dans cette situation. Donc je ne peux pas t'aider là dessus.

    Enfin dernier détail. Normalement lors que l'on utilise le pattern facade, les méthodes publiques de la facades sont sensées contenir du code métier et pas simplement une délégation directe (aka accésseurs). Si c'est le cas c'est qu'il y a surement une erreur dans la conception de ton architecture OO.

  5. #5
    Expert confirmé
    Avatar de Luc Hermitte
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2003
    Messages
    5 296
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Août 2003
    Messages : 5 296
    Par défaut
    Je ne suis pas un fervent partisant des accesseurs à tout prix. Voyez la FAQ pour cela -- Aurélien y avait repris une partie de ma prose.

    Une question très importante a été soulevée. C'est une classe n'aggrégeant que des données, ou bien une classe qui contient du code métier ?

    Dans le premier cas, autant filer l'accès direct. L'interface publique de la classe ... ce sont les données qu'elle nous expose.

    Dans le second cas, accesseurs ! Dernièrement, j'ai écrit 2-3 petites classes qui devaient stocker une table associative lue depuis un fichier, et permettre d'accéder au label associé à une paire d'identifiants. Les besoins sont parfaitement identifiés : ajout et récupération. Pas de parcours, pas de recherche de présence, pas de comptage, ...
    Ce que j'ai fait, cela a été de définir une petite classe contenant deux fonctions : add() et operator[]()const. Chacune des deux ayant la responsabilité de lever une exception en cas d'ajout pour la même clé, ou en cas de récupération pour une clé non renseignée.
    Le code étant très métier, j'ai tout encapsulé.

    Maintenant, si ta classe est hybride, comme pour les autres intervenants, cela me donne l'impression qu'il y a des trucs à revoir dans le design.


    Je pense à un truc. Ton problème ressemble aussi à celui d'une facade qui dot transmettre tous les messages reçus aux composant aggrégés. C'est ça d'une manière générale, ou bien tu n'aggrèges vraiment que des containers ?
    Blog|FAQ C++|FAQ fclc++|FAQ Comeau|FAQ C++lite|FAQ BS|Bons livres sur le C++
    Les MP ne sont pas une hotline. Je ne réponds à aucune question technique par le biais de ce média. Et de toutes façons, ma BAL sur dvpz est pleine...

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

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 641
    Par défaut
    En fait, j'aurais presque tendance à dire que cette structure pourrait tres bien ne se comporter que comme une struct C...

    Elle se contenterait d'agréger des données, et de permettre éventuellement à un élément se trouvant dans le troisième membre de savoir si le premier membre contient tel ou tel élément...

    D'un autre coté, tout le code réellement métier (gestion des éléments des différents membres) serait, lui, dévolu à des classes particulières (pour le chargement/la sauvegarde dans des fichiers, pour l'interfacage avec une GUI...)

    J'avouerai que, pour ma part, j'envisage d'utiliser, carrément une structure plutot qu'une classe, histoire de me laisser aller à ma fainéantise naturelle...

    Finalement, la question aurait tres bien pu être: "pousseriez vous de grands cris si, les choses étant posées, vous deviez rencontrer une classe dont tous les membres seraient publics, sachant que normalement, il n'y a aucun acces direct à cette classe"

    Visiblement, cela ne semble déranger personne, ce qui me conforte dans l'idée de me laisser aller à la facilité
    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
    Membre émérite Avatar de mchk0123
    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    816
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Janvier 2007
    Messages : 816
    Par défaut
    1. Avoir à se creuser la tête pour implémenter une Facade sont souvent liés à un mauvais design !
    2. Mettre tous les attributs et les méthodes d'une Facade en visibilité publique c'est comme ... !
    3. Tu ne peux pas nous dire 2 mots sur la nature de ton programme, quels données sont modélisées pas tes map, et qu'est-ce que ta facade est sensée faire ?
    4. Ma solution à base de macros ne te convient pas ?

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

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 641
    Par défaut
    En fait, j'ai plusieurs classes de données:

    Changements (qui, quoi quand)
    • AFaire (etat (a commencer/en cours/ a verifier/ fini),priorité, qui, quoi, deadline)
    • Type(nom_usuel, nom_reel) ou nom usuel représente "caractère" là ou nom_reel représente "char" - et de manière générale pour les type de bases - (nom_usuel==nom_reel dans le cas de type personnalisés/n'ayant pas de termes "spécifiques" )
    • Prototype (nom, renvoi, arguments(vector de))
    • strucutre (liste d'héritage, liste de membre, liste de fonctions)
    • classe (idem)

    La différence entre classe et structure étant simplement la visibilité par défaut de l'héritage, des membres et des méthodes

    Le tout, chapeauté par la classe qui me fait me questionner: module, qui contient
    • un liste de changements, classée par date, du plus récent au plus ancien
    • une liste de choses à faire, classée par deadline/priorité)
    • une liste de type, classée par nom
    • une liste de prototypes, classée par nom de la fonction
    • une liste de structures et une liste de classes... classée par nom

    (celles de structures et de classes pouvant, en définitive, parfaitement etre regroupées en une seule)

    Le fait étant que:
    • l'ajout d'une structure ou d'une classe provoque l'ajout du type correspondant
    • l'ajout d'un membre de structure ou de classe provoque la vérification de l'existance du type du membre
    • l'ajout d'un prototype provoque la vérification de l'existance du type de retour et du type des arguments que la fonction prend
    • le passage d'une chose à faire à l'état "fini" provoque son retrait de la liste, et son passage dans la liste "changements", mais on peut apporter des changements qui n'était pas dans la liste des choses à faire
    • on peut décider de supprimer une structure ou une classe de la liste, mais cela sous-entend la suppression du type correspondant


    Comme je l'indiquais dans le premier post, si je dois veiller à l'encapsulation à tout prix, je serai bon pour créer, directement dans la classe module, une bonne partie des fonctions qui sont déjà présentes dans les conteneurs utilisés...

    Comme, en plus, il y a un système à mettre au point pour l'interfacage avec une GUI et le chargement et un autre pour permettre la sauvegarde (AKA:lecture seule des éléments des différents conteneur), et que, idéalement, il peut y avoir plusieurs modules ouverts en meme temps...

    Je me dis de plus en plus que je pourrais, par facilité, laisser les membres des différentes classes publics et ne permettre un acces qu'au travers des systèmes d'interfacage...

    Bon, d'accord, je pourrais jouer avec les amités, mais, le résultat reviendrait sensiblement au meme...

    Finalement, avec les membres public (ou l'amité), je pourrais me contenter d'une fonction
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    void Facade::Add(Classe& c, Module* m)
    {
        m->Classes.insert(std::make_pair(c.name,m) );
        Type toadd(c.name,c.name);
        m->Types.insert(toadd.usuel,toadd);
    }
    alors que, avec les membre privé (et sans l'amitié), je devrais créer non seulement la fonction Facade::Add, mais aussi les fonctions d'insertion dans les différents membres, ce qui, non seulement, fait du travail supplémentaire, mais, en plus, sera (meme si c'est à peine) moins rapide à l'exécution
    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 émérite Avatar de mchk0123
    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    816
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Janvier 2007
    Messages : 816
    Par défaut
    On y voit un peu plus clair. Là tu as ton code "métier" :

    Citation Envoyé par koala01
    Le fait étant que:
    • l'ajout d'une structure ou d'une classe provoque l'ajout du type correspondant
    • l'ajout d'un membre de structure ou de classe provoque la vérification de l'existance du type du membre
    • l'ajout d'un prototype provoque la vérification de l'existance du type de retour et du type des arguments que la fonction prend
    • le passage d'une chose à faire à l'état "fini" provoque son retrait de la liste, et son passage dans la liste "changements", mais on peut apporter des changements qui n'était pas dans la liste des choses à faire
    • on peut décider de supprimer une structure ou une classe de la liste, mais cela sous-entend la suppression du type correspondant
    Toute cette mécanique doit être encapsulée dans ta Facade module. Cette Facade permet d'assurer que la cohérence de tes données entre elles : quand tu modifie une donnée, les autres données sont mises à jour en cascade afin d'être cohérentes.

    Ce serait une grosse erreur de conception que de mettre cette mécanique là en dehors de la Facade module. Et ce pour plusieurs raisons :

    - si tu as plusieurs endroits ou "module" est utilisé tu risque d'avoir à dupliquer le code de gestion de la cohérance
    - en cas de modification sur le stockage des données, tu devrait modifier partout le code utilisant "module"
    - ta logique de gestion de la cohérence risque d'être éclatée un peu partout ou tu vas utiliser "Facade"
    - si tu veux faire de ta Facade "module" un composant réutilisable, la logique métier doit être masquée. Sinon tu devra te replonger dans les dessous de la mécanique de gestion de la cohérence la prochaine fois que tu auras à réutiliser ton composant
    ...

    Par opposition, si tu encapsule correctement dans ta Facade "module", tu auras :

    - unification du code (au lieu d'un copier coller un peu partout)
    - risque de bug minimal en cas de MAJ de la gestion des données
    - centralisation du code métier pour une meilleure compréhension du code source
    - simplicité de l'API de ta Facade permettant une réutilisation simple dans x mois
    ...

    Pour moi il n'y à pas photo ...

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

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 641
    Par défaut
    Donc, si je te comprend bien, pour peu que l'encapsulation des données soit complete dans Facade, tu ne verrais aucune objection à ce qu'elle soit nulle dans les autres classes

    Etant entendu que tous les acces aux autres classes seront gérés au travers de Facade...
    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 émérite Avatar de mchk0123
    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    816
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Janvier 2007
    Messages : 816
    Par défaut
    Citation Envoyé par koala01
    ... tu ne verrais aucune objection à ce qu'elle soit nulle dans les autres classes
    Parfaitement !

    Citation Envoyé par koala01
    Etant entendu que tous les acces aux autres classes seront gérés au travers de Facade...
    Attention tout de même à ce que l'API de ta Facade ne manipule que des types de base (string, int, ...) et non pas des pointeurs sur classes AFaire, Type, Strucutre, ...

    Tout doit se passer comme si la Facade était de portée "public:" alors que tes classes de données étaient de portée "private:".

    On transpose la notion de portée (qui existe au niveau des méthodes avec les mots clefs "public:" et "private:"), au niveau des classes.

    Malheureusement le C++ n'a pas de notion de portée pour les classes.

    On peut contourner le pb. (si ce n'est pas trop lourd), en compilant la facade et autre classes en une biblothèque statique.
    Ensuite on ne publie (donne accès au développeur) que les fichiers "MaFacade.lib/a" et "MaFacade.h".

    Pour finir, regarde du côté du pattern "mediator" : il y a de fortes chances que ta facade soit également un "mediator".

  12. #12
    Expert éminent
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 641
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 641
    Par défaut
    Citation Envoyé par mchk0123
    On peut contourner le pb. (si ce n'est pas trop lourd), en compilant la facade et autre classes en une biblothèque statique.
    Ensuite on ne publie (donne accès au développeur) que les fichiers "MaFacade.lib/a" et "MaFacade.h".
    On n'en est pas encore là, mais, de fait, en version finale, on se rapprochera surement de cette solution
    [/QUOTE]
    Pour finir, regarde du côté du pattern "mediator" : il y a de fortes chances que ta facade soit également un "mediator".[/QUOTE]
    Ah, je l'avais oublié, celui-là...

    Mais, de fait, il semble utile d'avoir effectivement une composante "mediator" dans le lot
    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

  13. #13
    Membre émérite Avatar de mchk0123
    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    816
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Janvier 2007
    Messages : 816
    Par défaut
    A propos des modifications en cascade entre les classes gérées par ta Facade :

    Une autre idée qui me viens à l'esprit (jamais mis en pratique, mais c'est surement faisable) dés que je lis "plusieurs types de données" :

    Utiliser une classe template générique que tu instancierais pour chaque type de donnée (<AType>, <Struct>, <Control>, ...).
    Dans le cas ou tu rencontre des types dépendant de <T> (par exemple un iterateur sur map n'est pas forcément pareil qu'un iterateur sur vector, ...) : tu utilise le mécanisme de "traits".

  14. #14
    Expert éminent
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 641
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 641
    Par défaut
    Mais, ceci dit, le desing pour ce projet est déjà relativement bien fixé (mais pas figé ), et on s'écarte du sujet de base: qui serait pour une encapsulation minimale dans les classes de données et maximale dans les classes de facade/visiteur/médiateur et qui serait plutot pour une encapsulation forte au niveau des classes de données, quitte à multiplier les accesseurs nécessaires

    @mchk0123 merci quand meme d'avoir attiré mon attention sur certaines possibilités
    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

  15. #15
    Membre émérite Avatar de mchk0123
    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    816
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Janvier 2007
    Messages : 816
    Par défaut
    Mon idée ci-dessus à base de templates et de traits c'était pour titiller ton côté "fainéant" (les templates étants plus "propres" que ma première solution à base de macros).

Discussions similaires

  1. Actualisation des données, toutes les 10 secondes
    Par guillome29 dans le forum IHM
    Réponses: 2
    Dernier message: 10/02/2013, 16h55
  2. Réponses: 13
    Dernier message: 11/11/2008, 13h45
  3. Réponses: 1
    Dernier message: 14/10/2008, 10h14
  4. mise à jour des données toutes les semaines...
    Par Toff !!!!! dans le forum Access
    Réponses: 20
    Dernier message: 22/12/2005, 11h38

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