web-dev-qa-db-fra.com

Qu'est-ce que MVC, vraiment?

En tant que programmeur sérieux, comment répondez-vous à la question Qu'est-ce que MVC?

Dans mon esprit, MVC est une sorte de sujet nébuleux - et à cause de cela, si votre public est un apprenant, alors vous êtes libre de le décrire en termes généraux qui ne risquent pas d'être controversés.

Cependant, si vous parlez à un public averti, en particulier un intervieweur, j'ai du mal à penser à une direction à prendre qui ne risque pas une réaction de "eh bien ce n'est pas bien! ...". Nous avons tous une expérience différente du monde réel, et je n'ai pas vraiment rencontré le même modèle d'implémentation MVC deux fois.

Plus précisément, il semble y avoir des désaccords concernant la rigueur, la définition des composants, la séparation des pièces (quelle pièce convient où), etc.

Alors, comment dois-je expliquer MVC d'une manière qui est correcte, concise et sans controverse?

206
Nicole

MVC est une architecture logicielle - la structure du système - qui sépare la logique domaine/application/entreprise (selon ce que vous préférez) du reste de l'interface utilisateur. Pour ce faire, il sépare l'application en trois parties: le modèle, la vue et le contrôleur.

Le modèle gère les comportements fondamentaux et les données de l'application. Il peut répondre à des demandes d'informations, répondre à des instructions pour modifier l'état de ses informations et même informer les observateurs dans les systèmes événementiels lorsque les informations changent. Il peut s'agir d'une base de données ou d'un certain nombre de structures de données ou de systèmes de stockage. En bref, ce sont les données et la gestion des données de l'application.

La vue fournit efficacement l'élément d'interface utilisateur de l'application. Il rendra les données du modèle dans un formulaire adapté à l'interface utilisateur.

Le contrôleur reçoit les entrées de l'utilisateur et appelle les objets du modèle et la vue pour effectuer les actions appropriées.

Dans l'ensemble, ces trois composants fonctionnent ensemble pour créer les trois composants de base de MVC.

158
Bob

Analogie

J'ai expliqué MVC à mon père comme ceci:

MVC (Model, View, Controller) est un modèle d'organisation du code dans une application pour améliorer la maintenabilité.

Imaginez un photographe avec son appareil photo dans un studio. Un client lui demande de prendre une photo d'une boîte.

La boîte est le modèle, le photographe est le contrôleur et l'appareil photo est le vue.

Parce que la boîte ne fait pas savoir sur l'appareil photo ou le photographe, elle est complètement indépendante. Cette séparation permet au photographe de contourner la boîte et de diriger l'appareil photo à n'importe quel angle pour obtenir la photo/vue qu'il souhaite.

Les architectures non MVC ont tendance à être étroitement intégrées entre elles. Si la boîte, le contrôleur et la caméra étaient un seul et même objet alors, nous devions nous séparer puis reconstruire la boîte et la caméra chaque fois que nous voulait obtenir une nouvelle vue. De plus, prendre la photo serait toujours comme essayer de prendre un selfie - et ce n'est pas toujours très facile.


Explication détaillée

Ce n'est qu'après avoir lu la question/réponse mailliste suivante que j'ai eu l'impression de comprendre MVC. Citation: https://mail.python.org/pipermail/python-list/2006-January/394968.html

bwaha a écrit:

L'auteur fait référence à mvctree.py dans wxPython comme exemple de conception MVC. Cependant, je suis toujours trop vert, donc je trouve cet exemple particulier trop complexe et je ne comprends pas la séparation que l'auteur recommande.

MVC est tout au sujet de la séparation des préoccupations.

Le modèle est responsable de la gestion des données du programme (données privées et données client). Le View/Controller est chargé de fournir au monde extérieur les moyens d'interagir avec les données client du programme.

Le modèle fournit une interface interne (API) pour permettre à d'autres parties du programme d'interagir avec lui. Le View/Controller fournit une interface externe (GUI/CLI/formulaire Web/IPC de haut niveau/etc.) Pour permettre à tout ce qui est en dehors du programme de communiquer avec lui.

Le modèle est responsable du maintien de l'intégrité des données du programme, car si cela est corrompu, la partie est terminée pour tout le monde. La vue/le contrôleur est responsable de maintenir l'intégrité de l'interface utilisateur, de s'assurer que toutes les vues de texte affichent des valeurs à jour, de désactiver les éléments de menu qui ne s'appliquent pas au focus actuel, etc.

Le modèle ne contient aucun code de vue/contrôleur; pas de classes de widgets GUI, pas de code pour disposer les boîtes de dialogue ou recevoir les entrées des utilisateurs. La vue/contrôleur ne contient aucun code de modèle; aucun code pour valider les URL ou effectuer des requêtes SQL, et aucun état d'origine non plus: toutes les données détenues par les widgets sont uniquement à des fins d'affichage, et ne sont que le reflet des vraies données stockées dans le modèle.

Maintenant, voici le test d'une vraie conception MVC: le programme devrait être essentiellement fonctionnel, même sans View/Controller attaché. OK, le monde extérieur aura du mal à interagir avec lui sous cette forme, mais tant que l'on connaît les incantations appropriées de l'API du modèle, le programme conservera et manipulera les données normalement.

Pourquoi est-ce possible? Eh bien, la réponse simple est que tout cela est dû au faible couplage entre les couches Modèle et Vue/Contrôleur. Cependant, ce n'est pas l'histoire complète. La clé de tout le modèle MVC est la direction dans laquelle va cette connexion: TOUTES les instructions découlent de la vue/contrôleur à le modèle. Le modèle ne dit JAMAIS à la vue/au contrôleur quoi faire.

Pourquoi? Parce que dans MVC, alors que le View/Controller est autorisé à en savoir un peu plus sur le modèle (en particulier, l'API du modèle), mais le modèle n'a pas le droit de savoir quoi que ce soit sur le View/Controller.

Pourquoi? Parce que MVC consiste à créer une séparation claire des préoccupations.

Pourquoi? Pour aider à empêcher la complexité du programme de devenir incontrôlable et de vous enterrer en tant que développeur. Plus le programme est grand, plus le nombre de composants de ce programme est élevé. Et plus il existe de connexions entre ces composants, plus il est difficile pour les développeurs de maintenir/étendre/remplacer des composants individuels, ou même simplement de suivre le fonctionnement de l'ensemble du système. Demandez-vous ceci: lorsque vous regardez un diagramme de la structure du programme, préférez-vous voir un arbre ou un berceau de chat? Le modèle MVC évite ce dernier en interdisant les connexions circulaires: B peut se connecter à A, mais A ne peut pas se connecter à B. Dans ce cas, A est le modèle et B est la vue/contrôleur.

BTW, si vous êtes précis, vous remarquerez un problème avec la restriction `` unidirectionnelle '' qui vient d'être décrite: comment le modèle peut-il informer la vue/contrôleur des changements dans les données utilisateur du modèle lorsque le modèle n'est même pas autorisé à savez-vous que le View/Controller, ça ne fait rien, envoyez-lui des messages? Mais ne vous inquiétez pas: il existe une solution à cela, et c'est plutôt soigné même si cela semble un peu détourné au premier abord. Nous y reviendrons dans un instant.

Concrètement, un objet View/Controller peut alors, via l'API du modèle, 1. dire au modèle de faire des choses (exécuter des commandes), et 2. dire au modèle de lui donner des choses (renvoyer des données). La couche View/Controller envoie des instructions à la couche Model et extrait des informations à partir de la couche Model.

Et c'est là que votre premier exemple MyCoolListControl se passe mal, car l'API pour cette classe nécessite que les informations y soient poussées, vous êtes donc de retour à avoir un couplage bidirectionnel entre les couches, violant la MVC règne et vous replonge dans l'architecture du berceau du chat que vous essayiez [vraisemblablement] d'éviter en premier lieu.

Au lieu de cela, la classe MyCoolListControl doit suivre le flux, extraire les données dont elle a besoin de la couche ci-dessous, lorsqu'elle en a besoin. Dans le cas d'un widget de liste, cela signifie généralement demander combien de valeurs il y a puis demander chacun de ces éléments à tour de rôle, car il s'agit de la manière la plus simple et la plus lâche de le faire et donc de limiter au minimum le couplage. Et si le widget veut, par exemple, présenter ces valeurs à l'utilisateur dans l'ordre alphabétique de Nice, alors c'est sa prérogative; et sa responsabilité, bien sûr.

Maintenant, une dernière énigme, comme je l'ai laissé entendre plus tôt: comment garder l'affichage de l'interface utilisateur synchronisé avec l'état du modèle dans un système basé sur MVC?

Voici le problème: de nombreux objets View sont avec état, par exemple une case à cocher peut être cochée ou décochée, un champ de texte peut contenir du texte modifiable. Cependant, MVC impose que toutes les données utilisateur soient stockées dans la couche Modèle, donc toutes les données détenues par d'autres couches à des fins d'affichage (l'état de la case à cocher, le texte actuel du champ de texte) doivent donc être une copie subsidiaire de ces données de modèle principales. Mais si l'état du modèle change, la copie de cet état dans la vue ne sera plus précise et doit être actualisée.

Mais comment? Le modèle MVC empêche le modèle de pousser une nouvelle copie de ces informations dans la couche View. Heck, il ne permet même pas au modèle d'envoyer un message à la vue pour dire que son état a changé.

Enfin presque. D'accord, la couche Model n'est pas autorisée à communiquer directement avec d'autres couches, car pour ce faire, elle aurait besoin de connaître ces couches, et les règles MVC empêchent cela. Cependant, si un arbre tombe dans une forêt et que personne n'est là pour l'entendre, cela fait-il du bruit?

La réponse, vous voyez, est de mettre en place un système de notifications, fournissant à la couche Modèle un endroit où elle ne peut annoncer à personne en particulier qu'elle vient de faire quelque chose d'intéressant. D'autres couches peuvent ensuite publier des auditeurs avec ce système de notification pour écouter les annonces qui les intéressent réellement. La couche Model n'a pas besoin de savoir qui écoute (ou même si quelqu'un écoute du tout!); il publie simplement une annonce, puis l'oublie. Et si quelqu'un entend cette annonce et a envie de faire quelque chose après - comme demander au modèle de nouvelles données afin qu'il puisse mettre à jour son affichage à l'écran - alors tant mieux. Le modèle répertorie simplement les notifications qu'il envoie dans le cadre de sa définition d'API; et ce que quelqu'un d'autre fait avec cette connaissance dépend de lui.

MVC est préservé et tout le monde est content. Votre cadre d'application peut bien fournir un système de notifications intégré, ou vous pouvez écrire le vôtre sinon (voir le "modèle d'observateur").

...

Quoi qu'il en soit, j'espère que cela vous aidera. Une fois que vous comprenez les motivations derrière MVC, les raisons pour lesquelles les choses sont faites comme elles commencent à avoir un sens, même si - à première vue - elles semblent plus complexes que nécessaires.

À votre santé,

a

138
JW01

MVC est principalement un mot à la mode.

Auparavant, il était considéré comme un modèle, mais sa définition originale de 1979 a été simplifiée, transmise, mal interprétée, prise hors de son contexte d'origine. Elle a été mal redéfinie au point qu'elle commence à ressembler à une religion, et bien que cela aide certainement ses adeptes du cargo à la défendre, son nom ne s'associe plus à un ensemble solide de directives. En tant que tel, il ne peut plus vraiment être considéré comme un modèle.

MVC n'a jamais été conçu pour décrire des applications Web.
Ni systèmes d'exploitation modernes, ni langues.
(dont certains ont en fait rendu la définition de 1979 superflue)

Il a été fait pour. Et ça n'a pas marché.

Nous avons maintenant affaire à un hybride obscène web-mvc qui, avec son horrible statut de mot à la mode, sa mauvaise définition, et ayant des programmeurs semi-analphabètes en tant que cible démographique, fait une très mauvaise publicité aux modèles logiciels en général.

MVC est ainsi devenu une séparation des préoccupations distillée pour les personnes qui ne veulent pas trop y penser.

  • Le modèle data est géré dans un sens,
  • le voir dans un autre,
  • le reste est simplement nommé "contrôleur" et laissé à la discrétion du lecteur.

Les sites Web/applications Web des années 90 ne servaient pas vraiment à appliquer la séparation des préoccupations.

C'étaient des horribles tas de code de spaghetti entremêlés.
Les changements d'interface utilisateur, les remaniements et les réarrangements de données étaient incroyablement durs, coûteux, longs, déprimants, malheureux.

Les technologies Web comme ASP, JSP et PHP rendent trop facile à mélanger afficher les problèmes avec les données et les problèmes d'application. Les nouveaux venus sur le terrain émettent généralement des boules de boue de code inextricables comme dans ces vieux temps.

Ainsi, un nombre croissant de personnes ont commencé à répéter "utiliser MVC" en boucles sans fin sur les forums de support. Le nombre de personnes a augmenté au point d'inclure les gestionnaires et les spécialistes du marketing (pour certains, le terme était déjà familier, à l'époque de la programmation graphique, où le modèle avait un sens) et qui est devenu le monstre d'un mot à la mode auquel nous devons faire face maintenant .

En l'état, c'est le bon sens , pas une méthodologie .
C'est un point de départ , pas une solution .
C'est comme dire aux gens de respirer de l'air, ou faire des craquements , pas un remède contre le cancer .

87
ZJR

La meilleure façon de le définir est d'aller aux écrits originaux de Trygve Reenskaug , qui l'a inventé: http://heim.ifi.uio.no/~trygver/themes/mvc /mvc-index.html

Ce document, en particulier, est généralement considéré comme le texte de définition: http://heim.ifi.uio.no/~trygver/1979/mvc-2/1979-12-MVC.pdf

DES MODÈLES

Les modèles représentent la connaissance. Un modèle peut être un objet unique (plutôt inintéressant), ou une structure d'objets ...

Il devrait y avoir une correspondance biunivoque entre le modèle et ses parties d'une part, et le monde représenté tel que perçu par le propriétaire du modèle d'autre part. Les nœuds d'un modèle devraient donc représenter une partie identifiable du problème.

Les nœuds d'un modèle doivent tous être au même niveau de problème, il est déroutant et considéré comme une mauvaise forme de mélanger les nœuds orientés problème (par exemple, les rendez-vous de calendrier) avec les détails de mise en œuvre (par exemple, les paragraphes).

VUES

Une vue est une représentation (visuelle) de son modèle. Il mettrait généralement en évidence certains attributs du modèle et en supprimerait d'autres. Il agit ainsi comme un filtre de présentation .

Une vue est attachée à son modèle (ou partie de modèle) et obtient les données nécessaires à la présentation du modèle en posant des questions. Il peut également mettre à jour le modèle en envoyant des messages appropriés. Toutes ces questions et messages doivent être dans la terminologie du modèle, la vue devra donc connaître la sémantique des attributs du modèle qu'il représente. (Il peut, par exemple, demander l'identifiant du modèle et s'attendre à une instance de Text, il ne peut pas supposer que le modèle est de la classe Text.)

CONTRÔLEURS

Un contrôleur est le lien entre un utilisateur et le système. Il fournit à l'utilisateur une entrée en s'arrangeant pour que les vues pertinentes se présentent aux endroits appropriés sur l'écran. Il fournit des moyens de sortie utilisateur en présentant à l'utilisateur des menus ou d'autres moyens de donner des commandes et des données. Le contrôleur reçoit une telle sortie utilisateur, la traduit en messages appropriés et transmet ces messages à une ou plusieurs des vues.

Un contrôleur ne doit jamais compléter les vues, il ne doit par exemple jamais connecter les vues des nœuds en dessinant des flèches entre eux.

Inversement, une vue ne doit jamais connaître les entrées utilisateur, telles que les opérations de la souris et les frappes. Il devrait toujours être possible d'écrire une méthode dans un contrôleur qui envoie des messages à des vues qui reproduisent exactement n'importe quelle séquence de commandes utilisateur.

ÉDITEURS

Un contrôleur est connecté à toutes ses vues, elles sont appelées les parties du contrôleur. Certaines vues fournissent un contrôleur spécial, un éditeur , qui permet à l'utilisateur de modifier les informations présentées par la vue. Ces éditeurs peuvent être épissés dans le chemin entre le contrôleur et sa vue, et agiront comme une extension du contrôleur. Une fois le processus d'édition terminé, l'éditeur est supprimé du chemin d'accès et supprimé.

Notez qu'un éditeur communique avec l'utilisateur à travers les métaphores de la vue connectée, l'éditeur est donc étroitement associé à la vue. Un contrôleur saisira un éditeur en lui demandant la vue - il n'y a pas d'autre source appropriée.

39
Larry OBrien

MVC est un modèle de conception utilisé pour isoler la logique métier de la présentation.

Il diffère de beaucoup d'autres modèles de conception par le fait qu'il n'est généralement pas implémenté de manière succincte, mais constitue la base d'un cadre.

Alors qu'une application implémentant un modèle de stratégie n'est qu'un petit détail à ce sujet, dire qu'une application web utilise le modèle de conception MVC définit très bien son architecture.

11
Boris Yankov

MVC est une conception logicielle qui sépare les composants suivants d'un système ou sous-système:

  1. Modèle - Données sur l'état de l'application ou de ses composants. Peut inclure des routines de modification ou d'accès.
  2. Vue - Une interprétation des données (modèle). Ceci est uniquement limité à une représentation visuelle, mais peut être audio, des informations dérivées (par exemple des statistiques canalisées dans un autre objet de modèle), etc. En outre, un modèle unique peut avoir plusieurs vues.
  3. Contrôle - Gère l'entrée externe au système en invoquant des modifications sur le modèle. Le contrôle/la vue peut être étroitement lié (dans le cas d'une interface utilisateur). Cependant, d'autres entrées externes (telles que les commandes réseau) peuvent être traitées et sont totalement indépendantes de la vue.
8
lorean

Je dirais que MVC est un concept ou une famille de modèles similaires.

Je pense que cet article mérite d'être lu. Architectures GUI par Martin Fowler

6
franziga

Tout d'abord, vous devez déterminer qui est le demandeur de la question et quel type de réponse il recherche. Vous répondez à cette question par une autre question, telle que "Dans quel sens?"

Vous pouvez demander s'ils font référence à MVC en général, à une implémentation particulière de MVC (par exemple asp.net MVC, spring MVC, Smalltalk MVC, etc.), de quoi il s'agit techniquement, de quoi il s'agit philosophiquement (oui, il a un la philosophie aussi), etc.

S'il s'agit d'une question sur un test, et que vous ne pouvez pas demander au demandeur de clarifier, alors vous devrez deviner en fonction du contexte.

Une bonne réponse simple est:

MVC est une architecture d'interface utilisateur logicielle utilisée pour séparer les problèmes structurels et comportementaux afin de faciliter les logiciels plus maintenables.

Vous pouvez également dire:

En séparant la vue du contrôleur du modèle, il encourage l'isolement des composants en fonction de leurs responsabilités. En théorie, et généralement en pratique, cela contribue à améliorer la maintenabilité en empêchant les différentes parties du système de se mélanger et de créer des systèmes plus complexes.

Mais à la fin, vous serez jugés sur la question de savoir si vous donnez la réponse qu'ils attendent. La seule solution au problème est de savoir quel type de réponse ils attendent.

3
Erik Funkenbusch

Voici ce que j'en dirais. J'essaierais de l'expliquer en termes d'applications mobiles, parce que c'est ce que je connais le mieux et parce que je ne pense pas l'avoir bien compris avant de commencer à faire des applications mobiles.
Prenons par exemple Android.
Couche de présentation, c.-à-d. l'interface utilisateur peut (devrait, le plus souvent est) être spécifiée entièrement en xml. Par souci de simplicité, disons qu'un fichier xml décrit un écran dans l'application. Le fichier XML spécifie les contrôles, la disposition des contrôles, le positionnement, les couleurs, la taille, les étiquettes de chaîne ... tout ce qui concerne la présentation. Pourtant, il ne sait pas quand il sera appelé, quand sera-t-il placé sur l'écran. Sera-ce une disposition autonome ou une partie d'une plus grande disposition? Voilà: votre parfaite VUE .

Maintenant, la vue doit évidemment être placée sur l'écran à un moment donné, alors comment faire? Votre CONTRÔLEUR , dans Android appelé Activité. Comme son nom l'indique, l'activité fait une certaine activité. Même si son seul but est pour afficher la vue définie à l'étape 1, il effectuera une action. Ainsi, l'activité récupère une vue et l'affiche à l'écran. Comme la vue ne sait rien de l'activité, de même l'activité ne sait rien de la présentation réelle. Nous (les programmeurs) pourrions réorganiser la disposition de la vue plusieurs fois, sans même changer une seule ligne de code dans notre activité.

Maintenant, il n'est pas très utile de présenter votre mise en page XML brillante et bien définie sans vraiment faire quelque chose. Disons que nous voulons stocker les données saisies par l'utilisateur. L'activité doit s'attaquer à ce processus, de la prise des données de l'utilisateur à leur transmission à quelqu'un d'autre pour les gérer (les traiter, les stocker, les supprimer). À qui cela passera-t-il? Eh bien, pour un MODÈLE . J'aime à considérer un modèle comme une classe pure. Java qui ne sait rien du contexte d'application dans lequel il vit. (En pratique, ce ne sera presque jamais le Cas).

Disons que j'ai une personne de classe qui a trois propriétés: nom, adresse, âge. Ma disposition définie XML a 3 champs pour la saisie utilisateur: nom, adresse, âge. Mon activité prend les trois valeurs de l'entrée utilisateur, crée un nouvel objet Person et invoque une méthode qui sait comment gérer une logique spécifique à Person. Voilà. Modèle Vue Contrôleur.

2
Maggie

Je commence toujours par leur dire que le modèle n'est pas quelque chose de nouveau et existe depuis de nombreuses années ... à ce stade, ils me donnent un look curieux et BAM !, ils sont accrochés:

Et puis je parlerais à peu près des différents points comme les réponses précédentes, mais je pense qu'il est important d'être contextuel également, comme l'a dit JB King, ASP.NET MVC, etc.,

1
Dal