java - tutorial - Diferencias entre Ant y Maven
maven vs gradle comparacion (9)
¿Podría alguien decirme las diferencias entre Ant y Maven? Nunca he usado ninguno. Entiendo que se utilizan para automatizar la construcción de proyectos de Java, pero no sé por dónde empezar.
Ant es principalmente una herramienta de construcción.
Maven es una herramienta de administración de proyectos y dependencias (que por supuesto también construye su proyecto).
Ant + Ivy es una combinación bastante buena si quieres evitar a Maven.
En Maven: The Definitive Guide , escribí sobre las diferencias entre Maven y Ant en la introducción, el título de la sección es "Las diferencias entre Ant y Maven" . Aquí hay una respuesta que es una combinación de la información en esa introducción con algunas notas adicionales.
Una comparación simple
Solo te estoy mostrando esto para ilustrar la idea de que, en el nivel más básico, Maven tiene convenciones incorporadas. Aquí hay un archivo de compilación Ant simple:
<project name="my-project" default="dist" basedir=".">
<description>
simple example build file
</description>
<!-- set global properties for this build -->
<property name="src" location="src/main/java"/>
<property name="build" location="target/classes"/>
<property name="dist" location="target"/>
<target name="init">
<!-- Create the time stamp -->
<tstamp/>
<!-- Create the build directory structure used by compile -->
<mkdir dir="${build}"/>
</target>
<target name="compile" depends="init"
description="compile the source " >
<!-- Compile the java code from ${src} into ${build} -->
<javac srcdir="${src}" destdir="${build}"/>
</target>
<target name="dist" depends="compile"
description="generate the distribution" >
<!-- Create the distribution directory -->
<mkdir dir="${dist}/lib"/>
<!-- Put everything in ${build} into the MyProject-${DSTAMP}.jar file
-->
<jar jarfile="${dist}/lib/MyProject-${DSTAMP}.jar" basedir="${build}"/>
</target>
<target name="clean"
description="clean up" >
<!-- Delete the ${build} and ${dist} directory trees -->
<delete dir="${build}"/>
<delete dir="${dist}"/>
</target>
</project>
En este sencillo ejemplo de Ant, puede ver cómo debe decirle a Ant exactamente qué hacer. Existe un objetivo de compilación que incluye la tarea javac que compila el origen en el directorio src / main / java en el directorio target / classes. Tienes que decirle a Ant exactamente dónde está tu fuente, dónde quieres que se guarde el bytecode resultante y cómo empacar todo esto en un archivo JAR. Si bien hay algunos desarrollos recientes que ayudan a Ant a ser menos procesal, la experiencia de un desarrollador con Ant es codificar un lenguaje de procedimiento escrito en XML.
Contraste el ejemplo anterior de Ant con un ejemplo de Maven. En Maven, para crear un archivo JAR a partir de una fuente Java, todo lo que necesita hacer es crear un simple pom.xml, colocar su código fuente en $ {basedir} / src / main / java y luego ejecutar mvn install desde la línea de comando . El ejemplo Maven pom.xml que logra los mismos resultados.
<project>
<modelVersion>4.0.0</modelVersion>
<groupId>org.sonatype.mavenbook</groupId>
<artifactId>my-project</artifactId>
<version>1.0</version>
</project>
Eso es todo lo que necesitas en tu pom.xml. Al ejecutar mvn install desde la línea de comandos, se procesarán los recursos, se compilará el origen, se ejecutarán pruebas unitarias, se creará un JAR y se instalará el JAR en un repositorio local para su reutilización en otros proyectos. Sin modificación, puede ejecutar el sitio mvn y luego encontrar un archivo index.html en el destino / sitio que contiene enlaces a JavaDoc y algunos informes sobre su código fuente.
Es cierto que este es el proyecto de ejemplo más simple posible. Un proyecto que solo contiene código fuente y que produce un JAR. Un proyecto que sigue las convenciones de Maven y no requiere ninguna dependencia o personalización. Si quisiéramos comenzar a personalizar el comportamiento, nuestro pom.xml crecerá en tamaño, y en el más grande de los proyectos puede ver colecciones de POM Maven muy complejos que contienen una gran cantidad de personalizaciones de plugins y declaraciones de dependencia. Pero, incluso cuando los archivos POM de su proyecto se vuelven más sustanciales, contienen un tipo de información completamente diferente del archivo de compilación de un proyecto de tamaño similar que usa Ant. Los POM de Maven contienen declaraciones: "Este es un proyecto JAR", y "El código fuente está en src / main / java". Los archivos de compilación Ant contienen instrucciones explícitas: "Esto es proyecto", "La fuente está en src/main/java
", "Ejecutar javac
contra este directorio", "Poner los resultados en target/classses
", "Crear un JAR desde. ... ", etc. Donde Ant tenía que ser explícito sobre el proceso, había algo" incorporado "a Maven que solo sabía dónde estaba el código fuente y cómo debería procesarse.
Comparación de alto nivel
Las diferencias entre Ant y Maven en este ejemplo? Hormiga...
- no tiene convenciones formales como una estructura de directorio de proyecto común, debe decirle a Ant exactamente dónde encontrar el origen y dónde colocar el resultado. Las convenciones informales han surgido con el tiempo, pero no han sido codificadas en el producto.
- es procedural, tienes que decirle a Ant exactamente qué hacer y cuándo hacerlo. Tuviste que decirlo para compilar, luego copiar, luego comprimir.
- no tiene un ciclo de vida, debe definir metas y dependencias de objetivos. Debes adjuntar manualmente una secuencia de tareas a cada objetivo.
Donde Maven ...
- tiene convenciones, ya sabía dónde estaba su código fuente porque siguió la convención. Puso el bytecode en target / classes, y produjo un archivo JAR en el objetivo.
- es declarativo. Todo lo que tenía que hacer era crear un archivo pom.xml y poner su fuente en el directorio predeterminado. Maven se encargó del resto.
- tiene un ciclo de vida que invocó cuando ejecutó la
mvn install
. Este comando le dijo a Maven que ejecutara una serie de pasos de secuencia hasta que alcanzara el ciclo de vida. Como efecto secundario de este viaje a través del ciclo de vida, Maven ejecutó una serie de objetivos de complementos predeterminados que hicieron cosas como compilar y crear un JAR.
¿Qué hay de Ivy?
Bien, alguien como Steve Loughran leerá esa comparación y llamará foul. Él va a hablar sobre cómo la respuesta ignora por completo algo llamado Ivy y el hecho de que Ant puede reutilizar la lógica de compilación en las versiones más recientes de Ant. Esto es verdad. Si tienes un grupo de personas inteligentes que usan Ant + antlibs + Ivy, terminarás con una construcción bien diseñada que funciona. Aunque estoy muy convencido de que Maven tiene sentido, felizmente usaría Ant + Ivy con un equipo de proyecto que tenía un ingeniero de construcción muy astuto. Una vez dicho esto, creo que terminarás perdiendo una cantidad de complementos valiosos como el plugin Jetty y que terminarás haciendo un montón de trabajo que no necesitas hacer a lo largo del tiempo.
Más importante que Maven vs. Ant
- Es que usa un administrador de repositorio para realizar un seguimiento de los artefactos del software. Sugeriría descargar Nexus . Puede usar Nexus para proxy repositorios remotos y proporcionar un lugar para que su equipo implemente artefactos internos.
- Tiene la modularización adecuada de los componentes de software. Un gran componente monolítico rara vez aumenta con el tiempo. A medida que su proyecto se desarrolla, querrá tener el concepto de módulos y submódulos. Maven se presta muy bien a este enfoque.
- Adoptas algunas convenciones para tu construcción. Incluso si usa Ant, debe esforzarse por adoptar algún tipo de convención que sea coherente con otros proyectos. Cuando un proyecto utiliza Maven, significa que cualquiera que esté familiarizado con Maven puede recoger la compilación y comenzar a ejecutarla sin tener que jugar con la configuración solo para descubrir cómo hacer para compilarla.
Maven actúa como una herramienta de administración de dependencias, se puede usar para recuperar archivos jar desde un repositorio central o desde un repositorio que se configura, y como una herramienta de construcción declarativa. La diferencia entre una herramienta de compilación "declarativa" y una herramienta de compilación más "tradicional" es configurar lo que debe hacerse, no cómo se hace. Por ejemplo, puede decir en un script maven que un proyecto debe estar empaquetado como un archivo WAR, y maven sabe cómo manejarlo.
Maven confía en las convenciones sobre cómo se diseñan los directorios de proyectos para lograr su "declarativa". Por ejemplo, tiene una convención para dónde colocar su código principal, dónde colocar su web.xml, las pruebas de su unidad, etc., pero también le permite cambiarlas si es necesario.
También debe tener en cuenta que hay un complemento para ejecutar comandos ant dentro de maven:
http://maven.apache.org/plugins/maven-ant-plugin/
Además, los arquetipos de maven hacen que comenzar un proyecto sea realmente rápido. Por ejemplo, hay un arquetipo de Wicket, que proporciona un comando maven que ejecuta para obtener un proyecto tipo hello world completo, listo para ejecutar.
Maven también alberga un gran repositorio de proyectos de código abierto de uso común. Durante la construcción, Maven puede descargar estas dependencias por usted (así como las dependencias de sus dependencias :)) para que esta parte de la construcción de un proyecto sea un poco más manejable.
Puedo tomar a una persona que nunca ha visto a Ant - sus build.xml
s están razonablemente bien escritos, y ellos pueden entender lo que está pasando. Puedo tomar esa misma persona y mostrarles un Maven POM y no tendrán idea de lo que está pasando.
En una organización de ingeniería que es enorme, las personas escriben acerca de que los archivos Ant se vuelven grandes e inmanejables. He escrito esos tipos y limpio los scripts Ant. Realmente entiende por adelantado lo que debe hacer en el futuro y diseña un conjunto de plantillas que pueden responder al cambio y la escala en un período de más de 3 años.
A menos que tengas un proyecto simple, aprender las convenciones Maven y la manera Maven de hacer las cosas es bastante trabajo.
Al final del día no puede considerar el inicio del proyecto con Ant o Maven como un factor: es realmente el costo total de propiedad. Lo que se necesita para que la organización mantenga y amplíe su sistema de compilación en unos pocos años es uno de los principales factores que deben tenerse en cuenta.
Los aspectos más importantes de un sistema de compilación son la gestión de la dependencia y la flexibilidad para expresar la receta de compilación. Debe ser algo intuitivo cuando se hace bien.
Solo para enumerar algunas otras diferencias:
- Ant no tiene convenciones formales. Tienes que decirle a Ant exactamente dónde encontrar la fuente, dónde colocar los resultados, etc.
- Ant es de procedimiento. Tienes que decirle a Ant exactamente qué hacer; dile que compile, copie, luego comprima, etc.
- Ant no tiene un ciclo de vida.
- Maven usa convenciones. Sabe dónde está su código fuente automáticamente, siempre y cuando siga estas convenciones. No es necesario que le digas a Maven dónde está.
- Maven es declarativo; Todo lo que tiene que hacer es crear un archivo pom.xml y colocar su fuente en el directorio predeterminado. Maven se encargará del resto.
- Maven tiene un ciclo de vida. Simplemente llama a mvn install y se ejecuta una serie de pasos de secuencia.
- Maven tiene inteligencia sobre las tareas comunes del proyecto. Para ejecutar pruebas, simple ejecutar mvn test , siempre y cuando los archivos estén en la ubicación predeterminada. En Ant, primero deberías JUnit JAR file is, luego crear una classpath que incluya JUnit JAR, luego decirle a Ant dónde debería buscar el código fuente de prueba, escribir un objetivo que compila la fuente de prueba y luego ejecutar las pruebas unitarias con JUnit.
Actualizar:
Esto vino de Maven: The Definitive Guide . Lo siento, me olvidé de citarlo.
Yo diría que depende del tamaño de su proyecto ... Personalmente, usaría Maven para proyectos simples que necesitan una compilación, empaquetado e implementación sencillos. Tan pronto como necesite hacer algunas cosas más complicadas (muchas dependencias, crear archivos de mapeo ...), cambiaría a Ant ...
¿Maven o Ant? es una pregunta muy similar a esta, que debería ayudarlo a responder sus preguntas.
¿Qué es Maven? en el sitio oficial.
editar: para un proyecto nuevo o totalmente nuevo, recomiendo usar Maven: "convención sobre configuración" le ahorrará un tiempo decente en la escritura y la configuración de scripts de compilación e implementación. Cuando utilizas hormiga, la secuencia de comandos de construcción tiende a crecer con el tiempo en longitud y complejidad. Para proyectos existentes, puede ser difícil calzar su configuración / diseño en el sistema Maven.
Maven es un Framework, Ant es una Caja de Herramientas
Maven es un automóvil de carretera preconstruido, mientras que Ant es un conjunto de piezas de automóvil. Con Ant tienes que construir tu propio auto, pero al menos si necesitas conducir fuera de la carretera puedes construir el tipo correcto de auto.
Para decirlo de otra manera, Maven es un marco mientras que Ant es una caja de herramientas. Si está satisfecho trabajando dentro de los límites del marco, Maven lo hará bien. El problema para mí fue que seguí chocando con los límites del marco y no me dejaba salir.
Verbosidad de XML
tobrien es un tipo que sabe mucho sobre Maven y creo que proporcionó una comparación muy buena y honesta de los dos productos. Comparó un simple Maven pom.xml con un simple archivo Ant build y mencionó cómo los proyectos Maven pueden volverse más complejos. Creo que vale la pena echarle un vistazo a una comparación de un par de archivos que es más probable que veas en un proyecto simple del mundo real. Los siguientes archivos representan un solo módulo en una compilación de varios módulos.
Primero, el archivo Maven:
<project
xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-4_0_0.xsd">
<parent>
<groupId>com.mycompany</groupId>
<artifactId>app-parent</artifactId>
<version>1.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>persist</artifactId>
<name>Persistence Layer</name>
<dependencies>
<dependency>
<groupId>com.mycompany</groupId>
<artifactId>common</artifactId>
<scope>compile</scope>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>com.mycompany</groupId>
<artifactId>domain</artifactId>
<scope>provided</scope>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate</artifactId>
<version>${hibernate.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>commons-lang</groupId>
<artifactId>commons-lang</artifactId>
<version>${commons-lang.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring</artifactId>
<version>${spring.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.dbunit</groupId>
<artifactId>dbunit</artifactId>
<version>2.2.3</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.testng</groupId>
<artifactId>testng</artifactId>
<version>${testng.version}</version>
<scope>test</scope>
<classifier>jdk15</classifier>
</dependency>
<dependency>
<groupId>commons-dbcp</groupId>
<artifactId>commons-dbcp</artifactId>
<version>${commons-dbcp.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.oracle</groupId>
<artifactId>ojdbc</artifactId>
<version>${oracle-jdbc.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.easymock</groupId>
<artifactId>easymock</artifactId>
<version>${easymock.version}</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>
Y el archivo Ant equivalente:
<project name="persist" >
<import file="../build/common-build.xml" />
<path id="compile.classpath.main">
<pathelement location="${common.jar}" />
<pathelement location="${domain.jar}" />
<pathelement location="${hibernate.jar}" />
<pathelement location="${commons-lang.jar}" />
<pathelement location="${spring.jar}" />
</path>
<path id="compile.classpath.test">
<pathelement location="${classes.dir.main}" />
<pathelement location="${testng.jar}" />
<pathelement location="${dbunit.jar}" />
<pathelement location="${easymock.jar}" />
<pathelement location="${commons-dbcp.jar}" />
<pathelement location="${oracle-jdbc.jar}" />
<path refid="compile.classpath.main" />
</path>
<path id="runtime.classpath.test">
<pathelement location="${classes.dir.test}" />
<path refid="compile.classpath.test" />
</path>
</project>
tobrien usó su ejemplo para mostrar que Maven tiene convenciones integradas, pero eso no significa necesariamente que termine escribiendo menos XML. He encontrado que lo opuesto es verdad. El pom.xml es 3 veces más largo que el build.xml y eso sin desviarse de las convenciones. De hecho, mi ejemplo de Maven se muestra sin un adicional de 54 líneas que se requieren para configurar los complementos. Ese pom.xml es para un proyecto simple. El XML realmente comienza a crecer significativamente cuando comienza a agregar requisitos adicionales, lo que no es extraordinario para muchos proyectos.
Pero tienes que decirle a Ant qué hacer
El ejemplo anterior de My Ant no está completo, por supuesto. Todavía tenemos que definir los objetivos utilizados para limpiar, compilar, probar, etc. Estos se definen en un archivo de compilación común que es importado por todos los módulos en el proyecto de varios módulos. Lo que me lleva al punto acerca de cómo todo esto debe escribirse explícitamente en Ant, mientras que es declarativo en Maven.
Es verdad, me ahorraría tiempo si no tuviera que escribir explícitamente estos objetivos Ant. Pero cuanto tiempo? El archivo de compilación común que uso ahora es uno que escribí hace 5 años con solo algunos pequeños ajustes desde entonces. Después de mi experimento de 2 años con Maven, saqué el viejo archivo de compilación de Ant del armario, lo desempolvé y lo puse en funcionamiento nuevamente. Para mí, el costo de tener que decirle explícitamente a Ant qué hacer se ha sumado a menos de una semana en un período de 5 años.
Complejidad
La siguiente gran diferencia que me gustaría mencionar es la de la complejidad y el efecto del mundo real que tiene. Maven se creó con la intención de reducir la carga de trabajo de los desarrolladores encargados de crear y administrar procesos de compilación. Para hacer esto, tiene que ser complejo. Desafortunadamente, la complejidad tiende a negar su objetivo previsto.
Cuando se compara con Ant, el chico de la construcción en un proyecto de Maven pasará más tiempo:
- Documentación de lectura: hay mucha más documentación sobre Maven, porque hay mucho más que debes aprender.
- Educar a los miembros del equipo: Les resulta más fácil preguntar a alguien que sabe que tratar de encontrar las respuestas por sí mismos.
- Resolución de problemas de la compilación: Maven es menos confiable que Ant, especialmente los complementos no esenciales. Además, las compilaciones de Maven no son repetibles. Si dependes de una versión SNAPSHOT de un complemento, lo cual es muy probable, tu compilación puede romperse sin que hayas cambiado nada.
- Escritura de complementos de Maven: los complementos generalmente se escriben con una tarea específica en mente, por ejemplo, crear un paquete de webstart, lo que hace que sea más difícil reutilizarlos para otras tareas o combinarlos para lograr un objetivo. Por lo tanto, es posible que tenga que escribir uno de los suyos para resolver brechas en el conjunto de complementos existente.
A diferencia de:
- La documentación de Ant es concisa, completa y todo en un solo lugar.
- Ant es simple. Un nuevo desarrollador que intenta aprender Ant solo necesita comprender algunos conceptos simples (objetivos, tareas, dependencias, propiedades) para poder descubrir el resto de lo que necesita saber.
- Ant es confiable. No ha habido muchas versiones de Ant en los últimos años porque ya funciona.
- Las compilaciones Ant son repetibles porque generalmente se crean sin dependencias externas, como repositorios en línea, complementos experimentales de terceros, etc.
- Ant es completo. Debido a que es una caja de herramientas, puede combinar las herramientas para realizar casi cualquier tarea que desee. Si alguna vez necesita escribir su propia tarea personalizada, es muy simple de hacer.
Familiaridad
Otra diferencia es la familiaridad. Los nuevos desarrolladores siempre requieren tiempo para ponerse al día. La familiaridad con los productos existentes ayuda en ese sentido y los partidarios de Maven afirman con razón que esto es un beneficio de Maven. Por supuesto, la flexibilidad de Ant significa que puede crear las convenciones que desee. Entonces la convención que uso es poner mis archivos fuente en un nombre de directorio src / main / java. Mis clases compiladas van a un directorio llamado target / classes. Suena familiar, ¿no?
Me gusta la estructura de directorios utilizada por Maven. Creo que tiene sentido. También su ciclo de vida de compilación. Así que uso las mismas convenciones en mis compilaciones Ant. No solo porque tenga sentido, sino porque será familiar para cualquiera que haya usado antes a Maven.