Conception appropriée du modèle-vue -_____

14

J'ai lu des informations sur Model View Controller, Model View Presenter, Model View ViewModel, et ainsi de suite, et en général, le concept sous-jacent semble assez simple à comprendre: garder les jolis visuels et les tripes scientifiques aussi séparés et ignorants les uns des autres que possible. Pas de logique de beurre d'arachide dans le chocolat design; cool, j'aime ça.

Le problème est que je suis toujours un peu flou quant à cette troisième partie ... celle qui n'est pas un modèle ou une vue. Tout le monde semble avoir sa propre idée de comment l'appeler, de ce qu'elle devrait faire, de ce qui est juste, de ce qui est tout simplement faux ... et je deviens fou en essayant de comprendre quand un présentateur devient un ViewModel et quand une vue ne devrait pas '' t faire cela parce que c'est le travail du présentateur et--

Je divague.

Plutôt que de demander à quelqu'un d'expliquer la différence entre eux - parce que cela a déjà été fait maintes et maintes fois (je sais; j'ai lu plus d'articles que je ne peux compter) - je serais curieux d'entendre les pensées d'un quelques programmeurs sur le modèle que j'ai bricolé moi-même.

Cela dit, que classeriez-vous cette conception comme, et peut-être plus important encore, voyez-vous quelque chose à ce sujet qui est évidemment nul? Bien sûr, j'aimerais entendre que je fais du bien si c'est vraiment un design solide, mais je préfère de loin recevoir des conseils solides sur les éloges.

Remarque: je vais utiliser "le pont" pour la troisième partie mystérieuse de Model-View-? pour éviter toute suggestion inconsciente de ce qu'elle "devrait" être.

Modèle

  • Est l'autorité sur les données.
  • Reçoit des informations sur les modifications demandées du pont.
  • Contient et exécute toute la logique de la relation entre les données et les autres données.
  • Informe le pont lorsque les données changent (pour les données le pont a exprimé son intérêt). Modification du libellé: permet aux abonnés externes (dont il ne sait rien) de surveiller son état ou ses résultats de calcul.
  • N'a aucune connaissance de la vue.

Vue

  • Soucie de fournir à l'utilisateur un moyen de visualiser et de manipuler les données.
  • Reçoit des informations sur les mises à jour des données du pont.
  • Contient et exécute toute la logique de présentation des données et des contrôles à l'utilisateur.
  • Informe le pont lorsque l'utilisateur a effectué une action qui (éventuellement) affecte le modèle.
  • Informe le pont des informations qui l'intéressent.
  • N'a aucune connaissance du modèle.

Pont

  • Est le coordinateur et le traducteur entre le modèle et la vue.
  • Apporte toutes les modifications de mise en forme appropriées aux informations transmises entre le modèle et la vue.
  • Conserve des informations sur "qui a besoin de savoir quoi".
  • Connaît à la fois le modèle et la vue.

Notes complémentaires

  • Dans les programmes plus compliqués, il est courant qu'il y ait plusieurs modèles. Dans cette situation, le pont assume généralement la tâche de coordination / traduction entre les multiples modèles et devient ainsi l'autorité sur laquelle les protocoles / API / modèles de conception doivent être construits. (Par exemple, si vous créez un programme de jeu de cartes et que vous souhaitez créer un autre modèle de mélange de cartes, vous devez utiliser le pont pour déterminer les fonctions requises pour une communication correcte avec le pont.)
  • Dans les petits programmes simples avec une seule vue et un seul modèle, il est courant que le Bridge "assume" les fonctionnalités disponibles de chaque côté. Cependant, à mesure que les programmes deviennent plus complexes, il est recommandé que les vues et les modèles signalent leurs fonctionnalités au pont afin d'éviter les inefficacités et les hypothèses de bogue.

Je pense que ça couvre à peu près. Par tous les moyens, je me réjouis de toutes les questions que vous pourriez avoir sur la conception que j'ai tendance à utiliser, et j'encourage également toutes les suggestions.

Et comme toujours, merci pour votre temps.

KoratDragonDen
la source
2
Le bloc Afficher a une erreur de copier-coller. Je suppose que la dernière puce devrait se lire "N'a aucune connaissance du modèle." Et la dernière phrase de la 1ère note complémentaire devrait probablement se terminer par "modèle" et non "pont" ??
Johannes S.

Réponses:

7

Votre phrase

"Est le coordinateur et le traducteur entre le modèle et la vue."

indique que votre Bridge est le présentateur dans une architecture MVP.

MVP et MVC sont très similaires, sauf que dans MVP, seul le présentateur observe le modèle tandis que dans MVC, la vue est également autorisée à observer directement le modèle (sans le présentateur comme un "pont").

La responsabilité de votre modèle

"Informe le pont lorsque les données changent (pour les données le pont a exprimé son intérêt)."

est peut-être mal formulé ou peut-être une erreur: vous ne voulez pas que le modèle soit dépendant du pont / du présentateur / du contrôleur ou de la vue. Au lieu de cela, vous utilisez un modèle Observer, des événements ou une programmation réactive pour permettre au pont de s'abonner aux modifications du modèle. Et puis vous pouvez reformuler votre responsabilité comme:

"Permet aux abonnés extérieurs (dont il ne sait rien) de surveiller son état ou ses résultats de calcul."

Si votre modèle ne dépend pas de votre contrôleur ou de votre vue, il est plus facile à tester et beaucoup plus portable.

Larry OBrien
la source
1
Si la principale différence est que la vue peut ou ne peut pas observer le modèle, la conception est définitivement plus MVP; la vue et le modèle ne sont jamais autorisés à parler directement dans la conception que j'utilise.
KoratDragonDen
La responsabilité du modèle était une mauvaise formulation, je pense. Le modèle n'a pas vraiment la moindre idée ou ne se soucie pas du qui / quoi / pourquoi des choses qui veulent l'écouter, mais publiera simplement toutes les modifications qui ont été apportées à ses abonnés. Il est parfaitement content d'exister seul sans abonnés d'aucune sorte, et ne tente pas de solliciter de nouveaux abonnés.
KoratDragonDen
1
On dirait que vous avez un bon design, alors. PS La raison de considérer MVC plutôt que MVP est que, sans discipline, le présentateur peut devenir surchargé.
Larry OBrien
1
+1 pour simplement indiquer la différence entre MVC et MVP. Comme OP, le reste d'Internet m'a laissé complètement perdu quant à savoir si ces acronymes étaient même le moins différents.
Ixrec
5

Je soupçonne que l'une des choses qui vous déroutent est qu'il existe deux modèles entièrement différents qui sont tous deux communément appelés model-view-controller.

Il y a l'original, tel qu'implémenté dans smalltalk et qui est utile pour les systèmes GUI locaux, et il y a ce que j'ai tendance à considérer comme web-mvc, qui permute certaines des responsabilités des vues et des contrôleurs afin que les contrôleurs puissent s'asseoir sur le serveur avec vues étant sur le client (peut-être en html rendu, ou peut-être via ajax).

Votre description me semble comme si elle se situait dans la plupart des définitions de web-mvc.

Jules
la source
Cela pourrait expliquer pourquoi j'ai eu tant de mal à envelopper ma tête autour du concept. Je vous remercie; il est bon de savoir que je ne fais (probablement) rien d'horriblement mal avec le concept de MVC.
KoratDragonDen
Pour les applications Web modernes d'une seule page, nous revenons au modèle MVC classique côté client.
Kevin Cline
2

Il y a beaucoup de discussions dans la communauté de programmation sur cette nomenclature exacte. Personne ne semble être d'accord sur presque rien.

Pour moi, la façon dont le pont est câblé à la vue détermine principalement le nom.

  • S'il peut y avoir une collection de vues par pont, alors le pont est un contrôleur.
  • S'il y a toujours une vue par pont, alors le pont est un présentateur.
  • S'il peut y avoir une collection de ponts par vue, alors le pont est un modèle de vue.

Parfois, les choses ne sont pas aussi claires. Par exemple, un présentateur peut être connecté à une vue composite composée de plusieurs sous-vues ou un contrôleur peut être créé sans aucune connaissance de ses vues. Malgré cela, je pense que mes règles sont un bon début.


En guise de remarque, j'aime associer les responsabilités comme ceci:

Modèle

Responsabilité principale: conserver les données
Rôles secondaires: valider les mises à jour, informer les observateurs des mises à jour

Vue

Responsabilité principale: Présenter les données
Rôles secondaires: Accepter l'entrée, présenter l'UX

Pont

Responsabilité principale: mettre à jour les données
Rôles secondaires: nettoyer les entrées, synchroniser les données et les vues

Jeffery Thomas
la source
0

Bien que votre modèle suggéré semble correct en surface et fonctionnera sans aucun doute pour de petites instances, à mesure que votre application devient plus complexe, vous rencontrerez des problèmes lorsque vous ne savez pas ce qui met à jour quoi, qui écoute où et pourquoi j'essaye pour contrôler autant de modèles à partir de tant de vues, tous ceux qui ont besoin d'accéder les uns aux autres, etc.

Je recommande d'étendre vos idées en utilisant le modèle suivant (extrait de la conférence d'Amy Palamountain, Enemy of the State ):

Des modèles

  • État de synchronisation avec le magasin de données
  • Gérer la validation des données nouvelles / mises à jour
  • Déclenchez des événements lorsqu'ils changent d'état

Vues

  • Modèles de rendu
  • Gérer les événements du modèle
  • Gérer les événements DOM
  • Assure l'interaction entre le modèle et le DOM

Contrôleurs

  • Gère au plus un couple modèles et vues
  • Assure le suivi des vues dans un conteneur

Modules

  • Le regroupement logique d'un contrôleur et de ses vues et modèles
  • Testable
  • Petit et maintenable (responsabilité unique)
  • Coordonne (via le contrôleur) l'état et les événements des vues et modèles qu'il contient
  • Libre de présenter ses propres vues
  • Pas libre de choisir présenter ses vues

Gestionnaire de mise en page

  • Responsable de la composition de la mise en page
  • Définit un shell d'application dans le DOM avec des zones où les modules peuvent présenter leur contenu

Dispatcher

  • Écoute les événements (via le flux PubSub global)
  • Responsable du chargement de nouveaux modules en fonction des événements
  • Remettez les modules chargés au gestionnaire de disposition
  • Gère toute la durée de vie du module (création, nettoyage, mise en cache, etc.)
  • Exemples d'événements:
    • Changements d'itinéraire (y compris l'itinéraire de chargement initial)
    • Interaction de l'utilisateur
    • L'événement de module s'est propagé à partir d'un événement de modèle en raison d'un changement d'état côté serveur, etc.

Application

  • Responsable de la configuration globale, instancie des choses comme:
    • Dispatcher
    • Routeur
    • Flux PubSub
    • Enregistreurs
    • etc

Ce type de modèle permet à votre application d'être composable, testée à l'unité, supprime la complexité qu'un pont créerait au fil du temps, maintient les préoccupations bien séparées, etc.

Comme le souligne Amy: Faites attention à ne pas construire de serveur sur le client. Et attention à ne pas tomber dans la doctrine du "Je fais un framework MV *, donc je dois ___!" Au lieu de cela, prenez toutes ces idées (et les autres réponses ici) et trouvez ce qui fonctionne le mieux pour votre application et votre équipe.

Je recommande fortement de regarder le discours d'Amy Palamountain Enemy of the State (d'où ces idées sont venues), ou du moins de regarder les diapositives du discours .

Jess Telford
la source