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.
40.406683
-3.628032