Diseño de software

Resumen de YAGNI: por qué el «ya lo usaremos algún día» de los desarrolladores sale caro

«Parece que lo necesitaremos más adelante, ¿lo preparamos de antemano?»

4 min de lectura
Imagen de portada de Resumen de YAGNI: por qué el «ya lo usaremos algún día» de los desarrolladores sale caro

«Parece que lo necesitaremos más adelante, ¿lo preparamos de antemano?»

Durante el desarrollo, esta tentación aparece constantemente. Preparamos de antemano las opciones de configuración, la estructura para varios idiomas e incluso las tablas para poder cambiarlo todo desde el panel de administración.

YAGNI, el principio que tratamos hoy, responde precisamente «no» a esta tentación. Junto con KISS y DRY, se considera uno de los tres grandes principios del desarrollo.

YAGNI es el acrónimo de «You Aren’t Gonna Need It»: «eso no lo vas a necesitar de todos modos».

La expresión nació en la metodología de desarrollo Extreme Programming (XP). Lo que personas del entorno de XP, como Kent Beck y Ron Jeffries, repetían como una muletilla terminó consolidándose como un principio.

La idea central es una sola.

Implementa una funcionalidad cuando realmente la necesites, no cuando predigas que podrías necesitarla.


¿Qué problema hay en crearla de antemano?

La objeción «si la hacemos antes, luego será más cómodo, ¿no?» aparecerá enseguida. El problema es que esas predicciones suelen ser erróneas.

En un artículo sobre este tema, Martin Fowler divide el coste de las funcionalidades creadas por adelantado en cuatro categorías.

Coste Contenido
Coste de implementación El tiempo invertido en crear una funcionalidad que no se usará ahora mismo
Coste de retraso La funcionalidad real que deberíamos haber creado durante ese tiempo se retrasa
Coste de mantenimiento Aunque el código no se use, las pruebas, la refactorización y las correcciones de errores siguen siendo necesarias
Coste de reparación Cuando por fin se necesita, los requisitos han cambiado y hay que rehacerlo

Lo más doloroso es lo último. Cuando llega de verdad ese «más adelante», sus requisitos casi siempre son distintos de lo que imaginábamos. Al final pagamos también el coste de rehacer el código creado por adelantado: pagamos dos veces.


Situaciones en las que YAGNI se rompe en la práctica

Al explicarlo, todo el mundo asiente, pero en la práctica se introduce sigilosamente de estas formas.

1. Preparar los parámetros de antemano

// Ahora solo hay notificaciones por correo electrónico
func sendNotification(user: User, message: String, channel: String = "email",
                      retryCount: Int = 3, priority: String = "normal",
                      template: String? = nil) {
    // channelque funciona únicamente cuando "email"
}

Todos los puntos de llamada usan únicamente sendNotification(user: user, message: msg). Los demás parámetros se crearon «para usarlos al añadir notificaciones de Slack más adelante», pero ese requisito nunca llegó.

2. Preparar el protocolo de antemano

Es el caso de crear primero un protocolo aunque solo exista una implementación. Se crea un UserService junto con UserServiceProtocol, pero hasta que aparece una segunda implementación, ese protocolo solo sirve de adorno y aumenta el número de archivos.

3. «Es mejor sacarlo a configuración, ¿no?»

Por miedo al código hardcodeado, trasladamos todos los valores a archivos de configuración y paneles de administración. En realidad, casi nunca se cambian, y cuantos más ajustes hay, más preguntas surgen: «¿Qué afecta cambiar este valor?».

Incluso las opciones que no se usan generan costes de mantenimiento constantes
Incluso las opciones que no se usan generan costes de mantenimiento constantes

Lo que no es YAGNI

Para evitar malentendidos, tracemos la línea. YAGNI no significa lo siguiente.

Primero, no significa que no debas diseñar. Esforzarse por escribir código fácil de modificar (buenos nombres, funciones pequeñas y pruebas) tiene valor inmediato, así que no es objeto de YAGNI. De hecho, el código debe ser fácil de cambiar para poder crear rápidamente lo necesario «cuando llegue el momento».

Tampoco significa posponer las decisiones difíciles de revertir. Conviene pensar de antemano en elecciones como la base de datos o la especificación pública de una API, porque cambiarlas después resulta difícil. YAGNI apunta a «funcionalidades que podrían añadirse fácilmente más adelante, pero que se crean por adelantado».


Mi criterio para decidir

Cuando pienso «¿lo preparo de antemano?», me hago dos preguntas.

¿La evidencia de que necesitamos esta funcionalidad está en la hoja de ruta o solo en mi imaginación?

¿Añadirla más adelante será mucho más caro que hacerlo ahora?

Si la evidencia está solo en mi imaginación y añadirla más adelante cuesta prácticamente lo mismo, no la creo. La mayoría de los casos suelen estar en esta categoría.

Dos preguntas bastan para decidir
Dos preguntas bastan para decidir
No es tarde si la creas el día que haga falta
No es tarde si la creas el día que haga falta

Resumen

Hay tres ideas que conviene llevarse del principio YAGNI.

  • Crea las funcionalidades cuando las necesites, no cuando creas que podrías necesitarlas.
  • Las funcionalidades creadas por adelantado cobran cuatro veces: implementación, retraso, mantenimiento y reparación.
  • Eso sí, los buenos hábitos de diseño y las decisiones difíciles de revertir no son objeto de YAGNI.

Si juntamos KISS, DRY y YAGNI, los tres principios terminan convergiendo en una frase: crea lo que necesitas hoy, de forma sencilla y en un solo lugar.

Si tienes хотя бы una funcionalidad dormida que creaste pensando «ya la usaremos algún día», quizá dentro de 2 años tengas que borrarla con tus propias manos.