A diario, en el mundo de Java tenemos la necesidad de realizar diferentes tareas en nuestros proyectos, como compilar, testear, empaquetar, distribuir, desplegar, etc. Sin una herramienta que nos pueda ayudar en estas tareas, el manejo del ciclo de vida de los proyectos sería demandante y a veces tediosa. En este post repasaremos la manera en la que venimos trabajando ha ido evolucionando y como algunas herramientas nos han ayudado en el proceso.

Los viejos tiempos

Aquellos que empezaban con Java antes del 2000 lo más probable es que hayan simpatizado bastante con su terminal y línea de comandos haciendo uso de los comandos javac o make, creadon sus propios scripts para poder realizar tareas comunes. En el año 2000, apareció el proyecto Apache Ant, el cual es construido usado el lenguaje de programación Java y permite definir tareas mediante un archivo build.xml. Con el tiempo se convirtió, en la herramienta de construcción por defecto en el desarrollo de aplicaciones. Y bueno, no podemos negar que hoy en día aún podemos encontrar algunos proyectos haciendo uso de ant.

Desde Ant…​ pasando por Maven hasta Gradle

Ant fue la primera build tool, por decirlo de alguna manera y se basa simplemente en crear tareas en el build.xml. Un problema que se tenia a menudo era el manejo de dependencias y usualmente se creaba un directorio lib y los archivos jar se descargaban manualmente y se colocaban dentro de esa carpeta. Con el tiempo, un nuevo proyecto surgió como sub-proyecto de Apache Ant el cual es Apache Ivy y le permite el manejo de dependencias.

A continuación un ejemplo del build.xml:

<project name="java-sample" default="jar" basedir=".">

    <target name="clean" depends="init">
        <delete dir="${build.dir}"/>
    </target>

    <target name="init">
        <property name="project.name" value="helloWorld"/>
        <property name="src.dir" value="src"/>
        <property name="test.dir" value="test"/>
        <property name="build.dir" value="build"/>
        <property name="classes.dir" value="${build.dir}/classes"/>
        <property name="reports.dir" value="reports"/>
        <path id="junit.class.path">
            <pathelement location="lib/junit-4.12.jar"/>
            <pathelement location="lib/hamcrest-core-1.3.jar"/>
            <pathelement location="${classes.dir}"/>
        </path>
    </target>

    <target name="prepare" depends="init">
        <mkdir dir="${classes.dir}"/>
    </target>

    <target name="compile" depends="prepare">
        <javac srcdir="${src.dir}" destDir="${classes.dir}" includeantruntime="false"/>
        <javac srcdir="${test.dir}" destDir="${classes.dir}" includeantruntime="false">
            <classpath refid="junit.class.path"/>
        </javac>
    </target>

    <target name="test" depends="compile">
        <property name="junit.path" refid="junit.class.path"/>
        <echo message="JUnit ClassPath is: ${junit.path}"/>

        <junit printsummary="yes" haltonfailure="yes" showoutput="true">
            <classpath refid="junit.class.path"/>

            <batchtest fork="yes" todir="${reports.dir}/">
                <formatter type="xml"/>
                <fileset dir="${test.dir}">
                    <include name="*Test*.java"/>
                </fileset>
            </batchtest>
        </junit>
    </target>

    <target name="jar" depends="test, report">
        <jar destfile="${build.dir}/${project.name}.jar" basedir="${classes.dir}"/>
    </target>

    <target name="report" depends="init">
        <junitreport todir="${reports.dir}">
            <fileset dir="${reports.dir}" includes="TEST-*.xml"/>
            <report format="noframes" todir="${reports.dir}"/>
        </junitreport>
    </target>

</project>

Ver el ejemplo completo en Ejemplo de Ant.

Maven, por su lado surgió para estandarizar el ciclo de vida de los proyectos en java. Ofreciendo tareas en común para todos los proyectos y una estructura donde separamos nuestro código de producción de nuestro código de test. De alguna manera nos permite la customización del proyecto, aunque a veces este puede resultar siendo una tarea no tan sencilla. En este caso tambien trae un archivo llamado pom.xml, donde nos permite administrar las dependencias y la configuración del proyecto.

A continuación un ejemplo del pom.xml:

<?xml version="1.0" encoding="UTF-8"?>
<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/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>io.eddumelendez.maven</groupId>
    <artifactId>maven-sample</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>jar</packaging>

    <dependencies>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <reporting>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-surefire-report-plugin</artifactId>
                <version>2.19</version>
            </plugin>
        </plugins>
    </reporting>

    <build>
        <pluginManagement>
            <plugins>
                <plugin>
                    <groupId>org.codehaus.mojo</groupId>
                    <artifactId>sonar-maven-plugin</artifactId>
                    <version>2.3</version>
                </plugin>
            </plugins>
        </pluginManagement>
    </build>

</project>

Ver el ejemplo completo en Ejemplo de Maven.

Gradle, es una de las más recientes…​ bueno, no tan recientes…​ buils tools que ha invadido el ecosistema java. Permite crear un script usando Groovy (también en Kotlin desde la versión 3.x) y ofrece un poderoso DSL. La manera rígida en la que los proyectos con maven son creados no siempre son una buena opción, en el caso que nuestros builds y gestión del proyecto sea compleja necesitamos de mayor flexibilidad en la herramienta que usamos, en este caso gradle es la opción que estas buscando.

A continuación un ejemplo del build.gradle:

group 'io.eddumelendez.gradle'
version '1.0-SNAPSHOT'

apply plugin: 'java'

sourceCompatibility = 1.8

repositories {
    mavenLocal()
    mavenCentral()
}

dependencies {
    testCompile group: 'junit', name: 'junit', version: '4.12'
}

Ver el ejemplo completo en Ejemplo de Gradle.

Son nuevos tiempos

En estos tiempos, con el surgimiento de nuevas tendencias y tecnologías que emergen para dar solución a problemas de nuestra vida diaria en el mundo de desarrollo y donde nuestra productividad como desarrolladores depende de las herramientas que se elijan, debemos escoger las herramientas que más nos ayuden con su simplicidad y flexibilidad alineadas a las necesidades.


Eddú Meléndez

Java Software Engineer, Open Source Contributor