Rangos de dependencias con maven

 En maven todos estamos acostumbrados a poner las dependencias y en concreto, a poner la versión concreta que queremos de la dependencia. Por ejemplo, si nuestro proyecto depende de log4j, solemos poner algo como esto

<dependency>
   <groupId>log4j</groupId>
   <artifactId>log4j</artifactId>
   <version>1.2.13</version>
</dependency>

es decir, ponemos la versión concreta que deseamos de log4j, en esta caso, la 1.2.13

Pues bien, es menos conocido, quizás porque la documentación de maven es algo escasa, pero podemos indicar a maven un rango de dependencias, de forma que maven traerá la más moderna disponible. Para ello se utiliza la notación matemática para rangos de valores, donde se abre paréntesis o corchete, se pone el número de versión inicial, coma, el número de versión final y se cierra paréntesis o corchete. Un corchete indica que la versión inicial o final es válida, mientras que un paréntesis indica que no es válida. Dejar en blanco uno de los números de versión indica que no hay límite por ese lado. Así, por ejemplo

[1.2, 1.5)     Cualquier versión entre la 1.2 y la 1.5, incluyendo la 1.2 (corchete al principio), pero excluyendo la 1.5 (paréntesis al final)

[1.3, )           Versión 1.3 o superior, incluyendo la 1.3

[1.0, 2.0)     Cualquier versión 1.x.x, pero inferior a la 2.0

En realidad maven admite hasta tres números en la versión más un "cualificador". El cualificador es un nombre cualquiera que se pone detrás del número de versión separado por un guión. Por ejemplo, imagina que en nuestro proyecto entregamos una versión al cliente FEDERICO y creamos una versión congelada para ese cliente. Su número de versión podría ser 1.2.3-FEDERICO. O más común, si es una "Release Candidate", le ponemos 1.2.3-rc, o si es una beta, pues 1.2.3-beta.

No lo he probado, pero imagino que esto permite poner cosas como

[1.2, )-FEDERICO

de forma que maven traerá cualquier versión 1.2 o superior que tenga el cualificador FEDERICO, es decir, que sea del cliente FEDERICO.

Considero esto realmente interesante, porque en un proyecto grande en el que hay muchos jar desarrollados por la gente de nuestro equipo y en los que cada jar tiene sus responsables, cada responsable puede subir su número de versión cuando lo considere adecuado y los demás traerán automáticamente o no esa versión según lo que pongan en las dependencias. Si yo no quiero traerme los cambios que haga Juan en su jar, símplemente pongo que quiero la versión 1.4. Pero si me interesa traerme siempre su versión más moderna, entonces pongo [1.0, ).

Aunque supongo que es bastante conocido, aprovecho para poner aquí cual es el significado de esos tres números de versión. Si la versión es a.b.c, los números se incrementan normalmente siguiendo los siguientes criterios:

  • a se suele incrementar cuando el cambio es tan importante que hace la nueva versión incompatible con las anteriores. Si guardas datos con una versión 2.0 de un programa, posiblemente no puedas leer esos datos con la versión 1.0 del mismo programa (normalmente al revés si suele ser posible).
  • b se suele cambiar cuando no hay pérdida de compatibilidad, pero sí se han añadido nuevas funcionalidades. Por ejemplo, las versiones 1.3 y 1.4 pueden usar los mismos datos guardados indistintamente, pero la 1.4 permite imprimirlos mientras que la 1.3 no.
  • c se suele cambiar cuando se han arreglado errores respecto a la anterior. Por ejemplo, la 1.2.3 puede caerse cuando el usuario pulsa el botón A, luego minimiza la ventana y le da a la tecla de tabulador. La 1.2.4 ya no tiene ese error.

Por supuesto, esto es una convención más o menos aceptada, pero desde luego no es obligatoria.