vista refieren qué patterns patron mvc modelo los las estructura diseño controlador basados acciones asp.net-mvc model-view-controller design-patterns business-logic-layer

asp.net mvc - refieren - ¿Dónde encaja la "capa de lógica de negocios" en una aplicación MVC?



mvc python (4)

Con frecuencia me preguntaba cómo encajan exactamente los elementos de MVC en una estructura de aplicación web tradicional, donde tiene vistas (páginas), controladores, servicios y objetos de datos (modelo). Como dijiste, hay muchas versiones de eso.

Creo que la confusión existe debido a la arquitectura ampliamente aceptada anteriormente, que usa el patrón de "modelo de dominio anémico" (supuesto) -anti. No voy a entrar en muchos detalles sobre el "anti-patrón" del modelo de datos anémicos (puede ver un esfuerzo mío para explicar las cosas here (basado en Java, pero relevante para cualquier idioma)). Pero, en resumen, significa que nuestro modelo solo contiene datos, y la lógica de negocios se ubica en los servicios / gerentes.

Pero supongamos que tenemos una arquitectura impulsada por el dominio , y nuestros objetos de dominio son la forma en que se espera que tengan: tienen lógica de estado y de negocio. Y en esta perspectiva impulsada por el dominio, las cosas entran en su lugar:

  • la vista es la interfaz de usuario
  • el controlador reúne las entradas de la interfaz de usuario, invoca métodos en el modelo y devuelve una respuesta a la interfaz de usuario
  • el modelo es nuestros componentes de negocios: mantener los datos, pero también tener lógica comercial.

Supongo que eso responde a tus preguntas principales. Las cosas se complican cuando agregamos algunas capas más, como la capa de repositorio. A menudo se sugiere que debe ser invocado por la lógica de negocios colocada en el modelo (y, por lo tanto, cada objeto de dominio tiene una referencia a un repositorio). En el artículo mío que relacioné, sostengo que esta no es una buena práctica. Y eso, de hecho, no es malo tener una capa de servicio. Por cierto, el diseño impulsado por dominio no excluye la capa de servicio, pero se supone que es ''delgada'' y solo coordina los objetos de dominio (por lo que no hay lógica de negocios allí).

Para el paradigma de modelo de datos anémicos, que es ampliamente adoptado (para bien o para mal), el modelo sería a la vez la capa de servicio y sus objetos de datos.

En primer lugar, antes de que alguien grite tonto, me costó trabajo resumirlo en un simple título. Otro título podría haber sido "¿Cuál es la diferencia entre un modelo de dominio y un modelo MVC?" o "¿Qué es un modelo?"

Conceptualmente, entiendo un Modelo como los datos utilizados por las vistas y el controlador. Más allá de eso, parece haber una gran cantidad de opiniones diferentes sobre lo que conforma el modelo. ¿Qué es un modelo de dominio, frente a un modelo de aplicación, frente a un modelo de vista, frente a un modelo de servicio, etc.

Por ejemplo, en una pregunta reciente sobre el patrón del repositorio, me dijeron que el repositorio es parte del modelo. Sin embargo, he leído otras opiniones de que el modelo debe separarse del modelo de persistencia y la capa de lógica de negocios. Después de todo, ¿no se supone que el patrón Repository desacopla el método de persistencia concreta del modelo? Otras personas dicen que hay una diferencia entre el modelo de Dominio y el modelo de MVC.

Tomemos un ejemplo simple. El AccountController que se incluye con el proyecto predeterminado de MVC. He leído varias opiniones de que el código de la cuenta incluida es de diseño deficiente, infringe el SRP, etc., etc. Si se diseñase un modelo de membresía "adecuado" para una aplicación de MVC, ¿qué sería?

¿Cómo separaría los servicios de ASP.NET (proveedor de membresía, proveedor de roles, etc.) del modelo? ¿O lo harías en absoluto?

De la forma en que lo veo, el modelo debe ser "puro", tal vez con una lógica de validación ... pero debe estar separado de las reglas comerciales (aparte de la validación). Por ejemplo, supongamos que tiene una regla comercial que dice que alguien debe ser enviado por correo electrónico cuando se crea una nueva cuenta. Eso en realidad no pertenece al modelo en mi opinión. Entonces, ¿a dónde pertenece?

¿Alguien quiere arrojar algo de luz sobre este tema?


El patrón MVC y el marco Asp.net no hacen distinción en lo que debe ser el Modelo.

Los propios ejemplos de MS incluyen clases de persistencia en el modelo. Su pregunta acerca de la membresía está en el modelo. Esto depende. ¿Las clases de tu modelo son propiedad de algo? ¿Existe un vínculo entre quién inicia sesión y qué datos se muestran? ¿Hay filtrado de datos parte de un sistema de permisos editable? ¿Quién actualizó o editó un objeto como parte de tu dominio como alguien más necesita verlo o algo para soporte de back-end?

El ejemplo del correo electrónico también depende. ¿Está familiarizado con eventos o eventos de dominio en particular? ¿Tiene un servicio separado para enviar correos electrónicos? ¿Es el acto de enviar un correo electrónico parte de su dominio o es una preocupación a nivel de aplicación fuera del alcance de su sistema? ¿La UI necesita saber si un correo electrónico se envió con éxito o no? ¿Los correos electrónicos que no se envían necesitan reintentos? ¿El contenido del correo electrónico enviado debe almacenarse para soporte o requisitos de servicio al cliente?

Este tipo de preguntas son demasiado amplias y subjetivas, pero estoy respondiendo para que usted y todos los que lo votaron comprendan esto.

Sus requisitos / líneas de tiempo / recursos sangran en la arquitectura de su sistema. Incluso el modelo de ingresos puede tener un efecto. También debe considerar el patrón para el que está disparando. DDD es muy diferente de las aplicaciones de persistencia como modelo y todas las caídas intermedias también son válidas para ciertas aplicaciones. ¿Estás disparando para probar la aplicación? Todo esto tiene un efecto.


En mi opinión,

Modelo -

No debe contener lógica comercial, debe ser conectable (escenario como WCF). Se usa para enlazar para ver, debe tener propiedades.

Lógica de negocios -

Debe colocarse en "Capa de servicios de dominio", es una capa separada por completo. Además, agregará una capa más aquí "Servicios de aplicación".

App Services se comunica con la capa de Servicios de dominio para aplicar la lógica empresarial y, finalmente, devolver el Modelo.

Entonces, el Controlador le preguntará a Application Service for Model y el flujo será como:

Controller->Application Services(using domain services)->Model


La forma en que lo he hecho, y no digo que sea correcto o incorrecto, es tener mi Vista y luego un modelo que se aplique a mi punto de vista. Este modelo solo tiene lo que es relevante para mi vista, incluidas las anotaciones de datos y las reglas de validación. El controlador solo alberga la lógica para construir el modelo. Tengo una capa de servicio que alberga toda la lógica comercial. Mis controladores llaman a mi capa de servicio. Más allá de eso está mi capa de repositorio.

Mis objetos de dominio están alojados por separado (en su propio proyecto, en realidad). Tienen sus propias anotaciones de datos y reglas de validación. Mi repositorio valida los objetos en mi dominio antes de guardarlos en la base de datos. Debido a que cada objeto en mi dominio hereda de una clase base que tiene validación incorporada, mi repositorio es genérico y valida todo (y requiere que herede de la clase base).

Puede pensar que tener dos conjuntos de modelos es una duplicación de código, y lo es en cierta medida. Pero, hay casos perfectamente razonables en los que el objeto de dominio no es apropiado para la vista.

Un buen ejemplo es cuando trabajamos con tarjetas de crédito: tengo que solicitar un CVV al procesar un pago, pero no puedo almacenar el CVV (es una multa de $ 50,000 para hacerlo). Pero, también quiero que pueda editar su tarjeta de crédito: cambio de dirección, nombre o fecha de vencimiento. Pero no me va a dar el número o el cvv cuando lo edite, y ciertamente no voy a poner su número de tarjeta de crédito en texto sin formato en la página. Mi dominio tiene estos valores necesarios para guardar una nueva tarjeta de crédito porque me la entrega, pero mi modelo de edición ni siquiera incluye el número de tarjeta o cvv.

Otro beneficio de tantas capas es que si se ha diseñado correctamente, puede usar structuremap u otro contenedor IoC y cambiar piezas sin afectar negativamente su aplicación.

En mi opinión, el código del controlador solo debería estar codificado en la vista. Muestre esto, oculte eso, etc. La capa de servicio debe contener la lógica comercial para su aplicación. Me gusta tener todo en un solo lugar, así que es fácil cambiar o modificar una regla de negocios. La capa de repositorio debe ser relativamente tonta, desprovista de lógica comercial y solo consultar sus datos y devolver los objetos de su dominio. Al separar los modelos de vista del modelo de dominio, tiene mucha más flexibilidad cuando se trata de reglas de validación personalizadas. También significa que no tiene que volcar cada dato en su vista en campos ocultos y empujarlo hacia adelante y hacia atrás entre el cliente y el servidor (o reconstruirlo en el back-end). El modelo de su vista albergará solo la información relevante para la vista, y puede personalizarse para tener bools para ver la lógica o los recuentos o enumeraciones para que la vista en sí misma no esté llena de complicadas declaraciones lógicas como

<% if (!String.IsNullOrEmpty(Model.SomeObject.SomeProperty) && Model.SomeObject.SomeInt == 3 && ...) { %>

Si bien todo parece disperso y superpuesto, tiene un propósito para ser diseñado de esta manera. ¿Es perfecto? realmente no. Pero prefiero algunos diseños anteriores de repositorios de llamadas desde el controlador y tener la lógica de negocios mezclada en el controlador, el repositorio y el modelo.