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 :

Annuler une construction [Débutant]


Sujet :

C#

  1. #1
    Membre éprouvé
    Profil pro
    Inscrit en
    Novembre 2004
    Messages
    2 766
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2004
    Messages : 2 766
    Par défaut Annuler une construction
    Bonjour,

    J'ai un constructeur qui prend un argument.

    Si la valeur de cet argument n'est pas valide, que puis-je faire ?
    Jeter une exception ? Pas d'autres solution ?

  2. #2
    Membre émérite

    Homme Profil pro
    Développeur .NET
    Inscrit en
    Juin 2011
    Messages
    487
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Seine et Marne (Île de France)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : Finance

    Informations forums :
    Inscription : Juin 2011
    Messages : 487
    Par défaut
    Bonjour,

    Jeter une exception dans un constructeur est une très mauvaise pratique. En C#, ça va parce que tout est géré par le framework mais dans certains langages comme c++ ça peut être très problématique car tu peux te retrouver avec des objets incomplets.

    Le meilleur à faire dans ton cas serait de créer une Factory qui vérifie ton argument et renvoie ton objet. Je te laisse googler ce design pattern afin d'en savoir plus mais il n'y a rien d'extrèmement compliqué
    Mon blog sur les technos .NET et Agile -> http://blog.developpez.com/maximepalmisano/

  3. #3
    Membre Expert Avatar de DonQuiche
    Inscrit en
    Septembre 2010
    Messages
    2 741
    Détails du profil
    Informations forums :
    Inscription : Septembre 2010
    Messages : 2 741
    Par défaut
    Je voudrais faire entendre un son de cloche différent. Lancer des exceptions depuis un constructeur ne pose aucun problème et, d'ailleurs, plusieurs types du framework font cela. Il ne faut donc surtout pas hésiter à mes yeux, surtout s'il ne s'agit que de quelques vérifications.

    Cela dit, attention tout de même ! Si une exception est lancée dans le constructeur, il est vrai que l'objet ne sera pas accessible par le code qui instanciait, ce qui est bien (même en cas de bloc using sur un type implémentant IDisposable : on n'entrera jamais dans le bloc et Dispose ne sera jamais appelé). En revanche, l'instance a bien été créée et reste accessible par le seul GC qui appellera le destructeur. C'est la grosse différence avec le C++. Gaffe, donc, a bien écrire la destructeur avec cette perspective en tête.

    Enfin, utiliser une méthode factory statique (MyType.Create()) me semble toutefois acceptable dans le cas d'un processus de création particulièrement coûteux (temps CPU, ressources systèmes, etc). Non pas que cela poserait problème si c'était fait dans un constructeur mais on attend intuitivement d'un constructeur qu'il soit léger. Garder le constructeur privé et fournir une telle méthode statique est donc une simple indication à l'usage des consommateurs de la classe. Mais c'est lourd et en abuser est à mes yeux un anti-pattern. Je garde plutôt ces méthodes pour les cas où je préfère renvoyer null plutôt que de lever une exception où, bien sûr, pour tous les cas où le pattern factory est approprié.


    PS : MSDN est toujours une bonne source : Constructor design guidelines

  4. #4
    Expert confirmé

    Homme Profil pro
    Chef de projet NTIC
    Inscrit en
    Septembre 2006
    Messages
    3 580
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Chef de projet NTIC
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Septembre 2006
    Messages : 3 580
    Par défaut
    salut

    vu que ton constructeur prends un argument, rien n'empeche ton objet après construction de positionner un "état - Je suis pas bien construit"...

    Après, en théorie, si la construction de ton objet est impossible parce que un argument contient une mauvaise valeur, alors il vaut peut-etre mieux une factory...

    Ou alors, construire ton objet et avoir une méthode dans laquelle tu passes ton argument et qui te retournera un boolean pour dire si les choses à construire à partir de cet argument se sont construites

  5. #5
    Expert éminent Avatar de Pol63
    Homme Profil pro
    .NET / SQL SERVER
    Inscrit en
    Avril 2007
    Messages
    14 204
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Puy de Dôme (Auvergne)

    Informations professionnelles :
    Activité : .NET / SQL SERVER

    Informations forums :
    Inscription : Avril 2007
    Messages : 14 204
    Par défaut
    Citation Envoyé par MaximePalmisano Voir le message
    Jeter une exception dans un constructeur est une très mauvaise pratique. En C#, ça va parce que tout est géré par le framework mais dans certains langages comme c++ ça peut être très problématique car tu peux te retrouver avec des objets incomplets.
    ne pas répondre sur un langage avec des arguments d'un autre langage ...

    et pour compléter DonQuiche que je puissoie, en général le throw est fait au début du constructeur, (if arg is null {throw argumentnullexception} par exemple) donc ça ne pose pas de soucis niveau mémoire
    Cours complets, tutos et autres FAQ ici : C# - VB.NET

  6. #6
    Expert confirmé

    Homme Profil pro
    Chef de projet NTIC
    Inscrit en
    Septembre 2006
    Messages
    3 580
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Chef de projet NTIC
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Septembre 2006
    Messages : 3 580
    Par défaut
    salut

    moi, comme je suis un peu neuneu, ce que je fais est un peu ce que fait Microsoft...

    Prenons l'exemple de la classe SerialPort qui permet de faire de la communication série. Si on regarde cette classe, dans le constructeur, on peut passer des arguments... Par contre, ce sont les méthodes de "communication" qui elles vont retourner une exception ou un boolean pour dire "Pas de Port Série".

    Et pour moi, c'est plutot logique...

    Pour moi, une classe devrait toujours pouvoir être construite. Par contre, si défaut d'argument, de ressources disponibles il y a , alors, les méthodes "obligatoires" de cette classe te le diront dès le premier appel.

    J'ai JAMAIS au cours de ma courte carrière de développeur (27 ans de dév ) eu une situation ou je me suis dit "Tiens, je vais lancer une exception dans mon constructeur"...

    Peut-etre parce que je privilégie les choses simples aux choses compliquées, alambiquées, divines au niveau design mais impossible à réaliser dans le temps imparti.. Peut-etre parce que je pense qu'un logiciel doit avant tout apporter la réponse au besoin avant d'être "magnifique" d'un point de vue architecture...

    En tout cas, même si la question est pertinente et interessante, j'avoue ne jamais avoir eu à traiter ce type de cas...

    Peut-etre que je crois trop que l'informatique, c'est TOUJOURS simple...

    Ma devise : "En informatique, rien n'est compliqué. Par contre, parfois, résoudre un problème peut-etre complexe"...

  7. #7
    Expert éminent Avatar de Pol63
    Homme Profil pro
    .NET / SQL SERVER
    Inscrit en
    Avril 2007
    Messages
    14 204
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Puy de Dôme (Auvergne)

    Informations professionnelles :
    Activité : .NET / SQL SERVER

    Informations forums :
    Inscription : Avril 2007
    Messages : 14 204
    Par défaut
    Citation Envoyé par theMonz31 Voir le message
    Prenons l'exemple de la classe SerialPort qui permet de faire de la communication série. Si on regarde cette classe, dans le constructeur, on peut passer des arguments... Par contre, ce sont les méthodes de "communication" qui elles vont retourner une exception ou un boolean pour dire "Pas de Port Série".

    Et pour moi, c'est plutot logique...

    Pour moi, une classe devrait toujours pouvoir être construite. Par contre, si défaut d'argument, de ressources disponibles il y a , alors, les méthodes "obligatoires" de cette classe te le diront dès le premier appel

    je ne suis pas trop d'accord
    en général dans une application on log les erreurs pour pouvoir débugger rapidement

    si une classe demande un paramètre dans son constructeur et qu'elle en a réellement besoin, ca me parait plus logique de thrower tout de suite, au moins dans le stacktrace on saurait à quel moment le paramètre était null
    car les objets peuvent venir de loin ... et si tu throw lors d'un appel à une méthode, tu ne sauras pas forcément à quel moment tu as instancié ta classe et donc le debug en sera moins aisé
    CA ça me parait logique !

    après si le paramètre n'est pas nécessaire au moment de la construction et peut etre fourni plus tard pas de soucis
    Cours complets, tutos et autres FAQ ici : C# - VB.NET

  8. #8
    Membre expérimenté Avatar de brachior
    Homme Profil pro
    Doctorant
    Inscrit en
    Mai 2011
    Messages
    190
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France, Seine et Marne (Île de France)

    Informations professionnelles :
    Activité : Doctorant
    Secteur : Enseignement

    Informations forums :
    Inscription : Mai 2011
    Messages : 190
    Par défaut
    Citation Envoyé par Pol63
    si une classe demande un paramètre dans son constructeur et qu'elle en a réellement besoin, ca me parait plus logique de thrower tout de suite
    Je suis aussi de cet avis,
    Si un constructeur ou une méthode ne peut résoudre un problème,
    Il est de son devoir d'en avertir au plus vite l'objet appelant ...

    L'objet sera forcement créé mais seul le Garbage aura un pointeur dessus
    (Ce qu'on appelle un «constructeur» est en fait un «initialisateur» ... La construction a déjà été faite avant ...
    Dans certains langages, il est possible de faire son propre constructeur (ex: python))

    Si le fait d'avoir un objet inutilisable qui traine au niveau du Garbage te gène,
    (parce qu'il est trop lourd, et/ou parce qu'il y en aura peut être beaucoup)
    Alors une Factory te sortirait de là ^^.

  9. #9
    Membre Expert Avatar de Er3van
    Homme Profil pro
    Architecte Logiciel
    Inscrit en
    Avril 2008
    Messages
    1 430
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Architecte Logiciel
    Secteur : Industrie

    Informations forums :
    Inscription : Avril 2008
    Messages : 1 430
    Par défaut
    Citation Envoyé par theMonz31 Voir le message
    Peut-etre que je crois trop que l'informatique, c'est TOUJOURS simple...
    L'informatique généralement c'est simple, à échelle micro, par contre, à échelle macro, ça ne l'est pas toujours.
    Et quand tu développes une solution IT qui répond à un besoin métier complexe, ta solution IT peut devenir complexe par extension (ou propagation...).

    Du coup, oui, quand tu fais une solution IT pour un besoin IT, ça me parait totalement justifié d'avoir recours à ce genre de pratique :
    Citation Envoyé par theMonz31 Voir le message
    Si on regarde cette classe, dans le constructeur, on peut passer des arguments... Par contre, ce sont les méthodes de "communication" qui elles vont retourner une exception ou un boolean pour dire "Pas de Port Série".
    Car dans ce cas, quelqu'un avec la compréhension métier de ton application qui doit un jour comprendre les mécanismes utilisés comprendra la raison.

    Par contre, dans le case d'une solution IT pour un besoin business, ça me parait totalement justifié d'avoir recours à ce genre de pratique là :
    Citation Envoyé par Pol63
    si une classe demande un paramètre dans son constructeur et qu'elle en a réellement besoin, ca me parait plus logique de thrower tout de suite, au moins dans le stacktrace on saurait à quel moment le paramètre était null
    Qui se traduirait par exemple par un :
    Code c# : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    try {
           CreateCommand(product, customer);
    }
    catch(CommandCreationException cce) { /* do something */ }
    Car dans ce cas, tu sais que telle création n'a pas fonctionné, c'est aussi simple que ça. Tu décomposes ainsi de façon plus "macro".

    Du coup, j'aurais tendance à dire que vous avez tous raison, mais que c'est le contexte d'application qui fait la différence.

  10. #10
    Expert éminent Avatar de Pol63
    Homme Profil pro
    .NET / SQL SERVER
    Inscrit en
    Avril 2007
    Messages
    14 204
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Puy de Dôme (Auvergne)

    Informations professionnelles :
    Activité : .NET / SQL SERVER

    Informations forums :
    Inscription : Avril 2007
    Messages : 14 204
    Par défaut
    Citation Envoyé par Er3van Voir le message
    Du coup, j'aurais tendance à dire que vous avez tous raison, mais que c'est le contexte d'application qui fait la différence.
    c'est ce que j'aurais tendance à dire aussi
    selon la classe le développeur doit choisir entre un factory, un throw dans le constructeur, ou un throw plus tard comme pour le serialport
    Cours complets, tutos et autres FAQ ici : C# - VB.NET

  11. #11
    Membre éprouvé
    Profil pro
    Inscrit en
    Novembre 2004
    Messages
    2 766
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2004
    Messages : 2 766
    Par défaut
    He bien... Je ne pensais pas déclencher autant de passion avec ma question.

    Toutes vos réponses sont intéressantes, mais j'hésite encore sur la solution que je vais choisir... car mon client n'est pas très doué en code (moi, c'est seulement en C#, que je ne suis pas doué ), et je le vois bien grimacer si je mets en place quelque chose qui lui paraît compliqué.

    Enfin bon. Vous m'avez donné toutes les cartes, et je vous en remercie.

  12. #12
    Expert éminent Avatar de Pol63
    Homme Profil pro
    .NET / SQL SERVER
    Inscrit en
    Avril 2007
    Messages
    14 204
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Puy de Dôme (Auvergne)

    Informations professionnelles :
    Activité : .NET / SQL SERVER

    Informations forums :
    Inscription : Avril 2007
    Messages : 14 204
    Par défaut
    le plus simple pour un développeur tiers doit être le throw dans le constructeur
    le design pattern factory n'est pas forcément connu de tous
    et avoir l'erreur tout de suite à l'instanciation est sans doute plus logique plutot que de se dire "putain telle méthode elle marche pas"
    Cours complets, tutos et autres FAQ ici : C# - VB.NET

  13. #13
    Membre Expert Avatar de Er3van
    Homme Profil pro
    Architecte Logiciel
    Inscrit en
    Avril 2008
    Messages
    1 430
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Architecte Logiciel
    Secteur : Industrie

    Informations forums :
    Inscription : Avril 2008
    Messages : 1 430
    Par défaut
    Citation Envoyé par oodini Voir le message
    He bien... Je ne pensais pas déclencher autant de passion avec ma question.

    Toutes vos réponses sont intéressantes, mais j'hésite encore sur la solution que je vais choisir... car mon client n'est pas très doué en code (moi, c'est seulement en C#, que je ne suis pas doué ), et je le vois bien grimacer si je mets en place quelque chose qui lui paraît compliqué.

    Enfin bon. Vous m'avez donné toutes les cartes, et je vous en remercie.
    De ce que j'en comprends, il faudrait que ton code soit plutôt orienté fonctionnel pour être compris, et donc la solution du Throw dans le constructeur me semble plus appropriée comme je l'ai expliqué plus haut.
    Maintenant, l'autre hypothèse est également valable, mais je conseillerai de bien la documenter.

  14. #14
    Expert confirmé

    Homme Profil pro
    Chef de projet NTIC
    Inscrit en
    Septembre 2006
    Messages
    3 580
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Chef de projet NTIC
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Septembre 2006
    Messages : 3 580
    Par défaut
    Je comprends toutes vos remarques

    Je me demande juste si il existe des classes dans le framework .Net qui ont ce genre de comportement ?

    Je serais curieux de savoir si des classes accessibles aux développeurs .Net retournent une exception à la construction ?

    Franchement, j'aimerais bien un exemple dans le framework si cela existe

  15. #15
    Expert éminent Avatar de Pol63
    Homme Profil pro
    .NET / SQL SERVER
    Inscrit en
    Avril 2007
    Messages
    14 204
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Puy de Dôme (Auvergne)

    Informations professionnelles :
    Activité : .NET / SQL SERVER

    Informations forums :
    Inscription : Avril 2007
    Messages : 14 204
    Par défaut
    rien que pour un throw new argumentnullexception si arg is null dans le constructeur (pas regardé pour d'autres types d'erreur) :

    non accessible il y en a énormément

    accessible il y en a plein aussi dont quelques exemples :
    new system.drawing.pen(brush)
    new System.IO.FileInfo(filepath)
    new System.Net.IPAddress(byte())

    etc...
    Cours complets, tutos et autres FAQ ici : C# - VB.NET

  16. #16
    Rédacteur
    Avatar de Nathanael Marchand
    Homme Profil pro
    Expert .Net So@t
    Inscrit en
    Octobre 2008
    Messages
    3 615
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Expert .Net So@t
    Secteur : Conseil

    Informations forums :
    Inscription : Octobre 2008
    Messages : 3 615
    Par défaut
    Citation Envoyé par theMonz31 Voir le message
    Je comprends toutes vos remarques

    Je me demande juste si il existe des classes dans le framework .Net qui ont ce genre de comportement ?

    Je serais curieux de savoir si des classes accessibles aux développeurs .Net retournent une exception à la construction ?

    Franchement, j'aimerais bien un exemple dans le framework si cela existe
    CHALLENGE ACCEPTED!

    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
     
    public StreamWriter(string path, bool append, Encoding encoding, int bufferSize) : base(null)
    {
    	if (path == null)
    	{
    		throw new ArgumentNullException("path");
    	}
    	if (encoding == null)
    	{
    		throw new ArgumentNullException("encoding");
    	}
    	if (path.Length == 0)
    	{
    		throw new ArgumentException(Environment.GetResourceString("Argument_EmptyPath"));
    	}
    	if (bufferSize <= 0)
    	{
    		throw new ArgumentOutOfRangeException("bufferSize", Environment.GetResourceString("ArgumentOutOfRange_NeedPosNum"));
    	}
    	Stream stream = StreamWriter.CreateFile(path, append);
    	this.Init(stream, encoding, bufferSize);
    }

  17. #17
    Expert confirmé

    Homme Profil pro
    Chef de projet NTIC
    Inscrit en
    Septembre 2006
    Messages
    3 580
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Chef de projet NTIC
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Septembre 2006
    Messages : 3 580
    Par défaut
    devant tant de connaissances, je ne peux qu'applaudir et m'incliner bien bas

  18. #18
    Rédacteur
    Avatar de Nathanael Marchand
    Homme Profil pro
    Expert .Net So@t
    Inscrit en
    Octobre 2008
    Messages
    3 615
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Expert .Net So@t
    Secteur : Conseil

    Informations forums :
    Inscription : Octobre 2008
    Messages : 3 615
    Par défaut
    Citation Envoyé par theMonz31 Voir le message
    devant tant de connaissances, je ne peux qu'applaudir et m'incliner bien bas
    Tu peux prendre un décompileur comme JustDecompile (ou Reflector) pour aller explorer un peu
    Cela dit, même sur les pages des constructeurs on peut voir qu'ils lèvent des exceptions:
    http://msdn.microsoft.com/en-us/library/3aadshsx.aspx

  19. #19
    Expert confirmé

    Homme Profil pro
    Chef de projet NTIC
    Inscrit en
    Septembre 2006
    Messages
    3 580
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Chef de projet NTIC
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Septembre 2006
    Messages : 3 580
    Par défaut
    J'ai honte .. je me cache

    Merci Nathanael... en tout cas !!!

  20. #20
    Membre Expert Avatar de DonQuiche
    Inscrit en
    Septembre 2010
    Messages
    2 741
    Détails du profil
    Informations forums :
    Inscription : Septembre 2010
    Messages : 2 741
    Par défaut
    Oui, en fait il y a beaucoup de classes du framework qui lèvent des exceptions dans le constructeur. Logique puisque, comme montré dans le lien MSDN que j'ai donné, c'est une des bonnes pratiques recommandées par MS.

    @theMonz31
    Et pourquoi donc une classe devrait-elle toujours pouvoir être construite ? En raison de quel argument théologique ? Si cette classe est inutile dans cet état incorrect, c'est toi qui complexifie le code, sa compréhension et son débogage en retardant les vérifications.

    Il n'y a aucune bonne raison de refuser dans l'absolu les levées d'exception dans les constructeurs. Et utiliser des méthodes plus ou moins tordues (le flag isInvalid... Beurk !) pour l'éviter ne peut que complexifier et obscurcir les choses. Le seul cas où on devrait accepter de créer un objet dans un état incorrect est le cas où les consommateurs peuvent précisément avoir besoin de manipuler et échanger un état incorrect.

    @Nathanael
    Petit hors-sujet, j'ai une petite préférence pour ILSpy personnellement. Ça me semble la meilleure alternative à Reflector désormais, ne serait-ce que parce qu'il offre un rendu C# et IL là où JustDecompile n'offre que le C#.

+ Répondre à la discussion
Cette discussion est résolue.
Page 1 sur 2 12 DernièreDernière

Discussions similaires

  1. annuler une impression en cour
    Par mondanikoffi dans le forum Bases de données
    Réponses: 1
    Dernier message: 05/07/2005, 20h56
  2. [Info]comment annuler une Externalization string?
    Par car dans le forum Eclipse Java
    Réponses: 1
    Dernier message: 17/04/2005, 09h51
  3. [JInternalFrame] Annuler sa construction
    Par wonderyan dans le forum Agents de placement/Fenêtres
    Réponses: 3
    Dernier message: 12/03/2005, 16h58
  4. Annuler une insertion dans un Trigger
    Par dreamanoir dans le forum Oracle
    Réponses: 2
    Dernier message: 10/01/2005, 13h04
  5. Annuler une suppression
    Par Harbaingan dans le forum SQL Procédural
    Réponses: 2
    Dernier message: 09/04/2003, 14h59

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