Ir al contenido principal

Versionado semantico

Cuando se trabaja con proyectos de software grandes y complejos, siempre acaban apareciendo versiones del software. Cuando la plataforma es grande, el desarrollo no termina con la entrega del programa, y su puesta en producción. Evolución de requisitos, corrección de errores, cambios normativos, cuellos de botella en el rendimiento.... Existen cientos de motivos que hacen que una aplicación de tipo empresarial tenga que estar en evolución.

Si como desarrolladores no somos cuidadosos de conocer que es lo que tenemos publicado en explotación en cada momento, entonces corremos el riesgo de perder el control de lo que está desplegado. Es necesario saber en todo momento que funcioanlidades están desplegadas, y que suponen los cambios de una publicación posterior. Todo el mundo acaba numerando versiones de software para poder ubicar funcionalidades y errores. Sin embargo muchas veces esee numerado de versiones carece de sentido, y se convierte en una sucesión de números que crece excesivamente rápido, y sobre el que hay poco control o sentido.

Semver surgue de la mano de Tom Preston-Werner, con el objetivo de dar significado a los números de versión. De hecho, el propio nombre "Semver" es el apocope Sematic Versioning, que significa precisamente eso de darle significado a los números de versión.

Semver habla de tres bloques semanticos en un número de versión:

  • El número mayor, que se determina por el primer bloque de números y que distingue el aspecto general de la aplicación en esa versión. Un cambio en el número mayor implica modificaciones en el código que generan incompativilidades. Nadie debería cambiar el uso de una aplicación de la verisón 2.3.15 a la 4.1.7 a la lijera... Dos números de versión mayor significan un cambio muy grande, y posiblemente sea necesario hacer profundos cambios en la forma de usarla.
  • El número menor, que se determina por el segundo bloque de números y que distingue el nivel de completitud de una aplicación en esa versión. Cuando comparamos la versión 2.4.8 con la versión 2.11.9, lo que podemos saber rápidamente es que se han añadido una gran cantidad de funcionalidades adicionales.
  • El número de parche, que se determina por el tercer bloque de números, y que distingue la cantidad de correcciones de una aplicación en esa versión. Nuevamente si comparamos la versión 1.5.1 con la versión 1.5.22, sabremos de manera instintitva que la aplicación es exactamente la misma; pero que únicamente se han realizado multiples correcciones (tanto soluciones de bugs para el correcto funcionamiento, como optimizaciones de rendimiento).

Se pueden añadir dos sufijos adicionales, aunque su utilización no está recomendada para versión estables de producción:

  • El número de Pre-release, que se determina por el bloque, separado con un guión, y un prefijo más un número. Dichas versiones se utilizan para diferenciar las diferentes versiones de la aplicación que se publican en entornos de testing. Se suelen usar "-alpha", "-beta", o "-rc" para distingir las versiones que no han pasado ningún tipo de prueba funcional separada, de aquellas que han completados las pruebas funcionales básicas de aquellas que se consideran listas para su publicación.
  • El número de construcción, que se determna por un quinto bloque, separado con un simbolo más, y un número. El número de construicción indica el número de revisión del código fuente en el sistema de control de código (git o SVN), y más que para distinguir la versión de aplicación, aporta el conocimiento de la revisión de código fuente usada para crear el ejecutable.

Cuando iniciamos el desarrollo para una aplicación, empezaremos con la versión 0.1.0 ya que estamos desarrollando el primer conjunto de funcionalidades. Cuando nuestra aplicación se publique en producción por primera vez pasaremos a la versión 1.0.0.

Parche.

El caso más trivial para publicar una nueva versión de una aplicación es cuando se detecta algún problema en al versión publicada y es necesario hacer correcciones en dicha versión.

Las correcciones pueden ser optimizaciones para mejorar el funcionamiento, pequeños bugs que pueden estar afectando al redondeo de valores y a las que prácticamente nadie presta atención, o correcciones de bugs graves que generan cálculos incorrectos, o que exponen hacia afuera datos secretos de forma no autorizada.

La clave para mantener el cambio sólo en el número de parche es que no cambie en nada la aplicación. Todos los documentos de requisitos, manuales de usuarios, etc... serán exactamente iguales entre dos versiones que soló cambien en el número del parche. Igualmente se podrá volver arás en una versión para la que sólo cambie el parche sin que nadie se entere de nada.

Si estamos usando una versión de una librería o aplicación, es perfectamente posible reemplazarla por otra versión que tenga un número de parche tanto más alto, como más bajo, sin por ello perder funcionalidad en la aplicación. Existiran operaciones que no estén bien implementadas en determinado número de versión y habrá que tener cuidado con ese detalle.

Versión menor.

Cada vez que se añaden funcionalidades nuevas a un software en producción, se incrementa el número de versión menor. Tenemos que estar seguros de que no existe ningún cambio de compatibilidad hacia atras, y que sólamente estamos añadiendo nuevas funcionalidades.

Cuando cambiamos una versión por otra que tiene un número de versión menos superior, tenemos la seguridad de que todo lo que estaba funcionando hasta el momento seguirá funcionando de igual forma. No será necesario actualizar la documentación ya que las funcionalidades ya existentes deberán estar ahí, y conservar el mismo comportamiento.

El cambio hacia una versión menor anterior también es seguro. La aplicación deberá seguir funconando igual, aunque habrá determinados procesos que dejaran de estar disponibles. Sin embargo la estructura de los datos y las API se mantendran con completa compatibilidad.

Versión mayor.

Cada vez que sea necesario hacer algún cambio que no tenga compatibilidad hacia atras en las API publicas de la aplicación hacemos un aumento en el número de versión mayor. Esto significa que en alguna parte de la aplicación las cosas funcionaran distinto, y será necesario que la gente que los use haga cambios para que las integraciones sigan funcionando.

Un cambio de este estilo es algo que hay que meditar con mucho cuidado. Hacer un cambio de este estilo va a suponer cambios y problemas en todo el software que se integre con nosotros:

  • Si publicamos una librería con servicios, pero descubrimos que el uso de servicios dinámicos no es seguro en entornos de cluster, y tenemos que cambiar a algún tipo de modelo MVC. Cualquier software que use nuestra librería tendrá que reescribir todas sus llamadas a esos servicios.
  • Si usamos un esquema de base de datos que no represente todo lo que se necesita, y es necesario convertir columnas de base de datos de tipo "fecha" a tipo "timestamp con zona horaria", o separar a un tabla distinta los datos de contacto de un cliente. A partir de ese instante, la base de datos dejará de ser compatible con la versión anterior de la aplicación, y puede que no exista una manera sencilla de dar un paso atras, o de comprobar como "funcionaba antes" con los datos que se han añadido a posterior.
  • Si una determinada configuración por defecto genera una gran carga de procesador que entorpece la aplicación, y su aplicación no tiene sentido en la mayoría de los casos, podemos decidir que dicha configuración pase a ser necesaria de forma explícita. Instalaciones de la aplicación que están funcionando con la versión anterior sin problemas, pero que necesiten de esa configuración, van a fallar al intentar arrancar porque necesitan redeclarar la configuración.
  • Si en el recurso cliente de un api REST cambiamos el campo "email", que desaparece para cambiarlo por una lista de emails... Todos los formularios que hagan uso del campo emial tendrán que ser reescritos. Tanto los formularios de registro publico, los backoffice de administración, las notificaciones para suscripciones a listas de correos...

No es necesario que toda la aplicación cambie con una modificación de la versión mayor; pero estamos generando un cambio que va a requerir al menos trabajo de revisión en todas las instancias existentes para comprobar si dicho funcionamiento sigue siendo igual.

Junto a un cambio de versión mayor, se pueden añadir también funconalidades adicionales y correcciones.

Otros versionados no semanticos.

El estandar de SemVer lleva bastante tiempo en uso, y aporta una gran simplicidad y seguridad. Gestores de paquetes como npm permite definir dependencias en base a semver y dejar que automáticamente se actualicen las dependencias a versiones más estables sin miedo a que se modifique alguna dependencia por otra que introduzca errores. Sin embargo, no todo el mundo hace uso de dicho sistema de versionado. Existen otros, aunque es probable que generen problemas a la hora de llevar un mantenimiento automático de las versiones:

  • Números de marketing: Básicamente se trata de añadir un número delante de la versión mayor para representar un versión de "marketing" distinta. La única motivación detras de esa primer número es una cuestión comercial, posiblemente algún tipo de nombre propio para la versión.... Sin embargo ¿que ocurre cuando cambia una versión de marketing? ¿Si temos publicada la versión 3.2.7.9 y desde marketing deciden publicar la versión 4....? ¿Pasamos a la versión 4.0.0.0 y perdemos el versionado semantico que teníamos, o pasamos a la versión 4.2.7.9 y nos saltamos las versiones intermedias?.
  • Versiones publicas: Otro paso más relacionado con el marketing. En este caso lo que se opta es separar por un lado los número de versión sematicos, y tener por otro lado los números de versión publicos. Los números publicos no suelen responder a ningún tipo de semantica, y al final se añade un caos innecesario... ¿Cual es la semantica evolutiva de la versión 9 de Angular, cuando la mayor parte de los cambios de desde angular 5 son optimizaciones?
  • Versiónes de calendario: En este caso se utiliza la convención año-mes-dia correspondiente a la publicación de una versión para numerar dicha versión. Nuevamente estamos ante un problema porque no tenemos información que nos diga como de parecidas o distintas son las versiones 2019.8.12 y la 2020.10.22 ya que únicamente sabemos que hay más de un año de distancia. Sin embargo dicho a lo largo de ese año puede que los desarrollos hayan sido lentos. Que se hayan añadido sólo unas pocas funcionalidades muy complejas...

Comentarios