J'ai une application qui utilise MVC, mais je me bats un peu sur la façon dont le contrôleur doit être architecturé. Par exemple, la vue affiche uniquement un sous-ensemble des données du modèle à la fois. Cependant, je ne sais pas exactement comment cela devrait être organisé. Est-il normal que la vue ou le modèle appelle directement des fonctions sur le contrôleur, par exemple? Par une sorte d'interface? Ou sont-ils totalement encapsulés et ne connaissent jamais le contrôleur ou l'autre?
Tout comme un montage; il s'agit d'une application personnalisée qui n'est écrite dans aucun cadre Web, donc je ne recherche pas de détails spécifiques au cadre ici et j'ai la liberté de faire mon propre choix.
Réponses:
Le contrôleur contrôle le flux d'activité. L'utilisateur effectue cette action, le contrôleur transmet les données de vue au domaine qui fait tout ce qu'il doit faire ensuite, en fonction de la ou des réponses, le contrôleur indique au framework quelle vue afficher ensuite (et lui donne suffisamment de données à faire donc).
Le contrôleur doit donc être couplé au modèle de domaine, dans une certaine mesure. c'est à dire. Vous pouvez mettre une couche de service entre les deux mais, par définition stricte, cela fait partie du domaine.
Il est également couplé aux données de vue mais pas à la vue elle-même. c'est à dire. il dit simplement "afficher la vue du client en utilisant ce détail client". Le cadre décide ensuite où il doit trouver cette vue.
Maintenant, cela devrait vous permettre de dissocier le modèle de domaine de la vue, en utilisant un modèle de vue des mêmes données. Certains développeurs le font, d'autres non, et je pense que c'est en grande partie une question de préférence personnelle.
Dans Rails, vous êtes très encouragé à pousser les objets de domaine (ActiveRecord) vers la vue et à vous assurer que la vue ne profite pas de cet accès (par exemple, vous ne devriez pas appeler customer.save depuis la vue, même si elle serait disponible).
Dans le monde .NET, nous avons tendance à réduire les risques en n'autorisant pas les choses qui ne devraient pas se produire et, peut-être pour cette raison, il me semble que le modèle de vue détachée est plus populaire.
la source
Remarque: Robert C. Martin (alias Oncle Bob) explique cela d'une manière bien meilleure et humoristique dans son discours, Architecture the Lost Years . Un peu long mais enseigne plein de bons concepts.
tl; dr: Ne pensez pas et ne planifiez pas votre application en termes de MVC. Le framework MVC n'est qu'un détail d'implémentation.
La chose la plus déroutante à propos de MVC est que les développeurs essaient d'utiliser tous les composants collés ensemble.
Essayez de penser en termes de programme, pas en termes de cadre.
Votre programme a un but. Il prend des données, fait des choses avec les données et renvoie des données.
De cette façon, le
controller
est le mécanisme de livraison de votre programme.$user->addToCart($product)
addToCart
fonction de l'user
objet dans ce cas) fait le travail auquel il est destiné et renvoie une réponse (disonssuccess
)view
: par exemple. dans l'objet contrôleur$this->render($cartView('success')
De cette façon, les contrôleurs sont découplés du programme et utilisés comme mécanisme de livraison. Ils ne savent pas comment fonctionne votre programme, ils savent simplement quelle partie du programme doit être appelée pour les demandes.
Si vous souhaitez utiliser un autre framework, votre application n'aura pas besoin de changement, il vous suffira d'écrire les contrôleurs appropriés pour appeler votre programme pour les demandes.
Ou si vous souhaitez créer une version de bureau, votre application restera la même, il vous suffira de préparer un mécanisme de livraison.
Et le
Model
. Considérez-le comme un mécanisme de persistance.De la manière OO, il existe des objets dans votre programme qui contiennent les données.
Lorsque vous ajoutez un produit au panier, vous pouvez ajouter le
product::id
au auuser::shoppingCart
.Et lorsque vous souhaitez conserver les données, vous pouvez utiliser le
model
partie du framework, qui consiste généralement à utiliser un ORM, pour mapper les classes aux tables de la base de données.Si vous souhaitez modifier l'ORM que vous utilisez, votre programme restera le même, seules les informations de mappage changeront. Ou si vous voulez éviter les bases de données toutes ensemble, vous pouvez simplement écrire les données dans des fichiers en texte brut et votre application restera la même.
Alors, écrivez d'abord votre programme. Si vous programmez avec la méthode 'OO', utilisez de simples objets anciens du langage. Ne pensez pas en termes de MVC au premier abord.
la source
MVC
. C'est pourquoi j'ai écritMVC Framework
.Martin Fowler décrit bien le paradigme MVC. Voici un lien vers son article à ce sujet http://martinfowler.com/eaaDev/uiArchs.html
Notez sa citation sur la présentation séparée "L'idée derrière la présentation séparée est de faire une distinction claire entre les objets de domaine qui modélisent notre perception du monde réel, et les objets de présentation qui sont les éléments d'interface graphique que nous voyons à l'écran."
la source
Voici un exemple simple de la façon dont MVC peut être utilisé dans une application Java Swing typique ...
Disons que vous avez un panneau contenant un bouton et un champ de texte. Lorsque le bouton est enfoncé, un événement est déclenché, ce qui entraîne un changement d'état dans l'application. Une fois le changement d'état enregistré, le TextField devient désactivé.
Ce serait donc l'approche typique adoptée par une simple application MVC ...
Le contrôleur s'enregistre en tant qu'écouteur des événements de la vue. Lorsque le bouton est cliqué, la vue elle-même ne gère pas l'événement; le contrôleur le fait. Le contrôleur est spécifique à Swing car il doit gérer les événements liés à Swing.
Le contrôleur reçoit cette notification et doit décider qui doit la gérer (la vue ou le modèle). Étant donné que cet événement changera l'état de l'application, il décide de transmettre les informations au modèle qui est responsable des données et de la logique du programme. Certains font l'erreur de placer la logique du programme dans le contrôleur, mais dans la POO, les modèles représentent à la fois les données ET le comportement. Lisez Martin Fowler sur son point de vue.
Le message est reçu par le modèle dans le contexte approprié. Autrement dit, il est complètement vide de toute référence à Swing ou à toute autre référence spécifique à l'interface graphique. Ce message s'adresse au modèle et UNIQUEMENT au modèle. Si vous vous trouvez à importer des instructions javax.swing dans le modèle, vous ne codez pas correctement le modèle.
Le modèle définit ensuite son état sur «désactivé» et procède à la notification aux parties intéressées de ce changement de modèle. The View, intéressé par cet événement, s'est déjà inscrit en tant qu'observateur de tout changement de modèle. Une fois que l'événement de changement d'état du modèle est détecté par la vue, il procède à la désactivation de son TextField. Il est également légal pour la vue d'obtenir des informations en lecture seule directement à partir de son modèle sans avoir à passer par le contrôleur (généralement via une interface spécifique exposée par le modèle pour une telle activité).
En favorisant un tel couplage lâche entre la présentation et la logique métier et les couches de données, vous constaterez que votre code est beaucoup plus facile à gérer. À mesure que les systèmes grandissent, votre approche de MVC augmentera également. Par exemple, Hierarchical MVC est une extension souvent utilisée pour relier les triades MVC ensemble pour former de grands systèmes à l'échelle de l'entreprise sans coupler les sous-systèmes ensemble
la source
Le couplage (le type que vous souhaitez éviter) implique une dépendance mutuelle entre deux classes. Autrement dit, un Foo dépend d'une barre et une barre dépend d'un foo de sorte que vous ne pouvez pas vraiment modifier l'un sans modifier l'autre. C'est une mauvaise chose.
Cependant, vous ne pouvez pas vraiment éviter d'avoir QUELQUES dépendances. Les classes doivent se connaître un peu, sinon elles ne communiqueraient jamais.
Dans le modèle MVC, le contrôleur contrôle la communication entre le modèle de domaine et la vue de présentation. En tant que tel, le contrôleur doit en savoir suffisamment sur le modèle pour lui demander de faire ce qu'il est censé faire. Le contrôleur doit également connaître suffisamment la vue pour pouvoir la présenter au client ou aux utilisateurs. Ainsi, le contrôleur de
modèlea des dépendances sur les deux. Cependant, la vue peut parfaitement exister sans le contrôleur - il n'y a aucune dépendance là-bas. De même, le modèle n'a pas de dépendances sur le contrôleur - c'est simplement ce qu'il est. Enfin, le modèle et la vue sont complètement séparés l'un de l'autre.Essentiellement, le contrôleur est le niveau d'indirection qui dissocie la vue du modèle, afin qu'ils n'aient pas à se connaître.
la source
D'après mon expérience, le modèle ne dépend généralement que d' un vue, et non d'une vue spécifique, souvent en tant qu'observateur ... s'il possède un tel couplage.
La vue se couple généralement à tout ce qu'elle regarde, ce qui est logique. Difficile de trouver une vue qui pourrait être découplée de ce qu'elle regarde ... mais parfois vous pouvez avoir un couplage partiel ou quelque chose.
Le contrôleur a souvent tendance à se coupler aux deux. Cela a également un certain sens, car il est de transformer les événements d'affichage en changements de modèle.
Bien sûr, ce n'est qu'une tendance que j'ai observée et ne dit vraiment rien sur un exemple spécifique.
Pour comprendre ce qu'est MVC et ce que la relation de couplage a tendance à être, vous devriez voir comment MVC est devenu. L'environnement dans lequel MVC a été créé était un environnement dans lequel les "widgets" en tant qu'éléments de formulaire avec lesquels vous pouvez créer des dialogues n'existaient pas. Une "vue" était une boîte et elle dessinait des trucs. Une vue de texte serait une boîte qui dessinerait du texte. Une vue de liste était une boîte qui dessinait une liste. Le "contrôleur" a reçu tous les événements de souris et de clavier du système d'interface utilisateur qui ont eu lieu dans cette vue; il n'y a eu aucun événement "textChanged" ou "selectionChanged". Le contrôleur prendrait tous ces événements de bas niveau et générerait une interaction avec le modèle. Le modèle, une fois modifié, ferait part de ses vues; nous sommes depuis venus pour voir cette relation comme "observateur" et il '
C'EST l'essence du modèle MVC. Étant donné que ce type de programmation d'interface utilisateur de bas niveau n'est généralement plus effectué, le MVC a évolué dans de nombreuses directions différentes. Certaines choses qui portent ce nom aujourd'hui ne ressemblent presque pas du tout au MVC et devraient vraiment s'appeler autre chose. Il peut toujours être utilisé dans le sens d'une boîte de dialogue dans son ensemble interagissant avec un objet plus grand. Il existe cependant de bien meilleures alternatives.
Fondamentalement, tout ce que le MVC devait résoudre se produit maintenant à l'intérieur des widgets et nous ne devons plus l'utiliser.
Pour ceux qui pensent savoir mieux:
http://www.codeproject.com/Articles/42830/Model-View-Controller-Model-View-Presenter-and-Mod
http://msdn.microsoft.com/en-us/library/ff649643.aspx
Je suis sûr qu'il y en a plus, mais ce ne sont que le haut de la liste dans google. Comme vous pouvez le voir, le modèle dépend beaucoup d'une interface de vue dans de nombreuses implémentations. Généralement, un modèle est observable et la vue est un observateur.
Mais pourquoi laisser les faits gêner ...
Un article déjà publié dans une autre réponse corrobore également mes affirmations:
http://martinfowler.com/eaaDev/uiArchs.html
Si les gens veulent continuer à dire que TOUT LE MONDE dans l'industrie du design a tort, c'est bien.
la source
Si le contrôleur était étroitement couplé à une vue, nous serons alors dans un monde de formulaires Web. Vous auriez un code derrière lequel serait lié à un fichier de modèle (applicable aux formulaires Web ASP.NET)
Pour cette raison, le contrôleur n'est pas couplé à un modèle ou à une vue. C'est juste un mécanisme pour traiter les demandes et envoyer des réponses.
La vue est étroitement couplée à un modèle. Apportez des modifications à votre modèle (par exemple, modifiez sa propriété) et vous devrez apporter des modifications à votre vue.
Le modèle n'est pas étroitement couplé à une vue. Apportez des modifications à une vue et cela n'aura aucun effet sur un modèle.
Le modèle ne sait rien du contrôleur ni des vues où il peut être utilisé. Par conséquent, le modèle n'est pas étroitement couplé à une vue ou à un contrôleur.
Une autre façon de penser à cela:
Apportez des modifications à un contrôleur - la vue et le modèle ne seront pas affectés
Apportez des modifications à un modèle - la vue sera interrompue car elle dépend d'un modèle
Apportez des modifications à une vue - le modèle et le contrôleur ne seront pas affectés
Ce couplage lâche dans les projets MVC est ce qui les rend faciles à tester unitaire.
la source