web-dev-qa-db-fra.com

Les gros modèles et les contrôleurs maigres ressemblent à la création de modèles de Dieu

J'ai lu beaucoup de blogs qui préconisent l'approche modèles lourds et contrôleurs maigres, en particulier. le camp Rails. Par conséquent, les routeurs déterminent simplement quelle méthode appeler sur quel contrôleur et toute la méthode du contrôleur appelle la méthode correspondante sur le modèle, puis affiche la vue . J'ai donc ici deux préoccupations que je ne comprends pas:

  1. Le contrôleur et le routeur ne font vraiment pas de tâches très différentes autres que d'appeler simplement une méthode sur le modèle divin basé sur l'itinéraire.
  2. Les modèles en font trop. Envoi d'e-mails, création de relations, suppression et modification d'autres modèles, tâches de mise en file d'attente, etc. Fondamentalement, vous avez maintenant des objets semblables à Dieu qui sont censés faire tout ce qui peut ou non concerner la modélisation et le traitement des données.

Où tracez-vous la ligne? N'est-ce pas simplement tomber dans le modèle de Dieu?

87
Jungle Hunter

Ce n'est peut-être pas la meilleure idée de regarder Rails comme un élément de base du modèle de conception MVC. Ce cadre a été fait avec quelques défauts inhérents (je l'ai développé en quelque sorte dans un article différent) ) et la communauté vient tout juste de commencer à lutter contre les retombées. Vous pouvez considérer DataMapper2 développement comme la première étape majeure.

Un peu de théorie

Les personnes qui donnent ces conseils semblent être affectées par une idée fausse assez courante. Alors permettez-moi de commencer par clarifier les choses: Le modèle, dans le modèle de conception MVC moderne, n'est PAS une classe ou un objet. Le modèle est une couche.

L'idée principale derrière le modèle MVC est Séparation des préoccupations et la première étape est la division entre la couche de présentation et les couches de modèle. Tout comme la couche de présentation se décompose en contrôleurs (instances, responsables de la gestion des entrées utilisateur), vues (instances, responsables de la logique de l'interface utilisateur) et modèles/mises en page, la couche modèle en fait autant.

Les principales parties de la couche modèle sont les suivantes:

  • Objets de domaine

    Également connu sous le nom d'entités de domaine, d'objets métier ou d'objets de modèle (je n'aime pas ce dernier nom car il ne fait qu'ajouter à la confusion). Ces structures sont ce que les gens appellent généralement à tort des "modèles". Ils sont chargés de contenir les règles métier (tous les calculs et la validation pour l'unité spécifique de la logique du domaine).

  • Abstractions de stockage:

    Habituellement implémenté en utilisant le modèle mappeur de données (ne pas confondre avec ORM , qui ont abusé de ce nom). Ces instances sont généralement chargées du stockage et de la récupération des informations dans les objets de domaine. Chaque objet de domaine peut avoir plusieurs mappeurs, tout comme il existe plusieurs formes de stockage (DB, cache, session, cookies,/dev/null).

  • Prestations de service:

    Structures responsables de la logique d'application (c'est-à-dire l'interaction entre les objets de domaine et l'interaction entre les objets de domaine et les abstractions de stockage). Ils doivent agir comme "l'interface" à travers laquelle la couche de présentation interagit avec la couche modèle. C'est généralement ce qui, dans le code Rails, se retrouve dans les contrôleurs.

Il existe également plusieurs structures qui peuvent se trouver dans les espaces entre ces groupes: DAO , nités de travail et référentiels .

Oh ... et quand on parle (dans le contexte du web) d'un utilisateur qui interagit avec l'application MVC, ce n'est pas un être humain. L '"utilisateur" est en fait votre navigateur Web.

Et les divinités?

Au lieu d'avoir un modèle effrayant et monolithique avec lequel travailler, les contrôleurs devraient interagir avec les services. Vous transmettez les données de l'entrée utilisateur à un service spécifique (par exemple MailService ou RecognitionService). De cette façon, le contrôleur modifie l'état de la couche modèle, mais cela se fait en utilisant une API claire et sans gâcher les structures internes (ce qui provoquerait une abstraction qui fuit).

De telles modifications peuvent provoquer une réaction immédiate ou affecter uniquement les données que l'instance de vue demande à la couche modèle, ou les deux.

Chaque service peut interagir avec n'importe quel nombre (cependant, ce n'est généralement qu'une poignée) d'objets de domaine et d'abstractions de stockage. Par exemple, le RecogitionService ne pouvait pas se soucier moins des abstractions de stockage pour les articles.

Notes de clôture

De cette façon, vous obtenez une application qui peut être testée à n'importe quel niveau, avec un faible couplage (si elle est correctement implémentée) et une architecture clairement compréhensible.

Cependant, gardez à l'esprit: MVC n'est pas destiné aux petites applications. Si vous écrivez une page de livre d'or en utilisant le modèle MVC, vous vous trompez. Ce modèle est destiné à appliquer loi et ordre sur les applications à grande échelle.

Pour les personnes qui utilisent PHP comme langue principale, cet article pourrait être pertinent. C'est une description un peu plus longue de la couche modèle avec quelques extraits de code.

130
tereško

Si les classes "modèles" sont mal implémentées oui, votre préoccupation est pertinente. Une classe modèle ne devrait pas faire de messagerie (tâches d'infrastructure).

La vraie question est de savoir ce qu'implique le modèle dans MVC. Il n'est pas limité aux classes POCO avec quelques méthodes. Le modèle dans MVC signifie données et logique métier. Traitez-le comme un surensemble de modèles POCO de base classiques.

Afficher ==== Contrôleur ==== Modèle ---> Couche de processus métier -> Modèles de base

Ajoutez des assemblages d'infrastructure et des couches d'accès aux données et utilisez l'injection pour les remettre dans le BPL, puis votre processus utilise MVC comme prévu.

BPL peut invoquer des modèles UoW/Respository, exécuter des règles métier et appeler des fonctionnalités d'infrastructure au moyen d'objets injectés ou de patrons d'interface.

Ainsi, la recommandation de garder un contrôleur maigre ne signifie pas que la classe "personne" dans un modèle Core classique devrait avoir 50 méthodes et appeler directement Email. Vous avez raison de penser que c'est faux.

Le contrôleur peut toujours être tenu d'instancier et d'injecter des classes d'infrastructure dans la couche BPL ou la couche principale s'il est appelé directement. Il doit y avoir une couche de gestion ou au moins des classes orchestrant les appels entre les classes de modèle d'objet classique. C'est ma "vue" de toute façon ;-)

Pour une version générique de MVC, la description du wiki http://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93controller

Un petit blog qui parle du "M" dans MVC. http://www.thedeveloperday.com/skinny-controllers/

5
phil soady