September 21, 2005.

Pa'afuera y no pa'adentro!

Ok, ahora vamos a hacer nuestro primer "servicio" o aplicacion multi/nivel. Pero antes que vayamos a programar como locos, es bueno prepararse un poco, mental y tecnicamente. Evitando trampas comunes.

La teoría dice:

Separa la interfaz de usuario de la lógica de negocios del acceso a datos

Pero la práctica se encarga de arruinarlo. Por ejemplo, si empezamos a hacer un sistema de contabilidad uno imagina inmediatamente los formularios de edición, los combos, las grillas (grids), etc... Entonces la mayoría hace la parte gráfica y luego va armando el servidor en base a ella.

Mal hecho, chico. Ahora el "servicio" depende de la parte gráfica (asi sea conceptualmente), y luego no portará bien a otro tipo de cliente (como un cliente web o uno celular). Ahora bien, lo más probable es que la cosa no sea tan extrema como para soportar celulares, el construir a base de la GUI genera un monton de problemas de diseño, y le quita flexibilidad.

Para poder separar el servidor del cliente, debemos PRESCINDIR del cliente... o mejor dicho, de la representación gráfica del mismo. Una manera práctica es crear un "cliente" que sea la ventana de comandos de DOS (tipo Consola) o mucho mejor: Usar DUnit. Con DUnit, podemos hacer aplicaciones que hacen pruebas automatizadamente y a la vez, es un excelente cliente que nos permitirá probar nuestro servidor sin amarrarlo a la interfaz gráfica.

Un asunto con la programación Cliente/Servidor es que la programación del Cliente es mucho más RAD pero la del servidor requiere más trabajo de código y no es tanto la parte de pegar componentes o controles.

Adicionalmente, al forzarnos a trabajar en código causa que mejoremos el diseño de la interfaze del servidor.

Aunque parezca increible, muchas veces el tener que escribir el código y OBLIGAR a probarlo empieza a generar un efecto interesante: No me gusta escribir tanto código! Y como se vuelve un poco aburridor, obliga simplificar, reorganizar, reconstruir las clases hasta que hacen lo que tienen que hacer de la forma más práctica posible...

Muchas veces se observa que de forma rutinaria en múltiples lugares se llama un proceso y se repiten varias líneas de código con ligeros cambios o parametros, el hacer un cliente con DUnit obliga a evadir ese código y a expresarlo de forma sencilla. Otra trampa común que se ve alentada por lo "simple" de generar un demo ejecutable en minutos es evadir las especificaciones, diseño y todo eso.

De paso, es la forma más segura de agregarle unos cuantos meses (o años) a un desarrollo de por cierto complicado, con más dolores de cabeza y más noches sin dormir. Así, qué mejor en este tipo de aplicaciones es hacer POR LO MENOS las especificaciones. Me gusta este artículo que da sugerencias muy prácticas y que de hecho estamos implementando en mi empresa El malabarista y se siente la mejora.

##Pa' afuera, no pa' dentro

La mayoria de los programadores programa pa'dentro (empiezan por modelar los datos - como tablas y campos, vistas, etc... -) luego le meten el "alambre" que conecta a los datos y luego hacen los formularios. Luego las validaciones de entrada y por fin la lógica de negocios. Entonces quizás los reportes, el instalador, etc... La razón? es que es MUY fácil hacerlo asi.

El problema es que pronto estar? "hackeando" el código de lógica de negocios, para que se ADAPTE a los formularios, validaciones, campos, tablas, vistas y base de datos.

El punto es, el código de la base de datos, las tablas, los controles, etc... eso ya esta HECHO. Ya sea si usa Sql Server o Firebird o Paradox, el motor de base de datos ya sabe que hacer. Delphi tiene una excelente libreria, la VCL, y sabe que hacer. Lo UNICO que esta en DUDA es la lógica de la aplicación, el resto es carpinteria.

Programar pa'dentro es construir una casa asi: Se pavimenta la calle, se montan las paredes y el techo, se hace la parte de alambrado electrico y demás de las paredes, se pone los tomas de corriente, agua, gas, se cava hondo, se pone la tuberia interna, se cava mas, se ponen los cimientos. Ups! una roca estorbo la tuberia, toco cambiarla de puesto e interfiere con esa columna... rayos! eso desetabiliza el techo, reformemos el techo, No! el muro frontal hay que moverlo tan solo 1 centimetro!. Evidentemente, esta es una forma muy entretenidad de hacer casas. Y asi se entretienen la mayoria de los programadores, porque programa pa'dentro.

Es por eso que el orden lógico es: Lógica de negocios - Acceso a datos - Interface gráfica - Interface de Informes - Base de datos o sistema de almacenamiento - Todo lo demás.

O sea, como es una casa: Cimientos, tuberias, paredes, techo, pavimento. Pintura y acabado, perfecto!

El asunto es simple: El acceso a datos, la interface gráfica, los informes y la base de datos debe girar ALREDEDOR de la lógica de negocios y no al revez. Una vez que las clases y la funcionalidad interna estan estabilizadas, estas dictan de forma natural el diseño de la base de datos... incluso el acceso a datos se vera mucho más "limpio" y las consultas serán más simples. Conectar a la interface gráfica sera mucho más sencillo (en parte: La lógica de negocios tendra en si misma la mayor parte de las validaciones) y los informes seran más faciles de sacar (ya que la base de datos esta correctamente modelada a partir del modelo conceptual del programa!).

Va a sonar algo extraño que primero esta el "Acceso a datos" pero de ultimo esta "Base de datos" con mucho pasos intermedios. La razón? Es simple, el acceso a datos se deberia mantener en memoria! Esa es una de las grandes ventajas de usar pruebas automatizadas.

Es MUY complejo armar una prueba automatizada sobre bases de datos reales (toca recrear la base de datos y llenar con datos de prueba para obtener pruebas repetibles!) y como al principio se va a hacer cambios importantes, no aguanta! asi que lo mas sencillo de hacer es modelar las clases de forma tal que puedan manejar datos en memoria.

Eso no significa necesariamente que hay que renunciar a los TDataSet. De hecho, no hay razon para hacerlo. Simplemente se pueden crear DataSet en memoria (con TClientDataSet), llenar los campos y datos de prueba, que normalmente son muy pocos. Eso es asi al menos al principio.

Obviamente al ir conectando las partes se llegara a un punto en donde el modelo de la base de datos se vera de forma evidente, y se injecta en el proyecto.

Aquí metemos las pruebas de desempeño y simulación de cargas y demás cosas. El orden de desarrollo no es estrictamente secuencial, mas bien es un trabajo en paralelo. Evidentemente habra que hacer ajustes aquí y allá, pero si DEMORAMOS lo más posible el meter todo lo que NO ES logica de negocios, el numero de cambios se reducirá ampliamente.

Al programar pa'afuera, nos aseguramos de tener un cimiento solido sobre el cual construir. Eso en terminos de POO creara una alta cohesion y deberia bajar inter-dependencia (coupling) de las clases, que es lo mejor.

Asi que recuerde: Programar pa'afuera (primero los cimientos, entonces lo demas) no solo hara a un sistema en cuanto a su codigo mas sano y solido, sino que tambien ayuda a un desarrollo más rápido y flexible!