Où la “couche logique métier” s’intègre-t-elle dans une application MVC?

D’abord, avant que quelqu’un ne crie dupe, j’ai eu du mal à le résumer dans un titre simple. 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 un modèle comme étant 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 opposition à un modèle d’application, à un modèle de vue, à un modèle de service, etc.

Par exemple, dans une question récente concernant le modèle de référentiel, on m’a dit 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 Domain et le modèle MVC.

Prenons un exemple simple. Le AccountController inclus dans le projet par défaut MVC. J’ai lu plusieurs opinions selon lesquelles le code de compte inclus est de mauvaise conception, viole le SRP, etc. etc. Si l’on devait concevoir un modèle d’adhésion “approprié” pour une application MVC, ce serait quoi?

Comment sépareriez-vous les services ASP.NET (fournisseur d’appartenance, fournisseur de rôle, etc.) du modèle? Ou voudriez-vous du tout?

À mon avis, le modèle devrait être “pur”, peut-être avec une logique de validation, mais devrait être distinct des règles commerciales (autres que la validation). Par exemple, disons que vous avez une règle métier qui dit que quelqu’un doit être envoyé par courrier électronique lorsqu’un nouveau compte est créé. À mon avis, cela n’appartient pas vraiment au modèle. Alors, où appartient-il?

Quelqu’un veut-il faire la lumière sur cette question?

La façon dont je l’ai fait – et je ne dis pas que c’est bien ou mal, c’est d’avoir ma vue, puis un modèle qui s’applique à mon sharepoint vue. Ce modèle n’a que ce qui est pertinent pour ma vue – y compris les annotations de données et les règles de validation. Le contrôleur héberge uniquement la logique pour construire le modèle. J’ai une couche de service qui héberge toute la logique métier. Mes contrôleurs appellent ma couche de service. Au-delà, c’est ma couche de référentiel.

Mes objects de domaine sont hébergés séparément (dans leur propre projet, en fait). Ils ont leurs propres annotations de données et règles de validation. Mon référentiel valide les objects de mon domaine avant de les enregistrer dans la firebase database. Comme chaque object de mon domaine hérite d’une classe de base pour laquelle la validation est 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 pensez peut-être qu’avoir deux jeux de modèles est une duplication de code, et c’est dans une certaine mesure. Mais, il existe des cas parfaitement raisonnables où l’object de domaine n’est pas approprié pour la vue.

Par exemple, lorsque vous travaillez 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 $). Mais je souhaite également 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 ne vais certainement pas mettre votre numéro de carte de crédit en texte clair sur la page. Mon domaine a ces valeurs requirejses pour enregistrer une nouvelle carte de crédit parce que vous me les donnez, mais mon modèle d’édition ne comprend même pas le numéro de carte ou le CVC.

Un autre avantage de tant de couches est que si elles sont correctement architecturées, vous pouvez utiliser la structure structurelle ou un autre conteneur IoC et échanger des pièces sans nuire à votre application.

À mon avis, le code du contrôleur ne devrait être que le code ciblé sur la vue. Montrez-le, masquez-le, etc. La couche de service doit contenir la logique métier de votre application. J’aime avoir tout cela au même endroit, il est donc facile de modifier ou de modifier une règle d’entreprise. 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 objects de domaine. En séparant les modèles de vue du modèle de domaine, vous disposez d’une plus grande flexibilité en matière de règles de validation personnalisées. Cela signifie également que vous n’avez pas à vider chaque élément de données dans votre vue dans des champs cachés et à le faire passer entre le client et le serveur (ou le reconstruire sur le serveur). Votre modèle de vue ne contiendra alors que les informations pertinentes pour la vue – et il peut être personnalisé pour avoir une logique de vue, des décomptes ou des énumérations afin que la vue elle-même ne soit pas encombrée d’instructions logiques complexes telles que

<% if (!String.IsNullOrEmpty(Model.SomeObject.SomeProperty) && Model.SomeObject.SomeInt == 3 && ...) { %> 

Bien que tout semble étalé et surdimensionné, il a pour but d’être architecturé de cette manière. Est-ce parfait? pas vraiment. Mais je le préfère à certaines conceptions antérieures de référentiels d’appel à partir du contrôleur et à la logique métier mélangée dans le contrôleur, le référentiel et le modèle.

Je me suis souvent demandé comment les éléments MVC pouvaient être intégrés dans une structure d’application Web traditionnelle, dans laquelle des vues (pages), des contrôleurs, des services et des objects de données (modèle) étaient utilisés. Comme vous l’avez dit, il en existe de nombreuses versions.

Je crois que la confusion existe à cause de l’architecture largement acceptée ci-dessus, qui utilise le “modèle de domaine anémique” (modèle présumé) -anti. Je ne vais pas entrer dans les 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)). En bref, cela signifie que notre modèle ne contient que des données et que la logique métier est placée dans les services / gestionnaires.

Mais supposons que nous ayons une architecture pilotée par le domaine , et nos objects de domaine sont tels qu’ils sont censés être – ayant à la fois une logique d’état et une logique métier. Et dans cette perspective axée sur le domaine, les choses entrent en jeu:

  • la vue est l’interface utilisateur
  • le contrôleur rassemble les entrées de l’interface utilisateur, appelle des méthodes sur le modèle et renvoie une réponse à l’interface utilisateur
  • le modèle est constitué de nos composants métier – la possession des données, mais également la logique métier.

Je suppose que cela répond à vos principales questions. Les choses se compliquent lorsque nous ajoutons d’autres couches, comme la couche de référentiel. Il est souvent suggéré de l’appeler par la logique métier placée dans le modèle (et donc chaque object de domaine a une référence à un référentiel). Dans l’article que j’ai lié, je soutiens que ce n’est pas une bonne pratique. Et en fait, ce n’est pas une mauvaise chose d’avoir une couche de service. Par ailleurs, 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 objects 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 meilleur ou pour le pire), le modèle serait à la fois la couche de service et vos objects de données.

À mon avis,

Modèle –

Ne devrait pas contenir de logique métier, il devrait être enfichable (scénario similaire à WCF). Il est utilisé pour se lier à la vue, il devrait avoir des propriétés.

Business Logic –

Il doit être placé sur “Domain Services Layer”, il est complètement séparé. Aussi, appenda une couche supplémentaire ici “Services d’application”.

Les services d’application s’adressent à la couche Services de domaine pour appliquer la logique métier puis retourner le modèle.

Ainsi, le contrôleur demandera à Application Service pour Model et le stream se passera comme suit:

  Controller->Application Services(using domain services)->Model 

Le modèle MVC et le framework Asp.net ne font aucune distinction entre 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 est dans le modèle. Cela dépend. Les classes de votre modèle appartiennent-elles à quelque chose? Existe-t-il un lien entre la connexion et les données affichées? Existe-t-il un filtrage des données d’un système d’permissions modifiable? Est-ce que la dernière mise à jour ou la dernière modification d’un object de votre domaine a été effectuée par quelqu’un d’autre?

L’exemple d’e-mail dépend aussi de cela. Êtes-vous familier avec les événements ou les événements du domaine en particulier? Avez-vous un service séparé pour envoyer des emails? Est-ce que l’envoi de courriers électroniques fait partie de votre domaine ou s’agit-il d’une préoccupation au niveau de l’application en dehors du cadre de votre système? Est-ce que l’interface utilisateur doit savoir si un email a été envoyé avec succès ou non? Les e-mails qui ne parviennent pas à envoyer ont-ils besoin de nouvelles tentatives? Le contenu de l’e-mail envoyé doit-il être stocké pour les besoins d’assistance ou de service client?

Ces types de questions sont trop larges et subjectives, mais je réponds pour que vous et tous ceux qui vous ont voté puissent le comprendre.

Vos exigences / calendriers / ressources se retrouvent dans l’architecture de votre système. Même le modèle de revenu peut avoir un effet. Vous devez également tenir compte du motif que vous visez. DDD est très différent des applications basées sur la persistance et toutes les applications intermédiaires sont également valables pour certaines applications. Tirez-vous pour tester l’application? Tout cela a un effet.