Sur MVC, plusieurs vues peuvent-elles avoir le même contrôleur ou une vue doit avoir un contrôleur unique?

15

J'ai des questions lors de la conception d'une architecture pour un projet autour de MVC. (C'est un projet SDK C ++ / Marmalade, je n'utilise pas de framework MVC particulier, j'en fais un.)

Sur plusieurs articles (comme sur l'article original de Steve Burbek ), je continue de lire le concept "MVC triad" qui m'embourbe depuis que j'ai pris ce concept assez littéralement. Quand je l'ai lu la première fois, une application était construite autour d'unités "MVC triad" - une pour chaque pièce d'interface utilisateur que je supposais -, mais je trouve cela plutôt peu flexible et je pense que ce n'est pas ainsi que MVC devait être utilisé. Ensuite, en recherchant plus loin le problème, j'ai trouvé plusieurs exemples de couplage étroit du contrôleur et de la vue, à savoir, la relation 1 à 1 - TextEditView a TextEditController.

Mais quand je reviens à mon projet, je trouve qu'il pourrait être utile d'avoir un contrôleur (par «unité logique», comme AddElementController) et plusieurs vues pour ce contrôleur particulier.

Je pense clairement à quelque chose comme un AddElementController qui devrait avoir une sorte d'interface utilisateur d'onglet. Dois-je avoir un AddElementController qui a un AddElementTabView et plusieurs AddImageView, AddSoundView, etc. pour les onglets? Ou devrais-je avoir un «sous-contrôleur» différent pour chaque vue d'onglet?

En somme, et en ce qui concerne le modèle MVC (pas la compréhension / implémentation particulière de ce modèle X), est-il correct d'avoir plusieurs vues pour un contrôleur ou chaque vue devrait-elle avoir son contrôleur particulier?

En outre, est-il correct de conserver certaines informations d'état sur le contrôleur ou doit-il être sans état (ce qui signifie que l'état doit être placé sur un modèle d'état non-domaine)?

Merci à tous d'avance.

pedrosanta
la source

Réponses:

14

Le problème est que le modèle MVC a été conçu dans un système qui n'existe plus vraiment. Il a été inventé dans Smalltalk à une époque où les bibliothèques d'interface utilisateur n'existaient pas. Pour créer une boîte de dialogue de fenêtre, vous avez dessiné toutes les cases, mis en surbrillance les carrés appropriés, vous êtes assuré que le texte que vous dessiniez se retrouvait au bon endroit ... etc ...

Imaginez ce que ce serait d'écrire une application de dialogue en utilisant rien d'autre qu'une grande toile. C'est de là que vient le MVC.

Une "vue" dans ce système était une zone de texte et c'était une classe qui était chargée de dessiner la zone, le texte, de dessiner les zones sélectionnées, de répondre aux changements dans le texte, etc ...

Un "contrôleur" était une autre classe qui prenait en compte les événements de souris qui se produisaient dans cette boîte, comme le déplacement de la souris, la touche enfoncée, la touche enfoncée, les clics, etc ... et il déciderait de ce qui se passerait. Faut-il changer le texte? Faut-il changer la sélection? Des trucs comme ça.

Un "modèle" était encore une autre classe qui représentait les données de base et l'état du composant. Un modèle de zone de texte aurait le texte bien sûr, la police, la sélection, etc ...

Comme vous pouvez le voir, dans une situation comme celle-ci, les trois composantes sont très enchevêtrées dans la représentation d'une seule idée. Dans ce contexte, il est logique de parler de "triade".

Aujourd'hui, si vous travaillez à créer une bibliothèque d'interface utilisateur et à utiliser des commandes de dessin brutes, vous pourriez faire quelque chose de similaire. Mais l'application du modèle "MVC" a dépassé son objectif initial. De nos jours, vous avez une "vue" qui peut en fait être une boîte de dialogue complète et un contrôleur qui répond à des événements comme "textChanged" ou "buttonClicked". Le modèle dans le MVC d'aujourd'hui est normalement quelque chose d'assez déconnecté du système (mais généralement lié à la vue en fournissant une interface d'observation quelconque) et il peut y avoir de nombreuses vues associées au même modèle.

Dans un système que j'ai récemment conçu, par exemple, nous avions environ 10+ vues, tous observant un seul "titulaire" de document et son document actif. Une interface de dessin principale a interagi avec la mise en page du document, diverses vues de propriété qui ont observé l'élément sélectionné et fourni une interface d'enregistrement, et une représentation à plus petite échelle de la vue principale qui a montré tout le document au lieu de simplement la fenêtre visible. Certaines de ces vues avaient des contrôleurs de complexité variable qui transformaient les événements de l'interface graphique en modifications du document, qui à leur tour notifieraient ses différentes vues.

Pouvez-vous encore appeler une telle relation une "triade"? Peut-être, mais je pense que cela implique trop de l'ancienne, ancienne application de MVC.

Pourriez-vous partager des contrôleurs avec différentes vues? Cela dépend de la similitude des vues. J'ai trouvé qu'en général ce type d'objet a un comportement spécifique à la vue qu'il contrôle ET au modèle qu'il manipule pour être très réutilisable ... mais il y a toujours des exceptions.

Edward Strange
la source
5

Ça dépend. Il existe plusieurs variantes de MVC, certaines où seule une relation 1: 1 a du sens (comme "l'humble boîte de dialogue"), d'autres où ce n'est pas le cas. Je recommanderais de lire la série d'articles " Build Your Own CAB ", expliquant les variantes MVC les plus importantes.

Doc Brown
la source
3

Les vues n'ont pas de contrôleurs dans MVC. Le contrôleur est le boss, donc un contrôleur décide quelle vue doit être rendue et les vues ne se soucient pas du contrôleur qui a demandé la vue.

Vous pouvez / aurez absolument plusieurs vues d'un contrôleur. Pensez simplement à créer un modèle pour chaque vue si vous souhaitez vous en tenir au modèle MVC.

Mert Akcakaya
la source
3

Le but du contrôleur est de contrôler les interactions de l'utilisateur avec votre modèle de domaine - c'est-à-dire qu'il s'agit d'un niveau d'indirection entre ce que l'utilisateur voit (la vue) et l'état de vos applications (le modèle).

Lorsque l'utilisateur fait une demande, elle est dirigée vers un contrôleur. Le contrôleur décide comment transmettre cette demande à l'application, généralement via une sorte de classe de service. Il interprète ensuite la réponse de cette classe de service et décide quelle vue renvoyer à l'utilisateur.

Un contrôleur peut toujours retourner la même vue (1: 1) s'il n'y a qu'un seul type de demande que l'utilisateur peut faire du contrôleur, et cela nécessite toujours le même type de réponse. Par exemple, le HelloWorldControllerretourne toujours un HelloWorldViewaffichage "Bonjour, monde!"

D'un autre côté, un contrôleur doit souvent décider de différentes vues, selon ce que le modèle lui dit. Le TeamRosterControllerpeut retourner un RugbyTeamRosterViewou un FootbalTeamRosterView, selon le type de l'équipe demandée.

Il est généralement préférable que les contrôleurs soient sans état, bien qu'un certain accès à l'état de la session utilisateur puisse être nécessaire ou souhaitable. Si possible, vous devez gérer l'accès à cet état séparément.

Je recommande fortement de regarder un framework MVC réel pour voir ce qu'il fait et comment cela fonctionne. Vous n'êtes pas obligé de l'utiliser, mais vous obtiendriez certainement une meilleure compréhension avant de construire le vôtre.

Matthew Flynn
la source