Desde que empecé con MVC me he preocupado por aprender sobre las mejores prácticas al escribir código en esta tecnología; me interesa aplicar patrones de arquitectura probados que además sean eficientes y verdaderas piezas de código bien escrito.
Si leen los primeros artículos de este blog, podrán confirmar lo que digo ya que este interés me ha llevado a investigar hasta lo más profundo cada patrón, técnica o arquitectura que voy descubriendo. Hoy les hablare del camino que siguen los datos dentro de una aplicación MVC…
Escenario típico de creación de un registro.
Supongamos que vamos a trabajar con una aplicación escrita en MVC, ya hemos accedido al sistema y vamos a crear un nuevo registro:
- Hacemos clic en el botón de Nuevo.
- El controller recibe la solicitud de enviar la página que contiene los campos para capturar los datos que se requieren para crear un registro.
- El controller genera la página en HTML y la envía de regreso.
- El usuario recibe la página y de inmediato captura la información que se le indica, al terminar hace clic en el botón de enviar.
- El navegador envía el formulario a nuestra aplicación.
- Cuando la información llega el mecanismo del Model Binding de MVC se encarga del proceso de mapear esos datos con propiedades en una clase.
- Si todo resulta correcto, el controller envía esta clase a la capa de datos.
- Si todo sale como es debido, el controller nos enviara a otra pagina para ver o para continuar con nuestro proceso de captura.
En resumen, los datos viajaran desde el navegador del usuario hasta la base de datos; en cada paso los datos deben transitar desde un ámbito o capa a otro, primero como HTML, después como ViewModels, después como Entidades y por ultimo registros. Ahora vamos a ver como es esa transformación.
Model Binding.
Si son programadores con experiencia en ASP de inmediato habrá llamado su atención el mecanismo de Model Binding. Como es posible que MVC pueda mapear automáticamente los datos que llegan en un formularios de HTML con las propiedades en una clase?
Muy sencillo, convenios. En MVC los convenios simplifican mucho de nuestro trabajo pero solo si comprendemos y respetamos las reglas del juego. Lo más interesante es que el mecanismo de Model Binding o mapeo de datos, siempre lo codificábamos y ahora es automático. MVC se encarga de trasladar los datos desde el HTML hasta las clases ViewModel.
ViewModel.
Para comprender como es posible que los datos puedan moverse entre las diferentes capas, debemos conocer sus representaciones según el contexto en el cual nos encontremos.
Como ya todos han de saber, los datos que se presentan al usuario, no son todos los datos que hay en la tabla de la base de datos; a veces a nivel de la interface hay variables que no existen en la base de datos así como también hay datos (como los identificadores) que existen en la base de datos, pero que los usuarios no ven.
Si comprenden lo anterior, entonces le encontraran sentido a la idea de tener una clase que represente los datos a nivel de la interface, una clase diferente de la que representa un registro en la base de datos.
Me refiero a los ViewModels. Al principio me causaba mucha confusión ver que en una aplicación de MVC existía una entidad (que representa un registro en la base de datos) y una clase que servía únicamente para presentar los datos al usuario en la vista. Sin embargo hoy tiene mucho sentido, no creen?
Patrones usando ViewModels.
Si se toman algún tiempo navegando en internet, leyendo ejemplos sobre MVC se toparan con algunos ejemplos que usan VM y otros que nos los usan. Esto sucede, simplemente porque no existe una forma estándar y única de usar estas clases.
- Sin ViewModel: En este tipo de código, la entidad que representa el registro de la base de datos es la misma clase que se emplea para representar los datos en la vista. El código es muy sencillo y fácil de comprender, es perfecto para ejemplos, pero se romperá en una aplicación de la vida real.
Por que como ya hemos dicho previamente, los datos que se necesitan para representar la información en la vista no son los mismos que al final se almacenaran en los registros.
- Con ViewModel: Este requerimiento, nos obligara a realizar traslado o mapeo de datos entre clases, además del traslado que se hace de forma automática con el Model Binding; esto representara mas líneas de código, pero es la mejor y más robusta forma de escribir código para MVC. Simplifica la validación de captura del usuario al separar las reglas de la base de datos, con las de la vista, a pesar que algunas podrían ser similares.
Si decidimos usar ViewModels, será necesario crear una clase Entidad que represente un registro de una tabla de la base de datos y una clase ViewModel que represente ese mismo registro pero que servirá únicamente para las vistas. Al principio tendrán las mismas propiedades, sin embargo conforme avance la programación, la clase VM terminara con mas propiedades.
Entonces son diferentes?
Efectivamente, un ViewModel y una entidad son diferentes por definición; sin embargo el secreto detrás de estas clases consiste en conservar en el ViewModel propiedades que son del mismo tipo que las de la entidad que representan y que además se llaman exactamente igual. (Las propiedades inciales).
Esto nos permite usar bibliotecas como AutoMapper para realizar el mapeo entre las clases ViewModel y las entidades con una sola línea de código. Esta biblioteca puede trasladar la información que contenga una clase en una propiedad que sea del mismo tipo y que se llame igual.
Las clases y su ámbito.
MVC refuerza el principio de separación de partes, en esta arquitectura cada parte tiene tareas específicas que deben ser independientes de las otras, con reglas establecidas como convenios que debemos respetar para que todo funcione a la perfección.
Por ejemplo: El código en una Vista no debe realizar accesos a clases del Model o el Controller no debe realizar acceso directo a los datos.
Como es posible esto? Muy fácil, el Controller únicamente trabajara con ViewModels, jamás creara una instancia de una Entidad que representa un registro de la tabla. Las vistas siempre empleara ViewModels para presentar los datos al usuario.
En el ámbito del Model tendremos al menos dos capas y cada una trabaja con una de estas clases:
- Servicios: Se encargan de recibir los datos del Controller como VM y los traducen con la ayuda del AutoMapper en Entidades que enviaran al Repositorio. Así mismo cuando reciben Entidades del Repositorio, las traducirán en VM antes de enviarlas al Controller.
- Repositorios: Siempre reciben y envían Entidades. Se creara un repositorio por cada tabla en la base de datos, tal y como lo indica el patrón. El repositorio es el encargado de las acciones del CRUD. El repositorio podría no tener conocimiento del tipo de base de datos que estamos usando.
Los repositorios y el nHibernate.
Ya hemos visto que usando el AutoMapper podemos realizar el traslado entre los ViewModels y las Entidades. Ahora nos preguntaremos y como se trasladan los datos desde la entidad hasta el registro en la base de datos?
Este paso es responsabilidad del Fluent-nHibernate; por medio de esta biblioteca podemos escribir clases de Mapeo que le servirán a nHibernate para saber que propiedades de la clase Entidad corresponden con los campos de la Tabla. Pero esto será motivo de otro artículo.
Comentario Final.
Como ya han visto los datos se encontrarán en diferentes ámbitos, cada ámbito puede tener una representación de estos, con clases especificas, que sirven para su propósito en cada capa, pero al final los datos importantes deben ser del mismo tipo y llamarse de la misma forma en todas estas clases. Ya sea como capo de un formulario HTML, como Viewmodel, Como Entidad o como campo de un registro de la tabla en una base de datos. Este es el secreto de todo.
Suerte.
No hay comentarios:
Publicar un comentario