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

 Delphi Discussion :

Choses à ne surtout pas faire dans vos applications [Débat]


Sujet :

Delphi

  1. #21
    Expert confirmé
    Avatar de anapurna
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Mai 2002
    Messages
    3 442
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Arts - Culture

    Informations forums :
    Inscription : Mai 2002
    Messages : 3 442
    Points : 5 862
    Points
    5 862
    Par défaut
    Salut

    je reviens sur un code proposé ce qui m’énerve le plus c'est la non exploitation du sender dans les Evénement des composants

    je reviens donc sur un code fournis
    voici un exemple concret
    Citation Envoyé par Ph. B. Voir le message
    Bonjour,
    ......
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    procedure TForm1.Button1Click(Sender: TObject);
    begin
      // 
      Self.Button1.Enabled := False;
      //
      Self.MonTraitement;
      //
      Self.Button1.Enabled := True;
    end;
    j'aurais cent fois préféré cette solution


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    procedure TForm1.Button1Click(Sender: TObject);
    begin
      // 
      (Sender as Tbutton).Enabled := False;
      //
      MonTraitement;
      //
      (Sender as Tbutton).Enabled := True;
    end;
    cela facilite la maintenance du code quand vous modifiez le nom du composant on est pas obligé de revenir dans tout le code ou le nom de celui-ci est écrit en dure
    de plus cela permet d'affecter un même événement a plusieurs composant de même type ayant la même action a généré

    mes 2 cents

  2. #22
    Expert confirmé
    Avatar de Ph. B.
    Homme Profil pro
    Freelance
    Inscrit en
    Avril 2002
    Messages
    1 786
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 58
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Freelance
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2002
    Messages : 1 786
    Points : 5 918
    Points
    5 918
    Par défaut
    Bonjour,
    Citation Envoyé par anapurna Voir le message
    ...
    j'aurais cent fois préféré cette solution

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    procedure TForm1.Button1Click(Sender: TObject);
    begin
      // 
      (Sender as Tbutton).Enabled := False;
      //
      MonTraitement;
      //
      (Sender as Tbutton).Enabled := True;
    end;
    cela facilite la maintenance du code quand vous modifiez le nom du composant on est pas obligé de revenir dans tout le code ou le nom de celui-ci est écrit en dure
    de plus cela permet d'affecter un même événement a plusieurs composant de même type ayant la même action a généré
    Soit, mais il faut dans ce cas pousser la logique jusqu'au bout !
    A savoir :
    1. Ne pas laisser dans le nom de la méthode gestionnaire de l'évènement une référence à un composant précis, mais renommer la méthode, soit avec un nom générique, soit avec un nom relatif au traitement,
    2. Eviter de refaire ce qui l'a déjà été, en l'occurrence que le Sender est bien une instanciation de la classe TButton ou d'un de ses descendants, puis de le trans-typer.
      Code : Sélectionner tout - Visualiser dans une fenêtre à part
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      procedure TForm1.AnyButtonClick(Sender: TObject);
      var 
        AButton: TButton;
      begin
        if not (Sender is TButton) then
          raise Exception.Create('Sender n''est pas un objet de type TButton');
        //
        AButton := TButton(Sender); 
        AButton.Enabled := False;
        //
        Self.MonTraitement;
        //
        AButton.Enabled := True;
      end;

    D'autre part, comme je l'avais dit précédemment, Self peut s'avérer discriminant quand une fonction (ou une procédure) et une méthode portant le même nom sont dans le même espace de visibilité ou que l'on utilise une instruction with... Sa suppression ne facilite pas forcément la maintenance du code...

  3. #23
    Expert confirmé
    Avatar de anapurna
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Mai 2002
    Messages
    3 442
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Arts - Culture

    Informations forums :
    Inscription : Mai 2002
    Messages : 3 442
    Points : 5 862
    Points
    5 862
    Par défaut
    salut

    dans le cas de sa propre méthode tu n'a pas besoin de tester si c'est un bouton vu que l’émetteur de l’événement est le bouton lui même
    c'est quand tu bidouille avec les événement qu'il est dans ce cas obligatoire de se proteger
    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
    procedure TForm1.AnyButtonClick(Sender: TObject);
    var 
      AButton: TButton; // la variable supplementaire est ce bien utile ? 
    begin
      if not (Sender is TButton) then   <== ok si tu bidouille avec les événement sinon aucune raison d’être  
        raise Exception.Create('Sender n''est pas un objet de type TButton');
      //
      AButton := TButton(Sender); <=== je ne connais pas la différence entre TButton(Sender) et (Sender as TButton) 
                                              // peut etre existe t'il un controle supplementaire
                                              // a voir    
      AButton.Enabled := False;
      //
      Self.MonTraitement;
      //
      AButton.Enabled := True;
    end;
    voila mes deux cents

  4. #24
    Membre éclairé
    Profil pro
    Inscrit en
    Octobre 2002
    Messages
    707
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2002
    Messages : 707
    Points : 777
    Points
    777
    Par défaut
    Citation Envoyé par anapurna Voir le message
    salut

    dans le cas de sa propre méthode tu n'a pas besoin de tester si c'est un bouton vu que l’émetteur de l’événement est le bouton lui même
    c'est quand tu bidouille avec les événement qu'il est dans ce cas obligatoire de se proteger
    Oui... mais non ! On peut toujours avoir un appel à AnyButtonClick depuis n'importe où dans le code ! Et donc lui passer en paramètre ce que l'on veut.

  5. #25
    Rédacteur/Modérateur
    Avatar de Andnotor
    Inscrit en
    Septembre 2008
    Messages
    5 803
    Détails du profil
    Informations personnelles :
    Localisation : Autre

    Informations forums :
    Inscription : Septembre 2008
    Messages : 5 803
    Points : 13 493
    Points
    13 493
    Par défaut
    Citation Envoyé par anapurna Voir le message
    dans le cas de sa propre méthode tu n'a pas besoin de tester si c'est un bouton vu que l’émetteur de l’événement est le bouton lui même
    C'est une méthode de type TNotifyEvent. On peut donc la lier à tout événement correspondant à ce prototype, quelque soit le composant (ou objet de manière générale).

    if not (Sender is TButton) then, à réserver pour du release et plutôt pour tester différents types pour des actions différenciées. Pour les erreurs de design, il vaut mieux passer par Assert(Sender is TButton); qui a le double avantage de 1) afficher l'unité concernée et le numéro de ligne fautif et 2) être un test automatiquement supprimé en release (optimisation).

    Citation Envoyé par anapurna Voir le message
    je ne connais pas la différence entre TButton(Sender) et (Sender as TButton)
    C'est une question de test de validité à la compilation. TButton(Sender) est un transtypage brut, il n'y a aucun contrôle. S'il y a une erreur, c'est à l'exécution qu'on la verra (une VA probablement). La construction (Sender as TButton) avertit d'une incompatibilité à la compilation.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    var
      Edit :TEdit;
    begin
      //Compile
      TButton(Edit).click;
     
      //Ne compile pas
      (Edit as TButton).click;
    end;

  6. #26
    Rédacteur/Modérateur
    Avatar de Andnotor
    Inscrit en
    Septembre 2008
    Messages
    5 803
    Détails du profil
    Informations personnelles :
    Localisation : Autre

    Informations forums :
    Inscription : Septembre 2008
    Messages : 5 803
    Points : 13 493
    Points
    13 493
    Par défaut
    procedure TAdminCentralInventoryExtendedFormDetail.cxPgCtrlTcxPageControlPropertiesTcxPCCustomButtonsButtons0Click(ASender: TObject);

    Cela fait partie des choses que je ne conseillerais pas. On arrive à la fin qu'on a oublié le début

    De plus en terme d'efficacité, c'est pas ça ! Il faut 7 secondes pour lire cette seule déclaration (si, si, j'ai chronométré )

  7. #27
    Expert éminent sénior
    Avatar de Paul TOTH
    Homme Profil pro
    Freelance
    Inscrit en
    Novembre 2002
    Messages
    8 964
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 55
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Freelance
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Novembre 2002
    Messages : 8 964
    Points : 28 457
    Points
    28 457
    Par défaut
    Citation Envoyé par anapurna Voir le message
    Salut

    je reviens sur un code proposé ce qui m’énerve le plus c'est la non exploitation du sender dans les Evénement des composants

    je reviens donc sur un code fournis
    voici un exemple concret


    j'aurais cent fois préféré cette solution


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    procedure TForm1.Button1Click(Sender: TObject);
    begin
      // 
      (Sender as Tbutton).Enabled := False;
      //
      MonTraitement;
      //
      (Sender as Tbutton).Enabled := True;
    end;
    cela facilite la maintenance du code quand vous modifiez le nom du composant on est pas obligé de revenir dans tout le code ou le nom de celui-ci est écrit en dure
    de plus cela permet d'affecter un même événement a plusieurs composant de même type ayant la même action a généré

    mes 2 cents
    non en fait je n'aime pas cet exemple

    tu peux très couramment associer le même évènement à un MenuItem et un Button, si tu présuppose que le Sender est un TButton, tu ne peux plus le faire.

    d'autre par, je préfère cette approche:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    procedure TForm1.Button1Click(Sender: TObject);
    begin
      DisableSave();
    end;
     
    procedure TForm1.DisableSave();
    begin
      btSave.Enabled := False;
      mnSave.Enabled := False;
      mnSaveAs.Enabled := False;
    end;
    ou à la rigueur

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    procedure TForm1.DisableSave(Sender: TObject);
    begin
      btSave.Enabled := False;
      mnSave.Enabled := False;
      mnSaveAs.Enabled := False;
    end;
    comme ça tu peux indiquer directement dans Button1 que OnClick fait un DisableSave...mais tu es obligé de revenir à la première écriture dès que tu as plusieurs actions pas forcément déclenchée en même temps:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    procedure TForm1.Button1Click(Sender: TObject);
    begin
      SaveDocument();
      DisableSave();
    end;
     
    procedure TForm1.Button2Click(Sender: TObject);
    begin
      NewDocument();
      DisableSave();
    end;

  8. #28
    Expert confirmé
    Avatar de Ph. B.
    Homme Profil pro
    Freelance
    Inscrit en
    Avril 2002
    Messages
    1 786
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 58
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Freelance
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2002
    Messages : 1 786
    Points : 5 918
    Points
    5 918
    Par défaut
    Bonsoir,

    Citation Envoyé par anapurna Voir le message
    dans le cas de sa propre méthode tu n'a pas besoin de tester si c'est un bouton vu que l’émetteur de l’événement est le bouton lui même
    c'est quand tu bidouille avec les événement qu'il est dans ce cas obligatoire de se proteger
    Non on peut écrire quelque part dans une méthode de la fiche Self.AnyButtonClick(nil); ou Self.AnyButtonClick(MenuItem1);
    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
    procedure TForm1.AnyButtonClick(Sender: TObject);
    var 
      AButton: TButton; // la variable supplementaire est ce bien utile ? 
                        // Oui pour la maintenance et la lisibilité du code.
                        // Et cela évite de réécrire x fois TButton(Sender)
    begin
      if not (Sender is TButton) then   <== ok si tu bidouille avec les événement sinon aucune raison d’être   Voir ma réponse ci-dessus...
        raise Exception.Create('Sender n''est pas un objet de type TButton');
      //
      AButton := TButton(Sender); <=== je ne connais pas la différence entre TButton(Sender) et (Sender as TButton) 
                                              // peut etre existe t'il un controle supplementaire
                                              // a voir    
                                              // Avec "as", on réalise un contrôle du type avant trans-typage et une exception est levée en cas de non concordance sauf pour nil
                                              // Le trans-typage se fait directement et sans contrôle, C'est plus rapide en terme d'exécution
                                              // D'ailleurs pour être encore plus rigoureux, il faudrait également tester en entrée de la méthode que Sender <> nil ou Assigned(Sender)
      AButton.Enabled := False;
      //
      Self.MonTraitement;
      //
      AButton.Enabled := True;
    end;
    Deux cents supplémentaires

  9. #29
    Expert confirmé
    Avatar de Ph. B.
    Homme Profil pro
    Freelance
    Inscrit en
    Avril 2002
    Messages
    1 786
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 58
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Freelance
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2002
    Messages : 1 786
    Points : 5 918
    Points
    5 918
    Par défaut
    Citation Envoyé par Paul TOTH Voir le message
    tu peux très couramment associer le même évènement à un MenuItem et un Button, si tu présuppose que le Sender est un TButton, tu ne peux plus le faire.
    On peut aussi dans ce cas utiliser les actions (TActionList) qui peuvent être associées à ces 2 types de composants et à certains autres, par contre si on utilise un TPanel, on ne peut plus le faire...

  10. #30
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 634
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Développeur C++\Delphi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2006
    Messages : 13 634
    Points : 25 352
    Points
    25 352
    Par défaut
    Citation Envoyé par Andnotor Voir le message
    procedure TAdminCentralInventoryExtendedFormDetail.cxPgCtrlTcxPageControlPropertiesTcxPCCustomButtonsButtons0Click(ASender: TObject);

    Cela fait partie des choses que je ne conseillerais pas. On arrive à la fin qu'on a oublié le début

    De plus en terme d'efficacité, c'est pas ça ! Il faut 7 secondes pour lire cette seule déclaration (si, si, j'ai chronométré )
    Tu sais l'efficacité, mon collègue, c'est l'opposé, on est trois dans l'équipe,
    à deux on commit 95% des sources,
    l'autre, je me demande ce qu'il fait !
    Mais avec ta remarque, je comprends mieux, il passe son temps à relire son code au lieu de pouvoir en écrire d'autre

    Tu comprends mon calvère quand je suis obligé de maintenir ce genre d'application !
    Et encore, ce développeur est un roi du copier-coller, rien qu'en transformant 100 fonctions en une fonction réutilisable appelé par les 100 autres, on pourrait économiser 5000 lignes !
    Pour le moment, je n'ai eu le courage que de réduire que 40 fonctions pour 2000 lignes

    Je lui ai fourni la fonction, je lui ai montré les refactoring,
    il n'en a rien à secouer et en a même ajouter 11 depuis mes remarques toujours en copier coller !

    Mon collègue est le roi du CANPF !

    Il est capable de prendre un TForm+TDataModule environ 9000 lignes les deux réunis
    de copier coller les deux pour ne modifier que 200 lignes (principalement le SQL) pour ajouter deux colonnes et deux TEdit


    Pour faire une liste d'entier, il préfère utiliser une TIntegerList héritée d'une TStrings (oui à coup de reintroduce pour faire disparaitre le type string) au lieu d'un TList<Integer> !
    Tout ça parce qu'il reste attaché à ce code qu'il a écrit en 2013 sur XE2 par méconnaissance des superbes et fantastiques nouveautés de Delphi<>

    Merci pour la maintenance !

  11. #31
    Expert confirmé
    Avatar de anapurna
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Mai 2002
    Messages
    3 442
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Arts - Culture

    Informations forums :
    Inscription : Mai 2002
    Messages : 3 442
    Points : 5 862
    Points
    5 862
    Par défaut
    salut ,

    arf heureusement que dans mes commentaires j'avais parlé de bidouille avec les événements

    je sais bien que si tu te sert de ton événements autrement que dans le cadre classique d'une construction graphique
    il faut penser à toutes les éventualités, donc dans le cas où l'utilisation de l’événement n'est pas strictement réservé au composant qui l'emploi
    je suis d'accord pour faire les différents test demandé

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
    Procedure TForm1.AnyButtonClick(Sender : Topbject);
    begin
       if assigned(Sender) Then 
       begin
           Assert(Sender is TButton); // j'ai bien compris qu'il été préférable d'utiliser assert 
           TButton(Sender).Enabled := False;
          //
           MonTraitement();
         //
          TButton(Sender).Enabled := True;
       end;
    end;
    quand au code de Paul ... je me sert régulièrement de cette méthode pour gérer le panel de bouton général de mes formes
    ce code est valide quand tu as plusieurs action à réaliser simultanément
    quand a l'utilisation du sender qui ne sert a rien je ne suis pas pour

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    procedure TForm1.DisableSave(Sender: TObject);
    begin
      btSave.Enabled := False;
      mnSave.Enabled := False;
      mnSaveAs.Enabled := False;
    end;
    j'aurai préféré

    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
     
    procedure TForm1.Save_Enable(Bool : Boolean);
    begin
      btSave.Enabled      := Bool;
      mnSave.Enabled    := Bool;
      mnSaveAs.Enabled := Bool;
    end;
     
    procedure TForm1.SaveDocClick(Sender: TObject);
    begin
      SaveDocument();
      Save_Enable(False);
    end;
     
    procedure TForm1.newDocClick(Sender: TObject);
    begin
      NewDocument();
      Save_Enable(true); // bin oui pour un nouveau document on a le droit de le sauvegarder
    end;
    mes deux cents

  12. #32
    Expert éminent sénior
    Avatar de Paul TOTH
    Homme Profil pro
    Freelance
    Inscrit en
    Novembre 2002
    Messages
    8 964
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 55
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Freelance
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Novembre 2002
    Messages : 8 964
    Points : 28 457
    Points
    28 457
    Par défaut
    Citation Envoyé par anapurna Voir le message
    ...

    quand a l'utilisation du sender qui ne sert a rien je ne suis pas pour
    ...

    j'aurai préféré
    ..
    mes deux cents
    sans doute, mais ton code non plus n'utilise pas Sender

    bon pour être tout à fait honnête, il m'arrive de faire un code utilisant Txxx(Sender)...mais c'est plus dans le cadre d'une série de ToolButton dont le Tag permet de distinguer des actions similaires (bold, italic, ...), et dans ce cas ça peut aussi fonctionner avec TComponent(Sender).Tag et des menus équivalents.

  13. #33
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 634
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Développeur C++\Delphi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2006
    Messages : 13 634
    Points : 25 352
    Points
    25 352
    Par défaut
    Alors pour tout le monde, ce n'est pas un CANPF mais surement la plus belle bêtise que j'ai pu lire d'un développeur Web
    Cela entre dans les pires choses que vous ayez vu comme observé par Paul Toth pour la Base de Données mais dans la culture dans la programmation en générale mais surtout l'une des plus importantes compétences d'un développeur : "savoir se remettre en question !"
    Je n'ai pas trouvé de ce sujet "les pires choses que vous ayez vu" plus généraliste où exposer cette contre-vérité.

    Nom : Sans titre.jpg
Affichages : 262
Taille : 27,0 Ko

    Ce développeur étant généralement premier degré, je me pose la question du sérieux de la réponse qui était d'ailleurs totalement hors sujet de la question posée.


    Donc désormais, on va coder les drivers linux en JavaScript puisque c'est proche du matériel sans abstraction aucune.






    Le contraire n'est pas vrai non plus, c'est tellement plus complexe et tellement plus difficile à généraliser que toutes les affirmations de ce genre sont potentiellement fausses.

    C'est pour cela que je préfère me considérer comme un développeur médiocre, j'ai une toute petite et minuscule expertise mais je suis ignorant en informatique dans sa globalité, cela libère de toute pression, on peut apprendre tous les jour et l'on aura jamais assez de temps pour tout apprendre dans le domaine de l'informatique, celui qui prétend le contraire se ment d'abord à lui-même.

Discussions similaires

  1. [Freeware] Mettez un "Live Update" dans vos applications
    Par Hexanium dans le forum Mon programme
    Réponses: 10
    Dernier message: 18/07/2010, 03h34
  2. [Logging] Que tracez-vous dans vos applications ?
    Par le Daoud dans le forum Langages de programmation
    Réponses: 4
    Dernier message: 10/03/2006, 14h36

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