Est-ce une bonne idée d'ajouter ViewModel exactement comme Model

16

J'ai les couches suivantes dans ma solution:

  1. App.Domain
  2. App.Service
  3. App.Core (vous appelez peut-être celui-ci App.DataLayer)
  4. App.Web

Le modèle de conception de logiciel n'est pas ma question, j'ai le modèle suivant Domain

public class Foo {
    public int Id {get;set;}
    public int Name {get;set;}
    public int Value {get;set;}
}

Je veux utiliser ce modèle sur la vue (par exemple la page d'accueil) ET je veux utiliser Id, Name & Value, donc si je veux créer ViewModel, j'ajouterai ce qui suit:

public class FooViewModel {
    public int Id {get;set;}
    public int Name {get;set;}
    public int Value {get;set;}
}

Alors, c'est une bonne idée? ou simplement utiliser à la Fooplace de FooViewModel?

Mehdi Dehghani
la source
Je ne suis pas sûr de comprendre cela. N'est-ce pas Modelgénéralement transmis au View? Pourquoi avez-vous exactement besoin de recréer les champs du Modeldans le View? Si la séparation des préoccupations est un objectif MVC, dans quelles circonstances voudrait-on faire la même chose avec Modelet View? Si ViewModelc'est les deux, pourquoi ne pas étendre / composer les deux Modelet View?
null
veuillez lire mes commentaires sur la réponse de @ svidgen
Mehdi Dehghani
J'ai un problème connexe - où la validation (attribut requis) sur les modèles (et dans la base de données) indique que certaines valeurs doivent être saisies - mais dans les vues, ces valeurs n'ont pas besoin d'être - donc je suis obligé de copier certains champs de les modèles dans le modèle de vue - plutôt que de référencer directement le modèle. Cependant, à la réflexion, cela est probablement bien et ne viole pas DRY car ils sont à des fins différentes (pas trop mal de toute façon).
niico

Réponses:

20

Cela peut ressembler à une violation de la règle DRY au départ, mais je dirais qu'un code "similaire, voire identique" n'est pas nécessairement une "répétition" s'il fait quelque chose de différent ou s'il peut changer indépendamment. Et dans le cas des modèles de vue, le code définit ce que le «client» voit, pas nécessairement les entités et les opérations dont parle l'entreprise. Ainsi, vous dévoilez souvent au client ou à l'interface des modèles qui sont en quelque sorte "incidemment identiques". Vous pouvez modifier les règles et conditions commerciales ou la terminologie de l'utilisateur final indépendamment les uns des autres.

Donc, je vous retourne la question. Si le domaine change, est-il acceptable pour les clients "version 1" de continuer à utiliser les anciennes interfaces? Révélerez-vous jamais des termes ou des opérations dans l'interface qui ne font pas partie des "règles métier de base"? Et vice versa?

Ce genre de questions à l'esprit, si la "fonction" de votre vue est strictement de révéler le modèle de domaine sous-jacent, oui, cela semble violer la règle DRY.

Gardez également à l'esprit que l'exposition d'une vue qui change plus naturellement avec les changements de modèle peut également être effectuée dans certaines langues avec des attributs de membre et une réflexion. (Ou avec moins de répétition par d'autres exploits d'intelligence ... Mais, "l'intelligence" échoue souvent à justifier la répétition qu'elle vous épargne.)

svidgen
la source
Belles notes mentionnées (votez pour cela), comme je l'ai dit en commentaire de la réponse précédente, je parle d'utilisation générale, d'imagerie, peut-être quelques jours plus tard, j'ai décidé d'ajouter un nouveau champ / propriété Foo, donc si je l'utilisais Foocomme ViewModel aussi, le client obtiendra également une nouvelle propriété, alors qu'en est-il si ce nouveau domaine était un domaine de sécurité (peut-être vrai / faux pour la permission, ou quelque chose comme ça), que dois-je faire?
Mehdi Dehghani
@mehdi, vous devrez être plus précis sur le champ que vous envisagez d'ajouter et pourquoi vous pensez qu'il appartient ou non à la vue. Ou en général, quelle est la préoccupation.
svidgen
@mehdi pour être clair, si vous craignez que les utilisateurs finaux changent une valeur de sécurité, votre domaine ne devrait tout simplement pas permettre aux utilisateurs d'enregistrer des choses qu'ils ne sont pas autorisés à enregistrer
svidgen
Pourquoi utilisons-nous ViewModels? il y a certaines raisons, comme nous le savons, l'une d'entre elles est pour la sécurité, par exemple, dans User edit form, nous n'avons pas besoin de transmettre le IsAdminchamp au client, pour garder ce champ sécurisé, c'est donc ce qui m'inquiète. Désolé pour mon mauvais anglais.
Mehdi Dehghani
1
Autrement dit, je pense que la question d'origine est une question complète. La question que vous essayez de comprendre dans les commentaires ici est une autre question complète. Et les commentaires ne sont pas un bon moyen d'obtenir de bonnes réponses de qualité.
svidgen
2

J'aurais un modèle de vue qui contenait une seule propriété, une instance de Foo. De cette façon, vous ne violez DRY selon aucune définition de celui-ci, si Foo change, votre modèle de vue voit automatiquement le changement, et vous vous laissez libre d'une liaison directe du modèle de vue au modèle.

Si demain il est nécessaire que la vue montre autre chose ainsi que le Foo, vous pouvez simplement ajouter une nouvelle propriété, et l'intention de votre modèle de vue sera toujours claire, il contient un Foo et autre chose, vous n'aurez pas un mélange de propriétés de Foo avec d'autres propriétés indépendantes.

Je ne considérerais pas votre modèle de vue comme un FooViewModel, je le considérerais en termes de ce que la vue est censée afficher. S'il n'affiche qu'un Foo, le modèle de vue contient une propriété, un Foo.

Je ne sais pas si je l'ai expliqué clairement. Sinon, faites-le moi savoir et je vais essayer de le reformuler quand je suis réveillé!

Avrohom Yisroel
la source
-2

Je dirais que l'utilisation FooViewModelde cette manière viole le principe DRY. Lorsque vous devez apporter une modification, Foovous devez également effectuer une modification FooViewModel. Je pense que vous seriez mieux servi simplement en utilisant Foocomme modèle votre point de vue. Je considérerais un modèle de vue si vous avez besoin d'afficher des choses de Foo et quelque chose d'autre. Par exemple, supposons que vous ayez besoin de restituer certaines informations à partir Fooet à partir de Bar.

zero_dev
la source
S'il vous plaît dites-moi, si j'ai décidé d'ajouter un autre champ / propriété au Foo, donc parce que j'ai Fooaussi utilisé comme ViewModel, donc je dois aussi passer ce nouveau champ à la vue, je pense que ce n'est pas vraiment une bonne affaire, qu'en pensez-vous ?
Mehdi Dehghani
Je ne vois rien de mal à ce que la vue n'utilise qu'un sous-ensemble des données exposées par le modèle. Je pense que la plus grande faute est le couplage entre Fooet FooViewModel. Généralement, ce n'est pas une bonne idée de devoir modifier plusieurs fichiers pour une seule modification logique.
zero_dev
Qu'en est-il si ce champ ajouté était un champ de sécurité, comme une true/falsevaleur d'autorisation ou quelque chose comme ça.
Mehdi Dehghani
Vous n'avez pas à exposer ces champs dans la vue elle-même, mais vous devez toujours vous assurer que le reste de votre code ne permet pas à l'utilisateur de modifier son niveau de sécurité, au cas où un utilisateur malveillant essaierait de POSTER une telle modification.
Graham
On dirait qu'il serait ouvert aux attaques par affectation de masse
James