asp.net-mvc - ventajas - mvc php
¿Debería una capa de servicio devolver modelos de vista para una aplicación MVC? (5)
Digamos que tiene un proyecto ASP.NET MVC y está utilizando una capa de servicio, como en este tutorial de administrador de contactos en el sitio asp.net: http://www.asp.net/mvc/tutorials/iteration-4-make-the-application-loosely-coupled-cs
Si tiene viewmodels para sus vistas, ¿la capa de servicio es el lugar apropiado para proporcionar cada modelo de vista? Por ejemplo, en el ejemplo de código de capa de servicio hay un método
public IEnumerable<Contact> ListContacts()
{
return _repository.ListContacts();
}
Si, por el contrario, quisiera un IEnumerable, ¿debería ir en la capa de servicio, o hay otro lugar que sea el "correcto"?
Quizás de manera más apropiada, si tiene un modelo de vista separado para cada vista asociada con ContactController, ¿debería ContactManagerService tener un método diferente para devolver cada modelo de vista? Si la capa de servicio no es el lugar correcto, ¿dónde deberían inicializarse los objetos de modelo de vista para que los use el controlador?
En general, no.
Los modelos de vista están destinados a proporcionar información desde y hacia vistas y deben ser específicos de la aplicación, a diferencia del dominio general. Los controladores deben orquestar la interacción con repositorios, servicios (estoy haciendo algunas suposiciones de la definición de servicio aquí), etc. y manejar la construcción y validación de modelos de vista, y también contener la lógica de determinación de vistas para renderizar.
Al filtrar los modelos de vista a una capa de "servicio", se difuminan las capas y ahora se mezclan posibles aplicaciones y presentaciones específicas con lo que debería centrarse en las responsabilidades a nivel de dominio.
Esto ha venido un poco "depende" donde trabajo - generalmente hemos tenido un controlador consumiendo algunos servicios - luego combinando DTO devueltos en un ''ViewModel'' que luego se pasaría al cliente - ya sea a través del resultado JSON , o vinculado en la Plantilla Razor.
La cosa es, aproximadamente el 80% del tiempo: el mapeo de DTO a ViewModel ha sido 1-1. Estamos empezando a avanzar hacia ''Donde sea necesario, simplemente consuma el DTO directamente, pero cuando el DTO y lo que necesitamos en nuestro cliente / vista no coinciden, entonces creamos un ViewModel y hacemos la asignación entre objetos según sea necesario''.
Aunque todavía no estoy convencido de que esta sea la mejor o la mejor solución, ya que termina conduciendo a acaloradas discusiones acerca de si estamos agregando X al DTO para satisfacer las necesidades de la vista.
No, no lo creo Los servicios solo deben preocuparse por el dominio del problema, no por la vista que rinde resultados. Los valores devueltos deben expresarse en términos de objetos de dominio, no de vistas.
Según el enfoque tradicional o la teoría, ViewModel debe ser parte de la capa de la interfaz de usuario. Al menos el nombre lo dice.
Pero cuando empiezas a implementarlo tú mismo con Entity Framework, MVC, Repository, etc., entonces te das cuenta de algo más.
Alguien tiene que mapear los Modelos de Entidad / DB con ViewModels (DTO mencionado al final). ¿Debería hacerse esto en [A] la capa UI (por el Controlador), o en [B] la capa Servicio?
Voy con la Opción B. La Opción A es un no no por el simple hecho de que varios modelos de entidades se combinan para formar un ViewModel. Es posible que no pasemos datos innecesarios a la capa UI, mientras que en la opción B, el servicio puede jugar con datos y pasar solo el nivel requerido / mínimo a la capa UI después del mapeo (al ViewModel).
De nuevo, vamos a ir con la opción A, poner ViewModel en la capa de UI (y el modelo de entidad en la capa de Servicio).
Si la capa de servicio necesita correlacionarse con el modelo de vista, la capa de servicio necesita acceder a ViewModel en la capa de interfaz de usuario. ¿Qué biblioteca / proyecto? El modelo de vista debe estar en un proyecto separado en la capa de la interfaz de usuario, y este proyecto debe ser referenciado por la capa de servicio. Si ViewModel no está en un proyecto separado, entonces hay una referencia circular, así que no vayas. Parece incómodo tener la capa de servicio accediendo a la capa de interfaz de usuario, pero aún así podemos hacer frente a ella.
Pero, ¿qué sucede si hay otra aplicación UI que utiliza este servicio? ¿Qué pasa si hay una aplicación móvil? ¿Qué tan diferente puede ser ViewModel? ¿Debe el Servicio acceder al mismo proyecto de modelo de vista? ¿Todos los proyectos de UI accederán al mismo proyecto de ViewModel o tendrán el suyo propio?
Después de estas consideraciones, mi respuesta sería poner el proyecto Viewmodel en la Capa de Servicio. ¡Cada capa de interfaz de usuario tiene que acceder a la capa de servicio de todos modos! Y podría haber muchos ViewModels similares que todos podrían usar (por lo tanto, la asignación se vuelve más fácil para la capa de servicio). Las asignaciones se realizan a través de linq en estos días, lo cual es otra ventaja.
Por último, hay esta discusión sobre DTO. Y también sobre la anotación de datos en ViewModels. Los modelos ViewModels con anotaciones de datos (Microsoft.Web.Mvc.DataAnnotations.dll) no pueden residir en la capa de servicio sino que residen en la capa UI (pero ComponentModel.DataAnnotations.dll puede residir en la capa de servicio). Si todos los proyectos están en una solución (.sln), entonces no importa qué capa lo pones. En aplicaciones empresariales, cada capa tendrá su propia solución.
Así que DTO en realidad es un ViewModel porque en su mayoría habrá un mapeo uno a uno entre los dos (digamos con AutoMapper). Una vez más, DTO sigue teniendo la lógica necesaria para la interfaz de usuario (o múltiples aplicaciones) y reside en la capa de servicio. Y la capa de interfaz de usuario ViewModel (si usamos Microsoft.Web.Mvc.DataAnnotations.dll) es solo para copiar los datos de DTO, con algunos ''comportamientos'' / atributos añadidos.
[Ahora esta discusión está a punto de dar un giro interesante leer ...: I]
Y no crea que los atributos de anotación de datos son solo para la interfaz de usuario. Si limita la validación usando System.ComponentModel.DataAnnotations.dll, entonces el mismo ViewModel también se puede usar para la validación front-end y backend (eliminando así UI-residing-ViewModel-copy-of-DTO). Además, los atributos también se pueden usar en modelos de entidades. Por ejemplo, al utilizar .tt, los modelos de datos de Entity Framework pueden autogenerarse con atributos de validación para realizar algunas validaciones de DB, como max-length, antes de enviar al back-end. Otra ventaja es que si la validación de back-end cambia en DB, entonces .tt (lee los datos específicos de DB y crea el atributo para la clase de entidad) lo recogerá automáticamente. Esto puede obligar a las pruebas de la unidad de validación UI a fallar también, lo cual es una gran ventaja (para que podamos corregirlo e informar a todas las IU / consumidores en lugar de olvidar y fallar accidentalmente). Sí, la discusión se está moviendo hacia un buen diseño del marco. Como puede ver, todo está relacionado: validación de nivel, estrategia de prueba de unidad, estrategia de almacenamiento en caché, etc.
Aunque no está directamente relacionado con la pregunta. También vale la pena explorar ''ViewModel Façade'' mencionado en este enlace para ver el canal 9 . Comienza exactamente a los 11 minutos y 49 segundos en el video. Porque este sería el siguiente paso / pensamiento una vez que se resuelva su pregunta actual anterior: ''¿Cómo organizar ViewModels?''
También en su ejemplo "_repository.ListContacts ()" está devolviendo un ViewModel del repositorio. Esta no es una forma madura. Los repositorios deben proporcionar modelos de entidades o modelos de BD. Esto se convierte para ver modelos y es este modelo de vista el que devuelve la capa de servicio.
Supongo que eso depende de lo que consideren los "servicios". Realmente nunca me gustó el término servicio en el contexto de una sola clase; es increíblemente vago y no dice mucho sobre el propósito real de la clase.
Si la "capa de servicio" es una capa física, como un servicio web, entonces absolutamente no; los servicios en un contexto SOA deben exponer las operaciones de dominio / negocio, no los datos y no la lógica de presentación. Pero si el servicio solo se usa como concepto abstracto para un nivel adicional de encapsulación, no veo ningún problema con su uso de la forma en que lo desea.
Simplemente no mezcle conceptos. Si su servicio trata con modelos de vista, entonces debe ser un servicio de presentación y colocarse en capas sobre el modelo actual , sin tocar directamente la base de datos ni ninguna lógica comercial.