miércoles, 5 de noviembre de 2014


La API de tu interfaz (UserControls)


Introducción


Cuando uno desarrolla una aplicación de escritorio, piensa que el interfaz será estable, que una vez que se implemente, no se modificará y si se modifica son algunos detalles. Si se sigue este principio durante el desarrollo del UI, tendremos un problema. Ya que al cabo de una año o dos, por razones comerciales, de un cliente especial, de un nuevo jefe, se modifique gran parte del UI.

Un ejemplo, supongamos que estamos desarrollando un software para la gestión del video club, y en una parte del interfaz tenemos un ListView con el titulo de la pelicula, director, etc. Esta ListView se rellena desde una base de datos. Creo que el típico error aquí, es hacer visible la ListView con el resto de la aplicación. Es decir, seguir estos pasos:

- Leer información de las peliculas de la base de datos
- Añadir información a la ListView.



Pero vamos a complicar un poco la cosa. Ahora, una vez que se la información principal de la película, queremos que en otra parte de la pantalla, se muestre el argumento de la película.
Con lo cual, lo más normal es capturar el evento de selección de la ListView para actualizar y visualizar el argumento de la película seleccionada.



private void ON_lvFilms_SelectedIndexChanged(object sender, EventArgs e)
        {
            showPlotFromFilm();
        }



Así, el método showPlotFromFilm accederá al control listview, para obtener el titulo de la película y asi buscar en la base de datos o en memoria y mostrar el argumento. Aquí, hemos introducido un acoplamiento de miedo.

El problema viene cuando al cabo de un mes o un año, por el motivo que sea, hay que cambiar la listview por un treeview, ya que se ha decidido ver las películas por géneros y el treeview es por el momento el que más se ajusta.

Entonces, si hay que cambiarlo, habría que mirar todo el programa, desde donde es visible el listview para ahora engancharlo a un treeview. Podría llevar mucho tiempo, más luego los posibles bugs por un cambio que afecta tanto.

¿Cómo disminuir este riesgo?

Crear la API del UI para tu Aplicación


Para disminuir este riesgo, una opción (la verdad que otra de momento no alcanzo a verla) es crear un control de interfaz de usuario que su responsabilidad sea la de visualizar películas.

Al igual que existen los controles para visualizar texto (TextBox) o un fichero .jpg (PictureBox), nos creamos un control para representar un objeto del dominio del problema, en este caso, una conjunto de película (no escribo 'lista' para no sugerir que en la implementación que sea una lista).

El control que visualizará la lista de películas será FilmControl.cs (deriva de UserControl)

Y tendrá una propiedad:

public List<Kernel.Film> Films

Que de hay el control rellenará la lista de las peliculas en la lista que tiene interna, pero si en el futuro se cambia a un arbol, no afectaría externamente, es decir, fuera del ámbito del control.

Y luego tendría el evento:


[Description("Se selecciono una pelicula en el control.")]
public event selectFilmHandle ONselectFilm;




Que se dispara cuando el usuario seleccione una película en la listview. Si en el futuro fuese una arbol, la implementación por dentro, detectaría la selección en el arbol y lanzará despues el evento ONselectFilm.



Esta ha sido una forma algo simple de intentar explicar la buena practica de crear partes del interfaz de usuario que manejen directamente conceptos a nivel del dominio del problema y no de implementación.

En este ejemplo se ve por ejemplo en ONselectFilm, donde es un evento que se lanza cuando se selecciona una pelicula, pero por el contrario si fuese ON__lvFilms_SelectedIndexChanged, es un evento que se lanza cuando se selecciona un elemento de la lista, y lista es ya un elemento de la implementación, y sin embargo en ONselectFilm, no se hace referencia a ningún elemento de implementación del interfaz, sino que solamente se ha selecionado, ya sea por un ListView o un TreeView o cualquier otro UI más extraño. Así, hemos reducido el acoplamiento entre partes del programa enormemente.

Para descargar el código fuente de videoClub aquí.

Conclusión


Como experiencia, esta forma de trabajar me ha ahorrado bastantes horas de trabajo, ya que se intento crear una api UI para los objetos del dominio del problema (en la carpeta Kernel del ejemplo), de esta forma si una parte del interfaz se quiere llevar a otro sitio del interfaz, o recolocar la interfaz, será más rápido y menos propenso a errores (que los habrá claro).

Félix Romo

felix.romo.sanchezseco@gmail.com









No hay comentarios:

Publicar un comentario