jueves, 19 de mayo de 2011

Aplicaciones con el patrón de diseño Model-View/ViewModel


Desarrollar una interfaz de usuario de una aplicación profesional de software no es fácil. Puede ser una mezcla turbia de datos, diseño de interacción, diseño visual, conectividad, multitareas, seguridad, internacionalización, validación, test unitario y un toque de voodoo. Considerando que la interfaz del usuario expone un sistema y debe satisfacer los requerimientos de estilo impredecibles del usuario, puede ser el área más volátil de muchas aplicaciones.
Existen patrones de diseño populares que pueden ayudar a domar esta bestia difícil de manejar, pero separar y direccionar una multitud de preocupaciones puede ser difícil. Cuanto más complicados son los patrones, es más seguro que serán utilizados shortcuts que disminuyen los esfuerzos previos para hacer las cosas en el modo correcto.
No siempre falla el patrón de diseño. A veces utilizamos patrones de diseño complicados, lo cuales requieren la escritura de mucho código porque la plataforma UI en uso no se presta a sí misma para los patrones más sencillos. Lo que se necesita es una plataforma que haga fácil construir UIs utilizando patrones de diseño simples, testeados en el tiempo, y aprobados por desarrolladores. Afortunadamente, WPF y Silverlight proveen exactamente esto.
Mientras el mundo del software continua a adoptar WPF y Silverlight en un gran porcentaje, la comunidad ha estado desarrollando su propio ecosistema de patrones y prácticas. Hoy voy a revisar algunos de esas mejores prácticas para diseñar e implementar aplicaciones clientes con WPF/Silverlight. Aprovechando algunas características core de WPF en conjunto con el patrón de diseño Model-View-ViewModel, haremos un ejemplo de programa que demuestra cuan simple puede ser crear una aplicación WPF en el modo correcto.
Al finalizar este artículo, será claro como las plantillas de datos, comandos, enlace de datos, el sistema de recursos, y el patrón MVVM todos encajan para crear una aplicación simple, testable y robusta. El programa de demostración que acompaña este articulo puede servir como plantilla para una aplicación WPF que utiliza MVVM como su arquitectura central. Los test unitarios en la solución demo muestran como es fácil testear la funcionalidad de una interface de usuario cuando la funcionalidad existe en un conjunto de clases ViewModel. Antes de profundizar en los detalles, veamos porque debemos utilizar el patrón MVVM en primer lugar.
Orden vs Caos
Es innecesario y contraproducente usar un patrón de diseño en un programa simple Hello World. Cualquier desarrollador competente puede entender unas pocas líneas de código de un vistazo. Sin embargo, en la medida que el número de características en un programa se incrementa, el número de líneas de código y partes movibles incrementan en consecuencia. Eventualmente, la complejidad de un sistema, y los problemas recurrentes que contienen, alientan a los desarrolladores a organizar su código en un modo que es fácil de comprender, discutir, extender y solucionar problemas. Nosotros disminuimos el caos cognitivo de un sistema complejo aplicando nombres bien conocidos a ciertas entidades en el código fuente. Determinamos el nombre a aplicar a cada pieza de código considerando su rol funcional en el sistema.
Los desarrolladores a menudo estructuran su código de acuerdo a un patrón de diseño, opuesto a dejar que el patrón emerja naturalmente. No hay nada mal con ambos enfoques, pero en este artículo, examino los beneficios de utilizar explícitamente MVVM como la arquitectura de la aplicación. Los nombres de ciertas clases incluyen términos bien conocidos del patrón MVVM, como por ejemplo finalizar el nombre de la clase con ViewModel si la clase es una abstracción de una vista. Este enfoque ayuda a evitar el caso cognitivo mencionado anteriormente. En su lugar, puede felizmente existir en un estado de caos controlado, el cual es un estado natural en la mayorías de los proyectos de desarrollo profesionales.
La evolución del Model-View-ViewModel
Desde que la gente inicio a crear interfaces de usuario, existieron patrones de diseño populares para ayudar a hacer el trabajo más fácilmente. Por ejemplo, el Model-View-Presenter (MVP) tuvo popularidad en varias plataformas de programación de UI. MVP es una variación del patrón Model-View-Controller, el cual estuvo presente por décadas. En el caso en que nunca haya utilizado el patrón MVP, esta es una explicación simple. Lo que vemos en la pantalla es la View, los datos que muestra la View es el modelo, y el Presenter engancha los dos juntos. La view se basa en el Presenter para popular con los datos del modelo, reaccionar a la entrada del usuario, dar validación de entrada, y otras tareas.
Tiempo atrás 2004, Martin Fowler público un artículo a cerca de un patrón llamado Presentation Model (PM), el cual es similar al MVP en que separa una view de su comportamiento y estado. La parte interesante del patrón es que una abstracción de la vista es creada, llamada Presentation Model (modelo de presentación). Una view, entonces, se transforma en una representación del Presentation Model (modelo de presentación). En la explicación de Fowler, muestra que el Presentation Model frecuentemente actualiza la View, de modo que las dos permanecen en sincronía una con la otra. Esta lógica de sincronización existe como código en las clases del Presentation Model.
En 2005, John Gossman, actualmente uno de los arquitectos Microsoft de WPF y Silverlight, dio a conocer el patrón Model-View-ViewModel en su blog. El cual es idéntico al patrón de Fowler (Presentation Model), en que ambos patrones tienen como característica común la abstracción de una View, la cual contiene el estado y comportamiento de la View. Fowler introdujo Presentation Model como un medio para la creación de la abstracción de una view independiente de la plataforma de UI, donde Gossman introdujo MVVM como un modo estandarizado de aprovechar características centrales de WPF para simplificar la creación de interfaces de usuario. En ese sentido, yo considero MVVM a ser una especialización del patrón más general del Presentation Model, hecho a medida para las plataformas WPF y Silverlight.
A diferencia del Presenter en MVP, un ViewModel no necesita una referencia a una view. La view se enlaza a  propiedades de un ViewModel, el cual, a su vez, expone datos contenidos en objetos del modelo y  otro estado especifico a la view.  Los enlaces entre view y ViewModel son simples de construir porque un objeto ViewModel es establecido como DataContext de la View. Si los valores de las propiedades en el ViewModel cambian, estos nuevos valores automáticamente se propagan a la vista a través del enlace de datos. Cuando un usuario hace clic en un botón en la view, un comando en el ViewModel se ejecuta para realizar la acción requerida. El ViewModel, nunca la Vista, realiza modificaciones hechas a los datos del modelo.
Las clases View no tienen idea que las clases del modelo existen, mientras el ViewModel y el modelo están inconscientes de la view. Este es un diseño de acoplamiento flexible, que paga en muchos modos, como veremos.
Porque los desarrolladores aman MVVM
Una vez que el desarrollador esta cómodo con WPF/Silverlight y MVVM, puede ser difícil diferenciarlos. MVVM es lengua franca de los desarrolladores WPF Silverlight porque es bien adecuado para la plataforma, y WPF fue diseñado para hacer las cosas fáciles al construir aplicaciones usando el patrón MVVM. De hecho, Microsoft estaba utilizando MVVM internamente para desarrollar aplicaciones WPF como Expression Blend, mientras el centro de la plataforma WPF estaba bajo construcción. Muchos aspectos de WPF, el modelo look-less control y data templates, utiliza la fuerte separación de la visualización, del estado y comportamiento promovido por MVVM.
El único aspecto importante que hace MVVM un gran patrón para WPF es el uso de la infraestructura de enlace de datos. Enlazando propiedades del ViewModel a la view, obtenemos bajo acoplamiento entre los dos y quita la necesidad de escribir código en el ViewModel para actualizar directamente la view. El sistema de enlace de datos también soporta validación de ingreso de datos, el cual provee un modo estandarizado de transmitir errores de validación a la view.
Otras dos características de WPF que hacen este patrón tan útil son los data templates y el sistema de recursos. Data templates aplican Views a los objetos ViewModel que se muestran en la interfaz de usuario. Podemos declarar plantillas en XAML y dejar al sistema de recursos automáticamente localizar y aplicar estos templates por nosotros en tiempo de ejecución.
Si no fuera por el soporte de comandos en WPF, el patrón MVVM seria manos poderoso. En este artículo les mostrare como un ViewModel puede exponer comandos a una View, permitiendo a la vista consumir su funcionalidad. Si no estás familiarizado con commanding, recomiendo la lectura del artículo de Brian Noye’s, "Advanced WPF: Understanding Routed Events and Commands in WPF".
Además de hacer las características de WPF SILVERLIGHT un modo natural de estructurar una aplicación, el patrón es también popular porque las clases ViewModel son fáciles de hacer test unitarios. Cuando la lógica de interacción de la aplicación vive en un conjunto de clases ViewModel, podemos escribir fácilmente código que lo testea. En un sentido, Views (vistas) y test unitarios son dos tipo distintos de consumidores del ViewModel. Teniendo un framework de test para un ViewModel de una aplicación da la posibilidad de hacer test de regresión, el cual ayuda a reducir el costo de mantenimiento de la aplicación en el tiempo.
Promoviendo la creación de test de regresión automático, la testeabilidad de las clases ViewModel pueden asistir en diseñar apropiadamente interfaces de usuario.
Cuando estamos diseñando una aplicación, podemos a menudo decidir si algo va en la view o en el ViewModel. Si podemos escribir test unitarios para el ViewModel sin crear un objeto UI, podemos también encarnar el ViewModel porque no tiene dependencias en los elementos de la vista.
Como último, para los desarrolladores que trabajan con diseñadores visuales, utilizar MVVM hace mucho más fácil para crear un workflow suave en términos diseñador/desarrollador. Ya que la view es un consumidor arbitrario de un ViewModel, es fácil quitar una vista y colocar una nueva vista para visualizar el ViewModel. Este simple paso permite realizar prototipos rápidos  y una evaluación de interfaces usuario hecha por los diseñadores.
El grupo de desarrollo puede focalizarse en crear clases robustas ViewModel, y el grupo de diseño puede focalizarse en hacer views amigables con el usuario. Conectando el resultado de los dos grupos puede involucrar poco más que asegurar que existen los correctos enlaces en el archivo XAML de la vista.
En la próximo post, explicamos la aplicación Demo.


No hay comentarios:

Publicar un comentario