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.

Búsqueda incremental en Eclipse

2 comentarios
Ultimamente me ha dado por redescubrir Eclipse. Que si plugins, atajos, templates,... es soprendente lo fácil que es descubrir una nueva o simplemente desconocida funcionalidad.

Lo último ha sido la búsqueda incremental, en inglés Incremental Find. Una funcionalidad más que recomendable para aquellos que encontréis mejorable el clásico diálogo de búsqueda del editor (Ctrl+F), sobretodo después de usar todos los dias el buscar de Firefox.

Para usar la búsqueda incremental sobre un fichero basta con abrirlo en el editor y pulsar Ctrl+J. Ojo porque no aparecerá ningún diálogo ni nada visual salvo la frase Incremental Find en la barra de estado. En ese momento tecleamos la palabra a buscar y Eclipse irá buscando según tecleamos. Para moverte entre las distintas ocurrencias puedes usar las fechas arriba y abajo.

Cómo hacer que Eclipse ignore una carpeta

1 comentarios
A veces la carpeta build puede hacerse muy molesta cuando trabajamos con Eclipse, como cuando estamos buscando un fichero con el atajo Ctrl-May-R y acabamos editando la copia contenida en la carpeta build o cuando Eclipse se pone a validar todos sus ficheros.

Para hacer que Eclipse ignore una carpeta basta con pulsar con el botón derecho sobre ella, seleccionar Properties y hacer click en Derived. Rápido y efectivo, aunque podría haber sido más intuitivo.

Buenas prácticas de uso de un sistema de control de versiones (i)

3 comentarios
[MOD 081109(2): Ficheros de configuración del ide]
[MOD 081109(1): Formatea tu código antes de subirlo]

Este post es una recolección de lo que yo considero como buenas prácticas para el uso de un sistema de control de versiones (en adelante SCV). Esta recolección es fruto de mi experiencia usando tanto CVS como Subversion en múltiples proyectos con equipos formados con desde 2 hasta 5 desarrolladores donde he visto de todo (bueno y malo) y además de lo que he podido aprender leyendo a otra gente, en especial el libro Pragmatic Version Control using CVS.

Aún así lo que a mi me parezca como buena práctica podría no serlo para otros o existir una manera mejor de hacer las cosas, así que estaré encantado de leer vuestros comentarios como siempre.

Updates

Antes de nada haz un update. No empieces a programar sin estar seguro de que tu copia local del proyecto está actualizada. Evitarás caer en conflictos con otras modificaciones ya realizadas y programar algo que ya ha hecho un compañero.

Analiza los cambios realizados por tus compañeros. No le des al botón y punto. Al menos en los ficheros relacionados con tu tarea actual.

Usa un cliente y editor potente, como el de Eclipse, para comparar tu copia local de un fichero con la copia remota del servidor.

Commits

No hagas commit de algo roto. Antes de subir algo, asegúrate de que como mínimo compila (perogrullo?), la aplicación se construye bien y el servidor arranca. Un par de pruebas facilonas estaría bien, si son tests automatizados y repetibles mucho mejor. Para nota si compruebas que los tests existentes relacionados no fallan. Matrícula si añades el javadoc y pasas antes un analizador de código, tipo checkstyle, para una revisión automatizada. Intenta ser lo más estricto posible con esto, sobretodo si no cuentas con un sistema de integración continua que detecte de forma automática los fallos que se van introduciendo en el proyecto, al final ese trabajo hay que hacerlo y sale mejor poco a poco y cuando las cosas están frescas que todo al final, la semana antes de la entrega.

Formatea tu código antes de subirlo. Con un ide decente es una simple combinación de teclas o un click de ratón y evitarás conflictos.

Realiza commits regularmente. En plena fase de desarrollo lo normal sería realizar al menos un commit al día. No dejes que se acumulen modificaciones de muchos días sin subir o te llevarás más de una sorpresa en forma de conflicto en todas tus modificaciones.

Comentarios

Comenta siempre tus commits. Por mucha pereza que te de, por inútil que creas que sea, comenta tus commits.

Usa comentarios inteligentes y normalizados. Por ejemplo, clasifica los comentarios haciendo que empiecen por los prefijos ADD para nuevas caracteristicas, MOD para modificaciones y FIX para bugfixes.

Si usas un gestor de issues, tipo Jira, Trac, Mantis, etc., indica en el comentario el identificador de los issues afectados. De este modo conseguirás trazabilidad entre los issues y el código.

Estructura de un proyecto en SCV

La estructura del proyecto en el SCV debe contener todo lo necesario para construir la aplicación una vez realizado el checkout. Esto implica que si el proyecto no usa un sistema que gestione y obtenga las dependencias, como Maven o Ivy, debes añadirlas a la estructura para que estén siempre disponibles.

Sube los ficheros propios de configuración del ide sólo si es el oficial de tu organización. Un proyecto debe poder construirse de forma automática e independiente a cualquier ide por lo que no hace falta incluir los ficheros de configuración del proyecto dentro de ningún ide para cumplir con la buena práctica anterior. Sin embargo, como a los junior suele costarles demasiado configurar un proyecto en un ide, suele ser relativamente útil subir los ficheros de configuración del ide oficial de la empresa aunque contraproducente porque entonces los junior si que nunca aprenden y cambiar la ruta del JDK puede convertirse en un trauma.

No subas ficheros que son generados de forma automática como parte del propio ciclo de construcción del proyecto, como los ficheros .class, javadoc, reports o el mismo war. Como norma diría que se debe ignorar la carpeta build completa. Aquí yo hago siempre una excepción que son los ficheros .java generados a partir de un fichero wsdl, yo suelo añadirlos en la estructura SCV porque no me gusta bajarme un proyecto que no compila de primeras, no suelen cambiar con frecuencia y además su generación puede llegar a ser bastante lenta.

Conflictos

Analízalos con calma. Aunque el primer instinto es llamar al que hizo el último commit, la mayoría de los conflictos suelen ser triviales y con ayuda de un editor potente y un poco de atención podrás resolverlos solo.

Si necesitas ayuda pídela. Aún así puede que necesites ayuda, llevas poco tiempo en el proyecto, aún eres un junior, el fichero ha cambiado totalmente, crees que han podido introducir un bug,... no pasa nada, mejor que llames a tu compañero y lo resolvais juntos antes de meter la pata con tu código y el suyo.

Comenta el código una vez resuelto el conflicto si has modificado su funcionalidad. En la próxima actualización tu compañero verá que has cambiado su código, mejor que lea el motivo en el propio código antes de que te dedique algún bramido.


Esto sería todo para una primera parte, he dejado los temas avanzados y más interesantes como tags, branches y merges para una próxima segunda parte.