3 puntos por GN⁺ 5 시간 전 | 1 comentarios | Compartir por WhatsApp
  • YAGNI no es una simple regla de ahorro de “no escribas código que todavía no necesitas”, sino un principio que trata el costo de adelantarse a la estructura por suposición antes de que la necesidad esté confirmada
  • El centro del problema no es el diseño en sí, sino cuándo diseñar, y estructurar demasiado pronto puede ser tan riesgoso como estructurar demasiado tarde
  • La estructura anticipada genera tanto un costo de opcionalidad que cierra alternativas antes de que llegue la información, como un costo de NPV al adelantar costos y retrasar beneficios
  • Aunque el costo de generar código se acerque a 0, YAGNI no desaparece; al contrario, la generación barata puede facilitar aún más la creación de frameworks basados en suposiciones
  • La conclusión de construirlo cuando haga falta no se debe al costo de escribir código, sino a que el valor de la opcionalidad no ejercida y del dinero no gastado sigue existiendo

YAGNI no prohíbe diseñar

  • YAGNI, sigla de “You Aren’t Gonna Need It”, no es una excusa para no diseñar nunca nada que no sea estrictamente necesario
  • Si hace falta algo, se construye, pero el punto clave es el momento
  • El punto de partida es una anécdota repetida en proyectos: ante situaciones como “en 3 semanas una implementación simple ya no alcanzará, así que quiero hacer algo más complejo desde ahora”, la respuesta que se repetía era “You aren’t going to need it”
  • Este principio considera riesgoso tanto crear estructura demasiado pronto como hacerlo demasiado tarde

El problema no es el costo de escribir código, sino la estructura basada en suposiciones

  • Una interpretación común ve YAGNI como una regla de ahorro: “no escribas código que todavía no necesitas porque es caro”
  • Pero el verdadero objetivo de YAGNI no es el costo de producir código, sino la estructura especulativa (speculative structure) creada por adelantado antes de que una funcionalidad real la necesite
  • Ese tipo de estructura genera dos clases de costo, en momentos y por razones distintas

Primer costo: la opcionalidad

  • Si construyes estructura antes de que llegue la funcionalidad, terminas comprometiéndote por suposición frente a requisitos que todavía no conoces
  • La funcionalidad para la que te preparaste de antemano suele ser distinta de la que finalmente llega, y como resultado pagas dos veces
    • el costo de rodear una estructura con la forma equivocada
    • el costo de desarmar esa estructura y rehacerla
  • El problema no se limita a decir simplemente “predecir es difícil”
  • Incluso si la suposición resulta correcta, sigues perdiendo por haber renunciado a la opción de no comprometerte antes y construir luego la estructura correcta
  • Esperar no es pereza, sino conservar un activo llamado opcionalidad

Segundo costo: NPV

  • Así como el dinero tiene valor en el tiempo, las funcionalidades también tienen valor temporal
  • Si hoy construyes estructura para una funcionalidad que recién hará falta en 3 meses, adelantas el costo y retrasas la salida de las funcionalidades que sí generan dinero
  • Este costo existe incluso si la suposición fue correcta
  • Ni una predicción perfecta cambia el orden entre costos y beneficios; la pérdida aparece en el intervalo donde los costos se ubican antes que los beneficios
  • El costo de opcionalidad trata de “no te comprometas antes de que llegue la información”, y el costo de NPV trata de “no pagues antes de que sea necesario”
  • Incluso frente al argumento de que “más tarde será demasiado caro corregirlo”, esa remodelación costosa también puede ser otra predicción

YAGNI sigue vigente aunque generar código sea barato

  • Ninguno de estos dos costos incluye el costo de tipear código
  • Si el costo de escribir código se acerca a 0, entonces se derrumba la interpretación ahorrativa de YAGNI de “como el código era caro, no lo hagas antes de tiempo”
  • Pero como YAGNI no es una regla de ahorro, la generación barata de código no lo invalida
  • El costo de opcionalidad no nace de la cantidad de esfuerzo, sino del compromiso que cierra opciones futuras
  • El costo de NPV no surge del precio de producción, sino del momento del flujo de caja
  • La generación gratuita no debilita a YAGNI; de hecho, puede hacer todavía más fácil crear frameworks basados en suposiciones
  • La estructura generada sigue produciendo los dos costos y, como no fue escrita directamente, la comprensión de ella puede ser menor
  • La conclusión no es “espera porque el código es caro”, sino que la opcionalidad y el dinero valen más cuando aún no se han usado, así que constrúyelo cuando haga falta

1 comentarios

 
GN⁺ 5 시간 전
Opiniones en Hacker News
  • Creo que el costo de cambiar la estructura también bajó
    Gracias a la IA, se redujo el costo de reforzar el comportamiento con pruebas antes de cambiar la estructura, y también bajó el costo de implementar migraciones sin interrupciones
    Una de las grandes razones por las que Rust llamó la atención, incluso antes de la IA, era que el costo de cambiar la estructura interna de una aplicación era bajo, y ahora lo es aún más
    El costo de oportunidad de no poder cambiar la estructura de forma segura aumentó mucho, y hoy se optimiza ante todo por la capacidad de cambiar grandes partes del código y del producto de manera rápida y segura

    • La capacidad de cambiar grandes partes del código y del producto de manera rápida y segura ya era algo bueno de por sí, y tenía valor independientemente de la aparición de la programación con IA
      Pero antes de la IA los cambios estructurales tomaban mucho más tiempo, así que también podría verse como que el valor de aquello por lo que ahora se busca optimizar en realidad bajó
      Sigue siendo valioso, pero quizá un poco menos que antes
    • Me cuesta estar de acuerdo
      Con el aumento de pruebas generadas por IA que son frágiles, el costo de cambiar la estructura es mayor que antes
      Ordenar un conjunto de pruebas para que verifique la esencia del problema y no decisiones de diseño accidentales es algo que la IA todavía no hace bien
    • Exacto
      Pero también es demasiado fácil, sin hacer eso, terminar con un conjunto de pruebas frágil que está más o menos al 75%
      Mucha gente se conforma considerando una mejora objetiva pasar de “unas pocas pruebas mediocres y frágiles escritas por humanos” a “muchas pruebas mediocres y frágiles escritas por IA”
      Estoy completamente de acuerdo con usar las herramientas de esta manera, pero de ahí a decir que ya no hay que preocuparse por construir castillos en el aire equivocados demasiado pronto hay un trecho
      Un contrato de pruebas perfecto que resista la refactorización sigue siendo bastante difícil de diseñar
    • Esto me recuerda al principio abierto-cerrado, eso de “abierto a la extensión, cerrado a la modificación”
      Lo viejo volvió a sentirse nuevo
      Desde la eficiencia contextual de enfoques como DDD o arquitectura limpia hasta puntos como estos, la IA no crea nuevas compensaciones, sino que actúa como un amplificador
      Aumenta la productividad de los equipos que hacen las cosas bien, y también aumenta la deuda de los equipos con estándares bajos de diseño y arquitectura
    • Parece que cada vez se hace más trabajo inútil, apostando a que la IA lo arreglará después
      Lo único que se obtiene es no tener que pensar en profundidad
      Pensar en profundidad no requiere tanto tiempo ni esfuerzo, así que quienes usen la IA igual pero piensen lo suficiente para no hacer trabajo inútil les van a sacar ventaja
  • Kent Beck compara el código que aún no se escribió con una opción financiera que se puede comprar a un precio determinado
    Pero eso no deja de ser una analogía, y si se la lleva demasiado lejos se vuelve rara
    Si no escribiste nada de código, ¿tus opciones son infinitas? Aunque todavía no hayas invertido tiempo, eso no parece correcto
    También podría servir como argumento para quedarse en la etapa de planificación y posponer indefinidamente la escritura de código con tal de no fijar nada
    Aun así, si la analogía funciona, el costo podría estar en leer el código
    El código no escrito no necesita leerse, y si usas agentes de programación, tampoco ensucia el contexto con detalles irrelevantes
    El código que aún no se escribió tampoco necesita probarse, y las pruebas que aún no se escribieron no consumen tiempo de ejecución
    Por eso conviene mantener el proyecto lo más pequeño posible, y al postergar funcionalidades se puede retrasar al máximo el crecimiento de la base de código
    También implica que ejecutar código de terceros puede evitar muchos costos
    Si puedes usar una API estándar, no necesitas entender la implementación en detalle ni ejecutar sus pruebas, aunque agregar dependencias tiene riesgos

    • En “Tidy, First?” de Kent, se considera que el software crea valor de dos maneras: lo que hace hoy y la posibilidad de permitir hacer cosas nuevas mañana
      El código no escrito no tiene valor
      Para que el código escrito hoy cree valor, tiene que resolver la solicitud o el issue de hoy, o estar orientado a facilitar algo mañana
      Si contraes deuda técnica con una solución hacky o pierdes tiempo en algo que contradice YAGNI, no estás creando valor
      Lo importante no es el código no escrito, sino el código que se escribirá en adelante y su propósito
      Hay que hacer la compensación correcta entre resolver el ticket o la tarea de hoy y no pegarse un tiro en el pie en el futuro
      Escribir código es un compromiso: el valor de hoy se ve, pero el de mañana es más una estimación
      Aun así, como siempre habrá costos que pagar más adelante, terminas estimando para anticipar qué hará falta y minimizar esos costos
  • Creo que no se enfatizan lo suficiente las mejores prácticas de la era de la IA, pero hay una parte que Kent pasa completamente por alto
    Hay un valor considerable en descubrir más rápido qué funcionalidades se necesitan
    Crear una estructura especulativa puede funcionar como un mecanismo que obliga a concretar los requisitos, o al menos empieza a revelar cómo fallan las cosas
    Como puede ser más caro que esperar, no debería hacerse para la mayoría de los requisitos, pero a veces puede ser la mejor opción
    El costo de construir lo incorrecto ahora es mucho menor, así que el cálculo alrededor de YAGNI también cambia
    Aun así, sigue siendo necesario hacer el cálculo, y ahora cada equipo debe averiguar por sí mismo cómo cambió en su caso

    • Si creas la estructura especulativa como un spike y luego la descartas, está bien
      Si no la descartas, se convierte en un mecanismo que obliga a producir un resultado desordenado
    • Creo que las funcionalidades necesarias ya salen de los requisitos y del diseño del sistema que cumplirá esos requisitos
      YAGNI es el problema de construir algo que no está en los requisitos actuales porque se espera que los requisitos cambien después
      No es lo mismo que concretar los requisitos y restricciones actuales
      Esas cosas suelen surgir de conversaciones con stakeholders, usuarios y clientes, de recursos, y de restricciones y capacidades de ingeniería
      Un prototipo tiene valor cuando se conversa con stakeholders, se crea un modelo de gestión de proyecto o se hace investigación de ingeniería
      Fuera de eso, es poner el carro delante de los caballos
  • El enfoque de ver el software en ejecución como un activo es correcto
    Sin embargo, el costo de ejecutarlo y volverlo a crear bajó mucho
    El costo que no bajó es el de romper la cadena de confianza en resultados predecibles
    Una versión específica de software en ejecución ha ido acumulando confianza, y si se reescribe desde cero, ese capital se reinicia al momento del lanzamiento

  • En algún momento me cambió la forma de pensar
    Empecé a posponer lo concreto con YAGNI y a escribir, en la medida de lo posible, una versión abstracta
    ¿Hacer un UserStore? Parece lo más simple, pero quizá no haga falta una forma específica llamada User
    Entonces hago un Store que pueda contener cualquier cosa almacenable
    Si no estás acostumbrado, puede parecer sobreingeniería y un revoltijo de genéricos, pero paradójicamente es la forma que menos compromisos asume con cualquier implementación concreta

    • Exactamente parece sobreingeniería y un revoltijo de genéricos
      No solo hiciste una interfaz UserStore que probablemente no hacía falta, sino también una abstracción Store generalizada que definitivamente no hacía falta
      Para no comprometerte con una implementación concreta, implementaste capas pegajosas que no necesitas y que probablemente tampoco necesitarás en el futuro
      Si es una abstracción que no se basa en una necesidad real, aunque más adelante haga falta, es muy probable que la hayas hecho casi mal
      Al final seguramente vas a necesitar UserStore, así que eso era lo primero que debías hacer
  • No estoy de acuerdo con “no es un argumento de que la predicción sea difícil, como si un arquitecto más agudo pudiera evitarlo”
    Ese argumento solo se sostiene si parte de la premisa de que predecir es difícil

    • “Aunque adivines correctamente, es peor que no haberse comprometido” también me resulta confuso
      Si preparas de antemano la base para una funcionalidad muy probable y todo encaja, lanzas más rápido
      No hay garantía de que el equipo necesariamente crezca ni de que se mantenga la cantidad de gente, así que me parece peor felicitarse por la moderación que andar corriendo a último momento para cumplir con YAGNI
  • Hace poco tuve que salir funcionalmente de una base de código con muchísimo YAGNI acumulado, y aun con agentes fue un trabajo enorme
    En un sistema distribuido, ¿cómo sabes qué está realmente en uso? Hubo cosas que se me escaparon a mí y cosas que se le escaparon al agente, y todo tardó más de lo necesario
    No fue simplemente una migración 1:1; lo tomamos como una oportunidad para simplificar, así que había que entender por completo cómo funcionaba el sistema viejo
    Incluso cosas que en realidad no se usaban para nada entraban en lo que había que entender si no las identificábamos como tales

  • Creo que al final todo se reduce a explorar el problema e implementar una solución
    Siempre hay un costo por resolver el problema equivocado, y también hay un costo por implementar una mala solución para algo que ni siquiera se necesita
    A veces el desarrollo de software puede terminar siendo simple prueba y error en lugar de pensar en la estrategia y el conjunto de problemas que conviene explorar
    Hay casos en los que explorar un problema más a fondo en cierta dirección de lo necesario ayuda a largo plazo, pero implementar soluciones sin propósito nunca es bueno
    Creo que lo que Kent Beck realmente critica es la actitud de implementar algo “por si acaso” porque tal vez haga falta en el futuro

  • Dijo que “si construyes la estructura antes de que llegue la funcionalidad, te comprometes con una conjetura”, pero creo que en cualquier caso se hace una conjetura
    Puede ser muy probable que llegue la funcionalidad, pero no es seguro
    Si no construyes la estructura ahora, hay un costo de refactorización; si la construyes demasiado pronto y la funcionalidad no llega, desperdicias esfuerzo
    ¿Cuáles son los costos, probabilidades y compromisos entre esas posibilidades? Obviamente depende del contexto
    Todo YAGNI es, intencionalmente, una gran generalización
    Al final depende de las circunstancias
    En cualquiera de los dos lados suele haber muchas conjeturas y explicaciones a mano alzada, y es el mismo problema que con estimaciones de trabajo confiables
    Algunos desarrolladores que no toleran bien un mundo incierto intentan encontrar reglas en blanco y negro para todo

  • No he visto en los textos de Kent Beck nada que pudiera ser útil para una empresa de chips
    En una empresa de chips, mucha gente tiene que trabajar durante mucho tiempo, los clientes no pueden ver nada hasta que esté terminado, y para ganar dinero hay que vender en unidades de millones

    • ¿No es alguien que crea software y escribe sobre desarrollo de software?
      El hardware tiene restricciones fuertes
      De hecho, el software se inventó precisamente para escapar de esas restricciones
    • No es necesariamente cierto que los clientes nunca puedan verlo antes de que esté terminado
      Es verdad que muchas empresas de chips no comparten el trabajo en curso, pero se pueden compartir simulaciones, prototipos y muestras de ingeniería, y de hecho ocurre
      Claro que normalmente tiene que tratarse de un cliente grande
      Las ideas de una industria donde el costo del cambio es relativamente bajo no se aplican fácilmente a una industria donde el costo del cambio es alto, y lo contrario también suele ser cierto
    • Interesante
      ¿Cómo planifican esos proyectos las empresas de chips? ¿Agile, cascada, o usan un framework distinto al de la industria del software?