De escribir código perfecto a tomar decisiones imperfectas (pero correctas)

Por Juan Villarroel Publicado el 6 min de lectura

De escribir código perfecto a tomar decisiones imperfectas (pero correctas)
Arquitectura Producto Código limpio

Respuesta rápida: La madurez como desarrollador no se trata de escribir código más complejo, sino de tomar mejores decisiones. Este artículo habla sobre evitar la sobreingeniería, priorizar valor real y construir productos pensando en usuarios, no en el ego técnico.

La trampa silenciosa de quien ya domina lo técnico

Hay un punto en la carrera de casi todo desarrollador donde el problema deja de ser técnico y pasa a ser de criterio.

Ya no estás peleando con cómo hacer un loop, cómo conectar una base de datos o cómo levantar un servidor. Eso ya lo dominas. Ahora el enemigo es otro, mucho más incómodo:

Tomar decisiones.

Las decisiones que hacen que un producto funcione en el mundo real no siempre coinciden con las decisiones que hacen que el código se vea elegante, moderno o intelectualmente satisfactorio.

Este post es sobre esa transición.

Sobre dejar de ser solo alguien que escribe código para convertirse en alguien que construye cosas que realmente importan.


Elegir lo mejor para el negocio

Hay una pregunta que pesa más que cualquier bug:

"¿Esta feature que quiero hacer… realmente la necesita alguien?"

Porque seamos honestos, todos hemos tenido:

  • Esa funcionalidad que suena brutal.
  • Ese panel avanzado con mil filtros.
  • Ese sistema complejo que "se vería épico".

… pero que nadie pidió. Nadie validó. Nadie espera.

Aprender a decir:

"Esto está buenísimo, pero no es lo que más valor aporta ahora"

es uno de los mayores saltos de madurez como desarrollador.

No se trata de limitar la creatividad. Se trata de ponerla al servicio del impacto real, no del ego técnico.


El coste de complicarlo todo antes de tiempo

En algún momento descubrimos microservicios, Kubernetes, arquitecturas orientadas a eventos y CQRS, y queremos usarlos todos.

El problema es cuando lo haces en un proyecto que todavía no ha demostrado que necesita escalar.

Entonces aparecen problemas como:

  • Logs repartidos por 5 servicios.
  • Debugs donde no sabes ni por dónde empezar.
  • Dependencias cruzadas difíciles de seguir.
  • Incidentes cuyo origen no es evidente.

A veces solo necesitas un monolito bien organizado y una base de datos para validar tu idea.

Escalar está bien; escalar sin necesidad es sobreingeniería.


Los benchmarks no sustituyen al contexto

Un framework puede manejar cientos de miles de solicitudes por segundo, pero esa cifra importa poco si la API recibe unas decenas.

Muchísimas veces elegimos tecnología por benchmarks extremos, cuando el problema real está en otro lado:

  • Queries sin índices.
  • N+1 queries.
  • Traer 10.000 filas cuando solo necesitabas 20.
  • Nada de caché.
  • Paginación inexistente.

Cambiar de framework no arregla una consulta que tarda 2 segundos porque estás trayendo media base de datos.

La mayoría de APIs lentas no fallan por el router, sino por decisiones de datos mal resueltas.


A veces un docker compose up es suficiente

No todo proyecto necesita:

  • Clúster distribuido
  • Autoescalado
  • Service mesh
  • 4 entornos por microservicio

A veces necesitas:

  • Backend
  • Base de datos
  • Un Redis

Y que todo inicie de forma predecible.

Sencillo significa entendible; entendible significa mantenible; mantenible significa menos incidentes operativos.

La simplicidad no es mediocridad. Muchas veces es experiencia aplicada.


El falso microservicio: el monolito distribuido

Es un patrón frecuente porque muchos equipos han pasado por ahí.

"Tenemos microservicios", pero todos usan la misma base de datos.

Resultado:

  • Un cambio en una tabla rompe medio sistema.
  • Todo depende de todo.
  • Nadie puede desplegar sin coordinar con medio equipo.

Eso no son microservicios; es un monolito con problemas de red.

Si vas a separar, separa de verdad:

  • Límites claros.
  • Independencia de datos.
  • Comunicación por eventos o APIs claras.
  • Tolerancia a fallos entre módulos.

Si un servicio se cae y tumba todo el sistema… no era independiente como parecía.


La obsesión por el código perfecto

Todos hemos pasado horas:

  • Renombrando variables.
  • Reorganizando carpetas.
  • Haciendo refactors sin una necesidad observable.
  • Mejorando una arquitectura que nadie más ve.

Mientras tanto, la funcionalidad:

  • No se ha validado.
  • Nadie la pidió.
  • Nadie la usa.

Primero valida; luego mejora.

Refactorizar algo que sí se usa es una inversión. Perfeccionar algo que nadie quiere desperdicia tiempo y atención.


Tests: inversión temprana para reducir riesgo

Agregar tests en un proyecto ya gigante es como intentar poner cinturones de seguridad después del choque.

Sí, escribir tests desde el inicio toma tiempo. Pero agregarlos cuando el sistema ya es grande, frágil y lleno de parches cuesta mucho más.

Siempre es mejor que:

  • Romper algo sin darte cuenta.
  • Tener miedo de refactorizar..
  • No saber si tu cambio dañó otra parte.

Los tests no sirven para impresionar con cobertura. Sirven para dar confianza cuando el código crece y necesitas cambiarlo.


No te cases con una tecnología

Todos tenemos:

  • Lenguaje favorito.
  • Framework favorito.
  • Stack favorito.

Y está bien. Lo peligroso es pensar que esa es la solución para todo.

A veces usamos una tecnología porque:

"Es lo mejor del mundo"

Pero en realidad: Es lo más complejo del mundo para un problema simple.

Para ese problema específico, puede ser una solución desproporcionada.

No hay blanco o negro: hay contexto.

Elegir bien no es seguir la moda. Es entender qué necesito, qué sé usar y qué me permite avanzar sin añadir complejidad innecesaria.


La zona de confort también limita

Trabajar siempre con lo mismo se siente seguro, hasta que limita la capacidad de comparar alternativas.

Aprender cosas nuevas no siempre es para usarlas en producción.

A veces es solo para:

  • Mantener la curiosidad viva.
  • Entrenar el cerebro.
  • Recordar que aún puedes ser principiante.

Aprender debe ampliar el criterio, no convertirse en una obligación de adoptar cada novedad.


Las habilidades de comunicación también escalan

Saber explicar por qué una decisión técnica es correcta vale tanto como tomarla.

Escuchar a otros, entender el negocio, comunicar riesgos y negociar prioridades es lo que separa a un desarrollador fuerte técnicamente de uno realmente senior.

El código vive en repositorios; las decisiones viven entre personas.


Piensa antes de programar

Antes de escribir código, hazte preguntas incómodas:

  • ¿Esto resuelve un problema real?
  • ¿Hay una forma más simple?
  • ¿Estoy sobreingenierizando?
  • ¿Qué pasa si esto crece?
  • ¿Qué pasa si no crece?

Pensar es barato; reescribir sistemas no.


Programar menos, decidir mejor

Con el tiempo entiendes algo clave:

Ser buen desarrollador no es solo saber construir cosas complejas. Es saber cuándo no hacerlas.

La madurez técnica no se ve en la cantidad de herramientas que usas, sino en la cantidad de problemas que evitas crear.

A veces crecer no es agregar más capas… es quitar las que no hacían falta.

Y eso, aunque no siempre luzca espectacular en GitHub, es lo que realmente construye productos que sobreviven.

Aplicar el criterio en decisiones concretas

Esta idea se vuelve útil cuando deja de ser una frase y cambia una elección. En backend puede significar empezar con un monolito organizado por vertical slices y evaluar NestJS desde necesidades reales, sin copiar cada patrón disponible.

En frontend puede significar aprender de una experiencia real con Astro sin asumir que el mismo framework encaja en todos los productos. El patrón común es documentar el contexto, el riesgo aceptado y la señal que justificaría revisar la decisión.

Publicaciones Relacionadas