Esta charla desentraña las complejidades de Semantic Versioning (SemVer) mientras se adentra en las complejidades prácticas del mundo real de navegar por el infierno de las dependencias. Obtén nuevos conocimientos sobre el origen y los desafíos de la versiones, descubre los poderes ocultos del esquema de versiones semánticas existente y vislumbra el futuro de la gestión de paquetes. Ya seas un desarrollador experimentado que vive y respira commits convencionales o un recién llegado ansioso por comprender este aspecto esencial de nuestro ecosistema de paquetes, esta charla promete elevar tu comprensión de todo lo relacionado con las especificaciones.
Espec-tacular - SemVer y Más Allá
Video Summary and Transcription
¡Bienvenido a DevOpsJS 2024! Discutiremos semántica y esquemas de versionado, en particular Semantic Versioning (SEMVR). Existen preocupaciones sobre las fallas en SEMVR y la necesidad de abrazar el cambio en el desarrollo de software. El infierno de las dependencias en el ecosistema de JavaScript se ha abordado mediante el versionado semántico y nuevas capacidades. Sin embargo, todavía existen problemas con la especificación SEMBR, incluyendo definiciones ausentes y problemas con los metadatos de construcción. Para mejorar el versionado, debemos abordar las definiciones faltantes y considerar una nueva especificación para el futuro.
1. Introducción a la Semántica y la Versionización
¡Bienvenidos a DevOpsJS 2024! Hablaremos sobre semántica y esquemas de versionado, en particular el versionado semántico (SEMBR). Soy Darcy Clark, un ingeniero de software con más de 20 años de experiencia. Inspirado por la charla de Rich Hickey, tengo algunas preocupaciones sobre sus puntos de vista sobre Semver. ¡Vamos a sumergirnos!
Bienvenidos, gracias por unirse a DevOpsJS 2024 y mostrar interés en mi charla de hoy. Nos adentraremos en uno de mis temas favoritos, que es la semántica y más específicamente los esquemas de versionado, siendo el más popular el versionado semántico, también conocido como SEMBR. Primero un poco sobre mí. Mi nombre es Darcy Clark. He sido ingeniero de software durante más de 20 años, desarrollando software tanto de código abierto como cerrado. Tuve una larga carrera como consultor, trabajando con marcas increíbles, agencias y grandes empresas. También cofundé una empresa llamada Themify hace unos 10 años, que ofrece temas comerciales de WordPress y todavía está activa hoy en día. Pasé los últimos cuatro años trabajando en NPM en GitHub, en los equipos de la interfaz de línea de comandos (CLI) tanto de GitHub como de NPM. Estoy construyendo un nuevo registro y cliente de paquetes JavaScript en una empresa que fundé el año pasado llamada Volt, y puedes obtener más información en VLT.SH. Esta charla en realidad fue inspirada por una charla de Rich Hickey. En 2016, hizo una presentación llamada Especulación, en la que profundiza en el versionado de software y en el propio versionado semántico. Si no has visto alguna de sus charlas antes, te recomiendo encarecidamente que vayas a YouTube y eches un vistazo a su trabajo. Esta charla en particular es increíble, y creo que él es un gran orador con ideas impresionantes. Dicho esto, tengo algunas preocupaciones con algunas de las conclusiones clave de la charla de Rich, su charla de especulación. Hasta donde puedo ver, nadie ha planteado problemas en los últimos siete años, así que espero no estar solo.
2. Desafíos con Semver y Abrazar el Cambio
Rich cree que Semver tiene fallas y solo acepta cambios compatibles hacia atrás. Yo creo que el software debe reflejar la vida real, abrazando errores y cambios. La estancación y la excesiva permisividad pueden llevar a interfaces sobrecargadas. El versionado de software debe anticipar y comunicar los cambios necesarios.
El primero de ellos es que Rich cree ampliamente que Semver es una especificación deficiente. No estoy completamente en contra de él en este punto. Creo que hay mucho margen de mejora, y definitivamente profundizaremos en eso un poco más adelante. La segunda afirmación principal y conclusión es que nunca deberíamos lanzar cambios disruptivos, o si necesitamos lanzar cambios disruptivos, deberíamos hacerlo bajo un nuevo nombre. En otras palabras, él cree que los únicos cambios aceptables en el software deberían ser los compatibles hacia atrás. Y, por supuesto, por último, está de acuerdo con la idea de la estancación del software, lo cual está en línea con el segundo punto. Para mí, creo que la creación y versionado del software deberían imitar la vida real. A veces las cosas cambian y los cambios no son perfectos. Rompemos cosas, y eso es parte de la vida. No deberíamos tener miedo de cometer errores, y deberíamos sentirnos obligados a crear entornos donde sea fácil aprender con un impacto externo mínimo cuando nos equivocamos. En el caso de la estancación, es un fenómeno natural, pero no es algo que debamos promover o pensar que es positivo. La estancación del software es lo mismo. Negarse a fomentar y mantener el software significa que probablemente tendrá un final similar al del mundo real. La muerte, o peor aún, la irrelevancia. Cuando hablamos de flexibilizar las restricciones o crear una API más amplia, volvemos a encontrarnos en un territorio antinatural e incómodo nuevamente. Ser más permisivos con el software significa que con el tiempo terminarás con una interfaz pública sobrecargada que debes mantener. Esta es una carga autoimpuesta que solo puede ser reflejada a través de cambios disruptivos. Esto es similar a cómo es posible que necesites romper malos hábitos en el mundo físico. Pero eso termina prolongando tu vida útil. Por último, considero totalmente antinatural contaminar nuestros ecosistemas con espacios de nombres falsos. Nuestros esquemas de versiones deberían liberarnos de los contratos restrictivos que tenemos con interfaces históricas, siempre y cuando el propósito subyacente del proyecto no haya cambiado. Este punto de vista que tengo proviene de mi comprensión de que el software y el versionado de software son caóticos, al igual que la vida. El software cambia con el tiempo, y esto refleja cómo todos aprendemos y crecemos orgánicamente. Los cambios en el software pueden romper cosas, al igual que en el mundo real. No todos los cambios son esperados, y a veces rompen. Pero debemos respetar y aceptar que los cambios disruptivos son parte de la vida y son parte del crecimiento. Tener un esquema en su lugar que anticipe eso como algo necesario, es fundamental para crear un ecosistema próspero de software versionado. A veces, los cambios incluso pueden quitar cosas, lo cual es otro tipo de ruptura y cambio. Pero nuevamente, esto refleja la vida real. Y en última instancia, una especificación de versionado de software
3. Dependency Hell and the JavaScript Ecosystem
La versión semántica es una solución para el infierno de las dependencias, que tiene nueve círculos de problemas. Sunbird no resolvió el primer círculo, pero Node y NPM sí lo hicieron. El ecosistema de JavaScript ha adoptado la versión semántica y ha agregado nuevas reglas y capacidades para evitar el infierno de las dependencias.
4. The Sixth Circle of Dependency Hell
Nos enfrentamos al sexto círculo del infierno de las dependencias, conocido como herejía. Nuestro ecosistema carece de autocontrol en el consumo de dependencias, como se muestra por la cantidad excesiva de paquetes instalados. Los gestores de paquetes interpretan la especificación de manera diferente, lo que lleva a inconsistencias. Sin embargo, hay esperanza.
5. Problemas con la especificación SEMBR
SEMBR tiene buenas intenciones pero está plagado de definiciones malas y ausentes. La especificación actual tiene 11 años y presenta problemas con las versiones de parche y las compilaciones. La definición oficial de un parche es la compatibilidad hacia atrás, lo cual es prácticamente imposible. La definición de las compilaciones en la especificación fue cambiada, lo que ha causado consecuencias importantes. SEMBR 2.0.0-rc1 es la especificación más precisa para la numeración de versiones.
En este punto, probablemente estés pensando que estos son problemas que parecen sistémicos y que estamos definitivamente en una situación difícil. Pero te prometo que hay esperanza.
Entonces echemos un vistazo al estado actual de la especificación SEMBR en sí misma. Es importante destacar que SEMBR y las personas detrás de ella tienen buenas intenciones, pero desafortunadamente, en mi opinión, SEMBR está plagado de definiciones malas y extrañamente ausentes. Si aún no lo has hecho, lee la especificación en Sembr.org. La especificación actual, SEMBR 2.0.0, tiene aproximadamente 11 años y consta de 11 reglas. La versión normal básica en SEMBR se considera compuesta por una versión principal, una versión secundaria y una versión de parche. La versión principal representa cambios incompatibles en la API, la versión secundaria representa funcionalidad o capacidades adicionales que son compatibles hacia atrás, y la versión de parche representa correcciones destinadas a solucionar errores en la funcionalidad existente. Hay matices en esto, donde puedes encontrar fragmentos de versiones normales en materiales de marketing populares como 1.0, 3.0. Y se entiende que los valores se leen de izquierda a derecha y la precedencia de las versiones está bien definida. Entonces echemos un vistazo a algunas de las extensiones de SEMBR. Además de la versión normal, hay dos extensiones en la especificación SEMBR. Ambas versiones preliminares se definen con un guión, que las separa de la versión normal. Y los metadatos de compilación también se pueden agregar al final de la versión, separados por un signo más. En general, todos los componentes de una versión semántica son como se define hoy en día. Con esa visión general básica, profundicemos en las definiciones que la especificación actual tiene incorrectas. El primer problema que puedes encontrar con la especificación es en realidad la definición de un parche. La especificación oficial de SEMBR señala que las versiones de parche deben ser compatibles hacia atrás, lo cual es prácticamente imposible. La idea detrás de una corrección de errores es corregir un comportamiento que no fue intencional. No que sea incompatible con el comportamiento anterior. El lenguaje aquí debe ser modificado o de lo contrario se codificarán errores como características y viceversa. Esto anula la utilidad conceptual de un parche, lo cual obviamente es malo. Pero hay una definición aún peor y más importante en la especificación actual que debe ser cambiada. Eso es la compilación. Cuando se redactó por primera vez la versión 2.0.0 de la numeración semántica por Tom Preston Warner, él define compilaciones, no metadatos de compilación. Dos años después, dos personas del ecosistema de NuGet vinieron y cambiaron el propósito de las compilaciones, volviéndolas y su definición efectivamente inútiles. SEMBR 2.0.0-rc1 es, hasta donde puedo decir, la especificación más precisa para la numeración de versiones y abarca la práctica común de generar compilaciones o variantes de compilación. Estos cambios disruptivos en la especificación nunca deberían haber sido introducidos y han causado consecuencias sutiles pero importantes. En la especificación original SEMBR 2.0.0-rc1, las compilaciones funcionaban como el antítesis de las versiones preliminares. Incluso podrías llamarlas versiones posteriores si lo deseas.
6. Problemas con la numeración semántica y los metadatos de compilación
El problema es que las versiones con metadatos de compilación deberían tratarse de manera distinta pero no lo están actualmente. La implementación de Sembr de NPM elimina por defecto los metadatos de compilación, lo que causa confusión en el ecosistema. Introducir una gramática no funcional para comentarios sería una solución más clara.
7. Definiciones faltantes en la numeración semántica
Al combinar estos cambios, abordamos las definiciones faltantes de la numeración semántica, incluyendo contexto, conjuntos y subconjuntos. La biblioteca no estándar de NPM proporciona soluciones. Los operadores de rango y los conjuntos de compilación ayudan con la comparación y filtrado de versiones. También necesitamos definir conjuntos ordenados y no ordenados.
Lo más notable es la completa falta de contexto para describir el software, o los proyectos en sí mismos en la especificación actual de Sanvers. Leyendo directamente de la especificación actual, los números de versión y la forma en que cambian transmiten el significado sobre el código subyacente y lo que se ha modificado de una versión a la siguiente. Inherente a esto, hay una conexión entre las versiones y el contexto en el que se aplican. En este ejemplo, muestro cómo podría verse un esquema de contexto al anteponer una versión normal con un contexto alfanumérico, separado por un símbolo de arroba, que es común. Esta definición seguramente te resultará familiar porque lo vemos todo el tiempo en nuestros ecosistemas de gestión de paquetes existentes, especialmente NPM JavaScript.
Otra definición clave que falta es el concepto de conjuntos. Puede parecer pedante, pero no definir conjuntos o cómo se pueden crear, ordenar o desordenar los conjuntos, deja lagunas fundamentales en nuestra comprensión colectiva de cómo gestionar más de una versión de software. Como se mencionó, la especificación actual solo define la precedencia. En este caso, 1.0.0 es mayor que 2.1.6 y luego 2.3.9. La precedencia en sí misma no nos brinda suficiente claridad o lenguaje para crear y gestionar conjuntos de versiones.
Aquí es donde la biblioteca no estándar de NPM ha venido históricamente al rescate y ha llenado muchas de estas lagunas. Esta biblioteca maneja todo excepto la obtención de contexto de una versión. Si profundizas, descubrirás que NPM también ha resuelto ese problema. La biblioteca NPM package arg analizará el contexto de valores de versión no estándar, pero más completamente conceptualizados. Por ejemplo, react en carats 1, 2, 3. Esta biblioteca utiliza la biblioteca semver de nodo anterior bajo el capó. Entonces, ¿cómo se vería una definición de conjunto faltante para semver? Bueno, incluiría el contexto del software y una definición de conjuntos de versiones de software individuales. Esto codificaría los conjuntos inherentes del software. En estos dos ejemplos anteriores, puedes ver que las versiones de react no se pueden y no se deben comparar con las versiones de express. Este es el primer tipo de conjunto, el conjunto contextual. A continuación de los ejemplos, verás definiciones de los operadores de rango faltantes, que a menudo se incluyen en los gestores de paquetes, el más notable de los cuales es el asterisco o xgrammar, que coincide con cualquier versión dentro de un conjunto relativo. Aquí están los tres conjuntos faltantes para normal, prelanzamiento y postlanzamiento, también conocidos como conjuntos de compilación. Definirlos explícitamente nos permite saber cuándo estamos incluyendo o filtrando versiones particulares para comparación. Estas son delimitaciones útiles tanto para el consumidor como para el autor de la herramienta. Penúltimo, llegamos al concepto faltante de subconjuntos. En este ejemplo, puedes ver todos los diferentes subconjuntos que existen dentro de cada una de las versiones semánticas particulares. Estos representan todas las posibles versiones que podrían existir dentro
8. El Futuro de la Numeración Semántica
La especificación actual carece de la capacidad para manejar conjuntos desordenados. La numeración semántica 2.0 está desactualizada y no hay posibilidad de un lanzamiento 3.0. Para evitar el infierno de dependencias, necesitamos una nueva especificación. Consulta Sember.xyz para obtener actualizaciones. Se necesitan nuevas herramientas, infraestructura y responsables. Mejoremos el lenguaje para un crecimiento y éxito continuo en el ecosistema.
Check out more articles and videos
We constantly think of articles and videos that might spark Git people interest / skill us up or help building a stellar career