14

Actualmente en mi aplicación y usando el patrón de la unidad de trabajo y el repositorio genérico, todos mis controladores contienen toda la lógica comercial. Estoy en el proceso de poner todo a punto para usar ViewModels en lugar del Modelo directo.MVC 3 - Controladores y ViewModels - ¿Cuál debería contener la mayor parte de la lógica de negocios?

Si bien esta es una buena idea, ahora viene una pregunta que puede separar significativamente mi lógica comercial en los controladores. Para los controladores y ViewModels, ¿cuál debería contener la mayor parte de la lógica de negocios?

He intentado de varias formas hacer que mis ViewModels prácticamente contengan toda la lógica comercial. Sin embargo, tengo que tener un argumento en el constructor de mi ViewModel que tome una unidad de trabajo. ¿Es esta una buena idea?

Mi código huele me dice que sí. Sin embargo, estoy un poco preocupado de cómo será esto en coherencia con los controladores que realizan acciones que no necesitan ViewModels. En pocas palabras, las acciones que no requieren pasar un modelo/modelo de vista a una vista; este caso ocurre en acciones que redirigen a otras acciones. Lo que significa que mi lógica comercial puede permanecer en esa acción o podría separar esa lógica comercial en una función.

¿Cuál es la mejor práctica aquí?

Respuesta

7

Para los controladores y ViewModels, que debe contener la mayor parte de la lógica de negocio?

Ninguno de esos.

He intentado de varias maneras hacer que mis ViewModels prácticamente contengan toda la lógica comercial. Sin embargo, tengo que tener un argumento en el constructor de mi ViewModel que tome una unidad de trabajo. ¿Es esta una buena idea?

imho Es una muy mala idea. En primer lugar, está rompiendo varios de los principios SÓLIDOS. Agrupar todo el código en el modelo de vista hace que sea difícil probarlo. ¿Qué sucede si desea usar parte de la lógica comercial en otra vista? ¿Duplicas ese código?

¿Cuál es la mejor práctica aquí?

Regresemos primero al patrón MVC. Es una definición bastante amplia, pero sabiendo que debería darle una sensación de lo que debe colocar donde.

  • El "Modelo" en MVC es realmente todo lo que se utiliza para juntar los datos. Puede ser servicios web, una capa empresarial, repositorios, etc.

  • La vista es todo el código que genera el HTML (ya que estamos hablando de web).

  • El controlador debe considerarse como un pegamento entre el modelo y la vista. Por lo tanto, debe tomar la información del Modelo y transformarla en algo utilizable por la vista.

El problema con esa estructura es que es bastante fácil "filtrar" información específica de la capa en las otras partes del patrón. De ahí que Microsoft introdujo ViewModels en su implementación de MVC.

De esta manera, podemos eliminar toda la lógica de representación de las vistas y ponerla en el modelo de vista. En vez de hacer esto en su vista:

<span>@(model.Age == 0 ? "n/a" : model.Age)</span> 

pones ese código dentro del modelo de vista en su lugar y sólo tiene que llamar @model.Age. De esta forma, no tiene que duplicar ese código en todas las vistas que usan su modelo de vista.

La respuesta a su pregunta sobre el ViewModel es que solo debe contener la lógica que se utiliza para representar la información del "Modelo" correctamente.

En cuanto al controlador, tampoco pondría ninguna lógica comercial en él. Antes que nada, hace que sea muy difícil probar tu lógica. Luego le agrega más responsabilidades (y al hacerlo, rompe el SRP). La única lógica que es válida en el controlador es tomar la información del ViewModel y transformarla en algo utilizable por el "Modelo" y viceversa.

Espero que responda a su pregunta.

actualización

me gustaría crear un proyecto separado y añadir clases a la misma. Luego solo agrega una referencia de tu proyecto web y llama a esas clases en los controladores.

También comenzaría a usar un contenedor de inversión de control para obtener automáticamente las dependencias creadas para mí.

Autofac pueden descubrir sus servicios por usted (cero-configuración) e insertarse en MVC.

seguir el modelo de interfaz separados crean los siguientes proyectos:

  • YourProject.BusinessLayer < - Añada sus clases aquí
  • YourProject.BusinessLayer.Specification < - Añadir que las interfaces que define su capa de negocio aquí.
  • YourProject.Mvc < - El proyecto MVC.

El proyecto "Especificación" se puede utilizar para facilitar la prueba de cosas y facilitar el cambio de implementación (pueden ser solo unas pocas clases y no necesariamente toda la capa empresarial). Lea en "Patrón de interfaz separada"

+1

Buena respuesta. Me gustaría preguntar dónde iría mi lógica comercial. – TIHan

+0

Lee mi actualización. – jgauffin

+0

Gracias. Comenzaré a investigar esto. – TIHan

10

No puedo decir que mi enfoque sea una buena práctica, pero prefiero poner cualquier lógica comercial en una capa de "servicio" separada.

Tiendo a utilizar ViewModel para almacenar solo las propiedades requeridas para una vista específica. Si hay algún método en ViewModel, es probable que solo recuperen colecciones relacionadas con esa vista.

Mantengo mis controladores ligeros tratando de limitarlos a validación y redirección/visualización de vistas tanto como sea posible.

Así que si tengo alguna lógica compleja, tendré una llamada de acción del controlador a un servicio separado solo para manejar esa lógica. De esta forma, se aisla la lógica, lo que facilita la prueba, ya que ya no es necesario crear un controlador o ViewModel para probarlo. También es más fácil reutilizar un servicio que separar un ViewModel.

Espero que esto ayude. Buena suerte.

+0

+1 - Esto parece un enfoque razonable; pero, mi pregunta aún no ha sido respondida. Soy consciente de lo que es un ViewModel, estoy tratando de averiguar si ViewModel debe contener la mayor lógica de negocios posible. – TIHan

+2

@TIHan, dijo que ViewModel solo contiene los datos. El servicio hace el proceso. El controlador hace el control del tráfico. –

+0

El ViewModel debería simplemente ser un [poco] (http://en.wikipedia.org/wiki/Plain_Old_CLR_Object) que contenga todos los datos finales de la vista. Cómo se obtienen esos datos, se procesan, se formatean, etc. ... hasta una capa de servicio. –

3

Modelo-Vista-Vista El modelo (MVVM) es un patrón de diseño para crear interfaces de usuario. Su modelo de vista es una representación de código puro de los datos y operaciones en una interfaz de usuario. Por lo tanto, debe contener la lógica relacionada con esa interfaz de usuario.

Por ejemplo:

si va a implementar un editor de lista, su modelo de vista sería un objeto que sostiene una lista de elementos, y la exposición de los métodos para añadir y eliminar elementos.

De Wikipedia:

modelo de vista: el modelo de vista es un “modelo de la vista” lo que significa que es un abstracción de la idea de que también sirve en la unión entre el Vista y el Modelo de datos. Podría verse como un aspecto especializado de lo que sería un Controlador (en el patrón MVC) que actúa como un enlace de datos/convertidor que cambia la información del Modelo en información de Vista y pasa comandos de la Vista al Modelo. ViewModel expone propiedades públicas, comandos y abstracciones.El ViewModel se ha comparado con un estado conceptual de los datos en oposición al estado real de los datos en el Modelo. [7]

+0

Esto está bien, pero me pregunto cómo funciona esto con un repositorio genérico y el patrón de unidad de trabajo. – TIHan

1

su controlador llame a la UoW para obtener los datos necesarios para construir su modelo de vista. puede llamar a más de 1 método de su UoW

luego pasa todos sus datos necesarios a su constructor de viewmodel. (pasar el Uow para ver el modelo suena como realmente malo)

Si necesita una "lógica" compleja en su controlador llamando a muchos métodos desde la UoW, etc., debería considerar crear otro repositorio o una lógica de negocios solo que hace todo el trabajo duro y lo llama desde su controlador como

SomeClass something = Uow.BLGoodName.DoSomeFancyStuff(params ..) 
ViewData.model = new ControllerActionViewModel(something); 
Return View(); 
Cuestiones relacionadas