7 min de lectura

Emilio Carrión

El código bonito no paga facturas (pero el pragmatismo sí)

El purismo técnico no paga facturas. Aprende a decidir cuándo priorizar velocidad, cuándo invertir en arquitectura y cómo usar la deuda técnica con cabeza.

arquitecturadeuda técnicaproducto

Esta semana he estado reflexionando sobre un malentendido que he visto repetirse en mi carrera una y otra vez: confundir código bonito con profesionalidad. Y es que la realidad es algo más complicada.

En 60 segundos: Escribir código perfecto no te hace un gran profesional. El purismo técnico puede ser tu peor enemigo cuando tu startup necesita velocidad. La arquitectura perfecta tiene sentido solo en el momento adecuado del producto. Lo que separa a un developer de un senior no es saber más patrones, sino saber cuándo aplicarlos y cuándo no.

Hace poco monté una POC en mi trabajo. Un React en local conectado a una API sin testear, sin capas, sin nada. Dejé que GitHub Copilot se volviese loco y lo tuvimos listo en una tarde. ¿Tests? Ninguno. ¿Arquitectura? La mínima. ¿Abstracciones? Cero.

¿Está mal? Sí y no. Porque esa POC nos permitió enseñarle una demo a negocio y conseguir luz verde para el proyecto real. Al día siguiente, ese código fue directamente a la basura. Misión cumplida.

El mito del código perfecto

En producción, el purismo no paga facturas. Pero el pragmatismo, la visión de producto y de negocio sí que lo hacen.

Lo he visto en startups, en consultoría, en el corporate donde trabajo ahora. Siempre es lo mismo: los que más saben y los que más aportan al negocio no son aquellos que dominan más patrones. Son aquellos que saben cuándo aplicarlos y cuándo no.

Yo mismo he cometido este error. En el pasado me creía el mejor del mundo porque había aprendido un montón de cosas super chulas y quería aplicarlas ya. El resultado fue crear sistemas demasiado complejos para el problema que estaba resolviendo. Sobre-arquitectura. Complejidad accidental que retrasaba al equipo en vez de acelerarlo.

Las 3X de Kent Beck

Kent Beck propuso un framework que explica perfectamente cuándo aplicar rigor y cuándo priorizar velocidad. Se llama las 3X y divide el ciclo de vida del producto en tres fases:

1. Explore (Explorar)

Esta es la fase de descubrimiento. Aquí validamos el negocio, queremos reducir el time to market, adelantarnos a la competencia o aprender de nuestros usuarios.

En esta fase, una arquitectura perfecta puede ser un desperdicio de recursos. Si tu mercado pide para ayer la solución que estás intentando implementar, asegúrate de que puedes ir rápido. Lo que quieres es facturar y empezar a mover tu negocio.

Si tu código te impide pivotar, no tienes una obra maestra. Tienes un ancla que te arrastra.

2. Expand (Expandir)

Ya lanzaste la funcionalidad. Tiene adopción. Ahora lo que quieres es crecer rápidamente. Aquí es donde entran en juego performance, escala y growth. El código empieza a necesitar estructura para soportar el crecimiento.

3. Extract (Extraer)

Producto maduro que funciona. Ahora lo que buscas es que sea mantenible y sostenible en el tiempo. Aquí sí necesitas arquitectura robusta, tests exhaustivos y abstracciones bien pensadas.

El coste oculto de la abstracción prematura

Siempre nos han dicho "Don't Repeat Yourself". Y es cierto para la lógica de negocio inmutable. Si tienes una regla como "¿Cuántas columnas de cajas caben en un camión?", eso debe estar en un solo sitio.

Pero los servicios, los sistemas, las abstracciones... muchas veces es más barato duplicarlos que abstraerlos prematuramente.

¿Por qué? Porque no tenemos claro el problema ni la solución. Intentar abstraer y generalizar cuando no tenemos claridad es un problemón.

El ejemplo del notification service

Me acuerdo perfectamente cuando empecé. Me enfrenté al típico sistema de notificaciones. Empecé enviando emails. Después llegaron los SMS. "Ostras", pensé, "voy a crear un notification service super chulo con una interfaz abstracta".

Todo perfecto hasta que llegó Slack. Slack tiene una jerarquía de bloques, una forma de componer el mensaje que mi interfaz abstracta no permitía. Empecé a meter parámetros solo para Slack, excepciones, configuraciones extra. Lo que había creado para hacerme la vida más fácil estaba haciéndomela imposible.

El problema no es la repetición de código. Es el acoplamiento semántico.

Si hay dos cosas que cambian por razones totalmente diferentes, no son la misma cosa aunque el código se parezca. Si tienen razones diferentes y atemporales para cambiar, no las abstraigas. Estás hablando de dos conceptos diferentes.

Para decidir cuándo abstraer y cuándo duplicar, aplica este sistema de análisis de volatilidad:

Análisis de Volatilidad de Componentes
Recurso Recomendado

Análisis de Volatilidad de Componentes

Herramienta para decidir cuándo abstraer un componente y cuándo mantenerlo simple, basándose en su probabilidad de cambio.

Newsletter Semanal

¿Te gusta lo que lees?

Únete a otros ingenieros que reciben reflexiones sobre carrera, liderazgo y tecnología cada semana.

La deuda técnica como herramienta estratégica

La deuda técnica es ese préstamo que pedimos al futuro para validar hipótesis hoy.

Imagina que sales con un código de 200 líneas llenas de ifs. Horrible. Pero ese código te permite conseguir los primeros 1000 usuarios. Ha sido una decisión brillante. Te ha permitido salir rápido, validar y conseguir los primeros clientes que van a pagar las facturas.

El problema es saber cuándo decidir que ese código hay que desecharlo y construir uno más robusto.

Esta decisión es lo que separa a un developer de un verdadero senior. El senior no busca tener cero deuda, busca tener una deuda óptima que optimice la entrega, minimizando el coste de iterar hacia delante.

Código de prototipado vs. código productivo

Yo lo diferencio así:

Código de prototipado: Ese código feo que hemos hecho rápido para validar algo. Es desechable por diseño.

Código productivo: El que va a sobrevivir al tiempo y nos va a permitir ser estables a largo plazo.

Una vez validado el valor con el código de prototipado, lo transformamos en código productivo. Así obtenemos los beneficios de la velocidad sin comprometer el largo plazo.

El coste oculto del clean code

Por otro lado, hay un peligro real en el clean code mal implementado: la carga cognitiva.

Si tienes un código magnífico pero con 80 capas de indirección, si necesitas una arquitectura especial para modificar un dato en la base de datos, has creado complejidad accidental.

Si una persona nueva necesita un PDF de 40 páginas y una guía Enterprise para aportar valor, hemos fallado como arquitectos.

La elegancia técnica nunca debería estar por encima de la mantenibilidad operativa. Prioriza el valor aportado al negocio, no el purismo técnico.

Pero ojo, no os estoy pidiendo que seáis chapuceros. Os estoy pidiendo que seáis pragmáticos.

Pragmatismo vs. Negligencia

Hay una diferencia gigantesca entre pragmatismo y negligencia.

Ser pragmático es entender los tradeoffs, entender la deuda y saber cómo aplicarla.

Ser negligente es tirar para adelante sin nunca mirar atrás. Esto lo he visto en varios equipos y acabas con meses de refactor, de reconstrucción, porque lo que has montado es inmantenible.

Las cosas que siempre valen la pena

Hay prácticas que tienen sentido en cualquier fase:

  1. Observabilidad: Siempre quieres saber lo que está ocurriendo
  2. Testing: Casi siempre tiene un coste-beneficio positivo
  3. No abstraer prematuramente: Duplica código cuando sea posible, espera a que los patrones emerjan
  4. Trazar la deuda técnica: Anótala para no olvidarla

Cuando introduces algo que te hace ir más rápido ahora pero tiene un precio después, apúntalo. Ten un backlog donde sepas lo que has aprovechado y lo que tienes que pagar. Si no, se te va a olvidar y de ahí no vuelves.

La clave del equilibrio

No nos pagan por escribir código. Nos pagan por resolver problemas con software de forma sostenible y aportar valor al negocio.

Las mejores prácticas y los patrones son herramientas que tenemos a nuestra disposición. Como toda herramienta, tenemos que saber cuándo utilizarla.

La clave está en el contexto. Aplica cada cosa cuando tenga sentido. Si estás en fase de exploración, prioriza romper rápido, iterar, aprender del negocio. Si estás en una fase más avanzada donde necesitas robustez, ahí sí que merece la pena introducir arquitecturas más estructuradas.

El código limpio debe ser una herramienta, no un dogma.

Pregunta para ti: ¿En qué fase del framework 3X está tu proyecto actual? ¿Estás aplicando el nivel de rigor adecuado o estás sobre-arquitecturando?

Contenido de Newsletter

Este contenido fue enviado primero a mi newsletter

Cada semana envío reflexiones exclusivas, recursos y análisis profundos sobre ingeniería de software, liderazgo técnico y desarrollo de carrera. No te pierdas el próximo.

Únete a más de 5,000 ingenieros que ya reciben contenido exclusivo cada semana

Compartir:
Emilio Carrión
Sobre el autor

Emilio Carrión

Staff Engineer en Mercadona Tech. Ayudo a ingenieros a pensar en producto y a construir sistemas que escalan. Obsesionado con la arquitectura evolutiva y los equipos de alto rendimiento.