Archivo

Archivo para febrero, 2012

Maven contra Ant: Migrar nunca ha sido fácil

Sábado, 18 de febrero de 2012

En estos momentos estoy comenzando un proyecto para la compañía en la cual trabajo el cual consiste en mejorar la forma en como liberamos el código de nuestra aplicación en producción; Sin entrar en muchos detalles les puedo decir que estoy re-escribiendo el sistema de compilación que fué creado con Ant + Make en Maven.

El proyecto ha tenido sus dificultades (menores) y la curva de aprendizaje en mi caso no fué trivial ya que uno de los problemas que quería resolver es como compartir dependencias (archivos jar o ‘artefactos’) entre ellos:

  • Ant es declarativo. En Ant todos las acciones se especifican con mucho nivel de detalle, pero esto se hace tedioso especialmente cuando los proyectos son grandes o hay muchos proyectos (repetir una y otra vez). Makefile fué usado para manejar las dependencias entre proyectos de código nativo en C y luego para unir llamadas a Ant. Un desastre
  • Soporte para Eclipse, InteliJ: Debido a la forma en la compilación con Ant fué escrita, no se puede compilar en Windows de la misma manera que Linux. Muerta la portabilidad, además de que cada desarollador tenia que aprender ciertos trucos para poder compilar la aplicación en Linux.

Al principio traté de resolver el manejo de las dependencias en Ant usando Ivy. Pero la documentación de Ivy es espantosa y por irónico que parezca hace muchas referencias a Maven. Especialmente estoy último terminó por decidirme a usar Maven, convención sobre configuración, buen soporte especialmente en Eclipse e InteliJ.

No pienso escribir un tutorial sobre Ant contra Maven (Google les puede mostrar cientos de ellos), pero las comparaciones son obvias, miren por ejemplo como se compila a StupidZombie.com:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
< ?xml version="1.0"?>
<project name="StupidZombie" default="jar" basedir=".">
    <description>
StupidZombie is a program that allows you to ping several of your favorite Blog directories. The
idea is to avoid fill the same information over and over again.
 
StupidZombie es un programa el cual le permite hacer ping a varios de sus directorios de Blogs
favoritos. La idea es evitar rellenar la misma información una y otra vez.
    </description>
        <property file="build.properties"/>
 
        <path id="path.classpath">
                <pathelement location="${jar.xmlrpc-client}"/>
                <pathelement location="${ar.ws-commons-util}"/>
                <pathelement location="${jar.xmlrpc-common}"/>
                <pathelement location="${jar.codec}"/>
                <pathelement location="${jar.tidy}"/>
                <pathelement location="${jar.httpclient}"/>
                <pathelement location="${jar.net}"/>
                <pathelement location="${jar.log}"/>
        </path>
 
        <path id="path.test">
                <path refid="path.classpath"/>
                <pathelement location="${jar.junit}"/>
                <pathelement location="${build}"/>
                <pathelement location="${test}"/>
        </path>
 
    <target name="build" depends="init" description="Compile the source code">
        <javac srcdir="${src}" destdir="${build}" deprecation="true" optimize="false" debug="true">
                <include name="**/*.java"/>
                <classpath refid="path.classpath"/>
        </javac>
        <copy description="Copy the resourcebundles for all the classes" todir="${build}" overwrite="true">
                <fileset dir="${src}">
                        <include name="**/*.xml"/>
                </fileset>
                <fileset dir="${res}">
                                <include name="**/*.properties"/>
                </fileset>
        </copy>
    </target>
 
        <target name="init" description="Pre compilation tasks">
                <mkdir dir="${dist}"/>
                <mkdir dir="${build}"/>
                <mkdir dir="${test}"/>
        </target>
 
    <target name="clean" description="Artifact cleanup">
                <delete includeEmptyDirs="yes" failonerror="no">
                        <fileset dir="${build}"/>
                        <fileset dir="${dist}" />
                        <fileset dir="${test}" />
                </delete>
    </target>
 
        <target name="jar"
       <target
                name="jar"
                depends="build"
                description="Pack the project sources for distribution">
 
                        <manifest file="${jar.file.manifest}">
                                <attribute name="Main-class" value="com.stupidzombie.gui.StupidZombieGui"/>
                        </manifest>
 
                <copy description="Copy the images for the app" todir="${build}" overwrite="true">
                        <fileset dir="${img}">
                                        <include name="**/*"/>
                        </fileset>
                </copy>
 
                        <unjar src="${jar.xmlrpc-client}" dest="${build}"/>
                        <unjar src="${jar.ws-commons-util}" dest="${build}"/>
                        <unjar src="${jar.xmlrpc-common}" dest="${build}"/>
                        <unjar src="${jar.codec}" dest="${build}"/>
                        <unjar src="${jar.httpclient}" dest="${build}"/>
                        <unjar src="${jar.tidy}" dest="${build}"/>
                        <unjar src="${jar.log}" dest="${build}"/>
 
                        <jar jarfile="${dist}/${jar.project}"
                                basedir="${build}"
                                manifest="${jar.file.manifest}">
                                <exclude name="**/test/*"/>
                        </jar>
 
                        <signjar jar="${dist}/${jar.project}"
                                alias="StupidZombie"
                                keystore="StupidZombie.keystore"
                                storepass="StupidZombie"
                                verbose="false"
                        />
 
        </target>
      <target name="test"
                depends="jar"
                description="Unit tests">
                <echo>Running unit tests</echo>
                <javac srcdir="${src}"
                        destdir="${test}"
                        includes="com/stupidzombie/ping/**/Test*"
                        deprecation="true"
                        optimize="false"
                        debug="true">
                        <classpath refid="path.test"/>
                </javac>
 
                <junit fork="yes"
                        printsummary="on"
                        maxmemory="300m">
                        <classpath refid="path.test"/>
                        <formatter type="xml" />
                        <formatter type="plain" />
 
                        <sysproperty key="ping.blog.name"
                                value="StupidZombie"/>
 
                        <sysproperty key="ping.blog.url"
                                value="http://stupidzombie.com/blog"/>
 
                        <sysproperty key="ping.blog.directoryList"
                                value="technorati"/>
 
                        <test name="${testcase}"
                                todir="${test}"
                                if="testcase"/>
 
                        <batchtest </batchtest>
                </batchtest></junit>
 
                <junitreport todir="${test}">
                        <fileset dir="${test}">
                                <include name="TEST-*.xml"/>
                        </fileset>
                        <report format="frames" todir="${test}"/>
                </junitreport>
 
        </target>
</project>

Además de tener que guardar los archivos Jar en SVN (mala practica) el archivo de compilación es grande.

Mientras que en Maven:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
< ?xml version="1.0"?>
<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">
        <parent>
                <groupid>com.stupidzombie</groupid>
                <artifactid>stupidzombie</artifactid>
                <version>20120206</version>
        </parent>
        <modelversion>4.0.0</modelversion>
        <artifactid>ping</artifactid>
        <packaging>jar</packaging>
        <name>ping</name>
        <build>
                <plugins>
                        <plugin>
                                <groupid>org.apache.maven.plugins</groupid>
                                <artifactid>maven-jar-plugin</artifactid>
                                <configuration>
                                        <archive>
                                                <manifestfile>src/main/resources/META-INF/MANIFEST.MF</manifestfile>
                                        </archive>
                                </configuration>
                        </plugin>
                        <plugin>
                                <artifactid>maven-assembly-plugin</artifactid>
                                <configuration>
                                        <descriptors>
                                                <descriptor>src/assemble/bigjar.xml</descriptor>
                                        </descriptors>
                                        <archive>
                                                <manifestfile>src/main/resources/META-INF/MANIFEST.MF</manifestfile>
                                        </archive>
                                </configuration>
                        </plugin>
                </plugins>
        </build>
        <dependencies>
                <dependency>
                        <groupid>org.apache.xmlrpc</groupid>
                        <artifactid>xmlrpc-client</artifactid>
                        <version>3.1.2</version>
                </dependency>
                <dependency>
                        <groupid>ws-commons-util</groupid>
                        <artifactid>ws-commons-util</artifactid>
                        <version>1.0.1</version>
                        <scope>compile</scope>
                </dependency>
                <dependency>
                        <groupid>commons-codec</groupid>
                        <artifactid>commons-codec</artifactid>
                        <version>1.3</version>
                        <scope>compile</scope>
                </dependency>
                <dependency>
                        <groupid>commons-httpclient</groupid>
                        <artifactid>commons-httpclient</artifactid>
                        <version>3.1</version>
                        <scope>compile</scope>
                </dependency>
                <dependency>
                        <groupid>commons-net</groupid>
                        <artifactid>commons-net</artifactid>
                        <version>2.0</version>
                        <scope>compile</scope>
                </dependency>
                <dependency>
                        <groupid>jtidy</groupid>
                        <artifactid>jtidy</artifactid>
                        <version>4aug2000r7-dev</version>
                </dependency>
        </dependencies>
</project>

Mi migración a Maven no estuvo libre de dolores:

  • En Eclipse existen varios módulos con soporte para Maven; con IAM y M2E. IAM nunca me funcionó y M2E me dió problemas con SubClipse por lo que tuve que desinstalarlo para usar Subversive.
  • Usar Maven sin un controlador de artefactos como Archiva no tiene sentido (archiva facilita muchas cosas, como el manejo de versiones). Eso significa que hay que aprender también a instalar y configurar archiva, en especial para controlar como los desarolladores liberan artefactos.
  • Aún tengo muchas preguntas en Maven, como por ejemplo el uso de perfiles y de ‘snapshots‘. Sin embargo ya logré colocar los artefactos de mis proyectos con buen manejo de versiones y para quienes lo desean en mi grupo, pueden trabajar con M2E en Eclipse.

    Mucha gente habla maravillas de Gradle, sin embargo me parece que no tiene tanta tracción como Maven, soporte básico para Eclipse, además de que hay que aprender algo de GROOVY (no es necesariamente algo malo). ¿Alguno de ustedes ha tenido experiencia real con este entorno?

    kodegeek

    Mis primeras 4 millas: NYRR Gridiron Classic (4M) / Longest Football Throw Competition

    Domingo, 5 de febrero de 2012

    Just before  the race
    La calma antes de la tormenta

    Hoy es el domingo del Super Tazón aquí en los Estados Unidos y para celebrarlo me lancé una carrera de 4 millas; En esta ocasión me puse mi franela de la edición del torneo de este año: Giants contra Patriots.

    Realmente el foco de esta carrera no es correr rápido sino constante, ya que es parte de mi entrenamiento para el medio maratón de este año. También me sirve como trampolín para el maratón de New York en el 2013 (esta es mi carrera #2 de las 9 que tengo que completar para tener mi entrada asegurada).

    Coffee way before the race
    Una de las bebidas que siempre consumo antes de correr o levantar pesas es el café. Natural, con buenas propiedades curativas y sobre todo un excelente estimulante para rendir al máximo

    El día de la carrera estuvo frio y con mucho viento; Yo decidí ponerme menos capas de ropa para evitar recalentarme (algo que pasa a menudo cuanto entreno). Además de eso he venido probando un par de cosas para mejorar mi rendimiento:

    • Tomo jugo de remolacha antes de mi entrenamiento: Según varios articulos que leí por allí, dicen que ayuda a incrementar el oxido nítrico en la sangre, y demora la fatiga ya que los musculos consumen menos oxigeno. No puedo aseverar que produce resultados asombrosos pero no es tan costoso y cualquier cosa que pueda utilizar para mejorar mi desempeño (mientras que sea natural) sirve
    • Estrené todo el tiempo hasta esta carrera con mis Vibram 5 fingers. No he tenido problemas severos en las pantorillas como el año pasado y poco a poco he ido aumentando mis millas. Estoy siendo cuidadoso, pero hoy fué la prueba definitiva corriendo con ellos en una carrera de 4 millas y me siento super bien :-)

    They say that beet juice helps to improve endurance. Is all natural so why not?
    Tomando jugo de remolacha, ¿será que me ayudara aunque sea en %1 a mejorar mi desempeño? No pierdo nada con probar

    Mi idea de la carrera era tomarme las cosas con calma, sin esforzarme ya que después de todo debía correr hoy 5 millas y no 4 para mi entrenamiento para el medio maratón (ya les contaré que plan estoy siguiendo). Así que lo que hice fué calentar corriendo una milla suave y el resto del recorrido oficial de la carrera.

    Tired but happy, did a PR today: AGE % = 58.09 (60% is local competition)
    Cansado pero contento al final de la carrera. Tenía el presentimiento de que había hecho un tiempo decente

    Al final logré un pequeño récord ya que en mi grupo de edad logré quedar en el renglón de 58% (%60 es competencia local. Tengo que seguir empujando para llegar allí):

    Last Name First Name Sex/
    Age
    Bib Team City State Country Overall
    Place
    Gender
    Place
    Age
    Place
    Net
    Time
    Pace/
    Mile
    AG
    Time
    AG
    Gender
    Place
    AG %
    Nunez Zuleta Jose V M39 4631 0 DARIEN CT USA 1173 959 174 0:30:28 07:37 0:29:01 1097 58.09

    Vienen más carreras, poco a poco con un clima más cálido :-)

    correr, kodegeek, vida sana , , , , , , , ,