ASP.NET MVC: ¿debería existir la lógica empresarial en los controladores?

97

Derik Whitaker publicó un artículo hace un par de días que llegó a un punto sobre el que he sentido curiosidad durante algún tiempo: ¿ debería existir la lógica empresarial en los controladores?

Hasta ahora, todas las demostraciones de ASP.NET MVC que he visto ponen el acceso al repositorio y la lógica empresarial en el controlador. Algunos incluso lanzan validación allí también. Esto da como resultado controladores bastante grandes e hinchados. ¿Es esta realmente la forma de usar el marco MVC? Parece que esto va a terminar con una gran cantidad de código duplicado y lógica repartida entre diferentes controladores.

Kevin Pang
fuente
El enlace al artículo está muerto: web.archive.org/web/20150906064521/http://devlicio.us/blogs/… es una copia de archive.org para cualquier otra persona interesada.
Stuart Moore

Respuestas:

75

La lógica empresarial realmente debería estar en el modelo. Deberías apuntar a modelos gordos, controladores delgados.

Por ejemplo, en lugar de tener:

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

Yo preferiria tener:

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

Esto supone que los impuestos los calcula un servicio externo y requiere que su modelo conozca las interfaces con sus servicios externos.

Esto haría que su controlador se viera así:

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

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

O algo así.

Jonnii
fuente
1
Entonces, ¿inyectaría Servicios en sus controladores en lugar de repositorios? ¿Cómo entra en juego el principio de Unidad de Trabajo en ese caso?
Kevin Pang
Escribí algunas cosas más, espero que esto tenga más sentido. Es posible que también desee leer: weblog.jamisbuck.org/2006/10/18/skinny-controller-fat-model Aunque se trata de Rails, todavía es muy aplicable.
jonnii
Personalmente, llamaría servicio a un repositorio.
Brad Wilson
Definitivamente son un tipo de servicio, pero son específicamente para el acceso a datos. Es solo una convención que uso, no algo que defiendo específicamente.
jonnii
1
Esto hará que su modelo esté bien acoplado con ITaxService. Si desea reutilizar el modelo en otro proyecto u otro dll, debe tener una implementación o referencia de ITaxService, de lo contrario su modelo se romperá, lo que resultará en una violación de los principios SÓLIDOS. ITaxService debe tener una referencia de su modelo. De esta manera, puede reutilizar su modelo en otro proyecto sin necesidad de referencia de ITaxService.
Mehmet Ali Sert
65

Me gusta el diagrama presentado por Microsoft Patterns & Practices . Y creo en el adagio "Una imagen vale más que mil palabras".

El diagrama muestra la arquitectura de MVC y capas de servicios empresariales

AlejandroR
fuente
6
¡Eso es realmente útil! ¿Podría decirme dónde en ese sitio encontró este diagrama?
Rob Church
2
Esto es de la 'Implementación del lado del servidor' de Microsoft msdn.microsoft.com/en-us/library/hh404093.aspx
Justin
Está bien, pero en, digamos, una aplicación MVC, ¿a dónde va la lógica empresarial? ¿Parece que necesitamos una capa de servicio adicional o algo así?
niico
14

Ésta es una pregunta fascinante.

Creo que es interesante que una gran cantidad de aplicaciones MVC de muestra en realidad no sigan el paradigma MVC en el sentido de colocar verdaderamente la "lógica empresarial" por completo en el modelo. Martin Fowler ha señalado que MVC no es un patrón en el sentido de Gang Of Four. Más bien, es paradigma de que el programador debe añadir patrones a si se están creando algo más allá de una aplicación de juguete.

Entonces, la respuesta corta es que la "lógica de negocios" no debería vivir en el controlador, ya que el controlador tiene la función adicional de lidiar con la vista y las interacciones del usuario y queremos crear objetos con un solo propósito.

Una respuesta más larga es que necesita pensar un poco en el diseño de la capa de su modelo antes de mover la lógica del controlador al modelo. Quizás pueda manejar toda la lógica de la aplicación usando REST, en cuyo caso el diseño del modelo debería ser bastante claro. Si no es así, debe saber qué enfoque va a utilizar para evitar que su modelo se hinche.

Joe portador de almas
fuente
14

Puede consultar este increíble tutorial de Stephen Walther que muestra Validación con una capa de servicio .

Aprenda a mover su lógica de validación de las acciones de su controlador a una capa de servicio separada. En este tutorial, Stephen Walther explica cómo puede mantener una clara separación de preocupaciones al aislar su capa de servicio de su capa de controlador.

Leniel Maccaferri
fuente
2
Ésta es la respuesta más correcta. Personalmente, defiendo además no exponer los servicios al controlador, eligiendo en su lugar utilizar un concepto de ViewModel como el que se encuentra en el patrón MVVM. Imagine un escenario en el que desea escribir una aplicación empresarial con una interfaz de escritorio (por ejemplo, formularios de Windows o WPF) y también una interfaz web. Resolver ese problema te lleva al patrón de "controlador delgado", como también se defiende aquí. En pocas palabras: nunca coloque la lógica empresarial en un modelo o un controlador y no coloque nada en un controlador que no tenga también.
Sam
9

La lógica empresarial no debe estar contenida en controladores. Los controladores deben ser lo más delgados posible, idealmente seguir el patrón:

  1. Buscar entidad de dominio
  2. Actuar sobre la entidad de dominio
  3. Preparar datos para ver / devolver resultados

Además, los controladores pueden contener cierta lógica de aplicación.

Entonces, ¿dónde pongo mi lógica empresarial? En modelo.

¿Qué es el modelo? Esa es una buena pregunta. Consulte el artículo Patrones y prácticas de Microsoft (felicitaciones a AlejandroR por su excelente hallazgo). Aquí hay tres categorías de modelos:

  • Modelo de vista : esto es simplemente una bolsa de datos, con una lógica mínima, si la hay, para pasar datos desde y hacia las vistas, contiene validación de campo básica.
  • Modelo de dominio : modelo gordo con lógica comercial, opera en una o varias entidades de datos (es decir, la entidad A en un estado dado que la acción en la entidad B)
  • Modelo de datos : modelo de almacenamiento, la lógica contenida dentro de una sola entidad se relaciona solo con esa entidad (es decir, si el campo a, entonces el campo b)

Por supuesto, MVC es un paradigma que se presenta en diferentes variedades. Lo que describo aquí es MVC que ocupa solo la capa superior, vea este artículo en Wikipedia

Hoy en día, MVC y un modelo-vista-presentador (MVP) similar son patrones de diseño de Separación de preocupaciones que se aplican exclusivamente a la capa de presentación de un sistema más grande. En escenarios simples, MVC puede representar el diseño principal de un sistema, llegando directamente a la base de datos; sin embargo, en la mayoría de los escenarios, el controlador y el modelo en MVC tienen una dependencia flexible de una capa / nivel de servicio o de datos. Todo esto se trata de la arquitectura cliente-servidor

Jacek Glen
fuente
-1

Si usa inyectores de dependencia, su lógica de negocios irá a ellos y, por lo tanto, obtendrá controladores limpios y ordenados.

Chandresh Patel
fuente