Où la" couche logique métier " s'intègre-t-elle à une application MVC?
Tout d'abord, avant que quelqu'un ne crie dupe, j'ai eu du mal à le résumer dans un simple titre. Un autre titre aurait pu être " Quelle est la différence entre un modèle de domaine et un modèle MVC?"ou "qu'est Ce qu'un modèle?"
Conceptuellement, je comprends qu'un modèle soit les données utilisées par les vues et le contrôleur. Au-delà de cela, il semble y avoir beaucoup d'opinions divergentes sur ce qui constitue le modèle. Qu'est ce qu'un modèle de domaine, par rapport à un modèle d'application, par rapport à un modèle de vue, par rapport à un modèle de service, etc..
Par exemple, dans une question récente que j'ai posée sur le modèle de référentiel, on m'a dit à bout portant que le référentiel faisait partie du modèle. Cependant, j'ai lu d'autres opinions selon lesquelles le modèle devrait être séparé du modèle de persistance et de la couche de logique métier. Après tout, le modèle de référentiel n'est-il pas censé découpler la méthode de persistance concrète du modèle? D'autres personnes disent qu'il existe une différence entre le modèle de domaine et le modèle MVC.
Allons-y. prenez un exemple simple. Le AccountController qui est inclus avec le projet par défaut MVC. J'ai lu plusieurs opinions selon lesquelles le code de Compte inclus est de mauvaise conception, viole SRP, etc.. etc.. Si l'on devait concevoir un modèle d'adhésion "approprié" pour une application MVC, que serait-ce?
Comment sépareriez-vous le ASP.NET services (Fournisseur D'adhésion, fournisseur de rôles, etc..) à partir du modèle? Ou voulez-vous en tout?
La façon dont je le vois, le modèle devrait être "pur", peut-être avec la logique de validation.. mais devrait être séparé des règles métier (autres que la validation). Par exemple, disons que vous avez une règle qui dit que quelqu'un doit être envoyé par courriel lorsqu'un nouveau compte est créé. Cela n'a pas vraiment sa place dans le modèle à mon avis. Alors, où est-ce?
Quelqu'un veut faire la lumière sur cette question?
4 réponses
La façon dont je l'ai fait - et je ne dis pas que c'est bien ou mal, c'est d'avoir mon point de vue et ensuite un modèle qui s'applique à mon point de vue. Ce modèle a seulement ce qui est pertinent pour ma vue-y compris les annotations de données et les règles de validation. Le contrôleur ne contient que la logique de construction du modèle. J'ai une couche de service qui abrite toute la logique métier. Mes contrôleurs appellent ma couche de service. Au - delà, c'est ma couche de référentiel.
Mes objets de domaine sont logés séparément (dans leur propre projet, réellement). Ils ont leurs propres annotations de données et règles de validation. Mon référentiel valide les objets de mon domaine avant de les enregistrer dans la base de données. Parce que chaque objet de mon domaine hérite d'une classe de base qui a une validation intégrée, mon référentiel est générique et valide tout (et nécessite qu'il hérite de la classe de base).
Vous pourriez penser qu'avoir deux ensembles de modèles est une duplication de code, et c'est dans une certaine mesure. Mais, il y a tout à fait raisonnable cas où l'objet de domaine n'est pas approprié pour la vue.
C'est le cas lorsque je travaille avec des cartes de crédit-je dois exiger un cvv lors du traitement d'un paiement, mais je ne peux pas stocker le cvv (c'est une amende de 50 000 $pour le faire). Mais, je veux aussi que vous puissiez modifier votre carte de crédit-changement d'adresse, de nom ou de date d'expiration. Mais vous n'allez pas me donner le numéro ou le cvv lors de l'édition, et je certainement ne vais pas mettre votre numéro de carte de crédit en clair sur le page. Mon domaine a ces valeurs requises pour enregistrer une nouvelle carte de crédit parce que vous me les Donnez, mais mon modèle d'édition n'inclut même pas le numéro de carte ou cvv.
Un autre avantage pour tant de couches est que si elles sont correctement architecturées, vous pouvez utiliser structuremap ou un autre conteneur IoC et échanger des pièces sans affecter votre application.
À mon avis, le code du contrôleur ne devrait être que du code ciblé sur la vue. Montrez ceci, cachez cela, etc. La couche de service doit abriter la logique métier de votre application. J'aime avoir tout cela en un seul endroit, il est donc facile de changer ou de modifier une règle d'affaires. La couche de référentiel doit être relativement stupide-dépourvue de logique métier et interroger uniquement vos données et renvoyer vos objets de domaine. En séparant les modèles de vue du modèle de domaine, vous avez beaucoup plus de flexibilité en ce qui concerne les règles de validation personnalisées. Cela signifie également que vous n'avez pas à vider chaque donnée dans votre vue dans les champs cachés et à la repousser et-vient entre le client et le serveur (ou reconstruire sur le backend). Votre modèle de vue ne hébergera alors que les informations pertinentes à la vue - et il peut être personnalisé pour avoir des bools pour la logique de vue ou des comptes ou des énumérations afin que la vue elle-même ne soit pas encombrée d'instructions logiques compliquées comme
<% if (!String.IsNullOrEmpty(Model.SomeObject.SomeProperty) &&
Model.SomeObject.SomeInt == 3 && ...) { %>
Bien que tout semble étalé et superposé, il a un but pour être architecturé de cette façon. Est-il parfait? Pas vraiment. Mais je le préfère à certains modèles passés de appeler des référentiels à partir du contrôleur et avoir une logique métier mélangée dans le contrôleur, le référentiel et le modèle.
Je me suis trop souvent demandé comment exactement les éléments MVC s'intégraient dans une structure d'application web traditionnelle, où vous avez des vues (pages), des contrôleurs, des services et des objets de données (modèle). Comme vous l'avez dit, il existe de nombreuses versions de cette.
Je crois que la confusion existe en raison de l'architecture largement acceptée ci-dessus, qui utilise le "modèle de domaine anémique" (présumé) - anti. Je n'entrerai pas dans beaucoup de détails sur "l'anti-patternness" du modèle de données anémique (vous pouvez regarder un effort de moi pour expliquer les choses ici (basé sur Java, mais pertinent pour n'importe quelle langue)). Mais en bref, cela signifie que notre modèle ne contient que des données et que la logique métier est placée dans services / managers.
Mais supposons que nous ayons architecture pilotée par le domaine, et nos objets de domaine sont comme ils devraient l'être-ayant à la fois une logique d'état et une logique métier. Et dans cette perspective axée sur le domaine, les choses se mettent en place:
- , la vue est l'INTERFACE utilisateur
- le contrôleur rassemble les entrées de l'INTERFACE utilisateur, invoque des méthodes sur le modèle, et envoie une réponse à l'INTERFACE utilisateur
- le modèle est nos composants métier-contenant les données, mais ayant également une logique métier.
Je suppose que cela répond à vos questions principales. Les choses se compliquent lorsque nous ajoutons d'autres couches, comme la couche de référentiel. Il est souvent suggéré qu'il devrait être invoqué par la logique métier placée dans le modèle (et donc chaque objet de domaine a une référence à un référentiel). Dans le mon article que j'ai lié je soutiens que ce n'est pas tout à fait une meilleure pratique. Et qu'en fait, c'est pas une mauvaise chose d'avoir une couche de service. En passant, la conception pilotée par le domaine n'exclut pas la couche de service, mais elle est supposée être "mince" et ne coordonner que les objets de domaine (donc pas de logique métier).
Pour le paradigme du modèle de données anémique, qui est largement adopté (pour le bien ou pour le mal), le modèle serait à la fois la couche de service et vos objets de données.
, À mon avis,
Modèle -
Ne devrait pas contenir de logique métier, il devrait être enfichable(scénario de type WCF). Il est utilisé pour lier à vue, il devrait avoir des propriétés.
Logique Métier -
Il devrait être placé à "couche de services de domaine" , c'est une couche distincte tout à fait. En outre, ajoutera une couche de plus ici "Application Services".
App Services parle à Domain Services layer pour appliquer la logique métier, puis enfin renvoyer le modèle.
Donc, Le contrôleur demandera au service D'Application pour le Modèle et le flux ira comme,
Controller->Application Services(using domain services)->Model
Le modèle MVC et le Asp.net cadre ne fait aucune distinction sur ce que le modèle devrait être.
Les propres exemples de MS incluent des classes de persistance dans le modèle. Votre question sur l'adhésion étant dans le modèle. Cela dépend. Les classes de votre modèle appartiennent-elles à quelque chose? Existe-t-il un lien entre qui se connecte et quelles données sont affichées? Le filtrage des données fait-il partie d'un système d'autorisations modifiable? La dernière mise à jour ou modification d'un objet fait elle partie de votre domaine comme dans quelqu'un d'autre a besoin de le voir ou quelque chose pour le support backend?
L'exemple d'email est aussi cela dépend. Êtes-vous familier avec domain eventing ou eventing en particulier? Avez-vous un service distinct pour envoyer des e-mails? Le fait d'envoyer un e-mail fait-il partie de votre domaine ou est-ce une préoccupation au niveau de l'application en dehors de la portée de votre système? L'INTERFACE utilisateur de savoir si un courriel a été envoyé avec succès ou pas? Les e-mails qui ne parviennent pas à envoyer ont-ils besoin de nouvelles tentatives? Le contenu de l'email envoyé besoin d'être stocké pour les besoins de support ou de service à la clientèle?
Ces types de questions sont trop larges et subjectives, mais je réponds pour que vous et tous ceux qui vous ont voté puissiez comprendre cela.
Vos besoins / délais / ressources sont tous intégrés à l'architecture de votre système. Même le modèle de revenu peut avoir un effet. Vous devez également tenir compte du modèle que vous photographiez pour. DDD est très différent des applications de persistance en tant que modèle et de tous les slop entre sont également valables pour certaines applications. Êtes-vous de prise de vue pour le test de l'application? Tout cela a un effet.