39 votes

MVVM viole-t-il DRY?

Il semble que les ViewModels que j'ai l'air louche, comme les autres classes, et ils semblent demander beaucoup de répétition de code, par exemple, dans un projet en cours, j'ai:

  • SmartForm: Modèle qui représente une des données de formulaire à remplir, possède des propriétés:
    • IdCode
    • Titre
    • Description
    • collection de SmartFormFields
    • etc.
  • SmartFormControlView Vue
  • SmartFormControlViewModel ViewModel
    • IdCode
    • Titre
    • Description
    • collection de SmartFormFields
    • etc.

Donc, mon ViewModel est fondamentalement le même que celui de mon Modèle, juste avec tous les OnPropertyChanged caractéristiques de la liaison avec la Vue.

Il semble que je refactoriser et d'étendre ce que chaque petit changement que j'ai fait pour mon modèle, je dois faire un miroir de changement pour le ViewModel.

Ce qui semble violer une règle de base des habitudes de Ne pas se Répéter.

Suis-je mise en œuvre de la pattern MVVM de manière incorrecte ou est-ce juste une caractéristique inhérente de MVVM qu'il y a toujours un 1-de-1 répétition en cours entre le Modèle et le ViewModel?

23voto

micahtan Points 6457

Personnellement, je ne pense pas qu'il viole SEC, car le modèle et la vue-modèle (je préfère le terme de présentateur) ne pointez pas la même information. Par exemple, votre VM et M les deux ont un Titre de propriété, mais vos VM Titre de propriété pourrait également inclure la validation, alors que votre modèle de Titre de propriété pourrait assumer la validité.

Même s'il est vrai que La machine virtuelle peut contenir toutes les propriétés du modèle, il y a aussi la possibilité d'avoir des validations (par ex. le Titre doit être non vide), les données-dépendances, pouvant être liés à l'INTERFACE utilisateur des propriétés spécifiques (icônes, couleurs, pinceaux, etc.) qui ne font pas partie de la vue.

Essentiellement, tous les UI sont des motifs similaires "duplication" dans la façon dont vous l'état: à savoir une cascade de modifications. Essayez de modifier un modèle MVC sans changer le contrôleur.

Cela étant dit, MVVM (ou de tout motif de l'INTERFACE utilisateur conçue pour séparer l'INTERFACE utilisateur, la logique, et de l'état) peut être trop fastidieux pour les cas simples comme votre exemple. Quand la logique devient un peu plus d'état-passer à travers, la valeur séparant le contrôleur/présentateur/la vue-modèle diminue.

Dans votre cas précis, si il n'y a vraiment aucune logique, de la validation ou de l'INTERFACE utilisateur des propriétés spécifiques que votre VM n'est pas en surface, et votre modèle n'a pas à être conservées, sérialisé, ou fait compatible avec une structure existante (ou en ajoutant la logique de le faire dans votre VM est trivial), je vous encourage vivement à envisager la combinaison de la M et de la machine virtuelle afin d'éviter de créer des propriétés dont le seul but est d'obtenir/définir le modèle sous-jacent de ses propriétés.

3voto

Jose Points 4227

Une solution simple est d'avoir un résumé ViewModel(VM) de la classe de base qui expose le modèle. Vous pouvez choisir cette VM dans les scénarios où il fait sens.

c'est à dire

public abstract class ViewModelBase<T>
{
    public T Model { get; set; }
}

Si votre Modèle a INotifyPropertyChanged mise en œuvre de votre vue d'obtenir l'événement. Cela permet de faire, c'est de donner votre point de Vue de l'accès à tous les biens de votre Modèle qui n'est pas ce que vous voulez un peu de temps.

vous pouvez aussi utiliser la propriété initialiseurs comme ça(personnellement, je l'ai stocké dans des extraits de code):

public abstract class SampleViewModel
{
    public int MyProperty
    {
        get { return Model.MyProperty; }
        set
        {
            Model.MyProperty = value;
            OnPropertyChanged("MyProperty");
        }
    }
}

Dans la plupart des cas, la vue sera celui de faire des changements à votre VM et quand il n'a aucun contrôle qui est lié à celui de la propriété sera alors dit que quelque chose est arrivé.

Espérons que cela aide.

1voto

Thomas Levesque Points 141081

C'est une remarque intéressante... en effet, il est souvent nécessaire de modifier le ViewModel pour refléter les changements dans le Modèle.

Ce serait bien si elle pouvait être automatique... en fait je pense qu'il pourrait être possible, par la mise en œuvre de ICustomTypeDescriptor dans le ViewModel : GetProperties serait de retour de toutes les propriétés du modèle par le biais de la réflexion. Cependant, je ne suis pas sûr que cela aurait du sens, parce que le modèle ne peut pas se composent de propriétés à tous : cela pourrait être des méthodes, champs, ou quoi que ce soit, et de ne pas tout dans le modèle serait utile dans le ViewModel.

1voto

Eric J. Points 73338

D'autres ont fourni de bons commentaires sur les rôles des composants de l'architecture MVC/MVVM modèles. J'aimerais faire une observation fondamentale expliquant la répétitivité peu importe le modèle que vous sélectionnez.

Généralement il y aura une sorte de répétition entre votre couche de données, la couche métier et la couche d'INTERFACE utilisateur. Après tout, en général, vous devez montrer chaque propriété à la fin de l'utilisateur (UI), le modèle c'est le comportement (couche Métier) et persistent la valeur (de la couche de données).

Comme d'autres l'ont souligné, la propriété peut être traité un peu différemment sur chaque couche, ce qui explique la nécessité fondamentale d'un certain nombre de chevauchements.

Lorsque l'on travaille sur des systèmes assez grand (ou sur de petits projets avec l'équipe de droit), j'ai tendance à la modélisation de ce type de renseignements dans UML, et l'utilisation de la génération de code (souvent couplé avec des classes partielles) pour gérer les aspects répétitifs. Comme simple exemple, le Nom de la propriété peut avoir une exigence (dans mon modèle UML) que limiter la quantité de données à 50 caractères. Je peut générer du code pour l'application de cette limite dans ma couche d'INTERFACE utilisateur (par exemple en physique limitant l'entrée), de générer du code dans mon entreprise, la couche de vérifier que la limitation ("ne faites jamais confiance à l'INTERFACE utilisateur"), par exemple, de lancer une Exception si les données sont trop long, et générer ma couche de persistance (par exemple de type NVARCHAR(50) colonne appropriée ORM fichier de mapping, etc.).

Mise à Jour 2012

Microsoft Annotations de Données et leur soutien dans la couche d'INTERFACE utilisateur (par ex. ASP.Net MVC) et sur la couche de données (Entity Framework) va un long chemin vers la mise en œuvre de bon nombre des préoccupations que j'ai déjà le code généré pour.

1voto

Simon Fox Points 5691

Une chose qui semble avoir été omise ici et que votre exemple simpliste n'expose pas est le fait que vos vues agrégeront souvent les données contenues dans plusieurs types de modèle de domaine. Dans ce cas, vos modèles de vue contiendront des références à un certain nombre de modèles de domaine (de types différents), agrégeant ainsi un ensemble de données liées qu’une vue particulière peut souhaiter exposer.

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