La estabilidad como valor: por qué Elm casi no cambia
Elm publicó su última versión con novedades en 2018 y desde entonces el lenguaje apenas se ha movido. En cualquier otro ecosistema esa quietud se leería como abandono, y buena parte de la comunidad de desarrollo web la lee exactamente así. Esta lección examina el fenómeno desde las dos orillas: reconstruye la controversia con sus argumentos reales, sin caricaturizar a quienes se sienten defraudados por un lenguaje que dejó de avanzar, y después expone con toda su fuerza la tesis contraria, según la cual la estabilidad no es la ausencia de trabajo sino un rasgo de diseño deliberado y costoso, y el ritmo frenético de publicación al que nos hemos acostumbrado no es progreso sino un impuesto de mantenimiento que alguien paga. Al final se propone un criterio para distinguir, ante cualquier tecnología detenida, un proyecto muerto de un proyecto terminado.
Un desarrollador que llega a Elm desde el ecosistema de JavaScript hace, sin darse cuenta, una comprobación que ha automatizado a lo largo de los años: mira la fecha de la última publicación. Si han pasado meses, sospecha; si han pasado años, descarta. Esa heurística es razonable en un entorno donde el software se pudre por falta de mantenimiento, donde una dependencia sin tocar acumula avisos de seguridad y deja de compilar contra las herramientas del año siguiente. Aplicada a Elm produce un veredicto inmediato y casi siempre equivocado, porque mide una variable que en este proyecto no significa lo que significa en los demás. La pregunta interesante no es si Elm está vivo, que es una discusión sobre etiquetas, sino qué modelo de progreso hace que la quietud sea un síntoma en unos ecosistemas y una promesa cumplida en otros. Detrás de esa diferencia hay una postura filosófica explícita, sostenida durante más de una década contra una presión social considerable, y que merece analizarse con la misma seriedad con la que se analizaría cualquier otra decisión de diseño del lenguaje.
- Reconstruir la cronología de la quietud de Elm y por qué se lee como abandono desde fuera.
- Formular la controversia con los argumentos reales de quienes se sienten defraudados, sin caricaturizarlos.
- Exponer la tesis de la estabilidad como diseño y el coste oculto del ritmo de publicación continuo.
- Construir un criterio para distinguir una tecnología muerta de una tecnología terminada.
El reloj detenido
Los hechos son públicos y sencillos. La versión que introdujo los últimos cambios de calado se publicó en 2018, y al año siguiente llegó una revisión de correcciones. Desde entonces el lenguaje no ha incorporado sintaxis nueva, ni ha cambiado su semántica, ni ha modificado la biblioteca base de forma incompatible. No existe una versión 1.0 anunciada con fecha, y el número de versión sigue empezando por cero, lo cual en la convención habitual del sector significa inestabilidad, mientras que aquí convive con la estabilidad práctica más alta de todo el ecosistema web. Esa contradicción entre el número y la realidad es el primer motivo de confusión.
Sin sintaxis nueva
Un módulo escrito en 2019 compila hoy sin tocar una coma. No hay migraciones, ni modos heredados, ni banderas de compatibilidad.
Versión cero
El número sugiere provisionalidad y la práctica ofrece lo contrario. La convención del sector juega en contra de la percepción.
Ecosistema quieto
Los paquetes centrales tampoco se mueven, porque no hay cambios del lenguaje que los obliguen a moverse.
Silencio público
Los períodos largos sin comunicación oficial alimentan la lectura del abandono más que la ausencia de versiones.
-- Codigo escrito en 2019. Compila hoy sin ningun cambio.
module Contador exposing (Modelo, Msg, actualizar)
type alias Modelo =
{ cuenta : Int }
type Msg
= Incrementar
| Reiniciar
actualizar : Msg -> Modelo -> Modelo
actualizar msg modelo =
case msg of
Incrementar ->
{ modelo | cuenta = modelo.cuenta + 1 }
Reiniciar ->
{ modelo | cuenta = 0 }
La controversia, con sus mejores argumentos
Sería deshonesto presentar a los críticos como impacientes que confunden novedad con valor, porque sus objeciones son concretas y en buena medida ciertas. La primera es la ausencia de comunicación: no hay hoja de ruta pública ni calendario, y un equipo que decide adoptar una tecnología necesita algo más que confianza personal para justificar la elección ante quien firma los presupuestos. La segunda es que algunas carencias reconocidas del lenguaje llevan años sin resolverse y sin que se declare si van a resolverse alguna vez, de modo que quien tropieza con ellas no sabe si está esperando algo o está esperando en vano. La tercera es de dinámica social: cuando un proyecto no publica, la comunidad se encoge, las ofertas de empleo desaparecen y la decisión de adoptarlo se vuelve difícil de defender aunque técnicamente siga siendo buena.
Hay además un efecto de segundo orden que los defensores de la quietud tienden a minimizar y que es determinante en la práctica profesional. La adopción de una tecnología no es solo una decisión técnica: es una apuesta sobre la disponibilidad futura de personas que sepan usarla, sobre la existencia de respuestas cuando aparezca un problema raro y sobre la posibilidad de justificar la elección ante quien no la entiende. Un ecosistema que se percibe detenido pierde esas tres cosas aunque el lenguaje siga siendo excelente, porque la percepción se retroalimenta: menos ofertas de empleo producen menos aprendices, menos aprendices producen menos contenido, y menos contenido refuerza la percepción inicial. Contra esa espiral no vale el argumento de que el código sigue compilando, y quien defiende la estabilidad tiene que reconocer que está describiendo una propiedad del artefacto mientras el crítico describe una propiedad del mercado laboral.
Hay una crítica que no queda desactivada por el argumento de la estabilidad, y conviene concederla sin regates: estabilidad y silencio son cosas distintas. Un proyecto puede comprometerse a no romper nada y, aun así, decir públicamente en qué está trabajando, qué problemas considera abiertos y cuáles ha decidido no abordar. Lo primero es una virtud de ingeniería; lo segundo es una obligación con quien apuesta su producto. La ausencia de la segunda es la queja legítima que subyace a la mayoría de las discusiones sobre si Elm sigue vivo, y responder a ella con un elogio de la quietud es contestar a otra pregunta.
El coste oculto del movimiento
La tesis contraria empieza por una observación incómoda: el ritmo de publicación al que nos hemos acostumbrado no es gratis y su factura la paga alguien que rara vez aparece en la conversación. Cada versión con cambios incompatibles se multiplica por todos los proyectos que la usan, y el trabajo agregado de migración supera con enorme diferencia al de escribirla. Ese trabajo no produce ninguna funcionalidad nueva para ningún usuario: produce la misma aplicación de antes, funcionando sobre cimientos distintos. En un ecosistema con muchas dependencias que se mueven a ritmos descoordinados, ese impuesto se cobra de forma continua y se acepta como si fuera el clima.
flowchart LR R[Ritmo alto de publicacion] --> M[Migraciones constantes] M --> T[Tiempo sin valor para el usuario] E[Estabilidad deliberada] --> S[Cero migraciones] S --> A[Atencion libre para el dominio] T --> D[Decision de adopcion] A --> D style E fill:#a6e3a1,color:#11111b style R fill:#f38ba8,color:#11111b style D fill:#cba6f7,color:#11111b
Migraciones
Reescribir lo que ya funcionaba para que siga funcionando. Coste alto, valor entregado al usuario igual a cero.
Deprecaciones
Aprender dos veces la misma tarea: la forma antigua que hay que reconocer y la nueva que hay que adoptar.
Avisos en cadena
Cuanto mayor es el árbol de dependencias, más frecuente es el aviso y menos relación tiene con tu código.
Documentación caduca
Cada versión invalida artículos, respuestas y ejemplos, y el conocimiento colectivo se deprecia con ellos.
La última tarjeta señala un coste que rara vez se contabiliza y que es enorme: la depreciación del conocimiento compartido. Cuando una tecnología cambia cada pocos meses, todo lo que la comunidad escribió sobre ella se vuelve sospechoso, y quien busca una respuesta debe comprobar antes si sirve para su versión. El resultado es que el saber colectivo nunca llega a sedimentar, y cada persona reaprende individualmente lo que otras ya habían aprendido. En un ecosistema quieto ocurre lo contrario: una respuesta escrita hace seis años sigue siendo exacta, la documentación oficial describe el estado real de las cosas y una guía como esta no envejece entre que se escribe y se lee. Ese capital acumulado es invisible en cualquier comparativa de funciones y es probablemente el activo más valioso que posee un proyecto maduro.
-- La superficie que hay que aprender es pequena y no se mueve
-- Todas estas firmas son identicas a las de hace anos
-- List.map : (a -> b) -> List a -> List b
-- List.filter : (a -> Bool) -> List a -> List a
-- Maybe.withDefault : a -> Maybe a -> a
-- Result.map : (a -> b) -> Result e a -> Result e b
resumen : List Int -> Int
resumen numeros =
numeros
|> List.filter (\n -> n > 0)
|> List.map (\n -> n * 2)
|> List.sum
El segundo argumento es que añadir es fácil y quitar es imposible. Toda función incorporada a un lenguaje se vuelve permanente en el instante en que alguien la usa en producción, y a partir de ahí condiciona todas las decisiones futuras, interactúa con las funciones que vengan después y multiplica los casos que el compilador y las herramientas deben contemplar. Un lenguaje que acepta propuestas a buen ritmo acumula complejidad de forma monótona, y esa complejidad se cobra en el tiempo que cada persona nueva tarda en ser productiva. La política de rechazar casi todo es la única forma conocida de mantener pequeño un lenguaje durante décadas, y es una política que exige decir no muchas más veces de las que resulta agradable.
Aceptamos sin dificultad que una herramienta física esté terminada: nadie espera la versión nueva del martillo ni se preocupa por su última publicación. En el software hemos construido la intuición contraria, en parte por razones legítimas —los fallos de seguridad y los entornos que cambian debajo— y en parte por razones comerciales, porque el modelo de negocio dominante necesita novedad continua. Un lenguaje compilado a una plataforma muy estable, con una biblioteca pequeña y sin superficie de red propia, es de las poquísimas piezas de software que pueden aspirar legítimamente al estado de terminado. Que casi ninguna otra pueda no significa que la categoría no exista.
Cómo juzgar la quietud
Antes del criterio conviene desactivar una analogía tramposa que aparece siempre en estas discusiones: la del software que se pudre. Es cierta para el software conectado a una red, expuesto a atacantes o apoyado en una plataforma que cambia sola, y es falsa para un compilador que produce código destinado a una plataforma con un compromiso de compatibilidad casi absoluto. Un programa que no tiene superficie de red propia, que no ejecuta código ajeno en tiempo de compilación y que emite salida para un entorno que jamás rompe hacia atrás no se degrada con el tiempo: sigue haciendo exactamente lo mismo el año veinte que el primero. Confundir ambas situaciones lleva a exigir mantenimiento donde no hace falta y, lo que es peor, a tranquilizarse por la mera existencia de publicaciones frecuentes en proyectos donde sí haría falta auditar.
El criterio útil no es la fecha de la última publicación, sino tres preguntas que se responden con datos observables. Primera: qué ocurre si el proyecto no vuelve a publicar nunca; si la respuesta es que el código sigue compilando y funcionando durante años, la quietud es un riesgo bajo. Segunda: qué superficie de cambio externo hay debajo; una tecnología apoyada en interfaces muy estables envejece de forma distinta a una apoyada en un sistema operativo que se reinventa cada año. Tercera: quién paga si aparece un problema; aquí es donde la concentración del gobierno del proyecto sí importa, y ese es el asunto de la lección siguiente.
Aplica el criterio a un caso real antes de opinar en abstracto. Toma la aplicación que mantienes y responde con datos: cuántas veces cambiaste de versión mayor en alguna dependencia el año pasado, cuántas horas costó cada cambio, y qué habría pasado si no lo hubieras hecho. Verás que las respuestas se separan en dos grupos muy distintos: unos pocos cambios que evitaban un riesgo real y una mayoría que se hicieron por no quedarse atrás. Esa proporción, y no una discusión sobre filosofías, es la que debería decidir cuánto valoras la estabilidad al elegir la próxima pieza de tu pila.
La discusión sobre si Elm está vivo revela un supuesto que casi nunca se examina: hemos aprendido a medir la salud de una tecnología por la frecuencia con que cambia, que es exactamente la métrica que confunde actividad con progreso. La frecuencia de cambio mide cuánto trabajo se genera, no cuánto valor se entrega, y ambas magnitudes se correlacionan solo mientras el diseño está incompleto. Una vez que un diseño resuelve bien su problema, cada cambio adicional es más probable que empeore el conjunto que lo mejore, porque el espacio de decisiones compatibles con lo ya construido se ha estrechado y las mejoras locales empiezan a chocar entre sí. Los lenguajes que llevan décadas creciendo son testigos de ese fenómeno: nadie discute que sus funciones nuevas sean útiles, y sin embargo nadie sostiene que el conjunto resultante sea más comprensible que el de hace veinte años. La postura de Elm es que hay un punto en el que la mejor decisión de diseño es dejar de decidir, y que ese punto llega mucho antes de lo que la industria acepta. La postura tiene un coste evidente, que es quedarse sin resolver algunos problemas reales de sus usuarios, y una virtud que solo se aprecia con el calendario en la mano: cada año que pasa sin cambios es un año en que todo lo que sabías del lenguaje sigue siendo verdad, todo el código escrito sigue compilando y toda la documentación escrita sigue siendo exacta. Ese capital acumulado no aparece en ninguna nota de versión, pero es la razón por la que un equipo pequeño puede mantener durante siete años una aplicación grande sin dedicar un solo día a ponerse al día con su propia base tecnológica. La pregunta que deberías llevarte no es si Elm cambia poco, sino cuánto de tu tiempo del año pasado se fue en migraciones que ningún usuario pidió.
- Calcula cuántas horas dedicó tu equipo el año pasado a actualizar dependencias sin añadir funcionalidad y expresa el resultado como porcentaje del tiempo total.
- Elige tres dependencias de un proyecto tuyo y clasifica sus últimas versiones en corrección de seguridad, funcionalidad nueva o cambio incompatible.
- Responde por escrito, para una tecnología que uses, qué pasaría si no volviera a publicarse nunca; distingue el riesgo real del malestar.
- Redacta la mejor versión de la crítica a la quietud de Elm y después la mejor refutación; señala en qué punto exacto dejan de contradecirse.
- Busca una función que se añadió a un lenguaje que conoces y que hoy se considera un error; describe qué habría hecho falta para rechazarla a tiempo.
- Define tu propio umbral: qué evidencia concreta te haría concluir que una tecnología está terminada y no abandonada.