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

  1. #1
    Membre du Club
    Interprétation idéale de l'architecture MVC
    Bonjour,

    J'essaye de depuis quelques temps de comprendre le principe du MVC.
    J'ai donc suivi des tutoriaux sur le net et me suis documenté.

    Ce message s'adresse donc aux personnes ayant lu le livre "Swing" de la collection "les cahiers du programmeur" publié chez eyrolles.

    p167 est présenté un diagramme de classe MVC dit idéal puis p175 un diagramme de classes simplifié.

    Quel aurait été le diagramme de classe MVC idéal avec les classes HomeController, FurnitureController, et CatalogController (p175)?

    Par ailleurs, il me semble avoir compris que les MVC permettait de rendre les couches indépendantes et j'ai du mal saisir pourquoi c'est au contrôleur d'instancier la vue, pouvez vous m'expliquer ?. (J'aurais plutôt la vue être instanciée ailleurs et passée au contrôleur ensuite)

    Ensuite, si je désirais rajouter une base de données. Les interrogations à cette dernière interviendraient dans quelle entité du MVC ? (Je ferais ça dans le modèle mais je vois bien aussi le contrôleur le faire et ensuite le passer au modèle qui ne serait finalement plus qu'un cache)

    Merci d'avance pour vos réponses.

  2. #2
    Rédacteur/Modérateur

    Je ne peux pas trop parler du livre (pas lu) mais de ce qui est implemente en standard dans l'API par Sun :

    le petit probleme dans le MVC c'est que souvent (dans la plupart des implementations) le controlleur est en fait fortement dependant de l'aspect physique de la vue puisque c'est entre autre la vue qui sait quelles sont les zones qui peuvent ou non reagir a la souris.
    Ensuite de maniere plus gobale il ne faut pas se leurrer : il serait utopique de croire qu'on peut mettre m'importe quel type de controleur sur n'importe quelle vue et que tout se mette a fonctionner correctement comme par magie.

    Typiquement un controleur pour bouton ne fonctionnera que sur une vue pour bouton.

    Swing n'est pas vraiment MVC en fait mais plutot M et VC : la plupart des composants simples/unitaires disposent d'un modele (M) et d'une UIdelegate (VC, l'UIdelegate est a la fois une vue et un controleur). On a plutot une dependance :

    composant -> M
    composant -> VC


    En JavaFX c'est encore different : un Control (l'equivalent du composant) dispose d'une Skin (V) qui elle-meme a un Behavior (C). De part la nature meme du language il n'y a pas trop de classe dediee au modele bien que rien n'empeche d'en creer une et que par certains cotes on peut considerer que le controle lui-meme est un modele.
    Dans les implementation actuelles c'est le controle reference la skin et la skin qui reference le behavior en gros on a une dependance plutot dans le style :

    controle->V->C
    Merci de penser au tag quand une réponse a été apportée à votre question. Aucune réponse ne sera donnée à des messages privés portant sur des questions d'ordre technique. Les forums sont là pour que vous y postiez publiquement vos problèmes.

    suivez mon blog sur Développez.

    Programming today is a race between software engineers striving to build bigger and better idiot-proof programs, and the universe trying to produce bigger and better idiots. So far, the universe is winning. ~ Rich Cook

  3. #3
    Membre du Club
    Merci pour ta réponse mais ma question ne portait pas sur la façon dont le M-VC est implémenté dans Swing.

    Si sur un petit exemple avec un modèle (une liste de beans par exemple), il me semble être capable d'implémenter un MVC, je peine à voir son fonctionnement dans une application dans laquelle des objets graphiques "seraient construits" à partir de vues, ou même dans le cas où des Vues en utiliseraient d'autres pour "se construire".

    Un exemple, imaginons une application (Swing comme par hasard) avec un menu d'administration qui doit permettre d'accéder aux tables d'une base de données et de les gérer. Les modèles sont donc des Listes de beans que l'on contrôle.

    Pour un "modèle liste", je considère que la vue est composée
    - du tableau qui permet de voir l'état de la table, accompagnée de boutons d'ajouts et de modification (pour fixer les idées, mettons le tout dans un "panneau").
    - de la fenêtre qui s'ouvre lorsque l'on appuie sur ajouter ou modifier une ligne (pré-remplie si on appuie sur modifier).

    Lorsque j'appuie sur ajouter, le contrôleur se charge de rendre visible la fenêtre d'ajout. Je saisis des informations dans cette vue. Après un appuie sur "valider" dans la fenêtre de création, le contrôleur demande au "modèle liste" de changer, ce dernier change et notifie la vue, et cette dernière se met à jour.

    Maintenant si dans la fenêtre d'ajout j'ai à gérer des listes (des nouveaux modèles) qui remplissent une combo box. J'ai donc un contrôleur pour cette liste et la vue associée à ce modèle est une combo box, qui pourra être consultée et utilisée par le "modèle liste" ou éventuellement remplie à l'aide d'un bouton d'ajout à côté.


    J'ai donc besoin de la vue combo box pour construire la vue d'un "modèle Liste". Ce faisant j'ai deux contrôleurs à déclarer

    Voici mes questions :

    Est ce que le premier contrôleur doit instancier le second contrôleur (celui de la combo box) puis utiliser une méthode de type getVue() pour passer la "vue combox box" à la "vue Liste". Si tel est le cas il est impossible pour le contrôleur Liste (qui aurait été chargé de faire un new VueListe(modeleListe)) de faire le new VueListe(modeleListe) sans avoir à instancier un "controleur combo box", et l'on doit rajouter des méthodes pour transmettre des composant à la vue Liste.

    Vous voyez mon problème ? la stratégie proposée parait-t-elle viable ? Existe-t-il une solution ?

  4. #4
    Membre régulier
    C'est vrai que je trouve dommage d'avoir un getVue() sur un controleur.

    Je pense que le mieux c'est de pouvoir instancier une vue sans préciser son controleur, c'est à dire que la vue doit-être faiblement couplée sur le controleur.

    Pour se faire, mes vues n'appellent jamais le controleur directement après un évt utilisateur (ie click sur un bouton de validation par ex). Au lieu de cela, je déclare une interface listener pour ma vue qui déclare ce type d'évt et c'est le controleur qui s'y abonne et implémente ces traitement via un addListener() sur la vue. Contrairement à Swing ce sont des évts orientés métier (par ex un evt validerEditionPersonne associé au click sur le bouton Ok).

    Dans ton cas, tu pourrais donc instancier ta vue directement avec son modèle puis tu prends le controleur que tu souhaites et il s'abonne sur cette vue.

  5. #5
    Membre du Club
    Justement je trouve aussi dommage d'avoir à faire un getVue(), mais dans le livre que je cite, il passe d'un mvc dit "idéal" à un mvc "simplifié", mais dans les deux cas ils disposent de méthodes getView() ou getVue(). Ces méthodes renvoient dans le premier cas un élèment de type "IView" i.e un interface View disposant d'une méthode display(). Et dans le second cas, un JComponent. Par ailleurs, les contrôleurs sont imbriqués, i.e c'est à dire que des contrôleurs "plus généraux" en instancie d'autres et disposent de méthodes "getController()".

    D'après le livre ces types sont assez généraux pour ne pas perdre l'intérêt du MVC. Je rappelle que de la façon dont il fonctionne, chaque contrôleur instancie la vue. La vue ne connaît le contrôleur qu'au travers d'une interface ce qui évite d'avoir à déclarer les contrôleurs comme des écouteurss de vues, ce qui peut se comprendre car une vue est associée à un contrôleur contrairement dans le cas du modèle qui peut prévenir plusieurs écouteurs de ces changements.

    Je voudrais juste mettre l'accent sur le fait qu'il ne faut pas confondre le mvc2 ou le contrôleur est central et le mvc classique dans lequel la vue à par exemple accès en lecture au modèle.

  6. #6
    Membre régulier
    Je suis d'accord avec ce que tu dis. Ma façon de faire est inspirée de Swing et revient finalement au même que de créer une interface controleur.

    Cependant c'est cette histoire de getView() est gênante car comme le controleur instancie la vue, il est fortement couplé à une implémentation de sa vue et donc il n'est pas possible de le faire travailler avec une autre implémentation.

  7. #7
    Membre du Club
    PanicKernel: Donc si tu as des composants graphiques ou des vues construits à partir d'autres vues comment tu t'y prends ?

  8. #8
    Rédacteur

    Dans le cas où ton getView() renvoit une interface IView, tu as bien un découplage non ?

    Certes, le contrôleur dit bien qu'il a besoin d'une IView et d'une méthode display() (et en ce sens, il y a un couplage ! comment pourrais il en être autrement ?)
    Ensuite, le fait d'utiliser une interface permet d'avoir différentes implémentations de la vue.
    Il faut que l'instanciation de la vue soit déléguée à une fabrique ou faire de l'injection de dépendance.

    Tout le monde savait que c'était impossible. Il est venu un imbécile qui ne le savait pas et qui l'a fait. Marcel PAGNOL
    On ne savait pas que c'était impossible, alors on l'a fait. John Fitzgerald KENNEDY.
    L'inexpérience est ce qui permet à la jeunesse d'accomplir ce que la vieillesse sait impossible. Paul (Tristant) BERNARD
    La meilleure façon de prédire l'avenir, c'est de l'inventer.

  9. #9
    Membre régulier
    Dans les cas que j'ai rencontré, il fallait afficher un arbre de sélection à gauche et une vue à droite de détail sur le noeud sélectionné.

    Ce que je fais c'est que mon arbre et mon formulaire (vues métiers) sont à l'intérieure d'une vue composite technique qui ne génère aucun d'évt vers un controleur, ni ne connait de modèle. Elle se fait injecter les deux sous-vues "métiers" par constructeur (ou setter, au choix) depuis le controleur. Seules les deux vues métiers vont travailler avec un modèle et un controleur (via les évts qu'elles génèrent comme j'en ai parlé tout à l'heure).

    C'est clair ?

  10. #10
    Membre régulier
    Citation Envoyé par benwit Voir le message
    Dans le cas où ton getView() renvoit une interface IView, tu as bien un découplage non ?

    Certes, le contrôleur dit bien qu'il a besoin d'une IView et d'une méthode display() (et en ce sens, il y a un couplage ! comment pourrais il en être autrement ?)
    Ensuite, le fait d'utiliser une interface permet d'avoir différentes implémentations de la vue.
    Il faut que l'instanciation de la vue soit déléguée à une fabrique ou faire de l'injection de dépendance.
    En fait, je fais de l'injection via un addListener(), le listener étant le controleur.

  11. #11
    Membre du Club
    Donc si je vous suis bien l'imbrication de contrôleurs et l'utilisation de méthodes getIView() ne rompt pas le principe du MVC.

    Donc la stratégie suivante : un contrôleur plus global qui en instancierait d'autres (ces derniers feraient un "new IView()")) et utiliserait leur méthode getIView() pour construire sa vue (getController1().getIView() et getController2.getIView()) parait correcte ?

    S'il me semble comprendre qu'il faut déclarer une interface IControleurModel pour chaque vue d'un modèle (afin d'encapsuler les méthodes de changements du modèle) faut-t-il alors une seule classe IView implémentée par toute les Vues ou une "interface IViewModel" pour chaque modèle et implémentée par une classe concrète "ViewModel" ?

    Une autre question, est-t-il possible (dans la logique mvc car tout est possible ), d'avoir un contrôleur associé à une vue sans modèle (je pense que non)? Pourquoi car je pense à un contrôleur de l'application qui instancierait d'autres contrôleusr.

    Concrètement, dans l'exemple que je cite plus haut avec "la vue Liste"
    et la vue "Combo Box". Le "contrôleur Liste" instancierait le "contrôleur Combo Box" et par un "getControllerComboBox().getView()" le "contrôleur Liste" "construirait" sa vue.

  12. #12
    Membre régulier
    Donc si je vous suis bien l'imbrication de contrôleurs et l'utilisation de méthodes getIView() ne rompt pas le principe du MVC.
    Pas que je sache, l'imbrication de controleurs est nécessaire car on se retrouve souvent avec des hiérarchies de controleurs et de modèles.

    Donc la stratégie suivante : un contrôleur plus global qui en instancierait d'autres (ces derniers feraient un "new IView()")) et utiliserait leur méthode getIView() pour construire sa vue (getController1().getIView() et getController2.getIView()) parait correcte ?
    Pourquoi pas.

    S'il me semble comprendre qu'il faut déclarer une interface IControleurModel pour chaque vue d'un modèle (afin d'encapsuler les méthodes de changements du modèle) faut-t-il alors une seule classe IView implémentée par toute les Vues ou une "interface IViewModel" pour chaque modèle et implémentée par une classe concrète "ViewModel" ?
    Je n'ai pas lu le livre alors j'ai du mal à comprendre, mais il est possible de déclarer un super type IView pour abstraire les vues mais créer pour chaque vue une sous-interface de IView spécifique à ta vue. Après pour les interfaces d'accès en lecture ou écriture sur le modèle, fais comme tu veux mais le risque c'est de perdre du temps à suivre à la lettre les principes MVC sans réelle plus-value derrière.

    Une autre question, est-t-il possible (dans la logique mvc car tout est possible ), d'avoir un contrôleur associé à une vue sans modèle (je pense que non)? Pourquoi car je pense à un contrôleur de l'application qui instancierait d'autres contrôleusr.
    Une vue sans modèle ne peut rien afficher si elle ne représente rien. Un controleur sans modèle ça me semble bizzare, ce serait plus une classe d'initialisation de ta couche présentation mais pas un controleur à proprement parler.

    Concrètement, dans l'exemple que je cite plus haut avec "la vue Liste"
    et la vue "Combo Box". Le "contrôleur Liste" instancierait le "contrôleur Combo Box" et par un "getControllerComboBox().getView()" le "contrôleur Liste" "construirait" sa vue.
    Pourquoi pas, en effet.

  13. #13
    Membre habitué
    MVC + Delegate
    Je vais essayer d'apporter une petite part de réflexion.
    Je pense que le MVC devient puissant et intéressant lorsqu'on l'utilise avec le design pattern Delegate.

    La logique est de dire qu'une vue ne s'occupe que de son affichage sans jamais faire appel à un objet connu comme "contrôleur". La vue a par contre un objet "délégué" vers lequel elle envoit des messages à certains évènements (définition d'une interface si on n'est pas dans un langage dynamique).
    Le delegate de la vue serait le controlleur qui devrait implémenter les messages que la vue lui enverra.
    L'avantage est que le delegate peut réagir aux évènements de la vue sans savoir que cela vient d'une vue. Toutes les informations dont il a besoin pour la réponse sont passées dans les paramètres du message envoyé.

  14. #14
    Membre régulier
    Csperandio, je crois qu'on est d'accord

  15. #15
    Membre habitué
    Citation Envoyé par PanicKernel Voir le message
    Csperandio, je crois qu'on est d'accord


    Je trouve par contre que l'intégration du design pattern Delegate est quelque fois un peu lourd en Java (et tout langage assez stricte dans la déclaration des types).
    Je pense que c'est plus agréable et moins verbeux avec des langages comme ObjC, Ruby, Groovy, Python & Co.

    Quelques fois, on veut utiliser un objet delegate et on sait qu'un seul message lui sera envoyé. En Java, on est obligé de lui ajouter toutes les méthodes dépendantes de l'interface :/ C'est sans doute plus "propre" mais plus lourd. C'est mon avis.

  16. #16
    Membre régulier
    Citation Envoyé par csperandio Voir le message

    Quelques fois, on veut utiliser un objet delegate et on sait qu'un seul message lui sera envoyé. En Java, on est obligé de lui ajouter toutes les méthodes dépendantes de l'interface :/ C'est sans doute plus "propre" mais plus lourd.
    En java, on utilise communément des classes adapter qui implémentent un interface avec du code vide, comme cela il suffit d'hériter de l'adapter et de redéfinir les methodes liées aux evts effectivement traités. En plus avec les classes anonymes, c'est concis d'implémenter une gestion d'évt.

  17. #17
    Membre habitué
    Citation Envoyé par PanicKernel Voir le message
    En java, on utilise communément des classes adapter qui implémentent un interface avec du code vide, comme cela il suffit d'hériter de l'adapter et de redéfinir les methodes liées aux evts effectivement traités. En plus avec les classes anonymes, c'est concis d'implémenter une gestion d'évt.
    Merci pour cette information
    Mais, il ne peut pas avoir de souci par le manque d'héritage multiple ?

    Ma question est purement théorique

  18. #18
    Membre du Club
    Effectivement, on ne peut hériter que d'une seule classe en java (et c'est déjà bien suffisant). Donc, soit on sait que notre classe n'aura pas besoin de dériver d'une autre que l'adapter et on utilise ce dernier, soit on doit faire avec les toutes les méthodes qui composent (ce que je ne trouve pas si contraignant)

    Puisque j'y suis, j'ai ouvert une discussion sur les bonnes pratiques concernant le mappage d'une base de données et je vous invite à y participer : http://www.developpez.net/forums/d80...-schema-objet/

  19. #19
    Expert confirmé
    De la mauvaise utilisation du terme MVC pour le dev Web
    L'interprétation idéale de l'architecture MVC, c'est de ne pas parler de développement Web ! Si il y a bien un terme qui a été vidé de sa substance, c'est bien celui là, avec l'arrivée du développement Web.

    Pour rappel, le pattern MVC est issu du monde SmallTalk et repose fondamentalement sur une orientation objet. Ensuite, c'est un pattern, et en tant que tel, il offre une solution à un problème : celui d'assurer une corrélation/interaction entre les données d'une part, et les vues sur ces données d'autre part. Une communication par événements fait souvent office de glue pour tout cela.

    Les tutoriels fleurissent de toutes parts sur les frameworks MVC en PHP, en JAVA, en Ruby, etc. Leurs auteurs ne s'étonnent même pas de l'architecture MVC qu'il nous présentent fièrement. Ci-dessous un exemple qui nous est proche :
    http://c-maneu.developpez.com/tutori...intro/#LII-B-2
    Pourtant, on y voit clairement qu'un modèle peut notifier la vue de ses changements. En effet, il semble pertinent que la mise à jour des données implique de rafraîchir toutes les vues sur lesdites données. Or, il est totalement impossible de porter ce principe au développement Web ! En outre, la difficulté des auteurs à définir ce que contient précisément un contrôleur (en général un fourre-tout) aurait du leur mettre la puce à l'oreille sur cette terrible méprise.

    Du coup, de quoi parlent tous ces tutoriaux ? Et bien tout simplement d'un meilleur découpage de l'application pour faciliter l'évolutivité et la maintenance du code. A ce titre, ces frameworks ont du mérite. Mais de grâce, arrêtons de parler de MVC là ou il n'y en a pas, cela évitera aux novices bien des écueils.
    Il vaut mieux mobiliser son intelligence sur des conneries que mobiliser sa connerie sur des choses intelligentes --- devise SHADOKS

    Kit de survie Android : mon guide pour apprendre à programmer sur Android, mon tutoriel sur les web services et enfin l'outil en ligne pour vous faire gagner du temps - N'oubliez pas de consulter la FAQ Android

  20. #20
    Rédacteur

    @Hephaistos007, dans l'ensemble, ce que tu dis est juste.

    Néanmoins, j'aimerai apporter trois bémols.

    Citation Envoyé par Hephaistos007 Voir le message
    Or, il est totalement impossible de porter ce principe au développement Web !
    Ceci n'est pas vraiment exacte car avec du push serveur (comet, ...) il est possible de faire de la notification d'évènement du serveur vers le client.
    Je t'accorde cependant que c'est encore rare.

    Citation Envoyé par Hephaistos007 Voir le message
    arrêtons de parler de MVC là ou il n'y en a pas, cela évitera aux novices bien des écueils.
    Pour un puriste, je t'accorde que c'est énervant. Maintenant, on peut présenter des adaptations de MVC (sans une application à la lettre). Par exemple, je trouve des points communs (sans y ressembler toutefois) avec l'architecture en couche (M~Accès aux données et traitement métier, V~Présentation de ces données et C~Action de contrôle) car ils ont en commun un même intérêt, celui de présenter la séparation des responsabilités.

    Et pour finir, 3° point, si le MVC est difficilement applicable au client/serveur (sans communication bidirectionnelle), il peut exister à différents niveaux.
    Exemple, avec GWT, techno client centric, tu peux faire du vrai MVC uniquement côté client (même si pour ma part, j'y trouve quelques inconvénients)

    Tout le monde savait que c'était impossible. Il est venu un imbécile qui ne le savait pas et qui l'a fait. Marcel PAGNOL
    On ne savait pas que c'était impossible, alors on l'a fait. John Fitzgerald KENNEDY.
    L'inexpérience est ce qui permet à la jeunesse d'accomplir ce que la vieillesse sait impossible. Paul (Tristant) BERNARD
    La meilleure façon de prédire l'avenir, c'est de l'inventer.

###raw>template_hook.ano_emploi###