Anti-Pattern de números de versión

traducido por I. A.

publicado también en inglés en DZone 04.2020

Después de que la banda de los cuatro (GOF) Erich Gamma, Richard Helm, Ralph Johnson y John Vlissides publicaran el libro Design Patterns: Elements of Reusable Object-Oriented Software, aprender a describir problemas y soluciones se hizo popular en casi todos los campos del desarrollo de software. Del mismo modo, aprender a describir lo que no se debe hacer y los antipatrones se hizo igualmente popular.

En las publicaciones que trataban estos conceptos, encontramos recomendaciones útiles para el diseño de software, la gestión de proyectos, la gestión de la configuración y mucho más. En este artículo, compartiré mi experiencia con los números de versión para artefactos de software.

La mayoría de nosotros ya estamos familiarizados con un método llamado versionado semántico, un conjunto de reglas potentes y fáciles de aprender sobre cómo deben estructurarse los números de versión y cómo deben aumentar los segmentos.

Ejemplo de numeración de versiones:

  • Mayor: Cambios incompatibles en la API.
  • Menor: Añade nuevas funcionalidades.
  • Patch: Corrección de errores y correcciones.
  • Label: SNAPSHOT que marca el estado “en desarrollo”.

Un cambio de API incompatible se produce cuando se elimina o cambia el nombre de una función o clase accesible desde el exterior. Otra posibilidad es un cambio en la firma de un método. Esto significa que el valor de retorno o los parámetros se han modificado con respecto a su implementación original. En estos escenarios, es necesario aumentar el segmento Mayor del número de versión. Estos cambios suponen un alto riesgo para los consumidores de la API porque tienen que adaptar su propio código.

Cuando se trata de números de versión, también es importante saber que 1.0.0 y 1.0 son iguales. Esto tiene efecto en el requisito de que las versiones de una versión de software tienen que ser únicas. Si no, es imposible distinguir entre artefactos. En mi experiencia profesional, he participado varias veces en proyectos en los que no había procesos bien definidos para crear números de versión. El efecto de estas circunstancias era que el equipo tenía que asegurar la calidad del artefacto y se confundía con qué versión del artefacto estaba tratando en ese momento.

El mayor error que he visto es el almacenamiento de la versión de un artefacto en una base de datos junto con otras entradas de configuración. El procedimiento correcto debería ser: colocar la versión dentro del artefacto de forma que nadie después de una liberación pueda cambiarla desde fuera. La trampa en la que podrías caer es el proceso de cómo actualizar la versión después de un lanzamiento o instalación.

Puede que tenga una lista de comprobación para todas las actividades manuales durante una publicación. Pero, ¿qué sucede después de que una versión se instala en una etapa de prueba y por alguna razón otra versión de la aplicación tiene que ser instalada. ¿Todavía tiene que cambiar manualmente el número de versión? ¿Cómo averiguar qué versión está instalada o cuándo la información de la base de datos es incorrecta?

Detectar la versión correcta en esta situación es un reto muy difícil. Por esa razón, tenemos el requisito de mantener la versión dentro de la aplicación. En el próximo paso, discutiremos una forma segura y simple de resolver este problema de forma automática.

Nuestra precondición es una simple construcción de una librería Java con Maven. Por defecto, el número de versión del artefacto está escrito en el POM. Después del proceso de construcción, nuestro artefacto es creado y nombrado como: artefacto-1.0.jar o similar. Mientras no renombremos el artefacto, tendremos una forma adecuada de distinguir las versiones. Incluso después de un renombrado con un simple truco de empaquetado y comprobación, entonces, en la carpeta META-INF, somos capaces de encontrar el valor correcto.

Si usted tiene la Versión hardcoded en una propiedad o archivo de clase, también funcionaría bien, siempre y cuando no se olvide de actualizar siempre. Tal vez la ramificación y la fusión en los sistemas SCM como Git podría necesitar su atención especial para tener siempre la versión correcta en su código base.

Otra solución es utilizar Maven y el mecanismo de colocación de tokens. Antes de que corras a probarlo en tu IDE, ten en cuenta que Maven utiliza dos carpetas diferentes: sources y resources. La sustitución de tokens en sources no funcionará correctamente. Después de una primera ejecución, tu variable es reemplazada por un número fijo y desaparece. Una segunda ejecución fallará. Para preparar tu código para el reemplazo de tokens, necesitas configurar Maven como primero en el ciclo de vida de construcción:

<build>
   <resources>
      <resource>
         <directory>src/main/resources/</directory>
         <filtering>true</filtering>
      </resource>
   </resources>
   <testResources>
      <testResource>
         <directory>src/test/resources/</directory>
         <filtering>true</filtering>
      </testResource>
   </testResources>
</build>
XML

Después de este paso, necesita conocer la propiedad ${project.version} del POM. Esto le permite crear un archivo con el nombre version.property en el directorio resources. El contenido de este archivo es sólo una línea: version=${project.version}. Después de una compilación, encontrará en su artefacto la version.property con el mismo número de versión que utilizó en su POM. Ahora, usted puede escribir una función para leer el archivo y utilizar esta propiedad. Podrías almacenar el resultado en una constante para usarla en tu programa. ¡Eso es todo lo que tienes que hacer!

Ejemplo: https://github.com/ElmarDott/TP-CORE/blob/master/src/main/java/org/europa/together/utils/Constraints.java

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *