Pourquoi mettre la logique métier dans le modèle? Que se passe-t-il lorsque j'ai plusieurs types de stockage?

70

J'ai toujours pensé que la logique métier devait être dans l'automate et que l'automate, puisqu'il s'agit de la partie "centrale", restait statique et que le modèle / vue devait être encapsulé via des interfaces. De cette façon, vous pouvez modifier la logique métier sans affecter rien d'autre, programmer plusieurs modèles (un pour chaque base de données / type de stockage) et une douzaine de vues (pour différentes plates-formes, par exemple).

Je lis maintenant dans cette question que vous devez toujours intégrer la logique métier dans le modèle et que le contrôleur est profondément connecté à la vue.

Pour moi, cela n'a pas vraiment de sens et implique que chaque fois que je veux avoir les moyens de prendre en charge une autre base de données / type de stockage, je dois réécrire tout mon modèle, y compris la logique métier.

Et si je veux une autre vue, je dois réécrire à la fois la vue et le contrôleur.

Peut-on expliquer pourquoi ou si je me suis trompé quelque part?

Steffen Winkler
la source

Réponses:

69

La réponse d’ElYusubov est claire , la logique de domaine doit aller dans le modèle et la logique d’application dans le contrôleur.

Deux clarifications:

  • Le terme logique métier est plutôt inutile ici, car il est ambigu. La logique métier est un terme générique désignant toute la logique qui intéresse les hommes d’affaires, la séparant de simples aspects techniques tels que la manière de stocker des éléments dans une base de données ou de les restituer sur un écran. La logique de domaine ("une adresse e-mail valide ressemble à ...") et les flux de travail / processus métier ("lorsqu'un utilisateur s'inscrit demande son adresse e-mail") sont considérés comme une logique métier, le premier appartenant clairement à la liste. modèle et le dernier étant la logique d'application qui va dans le contrôleur.
  • MVC est un modèle pour mettre des choses sur un écran et permettant à l'utilisateur d'interagir avec elle, elle ne précise pas le stockage du tout . La plupart des frameworks MVC sont des frameworks full stack qui vont au-delà du simple MVC et vous aident à stocker vos données. Etant donné que les données devant être stockées se trouvent généralement dans le modèle, ces frameworks vous offrent des moyens pratiques de stocker votre modèle. données dans une base de données, mais cela n'a rien à voir avec MVC. Idéalement, les modèles doivent être agnostiques vis-à-vis de la persistance et le passage à un type de stockage différent ne devrait pas affecter du tout le code du modèle. Les architectures à part entière ont une couche de persistance pour gérer cela.
Waquo
la source
4
La plupart des frameworks MVC mélangent en quelque sorte tout le matériel de stockage / base de données dans le modèle afin de faciliter le stockage de vos modèles (souvent en vous obligeant à étendre la classe de modèles frameworks). C'est probablement la source de confusion. Techniquement, le code de modèle que vous écrivez devrait être le modèle actuel (couche de domaine), alors que le code fourni par la structure devrait traiter du stockage (couche de persistance). Par exemple, quelque chose comme User.find (...) (avec User en tant que modèle) fonctionne car la structure a implémenté le modèle de référentiel dans le cadre du modèle.
Waquo
3
View-Controller-Model-Storage est le principe général (bien que la relation entre M, V et C doive être visualisée sous forme de triangle). Lorsque votre infrastructure mélange le stockage à son "modèle", son fonctionnement est semblable à celui-ci: View-Controller- (Le modèle hérite du stockage de la structure).
Waquo
2
View-Controller-Model-Storage est plutôt brutal, car il ne devrait pas être plat. Par exemple, lorsqu'un contrôleur effectue quelque chose comme User.find (...) pour obtenir un modèle, il demande directement à la couche de stockage plutôt que de passer par la couche de domaine.
Waquo
2
Dans les architectures avec une superposition plus minutieuse, ce serait quelque chose comme UserRepository.find (). Par "modèle", j'entendais la classe "modèle" fournie par le cadre dont vous héritez. L'objet User renvoyé par User.find () est un modèle d'utilisateur en ce sens que quelqu'un modélise ce qu'est un utilisateur, comment il se comporte ...
mercredi
1
La logique commerciale @flipdoubt est une logique qui devrait rester la même si vous avez porté depuis mvc pour indiquer une application uwp.
Andy
23

Vous et de grandes parties du monde de la programmation semblent mal comprendre les rôles des parties MVC. En bref, ils sont:

Modèle = logique de domaine

Vue = logique de sortie

Contrôleur = logique d'entrée

Cela signifie que le modèle est responsable de toute la logique métier: tout ce qui est lié au dessin de widgets sur un écran, au pilotage d'une imprimante, à la sortie de données au format HTML, à l'analyse de requêtes HTTP, etc. n'appartient pas au modèle.

Cependant, de nombreux frameworks dits "MVC" modernes ne font pas du tout MVC, ou ils étiquettent mal leurs pièces. Très souvent, on appelle "modèle" la couche de persistance du modèle, tandis que la logique métier se situe dans ce qu'ils appellent le "contrôleur"; le contrôleur actuel est généralement un simple point d’entrée central avec une table de routage et un bit de code dans les "contrôleurs" individuels afin d’envoyer les données qu’ils reçoivent aux processus métier appropriés. Ce que ces frameworks appellent "view" représente en réalité un peu de tout: une logique de présentation (View), un peu de manipulation et de validation des entrées (Controller), et un peu plus de logique métier (Model). La part du lion de la vue réelle est généralement appelée "modèles".

Vous voudrez peut-être aussi en savoir plus sur l’architecture à plusieurs niveaux; où MVC est un peu à sens unique (le flux est Contrôleur -> Modèle -> Vue), le mode multiniveau est bidirectionnel (Présentation -> Logique -> Données -> Logique -> Présentation), et plusieurs les frameworks qui prétendent faire MVC font réellement trois niveaux, ré-étiquetant Presentation to View, Logic to Controller et Data to Model.

tdammers
la source
2
Je crois que vous représentez de manière erronée le modèle ("Model = domain logic"). Pour moi, il s’agit plus d’un vecteur de peuplement avec des données, qui sont ensuite restituées à l’aide d’une vue, dans la forme la plus pure du modèle MVC. Bien sûr, dans des cas d'utilisation très simples, vous pouvez le traiter comme une "logique de domaine", mais je vous garantis que la plupart des systèmes existants mériteraient d'être dépassés très rapidement. Mieux vaut diviser la "logique de domaine" en une couche / classe séparée, par exemple une couche de service.
A. Murray
@ A.Murray: Bien entendu, le modèle ne doit pas nécessairement être un bloc de code monolithique, et le séparer de la persistance, des structures de données et de la logique de domaine a généralement beaucoup de sens. Néanmoins, MVC regroupe ces trois préoccupations dans le modèle. Dans tous les cas, lorsque vos contrôleurs et vos vues contiennent une logique de domaine, ce n'est plus un réel MVC.
tdammers
@ Tdammers, j'aime la propreté de votre réponse et son accent mis sur la logique. À votre avis, à quoi appartiennent les préoccupations d'applications telles que la persistance et le traitement des transactions? On dirait que MVC devrait être un acronyme de quatre lettres comme MVCS où le S est pour le service.
flipdoubt le
15

Pour vraiment isoler la logique métier et la séparer de l'infrastructure de la couche de présentation, celle-ci doit être encapsulée par des services d'application. L'architecture MVC est un moyen d'implémenter la couche de présentation et elle doit rester dans cette étendue, en déléguant toute la logique métier à ces services d'application. Considérez les modèles de vue comme des adaptateurs entre la vue et les données devant être affichées et lues. Le contrôleur gère l’interaction entre les modèles de vue, les vues et les services d’application hébergeant la logique d’entreprise.

Les services d'application implémentent des cas d'utilisation métier et sont découplés de la couche de présentation, que ce soit MVC ou autre chose. À leur tour, les services d’application peuvent héberger des scripts de transaction ou une conception pilotée par un domaine .

Pour le stockage, le service d'application peut référencer un référentiel ou toute abstraction d'un mécanisme de persistance. Différentes implémentations peuvent être prises en charge en résumant l’accès aux données dans une interface. En règle générale, ces abstractions présentent des fuites et ne sont que partiellement portables entre les implémentations, ce qui est souvent une tentative futile d’atteindre la portabilité totale.

MISE À JOUR

Ma suggestion est basée sur l' architecture hexagonale . Dans une architecture hexagonale, votre modèle de domaine (logique métier) est au cœur de vos préoccupations. Ce noyau est encapsulé par des services d’application qui agissent comme une façade . Les services d'application sont des classes simples dont les méthodes correspondent aux cas d'utilisation de votre domaine. Pour une discussion approfondie sur les services d’application, reportez-vous à Services dans la conception par domaine . L'exemple de code contient un PurchaseOrderServicequi est un service d'application pour un domaine d'achat. (Notez qu'un service d'application n'implique pas l'utilisation d'une conception pilotée par un domaine.)

Dans une architecture hexagonale, une couche de présentation MVC est un adaptateur entre votre modèle de domaine (logique métier) et une interface graphique. Le modèle de domaine ne connaît pas la couche de présentation, mais la couche de présentation connaît le modèle de domaine.

Cette solution comporte certes des pièces en mouvement qu’une solution qui place la logique d’entreprise dans le contrôleur et vous devez en peser les inconvénients et les avantages. La raison pour laquelle je le suggère est que je préfère laisser la logique métier découplée de la couche de présentation afin de lutter contre la complexité. Cela devient plus important à mesure que l’application se développe.

eulerfx
la source
On dirait que vous décrivez un bâtard de MVC et MVVM qui possède à la fois des contrôleurs et des modèles de vue. De plus, je pense que l'architecture que vous décrivez est peut-être un peu lourde pour les besoins de OP.
Waquo
pour être honnête, j'aime davantage la réponse de Waquo. Principalement parce que je n'ai aucune idée de ce que vous entendez par «services d'application». Pourriez-vous expliquer ce terme? Mon GoogleFU ne fonctionne pas ici comme il semble.
Steffen Winkler
1
@Waquo Je conviens que l'architecture proposée est peut-être excessive, mais elle devrait être prise en compte. Je n'ai fait aucune mention de MVVM, qui est simplement un autre moyen d'implémenter une couche de présentation. Les services d’application s’appliquent que vous utilisiez MVC ou MVVM et rien de ce que je vous ai suggéré n’indique une combinaison des deux.
eulerfx
1

Cela dépend de ce que vous entendez par logique métier. Toute "logique" qui donne un sens au contenu du modèle devrait être dans le modèle. Dans la question liée, la réponse la plus votée semble définir la "logique métier" comme tout ce qui concerne les données; cela semble logique du point de vue que les données d'une entreprise sont ses affaires!

J'ai déjà vu un exemple du créateur de Rails (je pense) qui parlait exactement de cela, sans mettre de "logique commerciale" dans le modèle. Son exemple était une classe de contrôleur et une méthode d'enregistrement et de connexion d'application - un mot de passe fourni en texte brut était crypté avant d'être inséré ou interrogé dans le modèle (une base de données).

Je ne peux pas penser à un meilleur exemple de quelque chose qui n'est pas une logique de contrôleur et qui appartient directement au modèle.

Le modèle pourrait être une interface avec une myriade de magasins de données, atténuant les problèmes de portabilité. C'est ici que l'on pourrait trouver une confusion sur le fait que l'interface de modèle soit réellement le "contrôleur".

De manière générale, le contrôleur lie le modèle et la vue (qui sont les éléments essentiels de l'application). Dans le développement de Cocoa, il peut être simpliste au point que le contrôleur soit géré via l'interface graphique XCode (objets et liaisons de contrôleur).

La section "Design Patterns" du GoF sur MVC, vaguement citée:

Le triade de classes MVC est utilisé pour créer des interfaces utilisateur dans Smalltalk-80. Le modèle est l'objet d'application, la vue est sa présentation à l'écran et le contrôleur définit la façon dont l'interface utilisateur réagit à l'entrée de l'utilisateur. MVC dissocie les vues et les modèles en établissant un protocole de souscription / notification entre eux. Le diagramme suivant montre un modèle et trois vues. Nous avons laissé de côté les contrôleurs pour des raisons de simplicité.

MVC est tout au sujet des interfaces utilisateur. L'accent est mis sur le modèle et la vue - définition et affichage des données. Notez le "protocole abonnement / notification" - c’est là que votre contrôleur entre en jeu. Vous pouvez créer toutes les vues souhaitées; tant qu'ils adhèrent au protocole, vous ne devez jamais toucher le modèle ou le contrôleur.

Si vous parlez de développement Web en particulier, à mon humble avis, de nombreux frameworks Web populaires utilisent rapidement le terme MVC et ses définitions de composants.

Duc
la source
Je suis un développeur C # / Java (quelques projets seulement). Il semble que j'ai mal compris ce que fait le modèle. Mettre la «logique métier» dans le contrôleur n’était vraiment qu’une conséquence (ma pensée s’est alliée), j’ai le modèle de données (lire: connexion / stockage de base de données), ma logique d’entreprise doit donc entrer dans le contrôleur car Je dois l'appliquer avant de stocker les données dans la base de données. "Il suffit de tout déplacer d'un niveau vers le bas du contrôleur. En fait, cela résout un problème que je rencontrais actuellement (prise en charge de MySQL et de MSSQL dans un programme)
Steffen Winkler
0

Pourquoi n'introduisez-vous pas une couche de service?

Ensuite, votre contrôleur sera maigre et plus lisible, alors toutes vos fonctions de contrôleur seront des actions pures.

Vous pouvez décomposer la logique métier autant que vous le souhaitez au sein de la couche de service. La réutilisation du code est meilleure et il n'y a aucun impact sur les modèles et les référentiels.

Anil
la source