miércoles, junio 23, 2004

Refactoring

Recientemente me vi obligado a recodificar una aplicación en un cliente. Y digo "me vi obligado" porque mi conciencia no me permitía dejarla así.

Si bien en su momento el desarrollo cumplió su función perfectamente, y quienes la hicieron estaban "empujados" por la necesidad de tener algo rápido (les resulta familiar?), ya era tiempo de darle un nuevo "toque" de modernidad, que a la vez le permitiera seguir creciendo.

Esta pequeña aplicación tiene como meta transferir información entre los sistemas propietarios del cliente y el paquete Transportation Planning & Management de i2, a la vez que controla y modifica algunos aspectos de esa información.

Pues bien, luego del refactoring aplicado, una de las medidas que utilicé para probar y demostrar que existía la necesidad de hacerlo, fue la cantidad de clases:



AplicaciónClases de dominioClases utilitariasTotal
Original9330123
Nueva354479


¿Nada mal un 35% menos, verdad? También podemos considerar que antes había 0.3 clases de servicios por cada clase de dominio, y ahora 1.25.

Pero vayamos a lo importante, el reemplazo de clases propietarias por open source y patterns.
Todo lo que había en la aplicación era hecho a medida. Todo. ¡Habían unas 20 ruedas 20 veces reinventadas!

Las clases encargadas del scheduling fueron remplazadas por Quartz.

La persistencia, implementada en JDBC directamente, se rehizo con Hibernate.
Y para la configuración de la aplicación y la dependencia entre objetos por supuesto se utilizó Spring, que por otra parte ofrece un soporte inmejorable para Quartz e Hibernate.

En algunos casos se necesitaba también un número limitado de threads ejecutándose al mismo tiempo, por ejemplo no mas de 4 ftps simultáneos en determinado servidor. Para ello, nada mejor que commons Pool.

Para el pool de conexiones a base de datos, utilizado por hibernate, se utilizó commons DBCP. Es muy interesante destacar que en utilizando ls facilidades de IoC de Spring, cambiar este pool por otro, por ejemplo el del servidor de aplicaciones, es muy sencillo.

Para cache de la base de datos utilicé EHCache, que viene prácticamente integrado con Hibernate.

Y como quiero tener siempre una base de datos ejecutándose localmente durante el desarrollo, utilicé MySql, para luego cambiar a Oracle(la base del cliente) durante las pruebas de integración en adelante.

Dado que Spring basa su framework en la utilización de POJOs, el paquete commons beanutils resultó de gran utilidad.

La aplicación utiliza varias formas de conectarse con el resto de mundo: WebSphere MQ, webMethods, ftp(commons net) y webServices (Apache XML-RCP).

Exolab Castor es un data binding framework, y fue de gran utilidad la funcionalidad Java-to-XML binding es decir, la capacidad de hidratar/deshidratar un objeto a y desde XML.

Y por supuesto el infaltable log4j, mediante commons logging.

También he aprovechado para crear los test cases y pruebas unitarias, por lo que necesité utilizar lo stándard en estos momentos: JUnit, junto con DBUnit para la configuración de la base de datos durante las pruebas y JUnitDoclet para la generación automática de la base de los TestCases.

Como Hibernate tiene ficheros de configuración donde se mapea cada propiedad de cada clase que necesitas persistir a su respectiva tabla/columna, la creación/mantenimiento de estos .hbm puede ser muy tediosa. Pero para eso existe XDoclet, que se dedica a la creación de código en base a @tags en el codigo fuente, lo que se llama Attribute-Oriented Programming.

Claro que todo esto no sería nada sin la documentación adecuada de todos (si, todos) los javadocs. En este caso utilicé también java2html para convertir los .java a html, con todo el formato necesario, para su inclusión, mediante un link, en los javadocs.

Y finalmente Ant para ejecutar diversos pasos del proceso de desarrollo, sobre todo en la generación de código (XDoclet, JUnitDoclet), en la documentación (javadocs, java2html), en el deploy (Jar, War, Ear), en la ejecución de los TestCases (JUnit, DBUnit) e incluso en la "verificación de estilo" que proveen Hammurapi o CheckStyle.

En cuanto a la utilización de patterns, voy a extrañar el Singleton gracias a Spring :), pero el resto es de increíble utilidad a la hora de tener soluciones previamente "pensadas". Todo el mundo debería empezar por patterns primero y aprender Java mas adelante.

Como ven, no hay nada nuevo bajo el sol, pero siempre es bueno comprobar que se puede utilizar efectivamente opensource y buenas prácticas (o por lo menos prácticas estándard) en beneficio de un cliente corporativo.

2 comentarios:

ocanalejo dijo...

Me encanta !! Una lista de la compra muy útil Niko! Gracias amigo !! Me servirá para recordar cuáles son las soluciones open-source de partida (ya que este post es algo antiguo) y además para tener claro cuánto me he perdido en los últimos años haciendo el chimpancé en mi vida profesional, sin poder salir de sota-caballo-rey

Un abrazo

Anónimo dijo...

Excelente blog, muy interesantes tus temas, me servirán para cuando me ponga al día en los temas de programacion (estoy en eso :). Sigue así.

Joaquin.