J'essaie de bien comprendre comment implémenter un bon découplage entre une interface utilisateur et le modèle, mais je ne parviens pas à déterminer exactement où diviser les lignes.
J'ai examiné Model-View-Presenter, mais je ne sais pas exactement comment procéder pour le mettre en œuvre. Par exemple, ma vue comporte plusieurs boîtes de dialogue.
- Devrait-il y avoir une classe View avec des instances de chacun des dialogues? Dans ce cas, comment les dialogues devraient-ils interagir avec le présentateur? c'est à dire. Si un dialogue individuel doit demander des données au modèle via le présentateur, comment le dialogue doit-il obtenir une référence au présentateur? Via une référence à la vue donnée lors de la construction?
- Je pensais que peut-être la vue devrait être une classe statique? Ensuite, les dialogues GetView et obtenir le présentateur à partir de là ...
- J'avais pensé à configurer le présentateur avec la propriété de la vue et du modèle (par opposition à la vue ayant le présentateur et le présentateur ayant le modèle) et le présentateur enregistrant des rappels pour les événements dans la vue, mais cela semble beaucoup plus couplé (ou langue dépendante, au moins.)
J'essaye de:
- faire ceci aussi découplé que possible
- idéalement, il est possible de coupler le présentateur / modèle avec des vues d'autres langues (je n'ai pas fait beaucoup de choses inter-langues, mais je sais que c'est possible, en particulier si
void(void)
je peux en tenir plus, au moins une application C # avec un Bibliothèque C ++ ... - garder le code propre et simple
Alors .. des suggestions sur la façon dont les interactions devraient être gérées?
design-patterns
ui
interfaces
trycatch
la source
la source
Réponses:
Bienvenue sur une pente glissante. À ce stade, vous avez compris qu’il existait une variation infinie de toutes les interactions modèle-vue. MVC, MVP (Taligent, Dolphin, Passive View), MVVM, pour n'en nommer que quelques-uns.
Le modèle Présentateur de vue modèle, comme la plupart des modèles architecturaux, est ouvert à beaucoup de variété et d'expérimentation. Toutes les variations ont en commun le rôle du présentateur en tant qu '"intermédiaire" entre la vue et le modèle. Les deux plus courantes sont la vue passive et le présentateur / contrôleur superviseur - [ Fowler ]. La vue passive considère l'interface utilisateur comme une interface très peu profonde entre l'utilisateur et le présentateur. Il contient très peu de logique, voire aucune, déléguant autant de responsabilités à un présentateur. Superviseur Présentateur / Contrôleurtente de tirer parti de la liaison de données intégrée à de nombreux cadres d’interface utilisateur. L'interface utilisateur gère la synchronisation des données, mais l'animateur / contrôleur intervient pour une logique plus complexe. Dans les deux cas, le modèle, la vue et le présentateur forment une triade
Il y a plusieurs façons de le faire. Il est très courant de voir cela traité en traitant chaque boîte de dialogue / formulaire comme une vue différente. Plusieurs fois, il existe une relation 1: 1 entre les points de vue et les présentateurs. Ce n'est pas une règle difficile et rapide. Il est assez courant qu'un seul présentateur gère plusieurs vues associées, ou inversement. Tout dépend de la complexité de la vue et de la complexité de la logique métier.
Quant à la façon dont les vues et les présentateurs obtiennent une référence les uns aux autres, on parle parfois de câblage . Vous avez trois choix:
La vue contient une référence au présentateur
Un formulaire ou une boîte de dialogue implémente une vue. Le formulaire comporte des gestionnaires d'événements qui se connectent à un présentateur à l'aide d'appels de fonction directs:
Comme le présentateur n'a pas de référence à la vue, celle-ci doit lui envoyer des données en tant qu'arguments. Le présentateur peut communiquer avec la vue à l'aide des fonctions d'événements / de rappel que la vue doit écouter.
Presenter contient une référence à afficher
Dans le scénario, la vue expose les propriétés des données affichées à l'utilisateur. Le présentateur écoute les événements et manipule les propriétés de la vue:
Les deux font référence les uns aux autres, formant une dépendance circulaire.
Ce scénario est en réalité plus facile à travailler que les autres. La vue répond aux événements en appelant des méthodes dans le présentateur. Le présentateur lit / modifie les données de la vue via les propriétés exposées.
Il y a d'autres problèmes à prendre en compte avec les modèles MVP. Ordre de création, durée de vie de l'objet, lieu de câblage, communication entre les triades MVP, mais cette réponse a déjà suffisamment évolué.
la source
Comme tout le monde l’a dit, il existe des dizaines d’opinions et aucune d’entre elles n’est bonne ou mauvaise. Sans entrer dans la myriade de modèles et se concentrer uniquement sur MVP, voici quelques suggestions sur la mise en œuvre.
Gardez-les séparés. La vue doit implémenter une interface qui forme le lien entre la vue et le présentateur. La vue crée un présentateur et s’injecte dans le présentateur et expose les méthodes qu’il offre pour que le présentateur puisse interagir avec la vue. La vue est responsable de l’implémentation de ces méthodes ou propriétés à sa guise. En général, vous avez un seul point de vue: un présentateur, mais dans certains cas, vous pouvez en avoir plusieurs: un seul (Web, wpf, etc.). La clé ici est que le présentateur ne sait rien des implémentations de l'interface utilisateur et n'interagit avec la vue que via l'interface.
Voici un exemple. Nous avons d'abord une classe de vue avec une méthode simple pour afficher un message à l'utilisateur:
Maintenant, voici le présentateur. Notez que le présentateur prend un IView dans son constructeur.
Maintenant, voici l'interface utilisateur réelle. Cela peut être une fenêtre, une boîte de dialogue, une page Web, etc. Peu importe. Notez que le constructeur de la vue créera le présentateur en s'y injectant.
Le présentateur se fiche de la façon dont la vue implémente la méthode qu’elle utilise. Pour tous les présentateurs, il s’agit peut-être d’écrire dans un fichier journal et de ne pas le montrer à l’utilisateur.
Dans tous les cas, le présentateur travaille sur le modèle à l'arrière-plan et souhaite informer l'utilisateur de ce qui se passe. Nous avons donc maintenant une méthode quelque part dans le présentateur qui appelle les vues InformUser.
C'est là que vous obtenez votre découplage. Le présentateur ne fait référence qu'à une implémentation d'IView et ne se soucie pas vraiment de la façon dont il est implémenté.
Ceci est également une mauvaise implémentation pour l'homme car vous avez une référence au présentateur dans la vue et les objets sont définis via des constructeurs. Dans une solution plus robuste, vous voudrez probablement examiner les conteneurs d'inversion de contrôle (IoC) tels que Windsor, Ninject, etc.
la source
Je pense qu'il est important de se rappeler que l'action se déroule réellement dans le contrôleur / présentateur. Le couplage dans le contrôleur est inévitable par nécessité.
Le point essentiel du contrôleur est que, si vous modifiez la vue, le modèle n’a pas à changer et inversement (si le modèle change, la vue ne doit pas non plus l'être) car le contrôleur traduit les Modèle dans la vue et à nouveau. Mais le contrôleur changera lorsque les modifications de modèle ou de vue le seront, car vous devrez effectivement traduire dans le contrôleur la manière dont le modèle est visualisé pour que les modifications apportées à la vue reviennent dans le mode.
Le meilleur exemple que je puisse donner est que, lorsque j'écris une application MVC, je peux non seulement avoir des données dans la vue GUI, mais aussi écrire une routine qui insère les données extraites du modèle dans un
string
débogage. (et par extension dans un fichier texte brut). Si je peux prendre les données de modèle et les traduire librement en texte sans changer la vue ou le modèle et uniquement le contrôleur, alors je suis sur le bon chemin.Cela étant dit, vous devrez avoir des références entre les différents composants pour que tout fonctionne. Le contrôleur doit connaître la vue pour transmettre des données, la vue doit savoir que le contrôleur lui indique lorsqu'un changement a été effectué (par exemple, lorsque l'utilisateur clique sur "Enregistrer" ou sur "Nouveau ..."). Le contrôleur doit connaître le modèle pour extraire les données, mais je dirais que le modèle ne devrait rien savoir d’autre.
Mise en garde: Je viens d'un milieu totalement Mac, Objective-C, Cocoa qui vous propulse vraiment dans le paradigme du MVC, que vous le vouliez ou non.
la source
En général, vous souhaitez que votre modèle encapsule toutes les interactions avec ce modèle. Par exemple, vos actions CRUD (Créer, Lire, Mettre à jour, Supprimer) font toutes partie du modèle. Il en va de même pour les calculs spéciaux. Il y a deux bonnes raisons à cela:
Dans votre contrôleur (application MVC), vous ne collectez que les modèles à utiliser dans votre vue et appelez les fonctions appropriées du modèle. Toute modification de l'état du modèle se produit dans cette couche.
Votre vue affiche simplement les modèles que vous avez préparés. Essentiellement, la vue ne lit que le modèle et ajuste sa sortie en conséquence.
Mapper le principe général aux classes réelles
Rappelez-vous que vos dialogues sont des vues. Si vous avez déjà une classe de dialogue, il n'y a aucune raison de créer une autre classe "View". La couche Presenter lie essentiellement le modèle aux contrôles de la vue. La logique applicative et toutes les données importantes sont stockées dans le modèle.
la source