MVC: où mettre la logique des affaires?
tout d'Abord, j'ai vu beaucoup de questions, mais pas assez raisonnement derrière cela. Si ma question n'est pas assez bonne et doit être retirée, je comprendrai.
j'ai jeté un oeil, par exemple, ce et une réponse de 45+ voté dit qu'il vous conseille de mettre la logique de l'entreprise dans le modèle, ce qui semble assez logique.
Cependant, mon premier grand projet que j'ai fait avec tous mes BL complètement dans les controllers, parce que je n'ai pas questionné ces choses et regardé comment il est fait dans le AccountController
qui est le automatiquement ajouté si vous choisissez MVC avec l'authentification de forme. Toutes les méthodes ont l'air pleines de BL. Ou peut-être est-ce la moindre quantité de code possible à ajouter et j'oublie les choses?
une personne sur youtube m'a demandé s'il avait raison en mettant toute la logique dans ses modèles et au début je n'étais pas! Puis j'ai commencé à pensant que peut-être il avait raison!?
donc, après tout, Où dois-je mettre ma logique commerciale? si c'est dans les classes de modèles, alors, combien de code devrait être considéré comme une quantité saine dans une méthode qui est dans le contrôleur? Une ligne pour appeler une méthode du model dans un controller tout au plus et ensuite un retour à la vue?
10 réponses
je préfère mettre la logique du domaine dans le modèle pour quelques raisons.
-
le modèle ne doit pas comporter de code D'UI et doit donc être plus facile à tester. Dans la mesure du possible, j'aime avoir un modèle entièrement fonctionnel (c'est-à-dire une couverture complète du test) avant d'écrire un code D'assurance-chômage. Le contrôleur peut avoir confiance que le modèle fait la bonne chose et juste traiter les préoccupations D'UI.
-
si vous mettez la logique de domaine dans un contrôleur, ce n'est pas aussi facile à partager entre différentes applications, ou même entre différents contrôleurs.
j'aime garder mes modèles propres. Juste avec des propriétés et pas de logique commerciale. Je pense toujours qu'il est bon d'injecter des dépendances dans le contrôleur et ces dépendances contiennent la logique que j'exécute sur mes modèles. J'aime adhérer au principe de la responsabilité unique lorsque c'est possible et je trouve que les modèles avec des tonnes de méthodes se gonflent très rapidement. Il ya des avantages et des inconvénients pour les deux, l'injection d'un grand nombre de dépendances a un overhead mais permet de tester en isolement et garde les classes simples et vous finirez par avoir des contrôleurs plus maigres. En dépit de ma logique n'existant pas réellement sur mon modèle en tant que membres de la classe, sa logique toujours d'affaires. J'ai tendance à ne pas avoir de logique d'affaires définie dans le contrôleur comme moquant des choses comme le Httpcontext sont un peu un cauchemar et inutile.
la logique business appartient au domaine du problème et tout ce qui appartient au domaine du problème va au modèle dans MVC.
le contrôleur doit être responsable de la transmission des données du modèle vers la vue et de la vue vers le modèle. Le contrôleur est donc le pont entre ce avec quoi l'utilisateur interagit et comment le programme modélise et stocke l'état du problème. Le plomberie , pour ainsi dire.
la clé ici est la distinction entre la logique d'affaires et la logique de plomberie. À mon avis, ce que le contrôleur de Compte autogénéré fait est la plupart du temps plomberie, pas vraiment logique d'affaires. Gardez à l'esprit que la logique de plomberie n'est pas nécessairement courte du tout, de sorte que vous n'avez pas besoin d'imposer des limites artificielles (comme "X nombre d'appels au plus dans le contrôleur").
mon équipe lors du déplacement à mvc de webforms (asp.net) a fait de nombreuses recherches et a abouti à la structure suivante. Selon moi, il ne s'agit pas de la taille de l'application. Il s'agit de garder le code propre et clair.
DALProject
AccountsDAL.cs --- > Calls SP or any ORM if ur using any
BLLProject
AccountsBLL.cs ---> Calls DAL
WebProject
Model
AccountsModel --- > Contains properties And call BLL
Controllers
IndexController ---> Calls Models and returns View
Views
Index
les contrôleurs devraient être responsables du passage des données entre le modèle et la vue. En dehors de cela, il ne devrait pas y avoir de code inutile. Par exemple, si vous vous connectez, il devrait être fait au niveau du modèle, plutôt que de contrôleur.
Il semble y avoir une certaine confusion autour de ce sujet. La plupart du temps, il semble que les gens ont tendance à confondre le modèle MVC avec l'architecture n-tier comme une ou/ou situation. La réalité est que les deux approches peuvent être utilisées ensemble, mais on n'est pas dépendant de l'autre et il n'est ni nécessaire.
architecture N-tiers est concerné par séparation d'une application en plusieurs couches. Un exemple simple est lorsque l'application est scindée en une couche de présentation, une la couche logique métier, et une couche d'accès aux données.
MVC est un dessin ayant trait à la couche de présentation d'une application. Il est tout à fait possible de concevoir une application en suivant une approche MVC sans séparer la logique d'affaires et la logique d'accès aux données de la couche de présentation et ainsi finir avec une conception à un seul niveau.
le résultat, si vous suivez une approche MVC sans séparer également l'application en niveaux est que vous se retrouver avec des modèles, des vues, et des contrôleurs qui ont des bits de règles d'affaires et la logique d'accès aux données mélangées avec le reste de la logique.
par définition, dans une architecture n-tier, le niveau de présentation n'est censé être capable de communiquer qu'avec la couche logique de l'entreprise, de sorte qu'il devrait être soutenu que n'importe lequel des composants MVC ne peut communiquer qu'avec la couche logique de l'entreprise.
si vous construisez une application qui ne nécessite pas présentation, et donc pas une couche de présentation, vous ne devriez pas avoir à vous préoccuper du modèle MVC. Cependant, vous pouvez très bien diviser votre application en plusieurs niveaux et donc suivre un design N-tier même s'il n'y a pas de couche de présentation impliquée.
j'aime aussi garder mes modèles propres (réf: @Mark Walsh). Le problème de ne pas être capable de réutiliser la logique intégrée dans les controllers peut facilement être surmonté par l'injection de dépendances, ou, si vous pensez qu'il y aurait trop de cela, exposer votre logique d'entreprise/domaine à travers des interfaces et utiliser le motif de façade dans les controllers. De cette façon, vous obtenez la fonctionnalité dont vous avez besoin, mais garder les contrôleurs et le modèle nice et propre.
en général, la logique d'affaires ne devrait pas résider dans les joueurs MVC; elle ne devrait être consommée par vos actions de contrôleur.
comme beaucoup l'ont mentionné, il est préférable de créer une bibliothèque pour héberger la logique d'affaires comme un ensemble de clients agnostiques, composants réutilisables.
de cette façon, nous augmentons considérablement la réutilisabilité, la compatibilité, l'évolutivité et la testabilité avec notre logiciel. Nous réduisons également nos dépendance à l'égard de certaines caractéristiques du cadre, ce qui facilite la migration vers des technologies nouvelles ou différentes.
L'abstraction de notre logique commerciale en une assemblée (ou des assemblées) autonome nous a bien servi au fil des ans. Notre logique d'entreprise peut alors être consommée par pratiquement n'importe quelle technologie. ASP.NET MVC/API / Core, WPF, Win Forms, WCF, UWP, WF, Console, etc.).
en outre, nous aimons notre niveau intermédiaire pour gérer la règle d'affaires et la logique de validation pour réduire nos dépendances sur le cadre MVC de .NET. Par exemple, nous évitons d'utiliser les assistants de validation MVCs de .NET et nous nous en remettons aux nôtres. C'est un autre facteur qui nous permet de consommer facilement notre logique d'affaires à partir de n'importe quelle technologie.net.
la conception logique de notre niveau intermédiaire de cette façon nous a permis d'atteindre facilement cette architecture physique:
It a été écrit avec Peasy.NET , et nous a bien servis au fil des ans. Tellement bien en fait que nous avons décidé de l'ouvrir.
si quelqu'un est curieux de savoir à quoi ressemble notre niveau intermédiaire, voici un échantillon d'un client agnostique, couche d'affaires. Il présente également la consommation de TI par de multiples clients. net (ASP.NET MVC, Web Api, et WPF).
Espérons que cela aide quelqu'un!
je préférerais aussi garder les modèles propres. Les contrôleurs MVC ne doivent être utilisés que pour faire des appels et doivent également être maintenus propres. Ainsi, selon sa réutilisabilité, sa sensibilité et sa pertinence, la logique commerciale peut être écrite en
1.Contrôleur WebApi: l'avantage d'utiliser un contrôleur webapi est que vous pouvez exposer ces services plus tard à d'autres appareils rendant votre code réutilisable.
2. BAL / common common common commonent: il existe certaines logiques qui ont un usage spécifique et ne peuvent pas être exposées en tant qu'api, peut être poussé dans cette classe.
3. Dépôt: toutes les requêtes relatives à la base de données sont ajoutées dans un dépôt. Il peut y avoir un dépôt générique qui implémentera toutes les fonctions (opérations CRUD)ou des dépôts spécifiques pour chaque table. Dépendre les opérations à effectuer.
comme ahanusa a écrit, vous devez mettre vos logiques d'affaires dans DLL séparée ou répertoire séparé.
J'utilise souvent un répertoire nommé Logics au même niveau de Models et Controllers où je mets des classes qui font de la logics business.
De cette façon, je laisse les modèles et les contrôleurs nettoyer.
je sais que c'est une question à propos de MVC, mais je pense que l'exemple que je donne (API Web) sera utile.
je développe ma première API Web et je réutilise la logique commerciale d'autres applications. Pour être précis, il vient d'une DLL externe, donc mon API est utilisé juste pour "parler" avec une solution SAP, recevoir des requêtes de PO et envoyer des réponses.
comment mettre ma logique (déjà implémentée) dans mon contrôleur? Je n'ai pas besoin. Mon contrôleur ne recevra, ne validera que les requêtes et ne rédigera des réponses que pour renvoyer les données.
je travaille avec les classes ViewModel et tout ce qu'ils doivent avoir est une fonction de mapping, juste pour lire les informations de TransferObjects (qui vient de la DLL externe) et traduire en un ViewModel.
Je ne suis pas à l'aise avec mon application (dans ce cas-ci L'API Web) avec la logique d'affaires, je pense que la réutilisation sera perdue de cette façon.
je traite ma logique d'entreprise comme une dépendance que j'injecte dans controller.
j'ai fait beaucoup de remaniement dans le legacy pour fournir une solution Testable Unité, j'ai dû créer beaucoup d'interfaces et mettre en œuvre quelques modèles de conception dans le legacy pour fournir cette solution.
de mon point de vue, la couche affaires doit faire partie de l'application, de préférence dans une autre bibliothèque de classe. Vous aurez donc un vrai concept de séparation implémenté dans votre application.
bien sûr, si votre cœur de métier est votre application (API/site Web) , les règles d'affaires seront mises en œuvre dans vos classes MVC. Mais à l'avenir, si vous souhaitez développer une nouvelle application et de certaines règles de gestion sont les mêmes, je parie que vous aurez beaucoup de problèmes pour maintenir la même logique mise en œuvre dans les deux applications.