-
[MVC] Précisions
Salut,
J'aimerais avoir une précision sur l'implémentation correcte de la relation entre Vue et Controlleur dans l'approche MVC (Modèle-Vue-Contrôleur). La plupart des références bibliographiques que j'ai trouvé disent en gros que la vue transmet des évènements utilisateur au contrôleur qui ensuite se charge de les interpréter vis à vis du modèle.
J'aimerais savoir s'il y a une bonne pratique de conception qui précise où situer l'interface d'échange de ces évènements utilisateur.
Par exemple si j'ai un slider qui règle un volume sonore.
Je peux :
1- faire un controlleur avec une méthode setVolume(insigned int volume) et une vue qui détecte le déplacement du curseur et qui appelle controlleur.setVolume(slider.pos).
ou bien
2- faire un controlleur avec une méthode notifySliderChanged(SliderId id) et une vue qui détecte le déplacement du curseur et qui appelle controlleur.notifySliderChanged(mySliderId). Le controlleur fait alors le rapprochement (mySliderId <-> identifiant du curseur de volume), demande au slider sa nouvelle position et applique le volume.
Quelle est la bonne approche ? Y en a t-il d'autres ?
Merci pour vos conseils et réactions.
-
Salut,
De ma maigre expérience sur MVC, je dirais que l'approche la plus "orientée" MVC serait la deuxième.
A priori, la vue de doit pas avoir de notions sur ce qu'elle représente.
Dans ton exemple, la vue ne devrait pas avoir de notion de volume.
Le principe de MVC est de pouvoir changer l'une de ses trois parties (modèle, vue et controleur) de façon transparente pour les deux autres. Donc il faut toujours se demander ce qu'il se passerait si on changeait l'une des parties.
Par exemple (d'un intérêt limité a priori, je l'admet :roll:), avec ta première proposition, si un jour tu décides de ne plus gérer le volume mais la vitesse de lecture, tu devras modifier à la fois le controleur et la vue.
Le controleur puisque c'est lui qui doit gérer la logique de l'application, et la vue, puisqu'elle implémentait déjà la gestion du slider comme étant un volume et non une vitesse.
Je ne sais pas si je suis très clair, mais n'hésite pas à demander plus de détails sur les points restés obscurs.
Je rajouterais un petit détail sur ta deuxième proposition. Elle implique que le controleur interroge la vue sur l'état du slider, et je ne pense pas que ce soit son role.
Ici il serait plus simple de rajouter un paramètre :
Code:
controller.notifySliderChanged(mySliderId, cursorPosition)
J'espère avoir pu t'aider. Je te donne un lien sur lequel je me repose souvent lorsque j'ai un doute à propos de MVC, mais peut être l'as-tu déjà parcouru lors de tes recherches (en anglais):
http://java.sun.com/blueprints/patte...-detailed.html
-
Comme l'a dit tristan_m, ta deuxième proposition a un gros problème, elle implique que le controlleur doive aller interroger un élément graphique. Alors qu'il faudrait avoir le moins de code possible en relation avec une quelconque interface graphique. Plus tu as du code dépendant d'un framework graphique, plus tu auras de peine ensuite à changer l'interface graphique par exemple passer de Swing à SWT.
Donc la deuxième proposition est bonne, mais avec le changement que tristan_m y a ajouté. Maitenant qu'on a fait ce changement, la première proposition est presque la même que la deuxième.
-
Merci à tous les deux.
Effectivement dans la deuxième approche, le fait que le contrôleur aille chercher des infos dans la vue me perturbait quelque peu. Avec la modification proposée que la vue transmette tous les paramètres utiles au contrôlleur ainsi que l'identifiant de l'élément graphique à l'origine de l'évènement c'est effectivement moins perturbant.
Cela dit ça ne supprime pas totalement le fait que le contrôlleur doit avoir une connaissance de la représentation graphique (en effet il doit savoir quel changement associer à un changement sur SliderId...donc quelque part son implémentation dépend de la représentation graphique).
Tout mon problème c'est qu'ils doivent forcément échanger quelque chose et je ne sais pas où situer l'interface :
- soit le contrôleur impose son interface mais alors la vue a une notion de ce qu'elle représente.
- soit la vue impose son interface mais alors le contrôleur dépend de la représentation graphique.
J'aimerais avoir des arguments pour pouvoir trancher entre les deux ou bien trouver une troisième voie.
-
Le contrôleur a bien sûr une notion de la vue, c'est sûr, il faut bien qu'il connaisse la vue pour l'ouvrir, la fermer, ...
Une chose que tu peux faire pour le rendre encore moins dépendant de la vue, c'est créer une interface Vue qui contiendrait des méthodes close et open et d'autres méthodes si le contrôleur a besoin d'effectuer d'autres mises à jour sur la vue. Ensuite, il suffit que ta classe d'interface graphique implémente cette interface et le controleur n'a plus qu'à utiliser cette interface pour intéragir sur l'interface graphique. Donc en cas de changement d'interface graphique, il ne reste qu'une seule ligne à modifier dans le controleur.
En plus, il n'a pas besoin de la représentation graphique de l'interface, il ne devrait justement pas en avoir pour être encore plus indépendant. Si tu utiliser un sliderId, ca doit correspondre à quelque chose dans le controlleur mais tu n'as pas besoin de savoir à quoi ca correspond du coté de la vue. Personnellement, j'utiliserais plutot la méthode setVolume, ainsi tu n'as de problème à associer quelque chose et en plus, c'est tout de même plus clair comme méthode.
-
Bonjour,
Effectivement il y a malgré tout une dépendance quelque part. On ne peut pas remplacer la vue d'un lecteur multimedia par celle d'un jeu vidéo par exemple. D'ou l'importance, comme le signale wichtounet, de créer des interfaces pour les vues et les controleurs.
Pour la question du lieu où gérer la dépendance vue - controleur, mon avis n'est pas vraiment tranché, mais je pense qu'il faut se pencher encore une fois sur les modifications possibles de controleurs ou de vues.
En gros, si tu as de nombreux controleurs différents (resp. vues différentes) il sera préférable de gérer la dépendance dans les controleurs (resp. dans les vues).
Je m'explique :
1)Si tu as beaucoup de controleurs, c'est que ton appli peut passer dans de multiples états différents, et donc que la réaction face aux même événements de la vue risque d'être différente (un bouton play qui passe en bouton pause par exemple). Il est alors plus adéquate de donner un identifiant au bouton, et de laisser le controleur s'occuper de son implémentation.
2)Si par contre tu as plusieurs vues différentes (mode texte, mode 2d, mode 3d par exemple), alors il vaudra peut être mieux mettre cette dépendance dans les vues et passer par des méthodes type controller.volumeChanged() etc...
NB: même si concrètement ça ne change strictement rien, le nom 'setVolume' me gène un peu puisque ce n'est pas le controleur qui modifie la valeur mais le modèle.
Après il y a encore les deux cas particuliers où :
3) il y a à la fois beaucoup de controleurs et beaucoup de vues, et
4) il y a une seule vue et un seul controleur
Dans le cas 3, il faut peut être envisager d'insérer un objet entre la vue et le controleur qui associerait un id à une méthode controleur (voir le design pattern mediateur peut etre?).
Pour le cas 4, il faut d'abord prendre en compte les évolutions possibles ou envisagées, pour voir si tu ne te retrouveras pas à l'avenir dans un des 3 cas précédents.
Sinon (MVC est il alors nécessaire?), je pencherais finalement aussi du côté des méthodes controller.volumeChanged() appelées par la vue. C'est plus simple à implémenter, puisque ne nécessitant pas de table d'association 'idBouton<->action' ou de switch massif dans le controleur. (Dans l'idée, 'volume' fait ici référence au nom du slider et non au volume 'réel' représenté dans le modèle)
En espérant t'avoir éclairé un peu.
-
1 pièce(s) jointe(s)
Si je peux me permettre une remarque: l'utilisation du M(MVC)C.
Cela consiste a séparer le MVC "graphique" (valeur 0-100% / slider / evenements) et le MVC "metier" (Player / Volume / Variation).
Pourquoi cette séparation ? Et bien parceque généralement on a peu de controle sur le fonctionnement du MVC "graphique". Généralement ce n'est meme pas un vrai MVC, mais plutot un Form/Action ( Boucle de message, gestion evenementielle, ... ).
Pièce jointe 11501