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

Design Patterns Discussion :

Pattern commande et modèle complexe


Sujet :

Design Patterns

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

    Informations forums :
    Inscription : Mars 2012
    Messages : 4
    Points : 4
    Points
    4
    Par défaut Pattern commande et modèle complexe
    Je travaille actuellement sur un éditeur d'analyses syntaxiques (des forêts d'arbres), et je l'ai doté de fonctionnalités undo/redo en utilisant le pattern commande.

    Mais j'ai du mal à trouver une architecture qui me satisfasse vraiment. Je m'explique :

    Les opérations sur le modèle sont assez complexes : supprimer un noeud entraîne par exemple une réorganisation des arcs qui constituent mon graphe.

    Bref, pour enregistrer tout ce qui doit être fait et/ou défait par la commande, en gardant l'encapsulation du modèle, la seule manière que je vois est de faire créer les commandes par le modèle. Mais d'une certaine manière, pour rester cohérent, cela supposerait que le modèle ne soit doté que de méthodes créant des commandes (et de méthodes permettant de consulter les données), et d'aucune méthode de modification directe.

    ça me semble logique, mais je ne vois nulle part d'implémentation de ce genre. Est-ce que je suis à l'ouest ?

    Bien cordialement,
    R7

  2. #2
    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 918
    Points
    2 918
    Par défaut
    Typiquement le pattern Command met en jeu 3 parties :

    • Le client qui crée l'objet commande
    • L'invoker qui l'exécute
    • Le receiver qui contient les méthodes appelées par la commande


    Dans le cas de Undo/Redo, le client va créer la commande et en général la faire exécuter tout de suite au UndoRedoManager/CommandManager (l'invoker). En effet empiler une commande dans le stack Undo/Redo signifie aussi l'exécuter : l'étape préalable avant qu'on puisse faire un Undo/Redo est qu'on ait déjà fait un Do.

    D'après ce que je comprends, tu souhaiterais que le client soit aussi le receiver, c'est à dire que l'objet qui va créer la commande et demander au manager de l'empiler soit aussi celui qui déclare les méthodes exécutées dans cette commande ?

    Je pense que tu n'as pas dû tomber souvent sur ce genre d'implémentation car dans mon expérience, une commande "undoable" ne se limite pas à un appel de méthode mais est souvent constituée d'une séquence d'appels à plusieurs méthodes de divers objets. Le client/invoker est souvent un objet coordinateur au courant du contexte d'exécution de l'application, et pas le modèle lui-même.

    cela supposerait que le modèle ne soit doté [...] d'aucune méthode de modification directe.
    Par contre quand tu dis ça, tu penses à externaliser ces méthodes ailleurs que dans le modèle ou à passer des méthodes anonymes/lambda expressions à la commande ?

    Personnellement, j'ai implémenté un UndoRedoManager (en C#) en utilisant des lambda expressions et des closures (on "close" les données sur la commande passée au UndoRedoManager afin de pouvoir opérer sur ces mêmes données plus tard lorsqu'on fera un Undo ou un Redo) et ça marche pas mal.

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

    Informations forums :
    Inscription : Mars 2012
    Messages : 4
    Points : 4
    Points
    4
    Par défaut
    En fait, j'ai actuellement :

    * le client C est dans la couche graphique (l'action associée au menu)

    * l'invoker U est la classe Swing UndoManager

    * le receiver R est la façade de mon modèle.

    Donc, dans mon architecture actuelle, le client C demande à R de créer la commande (qui est exécutée dans la foulée), puis l'ajoute à U.

    Le truc, justement, est que l'exécution de la commande, pour être correcte, doit modifier pas mal de données dans le modèle. Je ne veux pas rendre ces données accessibles individuellement, du moins en modification.

    Du coup, je dédouble plus ou moins la logique : j'utilise UndoAbleEdit d'un côté, et, dans mon modèle, j'ai des classes internes (c'est en java, donc en gros des clôtures dans des langages plus riches côté fonctionnel), qui implémentent leur propre version de Commande, et l'implantation que j'utilise d'UndoAbleEdit sert d'adaptateur.

    L'objet créé par le modèle contient la liste des liens à supprimer, des liens à ajouter, des noeuds à supprimer et des noeuds à ajouter.

    C'est un peu tordu, et, même si ça tourne (le code est déjà écrit, je me demande comment mieux l'architecturer), ça me semble fragile.

    J'ai pensé à placer UndoAbleEdit directement dans mon modèle et économiser une couche serait raisonnable - c'est un type de fonctionnalité qui n'est pas réellement spécifique aux interfaces Swing.

    Mais, le fond du problème est le suivant :

    Dans la plupart des exemples de Commande, à la création de la commande, (ou à sa première exécution) on peut sans trop de problème préparer le "undo" sans casser l'encapsulation du receiver, éventuellement avec un peu d'aide.

    Par exemple, pour une commande "suppression" dans un traitement de texte, il faut récupérer la zone de texte supprimée pour pouvoir la recoller ensuite, mais c'est assez naturel à faire, ne serait-ce que parce qu'on aura aussi besoin de ce type de fonctionnalité pour les copier/coller, etc...

    Dans mon cas, la commande de suppression dans un graphe fait plein de plomberie, et je n'ai pas envie de la placer au niveau de l'interface.

    On sent qu'on aimerait quelque chose qui ressemblerait à un mémento, mais qui n'en est pas exactement un (il se rappelle des modifications et pas un état)...

  4. #4
    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 918
    Points
    2 918
    Par défaut
    Je crois que je vois le problème même si c'est un peu obscur sans exemple et sans connaître le contexte.

    Je vois une manière de résoudre ça : le client crée une commande (supprimer un noeud par exemple) qui est en réalité composite et va passer le relais au modèle pour y attacher une chaîne de sous-commandes associées (réorganiser les arcs, etc). Le modèle connaît chaque sous-opération et sait comment faire un Undo sur chacune donc on est OK.

    Le UndoManager connait la notion de commande composite et sait que pour en annuler une il faut annuler toutes ses sous-commandes en séquence.

Discussions similaires

  1. [Batch] Commande For très complexe
    Par Laoky dans le forum Scripts/Batch
    Réponses: 0
    Dernier message: 06/11/2010, 10h46
  2. [silverlight] implementer un pattern command
    Par herrs dans le forum Silverlight
    Réponses: 4
    Dernier message: 12/08/2009, 11h52
  3. Utilisation du Designe pattern command
    Par menzlitsh dans le forum Frameworks Web
    Réponses: 1
    Dernier message: 07/02/2009, 11h19
  4. Pattern Command et boost::function
    Par poukill dans le forum C++
    Réponses: 3
    Dernier message: 24/04/2008, 16h54
  5. [Pattern Command] Lien à mettre à jour
    Par poukill dans le forum C++
    Réponses: 14
    Dernier message: 21/02/2008, 08h41

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