web-dev-qa-db-fra.com

Pourquoi utiliser MVVM?

D'accord, j'ai examiné le modèle MVVM et chaque fois que j'essayais de l'examiner, j'abandonnais pour un certain nombre de raisons:

  1. Inutile De Codage Extra Long Enroulé
  2. Aucun avantage apparent pour les codeurs (pas de concepteurs dans mon bureau. Actuellement, seul moi-même deviendra bientôt un autre codeur)
  3. Pas beaucoup de ressources/documentation de bonnes pratiques! (Ou du moins difficile à trouver)
  4. Vous ne pouvez pas penser à un seul scénario où cela est avantageux.

Je suis sur le point de laisser tomber encore une fois, et j'ai pensé demander à voir si quelqu'un répondait aux raisons ci-dessus.

Honnêtement, je ne vois pas l'avantage d'utiliser ceci pour un codage simple/partenaire. Même dans les projets complexes avec 10 fenêtres. Pour moi, le DataSet est une vue assez bonne et contraignante comme dans la réponse de Brent suivant question

Quelqu'un pourrait-il donner un exemple d'utilisation du modèle MVVM en termes de gain de temps par rapport à XAML DataBinding?.

100% de ma liaison est faite en XAML pour le moment. Et par conséquent, je ne vois pas l’intérêt de VM en tant que code supplémentaire en plus derrière lequel je dois écrire et dépendre.

MODIFIER:
Après avoir passé l’après-midi à faire des recherches sur MVVM, j’ai enfin trouvé quelque chose qui m’a fait prendre conscience des véritables avantages de cette réponse - réponse .

70
Michal Ciechan

Résumé

  • L'utilisation de tous les modèles est situationnelle, et l'avantage (s'il en existe) réside toujours dans une complexité réduite.
  • MVVM nous explique comment répartir les responsabilités entre les classes dans une application à interface graphique.
  • ViewModel projette les données du modèle dans un format adapté à la vue.
  • Pour les projets triviaux, MVVM n'est pas nécessaire. Utiliser uniquement la vue suffit.
  • Pour les projets simples, la division ViewModel/Model peut ne pas être nécessaire, et le simple fait d'utiliser un modèle et une vue suffit.
  • Model et ViewModel n'ont pas besoin d'exister dès le départ et peuvent être introduits quand ils sont nécessaires.

Quand utiliser des motifs et quand les éviter

Pour une application suffisamment simple, chaque modèle est excessif. Supposons que vous écriviez une application graphique qui affiche un seul bouton et qui affiche "Hello world". Dans ce cas, les modèles de conception tels que MVC, MVP, MVVM ajoutent beaucoup de complexité, mais n’apportent aucune valeur. 

En général, il est toujours mauvais d’introduire un motif de conception simplement parce qu’il convient. Les modèles de conception doivent être utilisés pour réduire la complexité, soit en réduisant directement la complexité globale, soit en remplaçant la complexité inconnue par une complexité familière. Si le motif de conception ne peut pas réduire la complexité de l'une ou l'autre de ces deux manières, ne l'utilisez pas.

Pour expliquer la complexité familière et non familière, prenez les 2 séquences de caractères suivantes:

  • "D. € | Ré% dfà? C"
  • "CorrectHorseBatteryStaple"

Alors que la deuxième séquence de caractères est deux fois plus longue que la première, elle est plus facile à lire, à écrire plus rapidement et à mémoriser plus facilement que la première, car elle est plus familière. Il en va de même pour les modèles familiers dans le code.

Soyez conscient du fait que certains modèles peuvent ne pas être familiers à tous les développeurs qui travailleront avec le code à l'avenir. En termes de l'exemple précédent, la séquence suivante peut être ou ne pas être plus facile à mémoriser que l'une des séquences ci-dessus, en fonction de l'expérience et de la formation de la personne qui s'en souvient: "3.14159265358979323846264338327950". Dans certains cas où des modèles de conception plus avancés sont impliqués, l'utilisation d'un modèle de conception n'a de sens que si les développeurs de la maintenance le connaissent déjà bien.

MVVM

Cela dit, penchons-nous sur le sujet de MVVM à l'aide d'un exemple. MVVM nous explique comment répartir les responsabilités entre les classes dans une application graphique (ou entre les couches - nous en parlerons plus tard), dans le but d’avoir un petit nombre de classes, tout en limitant le nombre de responsabilités par classe.

"Propre" MVVM suppose au moins une application moyennement complexe, qui traite les données provenant de "quelque part". Il peut obtenir les données d'une base de données, d'un fichier, d'un service Web ou d'une multitude d'autres sources. 

Exemple

Dans notre exemple, nous avons 2 classes View et Model, mais pas ViewModel. Model encapsule un fichier csv qu'il lit au démarrage et enregistre à la fermeture de l'application, avec toutes les modifications apportées par l'utilisateur aux données. View est une classe Window qui affiche les données de Model dans une table et permet à l'utilisateur de les éditer. Le contenu de csv pourrait ressembler à ceci:

ID, Name, Price
1, Stick, 5$
2, Big Box, 10$
3, Wheel, 20$
4, Bottle, 3$

Nouvelles exigences: Afficher le prix en euros

Nous sommes maintenant invités à modifier notre application. Les données consistent en une grille bidimensionnelle comportant déjà une colonne "prix", contenant un prix en USD. Nous devons ajouter une nouvelle colonne indiquant les prix en euros en plus de ceux en dollars américains, sur la base d'un taux de change prédéfini. Le format du fichier csv ne doit pas changer car d'autres applications fonctionnent avec le même fichier et que ces autres applications ne sont pas sous notre contrôle. 

Une solution possible consiste simplement à ajouter la nouvelle colonne à la classe Model. Ce n'est pas la meilleure solution, car la Model enregistre toutes les données qu'il expose au csv - et nous ne voulons pas d'une nouvelle colonne de prix en euros dans le csv. Ainsi, la modification de la variable Model serait non triviale et il serait également plus difficile de décrire le rôle de la classe Model, qui est une odeur de code .

Nous pourrions également effectuer le changement dans la variable View, mais notre application actuelle utilise la liaison de données pour afficher les données directement telles qu'elles sont fournies par notre classe Model. Parce que notre structure d'interface graphique ne nous permet pas d'introduire une colonne calculée supplémentaire dans une table lorsque la table est liée à une source de données, nous devrions apporter un changement significatif à la View pour que cela fonctionne, rendant la View beaucoup plus complexe.Présentation du ViewModel.

Il n'y a pas de ViewModel dans l'application car jusqu'à présent, la Model présente les données exactement comme le Csv en a besoin, ce qui correspond également à la manière dont View en avait besoin. Avoir un ViewModel entre aurait été une complexité ajoutée sans but. Mais maintenant que la Model ne présente plus les données de la manière dont la View en a besoin, nous écrivons une ViewModel. La ViewModel projette les données de la Model de telle sorte que la View puisse être simple. Auparavant, la classe View était abonnée à la classe Model. Maintenant, la nouvelle classe ViewModel souscrit à la classe Model et expose les données de Model à la View - avec une colonne supplémentaire affichant le prix en euros. La View ne connaît plus la Model, elle ne connaît plus que la ViewModel qui, du point de vue de la View, a la même apparence que la Model l'a fait auparavant, à l'exception du fait que les données exposées contiennent une nouvelle colonne en lecture seule.

Nouvelles exigences: différentes manières de formater les données.

La demande suivante du client est que nous ne devrions pas afficher les données sous forme de lignes dans une table, mais plutôt afficher les informations de chaque élément (ou ligne) sous forme de carte/boîte, et afficher 20 zones à l'écran dans une grille 4x5, affichant 20 boîtes à la fois. Parce que nous avons gardé la logique de la View simple, nous remplaçons simplement la View par une nouvelle classe qui correspond aux souhaits du client. Bien sûr, un autre client a préféré l'ancienne View; nous devons donc maintenant prendre en charge les deux. Parce que toute la logique métier commune se trouve déjà dans la variable ViewModel, cela n’est pas vraiment un problème. Nous pouvons donc résoudre ce problème en renommant la classe View en TableView et en écrivant une nouvelle classe CardView qui affiche les données au format carte. Nous devrons également écrire du code collant, qui pourrait être un élément unique dans la fonction de démarrage.

Nouvelles exigences: taux de change dynamique 

La demande suivante du client est que nous extrayions le taux de change d’Internet plutôt que d’utiliser un taux de change prédéfini. C’est à ce stade que nous revenons sur ma déclaration précédente concernant les "couches". Nous ne changeons pas notre classe Model pour fournir un taux de change. Au lieu de cela, nous écrivons (ou trouvons) une classe supplémentaire complètement indépendante qui fournit le taux de change. Cette nouvelle classe devient partie intégrante de la couche modèle et notre ViewModel consolide les informations du modèle csv et du modèle de taux de change, qu'elle présente ensuite à la View. Pour ce changement, il n'est même pas nécessaire de toucher à l'ancienne classe Model et à la classe View. Nous devons renommer la classe Model en CsvModel et nous appelons la nouvelle classe ExchangeRateModel.

Si nous n'avions pas introduit le ViewModel lorsque nous l'avions fait, mais que nous avions attendu jusqu'à maintenant pour le faire, la quantité de travail nécessaire pour introduire le ViewModel serait plus importante car nous devons supprimer une quantité importante de fonctionnalités de View et de Model. et déplacez la fonctionnalité dans la ViewModel.

Postface sur les tests unitaires.

L'objectif principal de MVVM n'est pas que le code du modèle et du ViewModel puisse être soumis au test unitaire. Le but principal de MVVM est que le code soit divisé en classes avec un petit nombre de responsabilités bien définies. L'un des nombreux avantages d'avoir un code composé de classes avec un petit nombre de responsabilités bien définies est qu'il est plus facile de le mettre sous Test unitaire. Un avantage beaucoup plus important est que le code est plus facile à comprendre, à maintenir et à modifier.

The primary purpose of MVVM is not that the code in the Model and the ViewModel can be put under Unit Test. The primary purpose of MVVM is that the code is broken up into classes with a small number of well defined responsibilities. One of several benefits of having code consisting of classes with a small number of well defined responsibilities is that it is easier to put the code under Unit Test. A much larger benefit is that the code is easier to understand, maintain, and modify.

80
Peter

La mise en œuvre de modèles et le respect des meilleures pratiques vous donnent souvent l’impression d’être des poursuites vaines, mais vous deviendrez des convertis dans quelques mois, votre patron vous demandant d’ajouter ou de modifier une fonctionnalité. En utilisant MVVM (et les modèles en général), vous serez en mesure de suivre votre propre code et de satisfaire aux exigences en quelques heures ou quelques jours au pire au lieu de plusieurs semaines ou mois. (Il s’agira probablement de quelques lignes de code plutôt que de passer des semaines à essayer de comprendre comment vous avez fait ce que vous avez fait avant même d’essayer d’ajouter de nouvelles fonctionnalités.)

Suivi: Les modèles et les meilleures pratiques vont en fait ralentir le développement initial, ce qui est souvent difficile à vendre, tant pour la direction que pour l'ingénierie. Le retour sur investissement (ROI en termes commerciaux) provient du code bien structuré, qui est réellement maintenable, évolutif et extensible.

Par exemple, si vous suivez correctement MVVM, vous devriez pouvoir apporter des modifications très importantes à la logique d'affichage, telles que la permutation d'une vue complète, sans impact sur les données et la logique de commerce.

Une pensée sur l'utilisation des jeux de données pour votre modèle : (J'ai en fait craqué pour cela aussi.) Les jeux de données semblent être un moyen parfaitement valide de déplacer les données de modèle dans une application. Le problème vient de la façon dont vous identifiez les éléments de données. Comme vos données sont stockées dans des lignes et des colonnes, vous devez effectuer des recherches par nom de colonne ou par index, ainsi que pour filtrer une ligne particulière. Ces éléments de logique impliquent d'utiliser des chaînes et des chiffres magiques dans la logique de câblage de votre application. L'utilisation d'un ensemble de données typé permettrait d'atténuer un peu ce problème, mais pas complètement. En utilisant des jeux de données typés, vous vous éloigneriez de MVVM pour un couplage plus étroit entre l'interface utilisateur et la source de données. 

31
Paul Sasik

Cela vous aide à distinguer l'interface graphique et la logique du programme; Leur mélange peut rendre très difficiles les applications à maintenir, notamment lorsque votre projet évolue avec le temps. 

14
gammelgul

De ici :

Pourquoi devriez-vous, en tant que développeur, même se soucient de Model-View-ViewModel modèle? Il y a un certain nombre de avantages que ce modèle apporte aux deux Développement WPF et Silverlight . Avant de continuer, demandez-vous:

  • Avez-vous besoin de partager un projet avec un concepteur et d’avoir le flexibilité pour le travail de conception et travaux de développement à venir presque simultanément?
  • Avez-vous besoin de tests unitaires approfondis pour vos solutions?
  • Est-il important pour vous d'avoir des composants réutilisables, à la fois dans et à travers les projets de votre organisation?
  • Souhaitez-vous plus de flexibilité pour changer votre interface utilisateur sans avoir à refactoriser une autre logique dans le base de code?

Si vous avez répondu «oui» à l’une d’entre elles questions, ce ne sont là que quelques-unes des avantages que l’utilisation du modèle MVVM peut apporter pour votre projet.

6
Kent Boogaart
  • Il est plus facile de travailler avec des concepteurs (pas les programmeurs, juste les personnes utilisant Blend)
  • Le code est testable (tests unitaires)
  • Il est beaucoup plus facile de changer de vue sans jouer avec le reste du code
  • Pendant que vous développez l'interface utilisateur, vous pouvez simuler le modèle et développer votre interface sans exécuter de service réel (en utilisant simplement les données simulées du modèle). Ensuite, il vous suffit d'inverser le drapeau et de vous connecter au service. 
5
Vladimir Kojic

De Article de Josh Smith sur MVVM :

Outre les fonctionnalités WPF (et Silverlight 2) qui font de MVVM un moyen naturel de structurer un application, le motif est également populaire parce que les classes ViewModel sont facile à tester à l'unité. Quand un la logique d'interaction de l'application vit dans un ensemble de classes ViewModel, vous pouvez écrire facilement du code qui le teste. Dans un sens, les vues et les tests unitaires sont juste deux types différents de ViewModel les consommateurs. Avoir une suite de tests pour ViewModels d'une application fournit tests de régression gratuits et rapides, ce qui contribue à réduire le coût de maintenir une application au fil du temps.

Pour moi, c'est la raison la plus importante d'utiliser MVVM. 

Auparavant, j'aurais des contrôles qui mélangeaient la vue et le modèle de vue. Mais une vue a essentiellement des événements de souris et de clavier en entrée et des pixels dessinés en sortie. Comment testez-vous quelque chose comme ça? MVVM élimine ce problème en séparant la vue intestable du modèle de vue testable et en maintenant la couche de vue aussi fine que possible.

3
Wim Coenen

Je commence encore à comprendre le motif moi-même, mais je pense que c'est précieux. Le plus gros défi à l'heure actuelle est que l'approche est encore relativement nouvelle et qu'il y a donc beaucoup de confusion et que certaines composantes clés du modèle sont encore difficiles à mettre en œuvre. J'ai découvert quelques choses qui m'ont beaucoup aidé à mettre en œuvre des motifs plus propres:

  1. J'utilise beaucoup le RelayCommand de Josh Smith's MVVM Foundation . Cela rend la liaison de View à ViewModel via Commandes beaucoup plus propre.

  2. J'utilise AOP pour atténuer la douleur liée à la mise en œuvre d'INotifyPropertyChanged. J'utilise actuellement Postsharp, bien que je pense qu'il existe d'autres outils pour le faire. Si je n'avais pas découvert cela, j'aurais probablement déjà abandonné, car le code standard pour l'implémenter manuellement m'ennuyait vraiment.

  3. J'ai dû inverser mon approche quant à la mise en œuvre du logiciel. Au lieu d'avoir une classe de dictateur qui dit à tous ses sbires quoi faire, qui les utilise à leur tour, mon logiciel devient plutôt une question de services faiblement couplés qui disent:

    • C'est ce que je sais faire

    • Ce sont les choses que je dois avoir fait

Lorsque vous commencez à structurer votre code de cette manière et à utiliser des outils facilitant le câblage des dépendances (vous avez le choix entre un grand nombre de frameworks IoC), j'ai trouvé que cela simplifiait un peu l'inconvénient de MVVM vous pouvez réduire le code habituel associé à l'injection des modèles dans les modèles de vue et à la localisation de divers services de visualisation (tels que l'affichage de boîtes de dialogue de fichiers) que vos modèles de vue doivent consommer.

Apprendre cette approche différente représente un investissement énorme et, comme pour tout changement majeur dans la mise en œuvre, la productivité est beaucoup plus faible lorsque vous commencez à l'utiliser. Cependant, je commence à voir un peu de lumière au bout du tunnel et je crois que, une fois que je maîtriserai les détails compliqués, mes applications seront plus propres et beaucoup plus faciles à gérer.


Pour répondre à la question sur INotifyPropertyChanged via Postsharp, j'utilise un aspect basé sur l'exemple ici . Je l'ai un peu personnalisé pour mon usage, mais cela en donne l'essentiel. Avec cela, je tague simplement la classe [NotifyPropertyChanged] et toutes les propriétés publiques auront le modèle implémenté dans leurs paramètres (même s’ils sont des paramètres de propriété automatique). Cela me semble beaucoup plus propre, car je n'ai plus à me soucier de savoir si je veux prendre le temps de faire en sorte que la classe mette en œuvre INotifyPropertyChanged. Je peux simplement ajouter l'attribut et en finir.

3
Dan Bryant

Lisez l'introduction dans MVVM dans cet article article

En 2005, John Gossman, actuellement l'un des architectes WPF et Silverlight de Microsoft, a dévoilé le modèle MVVM (Model-View-ViewModel) sur son blog. MVVM est identique au modèle de présentation de Fowler, en ce sens que les deux modèles présentent une abstraction d'une vue, qui contient l'état et le comportement de la vue. Fowler a présenté Presentation Model comme moyen de créer une abstraction d’une vue indépendante de la plate-forme, tandis que Gossman a présenté MVVM comme moyen normalisé d’exploiter les fonctionnalités essentielles de WPF pour simplifier la création d’interfaces utilisateur. En ce sens, je considère MVVM comme une spécialisation du modèle plus général PM, conçu sur mesure pour les plates-formes WPF et Silverlight.

..

Contrairement au présentateur dans MVP, un ViewModel n'a pas besoin de référence à une vue. La vue se lie aux propriétés d'un ViewModel, qui à son tour expose les données contenues dans les objets de modèle et d'autres états spécifiques à la vue. Les liaisons entre view et ViewModel sont simples à construire car un objet ViewModel est défini en tant que DataContext d'une vue. Si les valeurs de propriété dans ViewModel changent, ces nouvelles valeurs se propagent automatiquement à la vue via la liaison de données. Lorsque l'utilisateur clique sur un bouton de la vue, une commande du ViewModel s'exécute pour effectuer l'action demandée. Le ViewModel, jamais la View, effectue toutes les modifications apportées aux données du modèle . Les classes de vue n'ont aucune idée de leur existence, alors que ViewModel et le modèle ne sont pas conscients de la vue. En fait, le modèle est complètement inconscient du fait que le ViewModel et la vue existent. Comme vous le verrez bientôt, il s'agit d'une conception très faiblement couplée, qui porte ses fruits à bien des égards.

En outre, l'article explique pourquoi utiliser ces modèles d'interface graphique:

Il est inutile et contre-productif d'utiliser des modèles de conception dans un simple "Hello, World!" programme. Tout développeur compétent peut comprendre quelques lignes de code en un coup d'œil. Cependant, lorsque le nombre de fonctionnalités d'un programme augmente, le nombre de lignes de code et de pièces mobiles augmente en conséquence. Finalement, la complexité d'un système et les problèmes récurrents qu'il contient incitent les développeurs à organiser leur code de manière à ce qu'il soit plus facile à comprendre, à discuter, à étendre et à résoudre les problèmes. Nous réduisons le chaos cognitif d'un système complexe en appliquant des noms connus à certaines entités du code source. Nous déterminons le nom à appliquer à un morceau de code en considérant son rôle fonctionnel dans le système.

Les développeurs structurent souvent intentionnellement leur code en fonction d’un modèle de conception, au lieu de laisser les modèles émerger de manière organique. Aucune approche n’est fausse, mais dans cet article, j’examine les avantages de l’utilisation explicite de MVVM en tant qu’architecture d’une application WPF. Les noms de certaines classes incluent des termes bien connus du modèle MVVM, tels que se terminant par "ViewModel" si la classe est une abstraction d'une vue. Cette approche permet d’éviter le chaos cognitif mentionné plus haut. Au lieu de cela, vous pouvez vivre dans un chaos contrôlé, ce qui est naturel dans la plupart des projets de développement de logiciels professionnels!

3
Tigraine

MVVM présente de nombreux avantages, mais le plus important est peut-être la possibilité de tester votre code (unité testant les modèles de vue).

Le manque de connexion entre view et viewmodel facilite également le couplage lâche. Il devient très facile de réutiliser les composants que vous codez. 

3
Svetlozar Angelov

Je suis d’accord pour dire que l’utilisation de MVVM donne plus de poids à nos épaules en écrivant du code, Mais regardez le bon côté des choses où tout est isolé, puis si vous êtes un concepteur afin que vous puissiez concevoir votre programme et que d’autres puissent le coder pour vous et d’autres. la couche de base de données pour vous, regardez à quel point l'environnement sera maintenable, en particulier dans les applications de grande entreprise si vous n'utilisez pas MVVM, alors la maintenance est en train de tuer .... Je l'ai moi-même utilisée lors du développement ERP solution maintenant la maintenance est assez simple en raison de ce niveau d'isolement

2
Adam

Vous serez heureux à long terme si vous utilisez un modèle tel que MVVM pour toutes les raisons que les autres ont publiées. N'oubliez pas que vous n'avez pas besoin de suivre les exigences du modèle Word-à-Word, assurez-vous simplement de bien séparer votre fenêtre (Affichage) de votre logique (code-behind).

1
ChrisNel52

MVVM est un code vraiment excessif. 

Quels sont les avantages offerts par le MVVM? 

C'est juste Séparation des préoccupations pas plus. Vous pouvez également écrire la logique ViewModel dans le contrôleur. Le ViewModel est juste responsable de la conversion (par exemple, et de l’objet dans une chaîne). En utilisant MVVM, vous utilisez un style de programmation plus orienté objet. En écrivant la logique de conversion dans le contrôleur, vous utilisez un style de programmation plus fonctionnel.

Cela revient donc à avoir plus de code avec une meilleure lisibilité ou moins de code avec de gros fichiers Controller. En conclusion, vous ne pouvez pas dire que vous devez utiliser MVVM, car il vaut mieux que MVC ou autre chose, il s'agit simplement d'une préférence personnelle.

Juste pour expliquer pourquoi je parle d’un contrôleur: MVVM a également un code de contrôleur quelque part. Je ne sais pas pourquoi il y a un large consensus pour quitter le C.

0
Ini

Avantages de MVVM

  1. Complexité réduite.
  2. Isolement de la conception et du développement.
  3. Injection de dépendance.
  4. L’avantage majeur réside dans le fait que vous possédez une application Windows Phone bien structurée sur MVVM et que vous souhaitez développer la même chose pour Windows Metro Desktop. Vous ne pouvez donc utiliser que le même modèle de vue.

J'espère que ça aide.

0
Sunil Kumar S C