38 votes

MVVM ViewModel doit-il effectuer une conversion / validation de type?

Nous sommes juste à entrer dans MVVM en WPF.

Nous avons mis en place notre Viewmodel avec "fortement typé' propriétés (int, double? etc.) qui nous lient à la vue.

Type de conversion fonctionne OK, pour la plupart, et donc de la saisie de données est assez simple. Mais nous nous heurtons à des problèmes de validation.

Si, par exemple, une valeur non numérique est entré dans une zone de texte liée à une propriété numérique, la conversion échoue, la propriété n'est jamais réglé, et nous n'avons jamais obtenir une chance de fournir une rétroaction à l'utilisateur. Pire, le site conserve sa valeur actuelle, conduisant à un décalage entre ce qui est affiché dans la vue et ce qui est fait dans le ViewModel.

Tout cela peut être traitée avec des convertisseurs de valeur, je le sais. Mais j'ai vu plusieurs avis à l'effet que la conversion ne doit pas être le point de vue de la responsabilité à tous. Ce qui est entré dans la vue sont des chaînes de caractères, et la conversion de, de validation, etc. devrait être le ViewModel de la responsabilité du (de sorte que l'argument va).

Si donc, nous devons réécrire la plupart des propriétés sur notre Viewmodel de la chaîne, et de fournir des informations d'erreur via l'interface IErrorInfo, par exemple. Il serait sûrement pour faire plus simple, plus légère XAML dans la vue. D'autre part, la conversion, la validation etc. sera moins déclarative, explicite et flexible, du point de vue du concepteur de vues.

Il nous semble que ces deux approches sont fondamentalement différentes, donc avant de nous décider, nous aimerions quelques informés AFIN d'avis sur la question.

Donc: faut-Viewmodel exposer un simplifiée, "texte" basés sur l'interface de la vue et de la poignée de la conversion en interne? Ou doit-ViewModel propriétés exposer les types de données réels, laissant ces tâches à la vue à la poignée?

Mise à jour:

Difficile de choisir un gagnant ici, mais j'ai finalement atterri sur l'un de vous qui conclut à plus ou moins comme moi.

Plus précisément, nous avons décidé de garder le ViewModel propriétés typées. La principale raison pour cela est la flexibilité qu'il offre à nous dans la conception de la vue, et la puissance de l'explicite, déclarative de conversion ou de mise en forme dans le code XAML.

J'ai remarqué une hypothèse, à vous, qui ne seront pas d'accord avec nous dans cette, que la conception de l'affichage est fixe et des prêts. Par conséquent, aucune décision au sujet de la conversion, mise en forme, etc. besoin d'être fait dans la vue. Mais la nôtre est un processus agile, et nous n'avons pas connaître tous les détails de l'INTERFACE utilisateur deviné à l'avance.

En fait, les détails de l'INTERFACE utilisateur d'être travaillé le long de la route laisse place à la créativité et d'ailleurs, à mon avis, encore une méticuleusement travaillé sur la conception, finiront toujours morphing tout au long du processus de mise en œuvre.

Le point de tout cela est que tandis que les entreprises des règles d'application de la loi appartient certainement dans le ViewModel, il nous semble que la simple conversion et de mise en forme est un point de vue-chose. Cela peut ressembler à de l'hérésie, mais je n'ai pas vraiment l'impression de conversion de type dans le point de vue des besoins de l'unité de dépistage à tous (à condition av nous avons unité de tester le type de convertisseurs).

Dans l'ensemble une grande discussion, les gens, avec bien formulées, des opinions éclairées. Merci.

13voto

Martin Harris Points 18057

C'est une question très intéressante et que je ne ressens pas a une réponse définitive, mais je vais faire de mon mieux pour jeter mes pensées là-bas.

En regardant le modèle MVVM si je comprends bien, au point de le ViewModel est d'exposer les données de manière que la Vue peut comprendre sans aucune hypothèse sur la façon dont la vue va l'utiliser. Pour un exemple, imaginons que nous sommes à la modélisation de la vitesse d'une voiture:

public class CarModel
{
    public int MilesPerHour { get; set; }
}

public class CarViewModel
{
    private CarModel _model;

    public int MilesPerHour
    {
        get { return _model.MilesPerHour; }
        set { _model.MilesPerHour = value; }
    }
}

Dans l'exemple ci-dessus, j'ai exposé la propriété comme un int, puisque c'est ce qu'il est dans le modèle. Les inconvénients de ce que vous avez mentionnés dans votre question, mais le principal avantage est qu'elle permet au créateur de la vue d'une information précieuse sur la façon d'afficher les données. N'oubliez pas que nous (comme les auteurs du ViewModel) ne savent pas que le point de Vue ressemble. En s'engageant à l'idée de les données d'une int la Vue peut utiliser une zone de texte ou un autre contrôle qui n'accepte que des nombres (cadran, par exemple) pour afficher les informations. Si nous disons que nous allons mettre en forme les données d'une manière qui nous supposons est utile à la Vue, il faut qu'une puissance importante loin de lui.

D'autre part, nous travaillons dans le monde réel. Nous avons tendance à savoir ce que le point de vue est. Nous avons rarement de brancher et de jouer différents points de vue sur le ViewModel et en ajoutant le code de conversion dans le ViewModel est tout simplement plus facile. Je ne pense pas que c'est juste, mais cela ne signifie pas que vous ne trouverez pas mon code de production de l'utiliser...

Enfin (et je suis sûr que vous savez cela, mais pour les achèvements de souci...) logique d'entreprise doit être fait dans le ViewModel. Si nous décidons que la voiture ne devrait pas aller au-dessus de 70mph alors ce n'est pas de la responsabilité de la vue de la faire respecter. Ainsi, vous aurez toujours la fin avec une sorte d'erreur de fournisseur, mais à une entreprise plutôt que de niveau d'affichage.


Bon, peut-être que ce n'était pas, enfin....

Je voulais répondre aux commentaires de Kent, et mes pensées ne rentre pas dans un commentaire.

Évidemment, la principale différence entre mon et Kent point de vue (que je comprends) est il lit ViewModel d'être un Modèle de la Vue et je l'ai lu à être la chose qui expose le Modèle de la Vue. Une subtile différence, je l'admets, mais je pense que le résultat est que je ne veux pas supprimer les informations que le modèle fournit, même si cela rend plus facile pour le point de vue spécifique, je suis en utilisant.

De mon point de vue est basé sur l'hypothèse que vous devez être en mesure d'échanger leurs points de vue, ils devraient être éphémère des choses qui peuvent changer selon les exigences de taille de l'écran, de matériel, plate-forme, de la latence et de l'environnement. L'aspect intéressant est que j'ai jamais vraiment besoin de cette fonctionnalité, ni vu quoi que ce soit (au-delà de la preuve de concept des applications) qui aient jamais utilisé, mais si nous acceptons que nous ne les utiliserons pas maintenant ou à tout moment dans l'avenir, et que chaque ViewModel va travailler avec un, et un seul, de la Vue et nous pouvons retourner à mettre tout le code dans le fichier code-behind et jeter le ViewModel complètement - après tout, c'est donc étroitement couplé qu'il peut aussi bien être la même classe.

Idéalement, je voudrais une situation où le ViewModel peut dire "cette valeur est un int, il sera toujours un int, et vous pouvez l'afficher en aucune façon que vous aimez. Mais vous pouvez donner quelque chose de nouveau pour moi et je vais faire de mon mieux pour le faire rentrer, et si je ne peux pas, je vais vous laisser savoir". Fondamentalement, mon MilesPerHour propriété doit avoir un int de lecture, mais un objet setter. De cette façon, le point de vue de garder toutes les informations je crois qu'ils en ont besoin, mais ne pas avoir à vous soucier de conversions ou de validation.

8voto

Kent Boogaart Points 97432

Absolument, il appartient à la vue du modèle, pour toutes les raisons habituelles, y compris:

  • Les concepteurs propre le code XAML. Voulez-vous les designers pour comprendre et mettre en œuvre la nécessaire conversion de type et la logique de validation?
  • La testabilité. Ne voulez-vous pas vérifier que votre conversion et de la logique de validation fonctionne correctement? Il est beaucoup plus difficile si il est intégré dans la vue.

D'autre part, la conversion, la validation etc. sera moins déclarative, explicite et flexible, du point de vue du concepteur de Vue

Je pense que c'est un point discutable, car le concepteur de vue devrait être responsable de ces choses. Le concepteur d'essayer de faire de l'ergonomie de l'INTERFACE utilisateur d'une certaine manière; c'est le développeur qui implémente la logique d'entreprise, y compris la conversion et la validation de la logique.

5voto

Greg D Points 24218

C'est une bonne question, et je peux certainement voir les deux côtés de la discussion.

Ma pensée est que ce que vous êtes vraiment à la recherche d'un bon NumericInputControl que vous pouvez utiliser dans votre xaml. Cela permettra d'offrir une meilleure expérience utilisateur parce que vos utilisateurs ne pourront pas accidentellement entrer du texte dans un champ de numéro et le, car le contrôle des contraintes d'entrée sans validation, vous pouvez maintenir le plus fortement typées ViewModel.

Je ne suis pas sûr de savoir comment vous voulez aller sur la mise en œuvre de l'un, je sais que le classique spinner/NumericUpDown contrôles sont à tomber hors de la faveur, parce qu'ils ne sont pas tactile, mais je ne crois pas que l'introduction d'un tel contrôle, viole les lois de la pureté de l'approche de la conception ou de votre Viewmodel. Vous recevrez un numéro que vous pouvez ensuite la gamme, à valider à l'endroit approprié, fournir un retour d'expérience via IDataErrorInfo comme d'habitude, et ainsi de suite. :) Cette technique permet d'obtenir le meilleur des deux mondes, sans réel des inconvénients (à l'exception de la création d'une commande numérique).

5voto

Zach Bonham Points 4460

Si le MVVM ViewModel effectuer type de conversion et de validation?

Oui.

Le modèle de vue est une couche d'abstraction entre le modèle et la vue - l'endroit idéal pour effectuer toutes les conversions de type (au lieu de la lourdeur des convertisseurs de valeur). La Validation doit absolument se produire dans le cadre du modèle de vue.

Nous utilisons notre Modèle d'Affichage pour gérer les conversions comme beaucoup que possible pour les types de données. Cela réduit la nécessité d'un convertisseur de valeurs à certaines circonstances très particulières. Vous souhaitez exposer quel que soit le type est plus facile pour le point de vue de consommer. Cela a bien fonctionné.

Une question spécifique que vous avez soulevé:

Si, par exemple, une valeur non numérique est entré dans une zone de texte liée à une propriété numérique, la conversion échoue, la propriété n'est jamais défini, et nous n'avons jamais obtenir une chance de fournir bon retour à l'utilisateur. Pire, la propriété conserve son actuel valeur, conduisant à un décalage entre ce qui est affiché dans la vue et ce qui est fait dans le ViewModel.

peut être gérée en exposant votre point de vue modèle type nullable type. Ce qui devrait encore permettre la source sous-jacente à être mis à jour, même si des données non valides est entré, et de déclencher la validation. Il a travaillé dans une situation similaire que nous avons eu avec DateTime et une date time picker.

Garder la vue aussi stupide. Nous n'avons pas officiel designers, les développeurs sont nos designers, afin de garder la vue muet a certains avantages:

  • Nous (les développeurs) arrivent à garder notre intégrité (XAML est un peu moins verbeux)
  • La logique d'affaires (y compris validation) reste dans le modèle de vue et peut permettre d'effectuer les essais

Bonne Chance!

-Z

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X