ASP.NET MVC - A lógica de negócios deve existir nos controladores?

97

Derik Whitaker postou um artigo alguns dias atrás que atingiu um ponto que eu estava curioso há algum tempo: a lógica de negócios deve existir nos controladores?

Até agora, todas as demonstrações do ASP.NET MVC que vi colocam o acesso ao repositório e a lógica de negócios no controlador. Alguns até lançam validação lá também. Isso resulta em controladores bastante grandes e inchados. Esta é realmente a maneira de usar o framework MVC? Parece que isso vai acabar com uma grande quantidade de código duplicado e lógica espalhada por diferentes controladores.

Kevin Pang
fonte
O link para o artigo está morto - web.archive.org/web/20150906064521/http://devlicio.us/blogs/… é uma cópia do archive.org para qualquer pessoa interessada.
Stuart Moore

Respostas:

75

A lógica de negócios realmente deve estar no modelo. Você deve buscar modelos gordos, controladores magros.

Por exemplo, em vez de ter:

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

Eu preferiria ter:

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

Isso pressupõe que o imposto é calculado por um serviço externo e requer que seu modelo conheça as interfaces de seus serviços externos.

Isso faria com que seu controlador se parecesse com:

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

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

Ou algo assim.

Jonnii
fonte
1
Então, você injetaria serviços em seus controladores em vez de repositórios? Como o princípio da Unidade de Trabalho entra em ação nesse caso?
Kevin Pang
Escrevi mais algumas coisas, espero que isso faça mais sentido. Você pode querer ler também: weblog.jamisbuck.org/2006/10/18/skinny-controller-fat-model Mesmo sendo sobre Rails, ainda é muito aplicável.
Jonnii
Eu chamaria um repositório de serviço, pessoalmente.
Brad Wilson,
Eles são definitivamente um tipo de serviço, mas são especificamente para acesso a dados. É apenas uma convenção que uso, não algo que defenda especificamente.
Jonnii
1
Isso tornará seu modelo bem acoplado com ITaxService. Se você quiser reutilizar o modelo em outro projeto ou outra dll, você deve ter a implementação ou referência de ITaxService, caso contrário, seu modelo será quebrado, o que resulta em violação dos princípios SOLID. ITaxService deve ter uma referência de seu modelo. Desta forma, você pode reutilizar seu modelo em outro projeto sem a necessidade da referência ITaxService.
Mehmet Ali Sert
65

Eu gosto do diagrama apresentado por Microsoft Patterns & Practices . E eu acredito no ditado 'Uma imagem vale mais que mil palavras'.

O diagrama mostra a arquitetura das camadas de MVC e serviços de negócios

AlejandroR
fonte
6
Isso é muito útil! Você poderia me dizer onde nesse site você encontrou este diagrama?
Rob Church,
2
Isto é da 'Implementação do lado do servidor' da Microsoft msdn.microsoft.com/en-us/library/hh404093.aspx
Justin
OK, mas em, digamos, um aplicativo MVC - para onde vai a lógica de negócios? Parece que precisamos de uma camada de serviço adicional ou algo assim ?!
niico
14

Esta é uma questão fascinante.

Eu acho que é interessante que um grande número de aplicativos MVC de amostra realmente falhe em seguir o paradigma MVC no sentido de realmente colocar a "lógica de negócios" inteiramente no modelo. Martin Fowler apontou que MVC não é um padrão no sentido do Gang Of Four. Pelo contrário, é paradigma de que o programador deve adicionar padrões para se eles estão criando algo além de um aplicativo de brinquedo.

Portanto, a resposta curta é que a "lógica de negócios" realmente não deveria residir no controlador, uma vez que o controlador tem a função adicional de lidar com a visualização e as interações do usuário e queremos criar objetos com apenas um propósito.

Uma resposta mais longa é que você precisa pensar um pouco no design da camada do modelo antes de apenas mover a lógica do controlador para o modelo. Talvez você possa lidar com toda a lógica do aplicativo usando REST, caso em que o design do modelo deve ser bastante claro. Caso contrário, você deve saber qual abordagem usará para evitar que seu modelo fique inchado.

Joe Soul-bringer
fonte
14

Você pode verificar este tutorial incrível de Stephen Walther que mostra Validando com uma camada de serviço .

Aprenda como mover sua lógica de validação de suas ações do controlador para uma camada de serviço separada. Neste tutorial, Stephen Walther explica como você pode manter uma separação nítida de interesses, isolando sua camada de serviço da camada do controlador.

Leniel Maccaferri
fonte
2
Esta é a resposta mais correta. Eu pessoalmente defendo ainda mais a não exposição de serviços ao controlador, optando por usar um conceito ViewModel, como o encontrado no padrão MVVM. Imagine um cenário em que você deseja escrever um aplicativo de negócios com uma interface de desktop (por exemplo, formulários do Windows ou WPF) e também uma interface da web. Resolver esse problema leva você ao padrão de "controlador magro", como também é defendido aqui. Resumindo: nunca coloque lógica de negócios em um modelo ou controlador e não coloque nada em um controlador que você também não tenha.
Sam
9

A lógica de negócios não deve estar contida em controladores. Os controladores devem ser o mais magros possíveis, de preferência, seguir o padrão:

  1. Encontrar entidade de domínio
  2. Agir na entidade de domínio
  3. Prepare os dados para visualizar / retornar resultados

Além disso, os controladores podem conter alguma lógica de aplicação.

Então, onde coloco minha lógica de negócios? No modelo.

O que é modelo? Essa é uma boa pergunta. Consulte o artigo Padrões e Práticas da Microsoft (parabéns a AlejandroR pelo excelente achado). Aqui, existem três categorias de modelos:

  • Modelo de visualização : este é simplesmente um saco de dados, com lógica mínima, se houver, para passar dados de e para visualizações, contendo validação de campo básica.
  • Modelo de domínio : modelo gordo com lógica de negócios, opera em uma ou várias entidades de dados (ou seja, entidade A em um determinado estado do que ação na entidade B)
  • Modelo de dados : modelo com reconhecimento de armazenamento, a lógica contida em uma única entidade se relaciona apenas a essa entidade (ou seja, se o campo a, então, o campo b)

Claro, MVC é um paradigma que vem em diferentes variedades. O que eu descrevo aqui é MVC ocupando apenas a camada superior, vide este artigo na Wikipedia

Hoje, MVC e model-view-presenter (MVP) são padrões de design de Separation of Concerns que se aplicam exclusivamente à camada de apresentação de um sistema maior. Em cenários simples, o MVC pode representar o projeto principal de um sistema, alcançando diretamente o banco de dados; no entanto, na maioria dos cenários, o controlador e o modelo no MVC têm uma dependência flexível em um serviço ou camada / camada de dados. Isso é tudo sobre arquitetura cliente-servidor

Jacek Glen
fonte
-1

Se você usar injetores de dependência, sua lógica de negócios irá para eles e, portanto, você obterá controladores organizados e limpos.

Chandresh Patel
fonte