Cierre y resumen del 2008

0 comentarios
Llegó el momento de despedirse de este largo año 2008, mirar atrás y hacer balance de lo bueno y lo malo. Así que aprovecharé para hacer un pequeño resumen de lo que ha sido el 2008 para este blog.

La criatura nació allá por febrero, como evolución de mi anterior blog en búsqueda de un mejor hosting y soporte en cuanto a widgets, templates y ficheros se refiere.

En total el año ha dado para 35 posts contando con éste, donde he tratado de compartir algunas experiencias y pensamientos, principalmente sobre gestión de equipos, Eclipse, Axis2 y Spring.

Sólo por comentar algunos números sacados de Feedburner y Google Analytics, en la actualidad el número de suscriptores se ha estabilizado en más de 40 y las visitas mensuales superan la cifra de 1700.

El top de los posts más visitados es el siguiente:
  1. Cuando usar / no usar Hibernate. Este post lo escribí motivado por varios debates que observé sobre si usar Hibernate (como implementación referencia de JPA) o JBDC a pelo. Para mi sorpresa ha sido con diferencia el post de más éxito en lecturas aunque no en comentarios.
  2. Cómo generar un cliente webservice con Axis2 y Ant. Aunque inicialmente no tuvo mucho tirón, las visitas de Google lo han colocado en segundo lugar y como el post más visitado de todos los que he publicado sobre Axis2.
  3. Revisiones de código automatizadas con Eclipse (II) - Cómo crear tu propia configuración en Checkstyle. Un post dedicado exclusivamente al analizador de código Checkstyle y cómo personalizar un juego de reglas para sacarle el máximo partido.
Tras estos 3 le sigue todo el resto sin muchas diferencias en cuanto a visitas, hasta llegar al último lugar ocupado por Elementos negativos, supongo que por culpa de ser precisamente el primer post del blog.

Aprovecho para agradeceros a todos vuestros comentarios y vuestros mails de agradecimiento. Y no querría despedirme sin desearos suerte para este Nuevo Año 2009 y dedicaros un brindis por el talento!

Cómo monitorizar el tiempo de ejecución con Spring AOP

2 comentarios
Anteriormente ya vimos cómo usar Spring AOP para implementar un servicio transversal de logging para nuestros proyectos. En esta ocasión vamos a desarrollar un aspecto que monitorice el tiempo de ejecución de los métodos de nuestro código.

Previos

Los pasos previos son casi los mismos del ejemplo del logging, es decir:
  • Copiar a la carpeta lib del proyecto al menos los módulos spring-aop.jar, spring-beans.jar, spring-context.jar y spring-core.jar de Spring, localizados en la carpeta dist/modules de tu instalación de Spring framework.
  • Copiar a la carpeta lib del proyecto las dependencias aopalliance.jar, aspectjweaver.jar, cglib-nodep-xxx.jar. Éste último puede que no sea necesario si estás usando Hibernate. Las encontrarás todas en la carpeta lib de tu instalación de Spring framework con dependencias.

Implementación

Esta vez haremos que nuestro aspecto, lo llamaremos TimeAopMonitor, implemente el interface org.aopalliance.intercept.MethodInterceptor para definir el método invoke que nos permita tener un control más directo del momento de la ejecución del método target que queremos monitorizar. De este modo podremos calcular el tiempo que ha tardado en ejecutarse. El código es muy sencillo:

public class TimeAopMonitor implements MethodInterceptor {

public Object invoke(MethodInvocation methodInvocation) throws Throwable {
long start = System.currentTimeMillis();
Object result = methodInvocation.proceed();
long total = System.currentTimeMillis() - start;

System.out.println(methodInvocation.getMethod()
.getDeclaringClass().getName() + "."
+ methodInvocation.getMethod().getName()
+ " = " + total + "ms.");

return result;
}
}

Por supuesto, si usas un logger en vez del System.out.println, mejor.

Ojo porque el System.currentTimeMillis() no es todo lo preciso que podría ser deseable en Windows. Lleva asociado un error de +-10 milisegundos. Si usas Java 5 o superior y necesitas mayor precisión puedes usar System.nanoTime() que cálcula el tiempo en nanosegundos. También es más costoso claro.

Configuración

El último paso es configurar. Hay que definir el monitor como un bean de Spring y declarar mediante Aop los puntos de ejecución donde queramos que aplique.

Para facilitar la configuración haremos uso del schema aop de Spring y por hacerlo un poco diferente del anterior post usaremos el tipo de pointcut bean, exclusivo de Spring Aop, para indicar, pej, que vamos a monitorizar los beans cuyo id termine en Dao.

Un ejemplo del fichero de configuración Spring sería el siguiente:

<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd">

<aop:config>
<aop:advisor pointcut="bean(*Dao)" advice-ref="timeAopMonitor" />
</aop:config>

<bean id="timeAopMonitor" class="example.util.TimeAopMonitor" />
[...]
</beans>

Conclusión

Esto es todo. Una solución elegante y rápida de implementar para monitorizar el tiempo de ejecución de tu código Java. Otras características serían:
  • Sencillo. ¿no?
  • Limpio. No es necesario modificar el código fuente a monitorizar.
  • De quita-y-pon. Activar y desactivar la monitorización es tan rápido como escribir o borrar unas líneas de XML, reiniciar y listo. Ideal para monitorizar sólo en la fase de test.
  • Totalmente configurable. La configuración permite seleccionar en detalle qué clases y métodos monitorizar.

2 meses después de Hudson

6 comentarios
2 meses después de implantar Hudson como servidor de integración continua dentro del modelo de construcción de software de mi equipo de desarrollo, llega el momento de hacer valoraciones y un poco de retrospectiva.

Por qué Hudson

Existen varios servidores de integración continua disponibles a coste cero además de Hudson, como Cruise Control, Continuum y Luntbuild. En su momento estuve probando Cruise Control pero finalmente elegí Hudson por su mayor facilidad de uso, es realmente intuitivo y muy vistoso, junto con su volcada comunidad y número de plugins en constante crecimiento, que ofrecen una cierta seguridad en el soporte para la integración con otras herramientas.

Para los que no tengais mucho tiempo para hacer vuestras propias pruebas, podéis echar un vistazo al estupendo estudio que hicieron en Xnoccio.

Dificultades

Como ante cualquier intento de cambio significativo en la rutina de un equipo, la principal dificultad suele ser de naturaleza humana y no técnica. Cuando hablé de ello, sólo recibí muestras de escepticismo e indiferencia, en definitiva resistencia al cambio. Ya me pasó con el uso del testing, que costó más de la cuenta implantarlo pero que hoy todos aprecian su valor.

Como además coincidió con que ibamos hasta el cuello de trabajo, ya no es que no tuviera tiempo (en realidad Hudson se instala y configura en 5 minutos) es que no me cabía una tarea más en la cabeza. Así que la cosa se fue alargando hasta que un nuevo compañero se atrevió a instalarlo en nuestro servidor de demos. 2 meses después y con 5 proyectos ya configurados, las dudas y la resistencia se han esfumado. Eso sí, algún programador aún podría sacarle más partido si quisiera.

La única dificultad técnica vino en forma de OutOfMemory después de hacer el build de nuestro proyecto estrella. La fase de testing dura más de media hora y creaba los informes con un log bastante grande debido a la baja categoría de log configurada. Esto provocaba el OutOfMemory durante el análisis del parser dom de Hudson. Lo raro era que por más memoria que le asignaramos seguía fallando. La solución fue tan sencilla como subir la categoría del log a error, pero en mi opinión deberían mejorar ese parser porque tampoco los informes eran tan enormes.

Qué hace Hudson por mi

Todos nuestros proyectos cuentan con un script Ant para realizar las tareas de build, testing y varios tipos de revisiones de código que forman parte de nuestro modelo de construcción de software.

Hudson se encarga ejecutar este script sobre la última versión del proyecto de forma automatizada, bajo demanda o planificada periódicamente, para posteriormente publicar los correspondientes informes con gráficas de tendencias y detalles muy cuidados. De este modo se puede disponer de toda la información sobre la salud de un proyecto actualizada y disponible a sólo un par de clicks de ratón.

En concreto las tareas que se ejecutan son:
  • Build. Compila, copia y, en algunos casos, genera código como los ficheros de mapeo Hibernate. En definitiva construye la aplicación para poder ejecutar los tests sobre ella.
  • Test. Ejecuta todos los tests definidos para el proyecto.
  • Checkstyle. Ejecuta el analizador de código Java Checkstyle para obtener un informe de la calidad del código. Revisa todo, desde sintaxis a tamaños, métricas, defectos de programación, código copy/paste, javadoc, etc. La configuración por defecto es, en mi opinión, excesivamente rigurosa con la sintaxis y el javadoc. Recomiendo dedicarle un rato y crear tu propia configuración.
  • FindBugs. Ejecuta el analizador de código Java FindBugs en busca de posibles defectos y malas prácticas de programación que no cubre Checkstyle. Es bastante listo.
  • Tareas abiertas. Detecta los todo y fixme contenidos en el proyecto.
Una de las cosas que hace Hudson que más me gusta, es que en la pantalla de cada build te muestra los comentarios hechos en los últimos commits. Esto es realmente útil para hacerte una idea rápida de por donde va el desarrollo y que se hizo el último día.

Futuro

A corto plazo quiero añadir las siguientes tareas:
  • Cobertura. Sin duda la métrica que nos falta es el nivel de cobertura de los tests sobre el código del proyecto. Hice mis pruebas con el mismo Cobertura pero daba un extraño error con unas clases de nuestro proyecto estrella. Así que probaré EMMA ya que con su plugin para Eclipse no he tenido problemas.
  • Selenium. Hasta ahora todos los tests ejecutados son a nivel de código Java. Una vez probadas las bondades del testing en este nivel, es el momento de dar el siguiente paso y llevarlo a la parte web. Si bien hemos probado Selenium, sólo lo hemos usado para cargar formularios muy largos o hacer un tour por todas las pantallas de la aplicación, pero siempre ejecutándolo luego de forma manual. El objetivo es usarlo más profundamente y automatizar también este tipo de tests.
  • Despliegue. Otro paso lógico, una vez construida la aplicación es hacer que se despliegue automaticamente en nuestro servidor de demos. Además de que resulta imprescindible para los tests Selenium. De hecho en principio sí teniamos el despliegue configurado pero nuestro servidor de demos tiene poca memoria, de modo que en pocos días había que reiniciarlo porque daba un OutOfMemory y no hay más. La solución pasa por automatizar también un reinicio del servidor.

Beneficios

Las ventajas de la integración continua son obvias, (1) detección temprana y automatizada de errores, (2) disponibilidad inmediata de las últimas versiones de los artefactos generados, (3) conocimiento actualizado del estado y calidad del código del proyecto y (4) ahorro del tiempo que supone la automatización de las tareas que forman parte del modelo de construcción del proyecto.

Ahora cada mañana lo primero que hago es navegar por nuestro Hudson. Basta con un par de minutos para revisar el estado de cada proyecto y tomar las medidas necesarias para que el equipo pueda iniciar la corrección de cualquier fallo detectado o situación sospechosa. Un par de minutos.

Además en estos 2 meses ha dado tiempo a observar otros gratos efectos secundarios a la implantación de Hudson.
  • Mayor calidad del código. Antes de implantar Hudon ya habiamos empezado a usar Checkstyle desde Eclipse pero sólo han empezado a verse verdaderos resultados al automatizar las revisiones diariamente y publicar los informes.
  • Disminución del número de tests fallidos. Antes algunos tests dejaban de funcionar y se podían quedar así semanas y semanas. Normalmente hasta que me daba cuenta yo y obligaba a arreglarlos. Ahora con Hudon en plan chivato intervengo mucho menos.
  • Mejores tests. El hecho de tener que arreglar los tests ha servido para comprobar de primera mano la importancia de programar tests repetibles e independientes.
  • Mayor sentido de la responsabilidad del código. Poco a poco se va notando que cada programador cuida más su código y el proyecto en general. Nadie quiere romper una build y empieza a verse en los comentarios de los commits como toman la iniciativa para reducir las faltas de las revisiones de código.

Y, por qué no decirlo, también está la satisfacción de estar creando un verdadero modelo de construcción de software moderno, ágil y que cuida la calidad.