Question

Je m'amuse à essayer de comprendre un peu le principe de MVP, en ce qui concerne les contrôles de l'utilisateur. J'utilise .NET WinForms (ou quelque chose de proche) et le motif Contrôleur de supervision (enfin, je pense que je le suis :).

Le contrôle utilisateur fait lui-même partie d'une application MVP (c'est la vue et est associé à un présentateur, etc.). Le présentateur est toujours démarré en premier, puis les modèles, puis les vues. La vue construit son interface utilisateur, dont une partie consiste à NEW la UC, qui est la vue.

Maintenant, le présentateur (de forme) doit connaître le présentateur d'UC, mais je pense qu'il ne sait rien de la composition de la vue. Le présentateur de formulaire, par exemple, ne sait pas que le UC fait partie de la collection Controls du formulaire, et ne le devrait pas non plus.

En outre, l’expérience en matière de conception ne doit pas être modifiée; IOW le dev de la Vue (formulaire) devrait juste pouvoir sélectionner un contrôle utilisateur dans la boîte à outils et le déposer sur un formulaire.

Alors, passons à mes questions. Premièrement, mes hypothèses ci-dessus sont-elles correctes? Quelque peu égaré? Foiré? WTF pensez-vous?

Deuxièmement, est-il juste (suffisant?) que le formulaire View invoque la vue UC, et que le formulaire Presenter invoque le présentateur UC et dispose d'un mécanisme permettant d'indiquer à la vue UC ce qu'est son présentateur? Cela rompt mon " Présentateur en premier " règle, mais je ne sais pas comment faire autrement.

Toute autre pensée, suggestion ou commentaire accepté avec plaisir.

- nwahmaet

Était-ce utile?

La solution

Un présentateur doit être considéré comme un "État autonome". dans le niveau de présentation. Cela signifie qu'il est responsable de la synchronisation de la présentation de l'état du modèle dans la vue. La raison pour laquelle je soulève cette question est parce que le "motif" MVP se perd souvent dans la vision dogmatique de la séparation . Il semble que ce soit l'une des raisons pour lesquelles Martin Fowler a décidé d'essayer de clarifier la terminologie entourant le modèle MVP .

Ma version préférée de MVP est la vue passive . Ma réponse est donc basée sur celle-ci. .

J'implémente très souvent les contrôles utilisateur et les formulaires composites à l'aide du modèle de vue passive. Il existe essentiellement 3 configurations différentes:

  1. Un présentateur pour tous les contrôles utilisateur de la hiérarchie. Aplatir la vue à l’aide d’une interface.
  2. Un présentateur pour chaque contrôle utilisateur de l’arbre composite. Chaque parent présentateur est responsable de l’instanciation et de l’initialisation de ses enfants présentateurs. Les contrôles utilisateur sont créés au moment de la conception et peuvent fonctionner sans présentateur (sans comportement de présentation)
  3. Un présentateur pour chaque contrôle utilisateur de l’arbre composite. Tous les présentateurs sont faiblement couplés via une classe de contrôleur de niveau supérieur. La classe de contrôleurs est responsable de la construction du présentateur, de son câblage et de la coordination de ses événements.

Bien que ce soit une solution de dernier recours pour moi (en raison de sa complexité), je pense que la dernière option est la solution que vous recherchez.

Autres conseils

Je rencontre ce problème depuis plusieurs mois dans une application sur laquelle je travaille. La conclusion à laquelle je suis très récemment arrivé est que, dans de nombreux cas, il pourrait être impossible d'appliquer le modèle MVP aux niveaux de contrôle de fenêtre ET utilisateur, sans "casser" le motif.

Je pensais que le contrôle de l'utilisateur faisait partie de l'implémentation de la vue et que le présentateur ne devrait pas savoir ce qui se passait dans l'implémentation de la vue, ce qui signifie que le présentateur au niveau de la fenêtre, par extension, ne devrait pas connaître l'utilisateur. le présentateur du contrôle, et par conséquent, il ne devrait y avoir aucune communication entre eux, y compris l'instanciation du dernier par le premier. On pourrait faire valoir que le présentateur du contrôle utilisateur fait partie de l'implémentation de la vue fenêtre et que, par conséquent, la vue fenêtre peut instancier le présentateur du contrôle utilisateur. Mais il ne peut pas injecter les classes de modèle dont le présentateur a besoin, car la vue n’est pas censée en avoir connaissance.

La conclusion à laquelle je pense en arriver est que TOUS les contrôles utilisateur sont spécifiques à une implémentation de vue, et doivent donc être entièrement contenus dans le silo de vues du modèle plus large. En tant que tels, ils ne peuvent pas avoir leurs propres présentateurs ... Du moins, pas intégrés à l'implémentation de contrôle elle-même. Au lieu de cela, ils doivent être manipulés indirectement par le présentateur de la fenêtre parente, via des champs d'intercommunication visibles sur l'interface de vue. En bref, le contrôle utilisateur est exposé au présentateur non pas par sa propre interface, mais plutôt via une interface d'intercommunication commune implémentée par sa vue parent. Appelez cette "interface de vue partielle".

Votre présentateur peut alors contenir des instances d'une classe de sous-présentateur réutilisable qui fonctionne uniquement avec cette interface de vue partielle et les éléments pertinents du modèle. Cela vous permettra d'éviter de réécrire le code du présentateur pour le traduire à partir du modèle à chaque fois que vous utiliserez le contrôle, ET évitera à la vue fenêtre d'avoir besoin de connaître le modèle pour transmettre des informations au présentateur du contrôle.

Cela a pour effet de séparer davantage le contrôle utilisateur, en tant que module, de votre modèle de données. Cela a du sens si vous considérez un contrôle utilisateur, dans son ensemble, comme un élément de la mise en œuvre de la vue. En tant qu’unité réutilisable, il s’agit d’une fonctionnalité de visualisation, dont aucune partie ne doit être liée à votre modèle de données.

Vos questions sont générales, à savoir qu’une variété de systèmes pourrait s’appliquer.

Dans ce cas, je suppose que vous devriez regarder Observer Pattern.

Vous avez une interface que tout ce qui utilise cette vue implémenterait. Ensuite, il s’enregistrerait lorsque l’application s’initialisera avec une collection de ces interfaces. Toute commande devant mettre à jour cette vue traverserait la collection en indiquant que chaque vue devait être mise à jour.

Contrairement aux exemples typiques, les vues seraient des contrôles utilisateur. Vous avez la possibilité de faire en sorte que n'importe quel élément d'interface utilisateur implémente cette interface afin que vous puissiez utiliser des boîtes de dialogue, des formulaires complets, etc. en plus de votre contrôle utilisateur.

Enfin, rappelez-vous que le contrôle de l'utilisateur n'est PAS la vue mais l'implémentation de la vue. Quel que soit le schéma que vous adoptiez, vous pouvez définir la vue aussi profondément que vous le souhaitez et laisser le contrôle de l'utilisateur implémenter cette interface.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top