¡Sueño de una noche de AVM! (parte 1)

Anoche tuve un sueño. Más bien creo que fue una pesadilla. Soñé que nuevamente estaba involucrado, de la forma más bizarra que se puedan imaginar, en un proyecto de desarrollo que tenía algo que ver con el AVM.

AVM

El AVM es un producto en el que trabajé junto a varios colegas entre el 2003 y el 2006 aproximadamente. Para esa época estaba desarrollado en Java (tengo entendido que luego lo migraron a .NET) y la última vez que lo vi, tenía poco más de 100k líneas de código. Para la época, creo que era una pequeña joya, al menos yo aprendí mucho de ese producto, tanto cosas buenas que luego replicaría en otros productos, como cosas malas que luego trataría de evitar. Creo que la compañía aún existe, se llamaba Amarant-IT, conste que de alemán no entiendo ni una palabra.

Voy a resumir la tecnología / arquitectura a grandes rasgos para no escribir mucho:

  • Implementado en Java.
  • Dos capas: presentación y persistencia, la lógica de negocio estaba, salvo en algunos cálculos muy específicos, incrustada en la capa de presentación (si, feo).
  • La capa de presentación estaba implementada en Swing.
  • La capa de persistencia estaba implementada con unos DAOs desarrollados “in-house”.
  • Al principio, se usaba un framework de reportes desarrollado “in-house” (¿AbiReports?), luego los reportes se migraron a JFreeReport (que creo ya no existe).
  • Soportaba I18N (Alemán, Inglés).
  • La base de datos era MS SQL Server 2000, u Oracle.
  • El cliente como ya lo he insinuado se conectaba directamente a la base de datos, es decir, no había una capa intermedia (algún web service o algun servidor de aplicaciones).

Ahora voy a detallar los puntos importantes.

La capa de persistencia estaba formada por unos primitivos aunque efectivos DAOs. Creo que los DAOs fueron desarrollados por un colega a quién le tengo mucha estima (pero no estoy seguro si fue él en verdad quien los implementó), y dados mis conocimientos de arquitectura de software (diseño orientado a objetos) de la época, creo que en su momento eran toda una obra de arte. Hoy en día se que definitivamente se puede programar algo mucho mejor.

Como ya dije, los DAOs eran una obra de arte, lo que NO era una obra de arte era la documentación, o mejor dicho, la forma en que la gente los usaba. Es decir, si se utilizaban de la forma correcta podían ser muy eficientes… si se usaban de la forma incorrecta, entonces eran un desastre en potencia. Y un desastre en potencia fueron en su mayoría. Supongo que por razones económicas, al proyecto le “metió mano” mucha gente y mucha de esa gente utilizó los DAOs de forma incorrecta, generando un sin fin de inconvenientes, disparates y parches.

Debo decir que nosotros no fuimos ningunos santos, al principio nos costó bastante entender la forma en que se usaban los DAOs y definitivamente lo hicimos mal, contribuyendo a nuestro modo con el desastre. Sin embargo, con el tiempo aprendimos a usarlos bien y poco a poco resolvimos el problema. De tanto en tanto, pienso en esto y definitivamente me gustaría saber lo que hubiera pasado de haber tenido la oportunidad de sacar los DAOs del medio e implementar la capa de persistencia con Hibernate o algo similar (y eso estuvo a punto de hacerse más de una vez).

Sobre la capa de presentación, recuerdo que se usaban algunos componentes de IU que básicamente eran mejoras o envoltorios de los componentes básicos de Swing. Recuerdo que estos componentes cambiaron de nombre muchas veces (por razones que son desconocidas para mi) y que el último nombre con el que los conocí fue el de AbiBeans. Los componentes hacían cosas muy tontas pero útiles, tales como añadir soporte de I18N a los textfields para que pudieran interpretar números en diferentes formatos y tonterías de ese tipo en general útiles. Recuerdo que el Grid (¿JTable?) básico de Swing también tenía algunas mejoras interesantes.

Sin embargo, el componente más importante de todos se llamaba LEA (click en la imagen para agrandar):

FrmLEA_th

Creo que el nombre LEA venía de List Edit A¿XXX? (¿Architecture?), donde no recuerdo exactamente que significaba la A. Era básicamente un CRUD, es decir, un componente que permitía fácilmente y con poco esfuerzo implementar un Create / Retrieve (Read) / Update / Delete para una tabla particular de la base de datos. Pienso que en su momento llegué a estar obsesionado con ese componente, es decir, era tanto el trabajo que ahorraba que bastaba simplemente con heredar de una clase, reescribir las funciones adecuadas y listo; uno tenía un formulario para listar, filtrar, crear, editar y eliminar los registros de una tabla de la BD.

Al final fue tal mi obsesión que lo reimplementé y mejoré una y otra vez, aunque finalmente ninguna de mis implementaciones realmente llegó a usarse, pero en el camino aprendí mucho, al grado que mucho de eso influenció mi trabajo posteriormente en el framework CLEDA (Create, List, Edit, Delete Architecture… ¿les suena?).

Si les soy sincero, nunca supe exactamente lo que hacía el AVM… se que calculaba el monto que tenía que pagar una empresa de producción o de servicios por concepto de impuestos por razones de reciclaje. Es decir, la empresa hacía cierto producto (o prestaba cierto servicio) y el AVM calculaba la cantidad de desechos (el impacto en términos de basura) que ese producto tenía en el ambiente. Luego calculaba el impuesto que tenía que pagar la empresa dependiendo de la cantidad de productos vendidos del país de Europa en el que operara y de la legislación vigente en ese país. Chris: si alguna vez lees esto ¿estoy en lo correcto?

Suena raro, viniendo de alguien que trabajó activamente en el proyecto como programador, el no saber exactamente lo que el software hacía, pero esa era la realidad en ese entonces y lamentablemente creo que es la realidad en muchos proyectos de software. El trabajo en realidad era simple: nos decían “queremos estas pantallas implementadas con estos campos” y nosotros las implementabamos. “Queremos estos reportes con estos campos” y nosotros los implementabamos, “queremos estos cálculos…” y bueno… nosotros los implementabamos.

Una de las cosas que recuerdo con más cariño es hacer los “actualizadores” de la base de datos (y si, estoy siendo sarcástico cuando uso la palabra “cariño”). De versión en versión, mucha gente hacía muchos cambios a la BD y nadie se tomaba la molestia de anotar que cambio había hecho. Al final, cuando se iba a sacar la nueva versión a producción… ¿adivinen que? ¡exacto! Era necesario migrar la base de datos de los clientes de la versión anterior a la versión actual.

Era entonces cuando se programaba un “updater” o un actualizador o como lo quieran llamar, que actualizaba una BD de la versión anterior a una BD de la nueva versión. El cliente corría la nueva versión, el AVM se daba cuenta de que versión de BD tenía instalada el cliente y pedía permiso al cliente para hacer los cambios, si el cliente aceptaba, entonces el “updater” hacía los cambios.

Como no habían registros de los cambios en la BD de una versión a otra, el proceso de programar el “updater” era un verdadero dolor de cabeza. Por cierto, la moraleja aquí es llevar un registro de los cambios que se le van haciendo a la BD.

¿Cómo se resolvía el problema entonces? De forma simple pero engorrosa: se hacía “dump” del esquema viejo de la BD (los CREATE TABLE, etc.) y un “dump” del esquema nuevo. Luego, hacía lo que me gustaba llamar un “diff humano”, es decir, abría dos editores de texto uno al lado del otro y tabla por tabla, comparaba las diferencias estructurales, campos nuevos, campos eliminados, tablas nuevas, las tablas eliminadas, etc. El resultado iba a un reporte muy básico (para tener en blanco y negro las diferencias) y a la implementación de una clase que se encargaba de hacer la actualización. En ese entonces no se escribían los ALTER TABLES directamente, sino que utilizábamos el patrón command (** alargo la mano, tomo el Gamma y verifico que el nombre del patrón sea correcto**) para hacer las actualizaciones en la BD. En otras palabras, teníamos una clase (muy grande por cierto, tanto que el eclipse se atoraba) en la que escribíamos comandos (otras clases), que metíamos en una cola y que eventualmente ejecutaban los ALTER correctos dependiendo si la base de datos era MS SQL Server u Oracle.

Otra de las cosas de las que estoy orgulloso dentro del AVM es del PLO (¿Package Loading Optimizer? Creo que el PLO merece un post aparte, pero al menos voy a decir a grandes rasgos que era un módulo (¿plug-in?) del AVM que permitía optimizar la distribución de cajas en una paleta de carga. Era bastante interesante ya que el producto generaba un reporte que mostraba la forma en que debían ser cargadas las distintas cajas en la paleta, así como una vista 3D que mostraba la distribución de las cajas la en la paleta de forma interactiva.

En fin, creo que esta entrada ya está quedando muy larga, así que me despido por los momentos… Se preguntarán: ¿qué pasó después de todo con la pesadilla? Bueno, les juro que ya la tengo escrita, así que a diferencia de otros sueños, éste no se me va a olvidar (aunque quizá desearía olvidarlo), pero por lo pronto, me parece que la pesadilla va a tener que esperar a otro post.