Herramientas de construccion de Java: ANT vs Maven

ACTUALIZACIÓN: Llegué a este artículo a través de un tweet de Kent Beek. Leelo bajo tu responsabilidad y lee los comentarios.
La mejor herramienta es la que has escrito tú. Cada proceso de construcción de un proyecto es único y a menudo los proyectos individuales necesitan ser construidos de diferentes maneras. Para los autores de estas herramientas es imposible anticiparse a cada requerimiento de construcción y temerario intentarlo (desarrolladores de Apache: tomad nota). Lo mejor que puede hacer cualquier herramienta es, proveer una libreria  flexible de tareas reutilizables, que se pueden adaptar fácilmente a tus necesidades, pero es insuficiente. Extraoficialmente las tareas nunca se adaptan a tu proyecto perfectamente. Perderás incontables horas luchando para hacer que estas tareas hagan lo que necesitas exactamente, solamente para darte por vencido y escribir un plugin en su lugar. Es rápido y fácil escribir tu propia herramienta de construcción personalizada, requiere menos mantenimiento del que temes. No te preocupes: las construcciones deberían ajustarse a tu proyecto, no al revés.
Si no quieres escribir tu propia herramienta, puedes usar Rake. Rake es la mejor herramienta de construcción para proyectos java. Proporciona un montón de métodos estándar para desarrollar las tareas de construcción más comunes, y cualquier cosa puede ser implementada rápidamente en Ruby. La gran ventaja de Rake sobre otras herramientas es que puede escribir scripts en un lenguaje de programacion real. Tiene otras ventajas, pero no son tan importantes.
De esta manera puedes escribir y personalizar herramientas de construcción para tus proyectos. Si no quieres puedes usar Rake. Si no quieres cambiar, deberías. Si la política impulsa las decisiones tecnológicas, si nunca te permitirán cambiar, entonces quedate en tu trabajo o deja el proyecto.
Si te falta coraje, entonces usa Ant. Ant es la segunda mejor herramienta de construcción existente para proyectos java. Es inferior a Rake, Ant sigue siendo una gran herramienta de construcción. Es maduro y estable, es rápido y viene con una rica librería de tareas. Hace posible script ricos (pero no todo es fácil), complejos procesos de construcción adaptados a las necesidades de tu proyecto.
Puedes escribir tu propia herramienta de construcción o cambiar a Rake, o pelear por cambiar a Rake, o irte a algún lugar donde puedas usar Rake. Y si todo esto falla, usa Ant hasta que puedas encontrar un nuevo trabajo donde se use Rake.
¡Eso es!, estas son las únicas que puedo recomendar, porque nunca, nunca, ¡bajo ninguna circunstancia uses Maven!.
Las construciones de Maven son una desesperacion infinita que lentamente te arrastrara al más profundo pozo de oscuridad del infierno (donde Maven fue forjada). Inicialmente tardaras 10 minutos en instalar y arrancar Maven, podrás ser feliz con él durante algún tiempo. Pero a medida que el proyecto evoluciona, y tu configuración de contruccion crece, el elemental pom.xml que iniciaste resultará inadecuado. Lentamente añadirás más configuraciones para trabajar con lo que necesitas, pero hay mucho que puedes configurar… (traductor: sigue hablando mal de Maven).
En serio, Maven es una implementación horrible de malas ideas. Creo que alguien en alguna lugar tenía (quizás todavia tiene) una visión de Maven que era razonable, sino seductora. Pero la actual implementación de Maven carece de cualquier vestigio de dicha vision. De hecho cada cosa en Maven está tan mal, que se sirve de ejemplos de como no hacer software.  Piensas que tu construcción es alucinante cuando funciona al revés que Maven.
Tenga en cuenta la salida de resultados de pruebas del plug-in Surefire de Maven. Todo parece bien cuando las pruebas se estan pasando, pero los informes de Surefire son una pesadilla para depurar cuando las cosas van mal. La única información conectada a la consola es el nombre del test que ha caído. Manualmente tienes que hacer una referencia cruzada con el nombre que se ha grabado en el fichero log, que se encuentra en el directorio target/surefire-reports, ¡pero estos logs estan escritos uno por test!, así que si fallan múltiples test, deberás separar múltiples ficheros logs. Parece una cosa menor, pero rápidamente será una molestia y hundirá la producción.
Los defensores de Maven reclaman que la herramienta cumple el Principio de la Convención sobre Configuración. Mienten. La única convención que soporta Maven es: compilar, ejecutar test unitarios, paquetes .jar. Usar Maven para hacerlo todo requiere configurar las convenciones. ¿Quieres empaquetar un fichero .war?, configúralo. ¿Quieres ejecutar tu aplicación desde la línea de comandos?, configúralo. ¿Quieres ejecutar test de aceptación o test funcionales o desarrollar test con tu ‘build’?, configúralo, esto implica no ejecutar los test unitarios, o no ejecutarlos mientras dura la fase convencional de test unitarios del proceso ‘build‘.  ¿Quieres generar un indicador del estado del código para tu proyecto? configúralo, pero los test se ejecutarán dos veces (o solamente una, pero no durante la ejecución normal de los test) y a veces informará de un estado de código de 0% a pesar del completo juego de test.
Hablando de confguración, Maven tiene la peor sintaxis de configuración desde Sendmail: alternando la forma normal XML. Como consecuencia, la configuración de Maven es abundante, difícil de leer y de escribir. Las cosas que puedes hacer en una o dos líneas de Ruby o XML con Rake o Ant requieren seis, siete u ocho líneas en la configuración del pom.xml (asumiendo que es posible hacerlo en Maven).
No hay nada coherente en la configuración de Maven. Algunas cosas son configuradas como ‘classpath references‘ (una referencia desde la ruta donde se encuentra la clase) hacia los ficheros ‘.properties’ construidos en ficheros ‘.jar‘ configurados como dependencias, algunas son configuradas como rutas absolutas o relativas de los ficheros en el disco y algunas son configuradas como propiedades del sistema en la JVM cuando se ejecuta Maven. Y algunas de estas rutas relativas son portadas a través de los proyectos porque Maven conoce como resolverlas correctamente, pero otras no. A veces Maven es lo suficientemente inteligente para construir recursivamente  proyectos en el orden correcto, pero a veces no.
¡Algunas cosas no son configuradas en el pom.xml!, como los repositorios Maven, los servidores, las credenciales de autentificación, que son configuradas en el fichero settings.xml. Es perfectamente razonable querer mantener el usuario y contraseña fuera del fichero pom.xml pues será comprobado dentro del repositorio de control de versiones del proyecto. Pero Maven tiene una solución terrible, toda la configuración está en el fichero settings.xml que vive fuera de cualquier directorio del proyecto. No puedes compartir directamente cualquiera de las configuraciones entre tu sobremesa y tu portátil, o con cualquier desarrollador, o con el servidor de tu proyecto. Pero es automáticamente compartido con cada proyecto único de Maven con el que trabajes y potencialmente con cada usuario que use el ordenador. Cuando un nuevo desarrollador se una a tu proyecto, deberá cambiar manualmente la configuración necesaria en el fichero settings.xml. Cuando un nuevo agente es añadido a tu granja de servidores, la configuración necesaria es manualmente fusionada en el settings.xml existente. Del mismo modo cuando quieras migrar a un nuevo ordenador. Y cuando cualquiera de estas configuraciones necesiten actualizarse, debe actualizarse manualmente en cada máquina. Esto estaba ya resuelto antes de que Maven llegase, también los archivos de propiedades. Los equipos de los proyectos pueden poner una configuración genérica como está en un fichero ‘properties‘ el cual es comprobado en el control de versiones y un desarrollador puede sobreescribir la información en el fichero ‘properties‘ local, el cual no está comprobado en el control de versiones.
Todas estas cosas en Maven -convenciones, configuraciones y procesos- son gobernados a la manera Maven. Desafortunadamente “la manera Maven” no esta documentada. Puedes encontrar algo fugaz buscando en la documentación de Maven, en Google, o comprando libros escritos por los desarrolladores de Maven. Otra manera de encontrar “la manera Maven” es tropezando con sus invisibles fronteras. Maven no fue creado para ser flexible y no soporta cada posible proceso de creación (‘build’). Fue creado para los proyectos de Apache, y asume todos los procesos espejos de construcción de proyectos de Apache como propios. Es una noticia genial para los desarrolladores open-source quienes voluntariamente en su propio tiempo entienden que liberar (‘release‘)  significa subir un fichero ‘.zip‘ a la web, para que otros manualmente lo encuentren, lo descarguen y lo añadan a sus propios proyectos. Es una faena para todo lo demas. Miestras Rake y Ant pueden acomodarse a cada proceso de construcción, Maven no. Es posible y muy probable que Maven no soporte la manera que tú tienes de construir tu software.
La gestión de dependecias que tiene Maven está completa, total e irrevocablemente rota. Actualmente, retiro lo dicho; la estrategia de Maven de descargar la biblioteca al directorio del usuario y volcarlo en el ‘classpath’ es increiblemente estúpido y equivocado y nunca debería ser confundido con “gestión de dependencias”. Recientemente trabajé con Maven en un proyecto que produjo un fichero ‘.war‘ de 51MB; Cambiando a Ant, con gestión de dependencias, reducimos a menos de 17MB. Hmmmmm 51 -17 = 34 = 17*2 ó 2/3 del tamaño original.
Las dependencias extrañas no solo consumen espacio en disco, consumen también la preciosa RAM. Maven es un traga memoria. Relativamente, proyectos simples, con solo  un pom.xml y unos pocos submódulos requiere una extensa memoria de la JVM con todos las fantásticas opciones de JAVA_OPTS; esto sólo lo puedes ver en los servidores de producción. Las cosas empeoran si tu construcción Maven está integrada en tu IDE. Es muy común aumentar el tamaño de la memoria dinámica de la JVM a cientos de megabytes, el tamaño máximo ‘permgen‘ a unos pocos cientos de megabytes, permitir a ‘permgen‘ generalizar el recolector de basura de las clases. Todo esto para construir tu proyecto o para trabajar con Maven en tu IDE.
Una historia bonita: en ese mismo proyecto, Maven tardó diez minutos en hacer un ‘mvn clean‘ porque pensaba que necesitaba más basura “rm -rf ./target/“. Actualmente no hay ninguna bonita historia, créeme, no quieras contruir una herramienta que automaticamente descarga dependencias no resueltas antes de limpiar los directorios de construcción. Hace tus construciones no deterministicas [teoría que supone que la evolución de los fenómenos naturales está completamente determinada por las condiciones iniciales.]
Y todo innecesariamente, sobrecargando de red. Pagas una penalizacion en el rendimiento, Maven rompe la gestión de dependencias en cada construcción. 10 minutos para limpiar la construcción es horrible, pero añadir unos minutos extra para cada construcción es aún peor. Estimo que la sobrecarga promedio adicional de Maven es de aproximadamente un minuto por cada construcción, basado en el hecho de que la única vez que cambié Maven por Ant, la media del tiempo de construcción se redujo de dos minutos y medio a uno y medio. Similarmente, la vez que cambié de Ant a Maven el tiempo medio aumentó de dos minutos a tres.
No tienes el control, tienes poca visibilidad de lo que pasa dentro, las dependencias se especifican por tus dependencias. Los ‘builds‘ se romperán por las diferentes copias que Maven descargará de diferentes artefactos en diferentes momentos. Tu ‘build‘ local se romperá de nuevo en el futuro cuando las dependencias de tus dependecias acidentalmente lancen nuevas, no compatibles hacia atrás con los cambios, sin recordar poner el número de versión. Estos son fallos inocentes. El escenario más probable que es tu proyecto depende de versiones específicas de algún otro proyecto que tendrá dependencias de versiones antiguas de algún otro proyecto. Cada versión de cada dependencia será una nueva opotunidad para tirar muchas horas rastreando extraños fallos de construcción.
Pero Maven es incluso peor, no solamente resuelve automáticamente las dependencias de tu proyecto, también resuelve automáticamente las dependencias de sus plugins. Así que ahora no sólo tienes que preocuparte por las instancias independientes que Maven descarga accidentalmente de artefactos incompatibles (o que la misma instancia descarga artefactos incompatibles en diferentes momentos), también tienes que preocuparte de construir herramientas que se comporten de manera diferente a través de máquinas diferentes en momentos diferentes.
La mala gestión de dependencias de Maven también tiene un enorme agujero de seguridad, desde el cual actualmente es imposible determinar de donde provienen los artefactos y si han sido o no manipulados. Los artefactos tienen una suma de comprobación (‘checksum‘) automática cuando son subidos a un repositorio, Maven automáticamente verifica que la suma de comprobación cuando descarga el artefacto, pero implicitamente confía la suma de comprobación en el repositorio desde el cual se ha descargado. El alcance actual de la seguridad de los artefactos en Maven es que los desrrolladores de Maven controlan quién tiene acceso de escritura para el repositorio autorizado en la ibiblio. Pero no hay manera de saber si el repositorio del cual descargas todas tus dependencias está envenenado, no hay manera de conocer si la caché de tu repositorio local está envenenada, y no hay manera de conocer de donde proviene el repositorio de artefactos que está en tu caché local.
Estos problemas no son causados por desarrolladores temerarios, y no se solucionan usando un gestor de repositorios para bloquear todo artefacto que Maven necesite. Maven está arruinado y mal enfocado, y asume que los humanos nunca cometen errores. Maven está arruinado y mal enfocado si requieres que los usuarios explícitamente expecifiquen cada versión de cada dependencia, para reducir la probabilidad de descargarse artefactos incompatibles. Maven esta arruinado y mal enfocado si requiere una tercera herramienta para prevenir que se conecte y se descargue mierda. Maven esta arruinado y mal enfocado si piensa que no es lento descargarse cada ‘build conectándode a la red y comprobando cada dependencia de cada actualización y descargándolo automáticamente. Maven está arruinado y mal enfocado si se comporta de manera diferente en mi portátil de la oficina y en el de casa. Maven está arruinado y mal enfocado si requiere una conexión a internet para eliminar un directorio. Maven estáarruinado y mal enfocado.
Herramientas de construccion de Java: ANT vs Maven

Principio de la Convencion sobre Configuracion

de la wikipedia

La filosofía general de Maven es la estandarización de las construcciones generadas por seguir el principio de Convención sobre configuración, a fin de utilizar existentes modelos en la producción de software. Esta estrategia necesariamente restringe ampliamente la variabilidad, lo que se refleja en la exhortación de Maven a adherirse a su modelo de proyecto. Mientras que Maven es adecuado para nuevos proyectos, los proyectos complejos ya existentes pueden ser simplemente no adaptables para que utilicen Maven. La falta de restricciones de la convención de capas del proyecto fue hecha de alguna manera más configurable con el lanzamiento de Maven 2.

Principio de la Convencion sobre Configuracion

Java Basico: constructores, uso de static y final

package com.codingdojo.pomodoro;
public class FirstName {
   // Constant 'final'
   protected static final String whoiam = "a person";
   // One Attribute for all inheritance 'static'
   protected static int id= 0;
      public FirstName(){
         System.out.print("Jose");
         ++id;<
   }
}
package com.codingdojo.pomodoro;
public class SecondName extends FirstName {
   public SecondName(String c) {
   System.out.println(" " + c);
      // in constructor I can modify o instatiate 'id' atribute
      // id = 3;
   }
   public void printData(){
      System.out.println("id: " + id);
      System.out.println("is: " + whoiam);
   }

   public static void main(String[] args) {
      SecondName p = new SecondName("Alberto");
      p.printData();
      System.out.println("#######################");
      p = new SecondName("Manuel");
      p.printData();
      System.out.println("#######################");
      p = new SecondName("Miguel");
      p.printData();
   }
}

Salida por consola:

Jose Alberto
id: 1
is: a person
#######################
Jose Manuel
id: 2
is: a person
#######################
Jose Miguel
id: 3
is: a person

El ‘id‘ viene a ser mas bien un contador. Me explico, al ser static, es compartida por todas las instancias de la clase superior. Por tanto si volviéramos a ver el id del primero (“Jose Alberto”), sería =4. Osea, un contador.

Java Basico: constructores, uso de static y final

Informes en Java, un estudio comparativo

(libre traducción)
Uno de los objetivos más importantes en el diseño de aplicaciones es que estas deben ser diseñadas para ser capaces de convertir los datos complejos en texto simple, atractivo y de la forma mas comprensible posible. Los “informes y  las gráficas”  todavía tienen un largo camino que andar para alcanzar este objetivo. Las aplicaciones java vienen siendo uno de los líderes en aplicaciones empresariales para visualizar datos complejos en forma de gráficos (de tarta, barras, etc), documentos (PDF, MS Excell, etc) o informes que son específicamente personalizados para una aplicación. Hay numerosas aplicaciones java para desarrollo, que pueden ser utilizadas para generar informes.
Este documento cubre algunos de los aspectos importantes de las herramientas más utilizadas, de libre disposición y de código abierto, utilizadas en el mundo Java.

Los concursantes:

Este artículo cubre tres de las herramientas de informes más usadas en las aplicaciones java, a saber: Jasper Reports, Data Vision y Birt (Business Intelligence and Reporting Tools). Estos son los favoritos para las aplicaciones Java por tres razones: son de libre disponibilidad, son de código abierto y tienen una buena documentación y opciones para aprovechar el soporte comercial.

Jasper Reports

Es una poderosa herramienta de informes java de código libre que tiene la habilidad de entregar contenidos enriquecidos en pantalla, para ser impresos en ficheros PDF, HTML, XLS, CSV y XML. Esta enteramente escrito en java y puede ser usado en una gran variedad de aplicaciones compatibles con java, incluyendo J2EE o aplicaciones WEB, para generar contenido dinámico. Su proposito principal es ayudar a crear páginas listas para imprimir documentos de una manera simple y flexible.
Características:
  • Amplia gama de formatos de salida
  • Fuentes de datos flexibles: jasper Reports puede usar cualquier proveedor de fuente de datos, permitiendo extender esta capacidad a los informes para la mayoría de las aplicaciones de terceros. Cuando no es posible acceder a los datos a través de JDBC, o cuando no quieres que JasperReports interactue directamente con la base de datos puedes implementar una fuente de datos JasperReports personalizada. Los informes Jasper pueden obtener los datos de las siguientes fuentes de datos: JDBC, XML, JavaBean, JRDataSource personalizada, CSV, JRDataSourceProvider, Hibernate, Spring cargando una conexion Hibernate, EJBQL, Mondrian OLAP, Query executor mode, Fuente de datos vacía, conexión personalizada de iReport, XMLA Server Connection.
  • Internacionalización.
  • Impresión condicional.
  • Rotación visual de texto.
  • Código de barras integrado de apoyo
  • Basado en la Web y los informes de pixel-perfect
Formatos de salida: PDF, HTML, XLS, CSV y XML. Puede crear informes personalizados diseñando nosotros la interfaz de usuario y la alimentacion de datos.
Completamente desarrollado en java y compatible con aplicaciones java

Puntos positivos:

  • Tiene iReport como herramienta de acompañamiento para diseñar informes.
  • Cuando no es posible acceder a los datos a través del JDBC, o cuando no quieres que JasperReports interactue directamente con la base de datos, puedes implementar una fuente de datos JasperReports personalizada. Además, cualquier informe puede usar datos de múltiples fuentes de datos, y estos pueden ser de diferentes tipos.
  • Muy usado para informes en aplicaciones Java.
  • Soporte Hibernate Query ademas de SQL Queries.

    Puntos negativos:

    • Hay que realizar compilaciones del informe en todo momento.
    • Alta curva de aprendizaje.
    • Las ‘Hibernate Queries’ son poderosas, pero pueden conducir a problemas de rendimiento a menos que se preste especial atención a la optimización.

      BIRT (Business Intelligence and Reporting Tools)

      Birt esta basado en Eclipse, sistema de informes de código libre para aplicaciones web, especialmente aquellas basadas en java y J2EE. A alto nivel, BIRT provee un entorno grafico de diseño de informes, empaquetado como un plug-in para Eclipse o como un como un diseñador de informes independiente. Con un API de tiempo de ejecución, para integrar informes en tu aplicación. Tiene dos componentes principales:  un diseñador de informes basado en Eclipse y un componente en tiempo de ejecución que se puede añadir a tu servidor de aplicaciones.

      Características:

      Puede añadir una amplia variedad de informes a tu aplicación tales como:
      • Listas: los informes simples son listas de datos. Como las listas pueden ser muy largas, puedes añadir grupos para organizar datos relacionados entre sí.
      • Gráficos
      • Tablas cruzadas: muestra datos en dos dimensiones.
      • Cartas y Documentos: noticias, formularios de cartas y otros documentos de texto son fáciles de crear con BIRT. los documentos pueden incluir testo, formato, listas, gráficos y mucho más.
      • Informes compuestos: muchos informes necesitan combinar todo lo anterios en un único documento.
      Formatos de salida: lista de datos, Graficos, tablas cruzadas, HTML, HTML paginado, PDF, WORD, XLS, y PostScript.

      Puntos positivos:

      • A diferencia de Jasper donde el dxml (que contiene información de diseño del informe) tiene que ser compilado cada vez a un archivo .jasper antes de convertir el informe en el formato de salida requerido.
      • BIRT separa la colección de datos del diseño, esto proporciona una serie de ventajas como: múltiples fuentes de datos.
      • BIRT soporta la reusabilidad con plantillas y librerias. La personalización de plantillas ayuda a controlar estrechamente la capacidad de redaccion de informes.
      Informes en Java, un estudio comparativo

      Principio de Pareto

      (Texto sacado de la wikipedia)
      En el mundo de la Ingeniería del Software el principio de Pareto puede ser enunciado de diferentes formas:
      * Así por ejemplo cuando hablamos de los costes de desarrollo podríamos decir que “el 80% del esfuerzo de desarrollo (en tiempo y recursos) produce el 20% del código, mientras que el 80% restante es producido con tan sólo un 20% del esfuerzo”
      * Si hablamos de Pruebas de Software, el principio nos dice que “el 80% de los fallos de un software es generado por un 20% del código de dicho software, mientras que el otro 80% genera tan solo un 20% de los fallos”.
      Además existen algunas particularizaciones o instancias conocidas del principio, como la Regla del noventa-noventa cuyo enunciado dice que “El primer 90% del código ocupa el 10% del tiempo de desarrollo. El 10% restante del código ocupa el otro 90% de tiempo de desarrollo.”
      Principio de Pareto

      Primer Coding Dojo

      Los precios de bienes en los supermercados
      En los supermercados existen precios simples (lata de conservas de X = 0,65$) y precios complejos:
      – tres por un dólar (¿Cuál es el precio si compro 4 o 5?)
      – 1.99$ kilo. ¿Cuanto cuesta 4 Kilos?
      – compra dos, llevate uno. (¿El tercer producto tiene precio?)
      Esta kata no requiere codificación, el objetivo es expirementar con diferentes modelos para la representación de dinero y precios. Dedica tiempo a examinar cuestiones tales como:
      – ¿Existe una moneda fraccionaria?
      – ¿Cuando (o nunca) se llevar· a cabo el redondeo?
      – ¿Cómo se mantiene un registro (auditorÌa) de las decisiones de fijación de precios?, ¿es necesario?
      – ¿El coste y el precio es lo mismo?
      – Si 100 latas tienen un precio “compre dos, llevate uno”, ¿Cómo valoras el stock?.
      Meta
      El objetivo de esta kata es practicar un estilo más flexible con los modelos experimentales. Pueden haber muchas maneras de manejar estos problemas. Ten en cuenta los pros y contras de cada una. ¿Qué técnicas son las mejores para explorar estos modelos? ¿y para grabarlos?, ¿Cómo se puede validar si un modelo es razonable?.
      Propuesta para esta cata, pensarla, madurarla y realizar tareas para un TDD en un pomodoro.
      Primer Coding Dojo