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

Design Patterns Discussion :

N'est-il pas un peu "sale" ?


Sujet :

Design Patterns

  1. #21
    Membre expérimenté Avatar de yann2
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    mai 2004
    Messages
    896
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France, Hauts de Seine (Île de France)

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

    Informations forums :
    Inscription : mai 2004
    Messages : 896
    Points : 1 600
    Points
    1 600
    Par défaut
    Citation Envoyé par Neckara Voir le message
    Vous allez rire mais c'est exactement un des exemple qu'on nous a donné en cours pour le DP décorateur.

    FenêtreAvecScrollBarre, FenêtreAvecMenu, FenêtreAvecBouton…
    À ce qui parait, ce serait utilisé dans certains logiciels.
    Utilisé ? FenetreAvecScrollBar et FenetreAvecMenu c'est un exemple qu'on peut trouver sur le net mais, je ne crois pas que ce soit beaucoup utilisé. A noter que c'est un peu moins farfelu que FenetreAvecBouton (bonjour pour placer les composants les uns par rapport aux autres si on construit notre fenêtre avec des décorateurs). Un autre exemple que je trouve farfelu est la gestion de listes d'ingrédients/goûts, via le pattern décorateur. Il y a plusieurs exemples sur le net : http://design-patterns.fr/decorateur-en-java. Qu'est ce qu'on veut exprimer ? On veut exprimer qu'un dessert a des ingrédients. Le fait d'utiliser le verbe avoir dénote une composition mais, plutôt que de faire une simple composition, ici, le concepteur choisi d'utiliser le pattern décorateur et se retrouve à faire une liste chainée d'ingrédients via ce pattern. Berk ! C'est un peu galère à gérer si le mec décide que finalement il ne veut pas de chantilly (pas impossible mais, galère...). D'autant plus que dans le speech sur la conception, l'auteur ne parle jamais de la solution la plus simple : une classe Dessert, une classe Ingredient avec deux attributs libellé/prix et la classe Desert est composée d'Ingredients. Voilà, pas besoin de décorateur et je peux avoir autant d'ingrédients que je veux !



    Citation Envoyé par Neckara Voir le message
    Oui, mais le décorateur sera "derrière" le "proxy".

    Je pense que je vais changer ma question en :
    Quand faut-il utiliser le DP décorateur et comment ? Quand ne faut-il surtout pas l'utiliser et que ne faut-il surtout pas faire avec?
    Car pour le moment, ce n'est pas très clair pour moi.
    Je pense qu'il faut faire attention à ce qui est naturel. Dans l'exemple plus haut je parle du verbe avoir qui dénote une agrégation ; en tout cas ça devrait être la première solution qui vient à l'esprit. Pour ma part, j'utilise le pattern décorateur pour surcharger certains comportements existant soit en :
    - redéfinissant complètement certains comportement (pas d'appel à l'objet décoré pour certaines opérations) ça peut arriver quand on utilise une API sur laquelle on n'a pas le contrôle.
    - ajoutant du comportement autour (orienté aspect) du comportement par défaut.

    L'exemple de Sébastien Meric sur developpez est déjà beaucoup plus intéressant que l'exemple de la FenetreAvecMenu : http://smeric.developpez.com/java/uml/decorateur/.

    Ce qu'il ne faut pas faire avec : là, ce n'est que mon avis, il ne faut pas gérer une agrégation avec le patron décorateur !!

    J'espère que ça sera plus clair.

    Yann

  2. #22
    Expert éminent sénior

    Avatar de Neckara
    Homme Profil pro
    Doctorant sécurité informatique — Diplômé master Droit/Économie/Gestion
    Inscrit en
    décembre 2011
    Messages
    8 575
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 26
    Localisation : France, Loire (Rhône Alpes)

    Informations professionnelles :
    Activité : Doctorant sécurité informatique — Diplômé master Droit/Économie/Gestion
    Secteur : Enseignement

    Informations forums :
    Inscription : décembre 2011
    Messages : 8 575
    Points : 21 475
    Points
    21 475
    Par défaut
    Citation Envoyé par yann2 Voir le message
    - redéfinissant complètement certains comportement (pas d'appel à l'objet décoré pour certaines opérations) ça peut arriver quand on utilise une API sur laquelle on n'a pas le contrôle.
    Ce n'est pas une sorte d'adaptateur/proxy au final?
    On est d'accord que "chaîner" les décorateurs n'a pas vraiment de sens ici (?).

    - ajoutant du comportement autour (orienté aspect) du comportement par défaut.
    Va falloir que je me renseigne un peu sur l'orienté aspect.

    L'exemple de Sébastien Meric sur developpez est déjà beaucoup plus intéressant que l'exemple de la FenetreAvecMenu : http://smeric.developpez.com/java/uml/decorateur/.
    Là on se sert des décorateurs pour deux choses :
    • l'affichage ;
    • la construction du message à afficher.

    Or on encapsule ces deux variations dans une seule hiérarchie, j'ai cru comprendre dans mon cours que ce n'était "pas super".

    Pour l'affichage, je pense qu'un DP Observeur/observable aurait plus de sens.
    Pour la construction de la chaîne, une liste de ConstructeurChaine dans logeur avec :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    for(ConstructeurChaine constructeur : constructeurs)
        chaine = constructeur(chaine);
    notify(chaine);
    Ou dans l'observateur :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    for(ConstructeurChaine constructeur : constructeurs)
        chaine = constructeur(chaine);
    afficher(chaine);
    Pour moi, ce code a plus de "sens".

    J'ai donc encore du mal à voir ce que nous apporte le DP décorateur dans cet exemple.
    "Parce que le diable est dans les détails, une vision sans nuance ne peut prétendre à la compréhension du monde."

    Mon ancienne page perso : https://neckara.developpez.com/

  3. #23
    Membre émérite
    Inscrit en
    janvier 2011
    Messages
    805
    Détails du profil
    Informations personnelles :
    Localisation : Autre

    Informations forums :
    Inscription : janvier 2011
    Messages : 805
    Points : 2 930
    Points
    2 930
    Par défaut
    Citation Envoyé par Neckara Voir le message
    Si on peut utiliser le DP de façon "dangereuse et illogique" facilement sans le faire vraiment exprès, je ne vois plus trop sont intérêt.
    Tout design pattern peut être mal utilisé si on perd de vue ce pour quoi il a été conçu à l'origine. Aucune disposition technique ne peut empêcher ça, tout comme pour reprendre l'analogie du dessert, aucune recette de gâteau au chocolat ne peut s'auto-contraindre à ne pas être utilisée comme base d'une quiche lorraine.

    Un design pattern, c'est la description d'un problème couramment rencontré et une solution. Beaucoup trop de gens oublient la partie problème et se contentent d'appliquer n'importe quel pattern à la mode ou dont ils ont entendu parler, souvent ils choisissent le mauvais et le tordent dans tous les sens pour le faire rentrer dans leur problème, c'est ça qui est dangereux. On trouve énormément de patterns utilisés à tort et à travers dans les forums et ailleurs, indépendamment de la validité de chaque pattern pris séparément.

    Citation Envoyé par Neckara Voir le message
    Disons qu'il est tout d'abord très peu intuitif pour un débutant.
    Qu'est-ce qui est peu intuitif dans

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    InputStream is = new GZipInputStream(new FileInputStream("file.gz"));
    par rapport à

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    InputStream is = new InputStream();
    is.Add(new FileInputDecorator("file.gz"));
    is.Add(new GZipInputDecorator());
    ?

    Citation Envoyé par Neckara Voir le message
    Je ne penses pas que ce soit une condition suffisante, car il n'y a aucun soucis de buffer si on utilise des versions des flux non-décorés.

    EDIT : on se répond depuis plusieurs posts, je pense qu'il faudrait qu'on commence à repréciser de quoi on parle pour éviter toute ambiguïté (en donnant un exemple de code ou que sais-je).
    Oui, peux-tu donner un exemple précis de code qui pose problème avec des flux décorés, et ne poserait pas de problème sans Décorateur ?

    La feuille de route du pattern Décorateur, c'est d'avoir une gamme de modificateurs de comportement autour d'un type d'objet qui soient composables et cumulables entre eux facilement, sans que le consommateur de cet objet (le code qui va finalement appeler la méthode qui produit le comportement) soit au courant de toutes les couches qui ont été ajoutées. Donc les qualités recherchées sont :

    - extensibilité
    - composabilité
    - abstraction

    Une implémentation où des décorations conflictuelles sont ajoutées à un objet relève à mon avis d'un mauvais choix fonctionnel, pas d'une défaillance du pattern en lui-même.

  4. #24
    Membre expérimenté Avatar de yann2
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    mai 2004
    Messages
    896
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France, Hauts de Seine (Île de France)

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

    Informations forums :
    Inscription : mai 2004
    Messages : 896
    Points : 1 600
    Points
    1 600
    Par défaut
    Citation Envoyé par Neckara Voir le message
    Ce n'est pas une sorte d'adaptateur/proxy au final?
    On est d'accord que "chaîner" les décorateurs n'a pas vraiment de sens ici (?).
    Non, c'est un décorateur :

    Nom : exempleredef.png
Affichages : 82
Taille : 32,6 Ko

    Je ne vois pas pourquoi on ne pourrait pas chainer. Je peux très bien ajouter un autre décorateur derrière mais, ça commencerait à devenir un peu cavalier.

    Citation Envoyé par Neckara Voir le message
    Là on se sert des décorateurs pour deux choses :
    • l'affichage ;
    • la construction du message à afficher.

    Or on encapsule ces deux variations dans une seule hiérarchie, j'ai cru comprendre dans mon cours que ce n'était "pas super".

    Pour l'affichage, je pense qu'un DP Observeur/observable aurait plus de sens.
    Pour la construction de la chaîne, une liste de ConstructeurChaine dans logeur avec :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    for(ConstructeurChaine constructeur : constructeurs)
        chaine = constructeur(chaine);
    notify(chaine);
    Ou dans l'observateur :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    for(ConstructeurChaine constructeur : constructeurs)
        chaine = constructeur(chaine);
    afficher(chaine);
    Pour moi, ce code a plus de "sens".

    J'ai donc encore du mal à voir ce que nous apporte le DP décorateur dans cet exemple.
    Oui, vous pouvez régler le problème de format avec une classe Formateur (que je préfère à ConstructeurChaine pour rester dans le jargon des Logger). L'exemple donne un décorateur qui modifie le message à loguer. Maintenant, imaginez un décorateur qui va vérifier qu'on a le droit de loguer. Vous allez encore modifier la classe Logger ?Le but, ici, est bien de séparer les responsabilités. Prenez exemple sur l'API des flux :
    - lire un flux (InputStream)
    - Bufferiser un flux (je ne sais pas si on peut dire tamponner) (BufferedInputStream)
    - Déchiffer (CipherInputStream)
    - etc.

    Là vous avez 3 "variations". Entre guillemets parce que pour moi ce sont 3 fonctionnalités différentes que je veux appliquer pour la même opération et pas des "variations" (pour être honnête je ne sais même pas de quoi vous parlez). L'intérêt, encore une fois, est de séparer les responsabilités (voir Single responsibility principle et separation of concerns)

    Pour les "affichages" (je dirai plutôt pour la consommation du log) il est tout à fait possible de résoudre le problème avec Observateur/Observable. On aurait dans ce cas, une classe LogRepository avec une liste de Log et l'instance LogRepository envoie des évènements à chaque fois qu'elle reçoit un Log, je ne vois pas d'inconvénients à ça (si il y avait une méthode miracle pour trouver la bonne conception ça se saurait ^^ )

    Yann

  5. #25
    Expert éminent sénior

    Avatar de Neckara
    Homme Profil pro
    Doctorant sécurité informatique — Diplômé master Droit/Économie/Gestion
    Inscrit en
    décembre 2011
    Messages
    8 575
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 26
    Localisation : France, Loire (Rhône Alpes)

    Informations professionnelles :
    Activité : Doctorant sécurité informatique — Diplômé master Droit/Économie/Gestion
    Secteur : Enseignement

    Informations forums :
    Inscription : décembre 2011
    Messages : 8 575
    Points : 21 475
    Points
    21 475
    Par défaut
    Citation Envoyé par yann2 Voir le message
    Non, c'est un décorateur :

    Nom : exempleredef.png
Affichages : 82
Taille : 32,6 Ko
    Pour être un décorateur, UneClasse ne devrait-il pas hériter d'une même interface que ton "décorateur" ?
    Je pense que je commence à comprendre pour ce cas de figure, je continue à réfléchir.


    Je ne vois pas pourquoi on ne pourrait pas chainer.
    On peut, mais est-ce que cela a vraiment du sens ?


    Oui, vous pouvez régler le problème de format avec une classe Formateur (que je préfère à ConstructeurChaine pour rester dans le jargon des Logger). L'exemple donne un décorateur qui modifie le message à loguer. Maintenant, imaginez un décorateur qui va vérifier qu'on a le droit de loguer. Vous allez encore modifier la classe Logger ?Le but, ici, est bien de séparer les responsabilités. *
    Sauf qu'un DP décorateur me semble inapproprié dans ce cas là :
    Le restriction sera dépendante de l'ordre dans lequel on aura "empilé" les décorateurs et on ne pourra pas restreindre l'accès à certains logs (écrire dans un fichier) mais pas à un autre (envoyer un e-mail).
    Cette problématique d'accès ne serait-elle pas plutôt de la responsabilité d'un "observateur" (ex. celui qui écris dans un E-mail) qui peut éventuellement la déléguer à une autre classe.

    Prenez exemple sur l'API des flux :
    - lire un flux (InputStream)
    - Bufferiser un flux (je ne sais pas si on peut dire tamponner) (BufferedInputStream)
    - Déchiffer (CipherInputStream)
    - etc.
    Je pense que cela a plus de sens de les voir comme des "filtres" que comme des décorations.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    Filters f;
    f.add(new FilterA() );
    Stream s;
    
    f.filter(s);
    //ou
    s.changeFilter(s);
    s.read();
    "Parce que le diable est dans les détails, une vision sans nuance ne peut prétendre à la compréhension du monde."

    Mon ancienne page perso : https://neckara.developpez.com/

  6. #26
    Expert éminent sénior

    Avatar de Neckara
    Homme Profil pro
    Doctorant sécurité informatique — Diplômé master Droit/Économie/Gestion
    Inscrit en
    décembre 2011
    Messages
    8 575
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 26
    Localisation : France, Loire (Rhône Alpes)

    Informations professionnelles :
    Activité : Doctorant sécurité informatique — Diplômé master Droit/Économie/Gestion
    Secteur : Enseignement

    Informations forums :
    Inscription : décembre 2011
    Messages : 8 575
    Points : 21 475
    Points
    21 475
    Par défaut
    Pour le cas :

    A interface ayant une méthode foo() et plusieurs implémentations de A existent déjà dans un code qui n'est pas le mien.

    Je veux exécuter une action avant/après l'appel de foo() (ex. incrémentation d'un compteur), pour par exemple compter le nombre d'appels à foo() dans une méthode calc, prenant un A.
    ie étendre le comportement de foo() des implémentations de A.
    En effet, ici la seule solution est d'utiliser un décorateurs vu qu'on ne peut pas modifier A, ses implémentations et calc().

    Par contre, l'objectif premier, ici, n'est pas de pouvoir chaîner les décorateurs, même si cela reste possible.
    On ne créé pas le décorateur dans le but de pouvoir les chaîner, mais dans le but d'étendre le comportement, le chaînage est donc plus un "effet de bord" dans ce cas là.

    On peut donc dire que c'est un demi-décorateur (oui je suis d'extrême mauvaise foi ).


    Par contre, je me demande s'il y a un autre cas de figure où on créerait le décorateur dans l'objectif d'étendre le comportement et de pouvoir le "chaîner" sans qu'une autre solution à base de DP plus "appropriée" existe.
    "Parce que le diable est dans les détails, une vision sans nuance ne peut prétendre à la compréhension du monde."

    Mon ancienne page perso : https://neckara.developpez.com/

  7. #27
    Membre expérimenté Avatar de yann2
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    mai 2004
    Messages
    896
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France, Hauts de Seine (Île de France)

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

    Informations forums :
    Inscription : mai 2004
    Messages : 896
    Points : 1 600
    Points
    1 600
    Par défaut
    Rebonjour

    Citation Envoyé par Neckara Voir le message
    Pour être un décorateur, UneClasse ne devrait-il pas hériter d'une même interface que ton "décorateur" ?
    Je pense que je commence à comprendre pour ce cas de figure, je continue à réfléchir.
    Pas nécessairement, cela reste un décorateur. Quand on ne contrôle pas l'API en question et si il n'y a pas d'interface on peut directement étendre la classe à décorer. C'est plus joli avec une interface mais bon...


    Citation Envoyé par Neckara Voir le message
    On peut, mais est-ce que cela a vraiment du sens ?
    Cela n'en n'aurait pas si je redéfini encore op1 sans appeler le comportement par défaut, c'est sûr.


    Citation Envoyé par Neckara Voir le message
    Sauf qu'un DP décorateur me semble inapproprié dans ce cas là :
    Le restriction sera dépendante de l'ordre dans lequel on aura "empilé" les décorateurs et on ne pourra pas restreindre l'accès à certains logs (écrire dans un fichier) mais pas à un autre (envoyer un e-mail).
    Cette problématique d'accès ne serait-elle pas plutôt de la responsabilité d'un "observateur" (ex. celui qui écris dans un E-mail) qui peut éventuellement la déléguer à une autre classe.
    Oui, dans l'exemple de la vérification des droits, ça va dépendre de l'ordre. Il faut le savoir

Discussions similaires

  1. Réponses: 3
    Dernier message: 11/10/2011, 10h17
  2. premier pas... un peu bizarre
    Par gaia-harastra dans le forum PostgreSQL
    Réponses: 4
    Dernier message: 10/01/2006, 10h00

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