ASP.NET MVC - La logique métier doit-elle exister dans les contrôleurs?

97

Derik Whitaker a publié il y a quelques jours un article qui a touché un point qui m'intéresse depuis un certain temps: la logique métier doit-elle exister dans les contrôleurs?

Jusqu'à présent, toutes les démos ASP.NET MVC que j'ai vues placent l'accès au référentiel et la logique métier dans le contrôleur. Certains y ajoutent même une validation. Il en résulte des contrôleurs assez gros et gonflés. Est-ce vraiment la manière d'utiliser le framework MVC? Il semble que cela va finir avec beaucoup de code et de logique dupliqués répartis sur différents contrôleurs.

Kevin Pang
la source
Le lien vers l'article est mort - web.archive.org/web/20150906064521/http://devlicio.us/blogs/… est une copie d'archive.org pour toute personne intéressée.
Stuart Moore

Réponses:

75

La logique métier devrait vraiment être dans le modèle. Vous devriez viser des modèles gras, des contrôleurs maigres.

Par exemple, au lieu d'avoir:

public interface IOrderService{
    int CalculateTotal(Order order);
}

Je prefererais avoir:

public class Order{
    int CalculateTotal(ITaxService service){...}        
}

Cela suppose que la taxe est calculée par un service externe et nécessite que votre modèle connaisse les interfaces avec vos services externes.

Cela donnerait à votre contrôleur un aspect comme:

public class OrdersController{
    public OrdersController(ITaxService taxService, IOrdersRepository ordersRepository){...}

    public void Show(int id){
        ViewData["OrderTotal"] = ordersRepository.LoadOrder(id).CalculateTotal(taxService);
    }
}

Ou quelque chose comme ça.

jonnii
la source
1
Alors injecteriez-vous des services dans vos contrôleurs au lieu de référentiels? Comment le principe de l'unité de travail entre-t-il en jeu dans ce cas?
Kevin Pang
J'ai écrit d'autres trucs, j'espère que cela a plus de sens. Vous voudrez peut-être aussi lire: weblog.jamisbuck.org/2006/10/18/skinny-controller-fat-model Même s'il s'agit de Rails, c'est toujours très applicable.
jonnii
J'appellerais un référentiel un service, personnellement.
Brad Wilson
C'est certainement une sorte de service, mais il est spécifiquement destiné à l'accès aux données. C'est juste une convention que j'utilise, pas quelque chose que je préconise spécifiquement.
jonnii
1
Cela rendra votre modèle étroitement associé à ITaxService. Si vous souhaitez réutiliser le modèle dans un autre projet ou une autre dll, vous devez avoir une implémentation ou une référence ITaxService, sinon votre modèle sera cassé, ce qui entraînera une violation des principes SOLID. ITaxService doit avoir une référence de votre modèle. De cette façon, vous pouvez réutiliser votre modèle dans un autre projet sans avoir besoin de la référence ITaxService.
Mehmet Ali Sert le
65

J'aime le diagramme présenté par Microsoft Patterns & Practices . Et je crois en l'adage «Une image vaut mille mots».

Le diagramme montre l'architecture des couches MVC et des services métier

AlejandroR
la source
6
C'est vraiment utile! Pouvez-vous me dire où sur ce site vous avez trouvé ce diagramme?
Rob Church
2
Ceci provient de Microsoft's 'Server-Side Implementation' msdn.microsoft.com/en-us/library/hh404093.aspx
Justin
OK, mais dans, par exemple, une application MVC - où va la logique métier? Il semble que nous ayons besoin d'une couche de service supplémentaire ou quelque chose?!
niico
14

C'est une question fascinante.

Je pense qu'il est intéressant qu'un grand nombre d'exemples d'applications MVC ne parviennent pas à suivre le paradigme MVC dans le sens de placer véritablement la «logique métier» entièrement dans le modèle. Martin Fowler a souligné que MVC n'est pas un modèle au sens du Gang Of Four. Au contraire, il est paradigme que le programmeur doit ajouter des motifs à s'ils créent quelque chose au - delà d' une application de jouet.

Donc, la réponse courte est que la "logique métier" ne devrait en effet pas vivre dans le contrôleur, puisque le contrôleur a la fonction supplémentaire de traiter la vue et les interactions utilisateur et nous voulons créer des objets avec un seul but.

Une réponse plus longue est que vous devez réfléchir à la conception de votre couche de modèle avant de simplement déplacer la logique du contrôleur au modèle. Vous pouvez peut-être gérer toute la logique d'application à l'aide de REST, auquel cas la conception du modèle doit être assez claire. Sinon, vous devez savoir quelle approche vous allez utiliser pour éviter que votre modèle ne devienne gonflé.

Joe Soul-bringer
la source
14

Vous pouvez consulter ce didacticiel génial de Stephen Walther qui montre la validation avec une couche de service .

Découvrez comment déplacer votre logique de validation hors des actions de votre contrôleur vers une couche de service distincte. Dans ce didacticiel, Stephen Walther explique comment vous pouvez maintenir une séparation nette des préoccupations en isolant votre couche de service de votre couche de contrôleur.

Leniel Maccaferri
la source
2
C'est la réponse la plus correcte. Personnellement, je recommande en outre de ne pas exposer les services au contrôleur, en choisissant plutôt d'utiliser un concept ViewModel tel que celui que l'on trouve dans le modèle MVVM. Imaginez un scénario dans lequel vous souhaitez écrire une application professionnelle avec une interface de bureau (par exemple, Windows Forms ou WPF) et également une interface Web. La résolution de ce problème vous amène au modèle de "contrôleur maigre" comme cela est également préconisé ici. Conclusion: ne mettez jamais de logique métier dans un modèle ou un contrôleur et ne mettez rien dans un contrôleur que vous n'avez pas trop.
Sam le
9

La logique métier ne doit pas être contenue dans les contrôleurs. Les contrôleurs doivent être aussi maigres que possible, idéalement suivre le motif:

  1. Rechercher une entité de domaine
  2. Agir sur l'entité de domaine
  3. Préparer les données pour afficher / renvoyer les résultats

De plus, les contrôleurs peuvent contenir une logique d'application.

Alors, où dois-je mettre ma logique métier? Dans Model.

Qu'est-ce que le modèle? Voilà une bonne question. Veuillez consulter l'article Microsoft Patterns and Practices (félicitations à AlejandroR pour l'excellente trouvaille). Ici, il y a trois catégories de modèles:

  • Modèle de vue : il s'agit simplement d'un sac de données, avec une logique minimale, le cas échéant, pour transmettre les données depuis et vers les vues, contenant une validation de champ de base.
  • Modèle de domaine : modèle Fat avec logique métier, fonctionne sur une ou plusieurs entités de données (c'est-à-dire l'entité A dans un état donné que l'action sur l'entité B)
  • Modèle de données : modèle prenant en charge le stockage, la logique contenue dans une seule entité ne concerne que cette entité (c'est-à-dire si le champ a, alors le champ b)

Bien sûr, MVC est un paradigme qui se décline en différentes variétés. Ce que je décris ici, c'est que MVC n'occupe que la couche supérieure, voyez cet article sur Wikipedia

Aujourd'hui, MVC et MVP (Model-View-Presenter) sont des modèles de conception de séparation des préoccupations qui s'appliquent exclusivement à la couche de présentation d'un système plus grand. Dans des scénarios simples, MVC peut représenter la conception principale d'un système, atteignant directement la base de données; cependant, dans la plupart des scénarios, le contrôleur et le modèle dans MVC ont une dépendance lâche sur un service ou une couche / niveau de données. Tout est question d’architecture client-serveur

Jacek Glen
la source
-1

Si vous utilisez des injecteurs de dépendances, votre logique métier leur sera transmise et vous obtiendrez ainsi des contrôleurs nets et propres.

Chandresh Patel
la source