Con IA, el problema no es construir software: es mantenerlo

Con IA, el problema no es construir software: es mantenerlo

La primera vez que vi a un agente de IA construir un prototipo de punta a punta me pasó lo que a casi todos: quería pedirle más. Un MVP que nos habría tomado semanas, en una tarde. La sensación de que construir software se había vuelto fácil, casi trivial, es adictiva. Y hasta cierto punto, es verdad: hoy cualquier equipo con una buena instrucción y una herramienta decente levanta un prototipo en días.

El problema es que en el desarrollo de software lo fácil nunca fue lo difícil. Lo difícil llega después: cuando el prototipo se convierte en producto, cuando las features nuevas llegan una tras otra, cuando el sistema tiene que seguir funcionando mientras cambia por dentro. Lo difícil no es construirlo. Lo difícil es mantenerlo.

Con IA, el problema no es construir software: es mantenerlo. La IA abarató la construcción hasta casi cero (exceptuando el uso de tokens, por supuesto 🙄), pero dejó intacto el trabajo de mantener (y lo encareció): cada feature nueva tiene que convivir con las anteriores, y los cimientos malos se pagan con intereses compuestos. Si tu codebase está bien diseñado, la IA es un multiplicador. Si no, es el acelerador más rápido de deuda técnica que he visto.

Construir es fácil; mantener es donde se decide todo

En mi experiencia como ingeniero (y lo he visto también en los proyectos de 23people), el momento de mayor entusiasmo de un proyecto es el primer prototipo. Y el momento de mayor dolor, el que nadie celebra, es el décimo cambio sobre el mismo código: la feature nueva que rompe algo que ya funcionaba, la dependencia que nadie se atreve a tocar, el archivo del que todos huyen. Construir malos cimientos es fácil; mantener algo sobre cimientos malos, con el tiempo, se vuelve casi imposible.

Esto no es nuevo. Los sistemas de software tienden al desorden: cada cambio que solo piensa en el cambio inmediato y no en el diseño del sistema completo hace el codebase un poco peor. Es la entropía del software que describen Hunt y Thomas en The Pragmatic Programmer. Lo que cambió con la IA es la velocidad: ahora producimos cambios mucho más rápido, y la entropía se acumula en consecuencia.

Matt Pocock lo dijo mejor que yo en su keynote Software Fundamentals Matter More Than Ever:

“I think code is not cheap. In fact, bad code is the most expensive it’s ever been. Because if you have a code base that’s hard to change, you’re not able to take all of the bounty that AI can offer, cuz AI in a good code base actually does really, really well.”

Traduzco: el código malo es ahora más caro, no menos. El código barato es el que la IA puede extender sin romper; el caro, el que no puede tocar sin romper algo. Y la IA amplifica la diferencia entre ambos. Lo he visto en carne propia: el mismo agente que en un codebase ordenado me entrega una feature limpia, en uno desordenado me entrega algo que parece funcionar y esconde tres regresiones. El problema no era el agente. Eran los cimientos. Ya lo decíamos en La IA puede ser usada como nuestro propio Kaio-ken: la IA es un multiplicador, y el multiplicador solo amplifica lo que ya tienes.

Hay un segundo efecto que se siente menos pero pesa igual: la verification tax. La IA genera código diez veces más rápido, pero validarlo no es diez veces más rápido; muchas veces es más difícil, porque el código generado no viene con el razonamiento que lo produjo. El cuello de botella ya no es escribir. Es revisar, entender qué hizo el agente y por qué, y mantener vivo el conocimiento del sistema mientras el sistema cambia más rápido que nunca. Por eso los proyectos legacy (los que arrastran años de deuda) son los que más sufren: la IA no los entiende, y modernizarlos es el trabajo de ingeniería más caro que existe.

Cómo saber si tu agente entiende tu codebase

Aquí llega la parte incómoda: muchas de las veces que un agente falla, no falla por la IA. Falla porque no entendió tu codebase. Matt lo describe exactamente al presentar su skill de codebase architecture:

“If you have a codebase like this, which AI is really good at creating codebases like, is that you’ll have a situation where AI doesn’t understand what your code is doing. It will attempt to explore the code, but because it’s poorly laid out, filled with shallow modules, it doesn’t maybe get to the right module in time or doesn’t understand all the dependencies.”

Un codebase lleno de módulos shallow (archivos pequeños, interconectados, sin una interfaz clara) confunde al agente: intenta explorar, no llega al módulo correcto a tiempo, no entiende las dependencias, y responde con código que empeora el problema. La ironía es que la IA es muy buena creando ese tipo de codebases: produce muchos archivos pequeños “para organizar”, y después no puede navegar el resultado. Amplifica la patología que ya existía.

¿Cómo saber si te está pasando? Hazte las mismas preguntas que le harías a un codebase antes de un refactor grande:

  1. ¿Entender una sola feature exige saltar entre cinco archivos? Si explicar qué hace una funcionalidad requiere recorrer varios archivos que se llaman entre sí, el conocimiento está partido en pedazos demasiado chicos. Un agente (o un humano nuevo) no llega al módulo correcto a tiempo y termina adivinando. Ejemplo: Para saber cómo se calcula el total de una orden, hay que abrir el controlador, el servicio, un helper de descuentos y el modelo de impuestos.
  2. ¿Las funciones están partidas en pedazos chicos “para poder testearlas”, pero los errores reales aparecen en cómo se combinan? Cada pedazo pasa su test individual, pero la lógica de verdad quedó distribuida en la composición, y la composición es justo lo que nadie testea. Ejemplo: calcularImpuesto() y aplicarDescuento() pasan sus tests, pero el bug está en que el impuesto se calcula antes de aplicar el descuento.
  3. ¿Cambiar algo pequeño en una parte del sistema rompe otra parte que no tendría por qué verse afectada? Cuando un cambio local produce daños en zonas que no anticipabas, los módulos están acoplados por costuras ocultas (estado compartido, dependencias implícitas). El efecto no es local: ni tú ni el agente pueden predecirlo mirando solo el diff. Ejemplo: Cambias el formato de un campo en el módulo A y una pantalla del módulo B, que dependía silenciosamente de ese formato, explota en producción.
  4. ¿El agente necesita que le expliques en el prompt lo que el código ya debería decir? Si tienes que describirle cada vez cómo funciona tu sistema para que no se equivoque, el código no está transmitiendo esa información por sí solo. Ejemplo: Tienes que escribir “ojo, el descuento se aplica después del impuesto” en cada instrucción, porque los nombres y la estructura no lo dejan claro.

Si respondiste “sí” a varias, no necesitas un mejor modelo. Necesitas mejores cimientos.

La respuesta no es documentar más: es que el código se explique solo

La tentación cuando el agente no entiende es documentar más: READMEs, comentarios, wikis. La documentación ayuda, pero es frágil: se desactualiza, se divide y el agente la lee en fragmentos. La solución más duradera es la que ya conocíamos antes de la IA: que el codebase sea auto-explicativo.

John Ousterhout lo formalizó en A Philosophy of Software Design: los deep modules. Una interfaz simple que esconde una implementación compleja, en vez de una cadena de archivos shallow donde la complejidad se filtra por todas partes. Un agente (y un humano) entiende un sistema de módulos profundos sin tener que recorrerlo entero.

Hay una segunda capa, menos obvia, que Frederick Brooks describió en The Design of Design y que Matt Pocock rescató para el trabajo con agentes: el design concept, la idea compartida de qué se está construyendo, que no vive en ningún archivo. “Me and the AI don’t share a design concept”: Cuando el humano y el agente no comparten esa teoría, el output del agente se siente “off” (funcionalmente correcto, pero construyendo algo distinto a lo que querías). El código bien diseñado es la materialización del design concept; el código mal diseñado lo borra.

Y está el contexto que el agente puede leer. Anthropic define a los agentes como modelos usando herramientas en un loop, y de esa definición se sigue algo contraintuitivo: lo que hace mejor a un agente no es el modelo, sino qué información puede leer y qué tan claro está el trabajo. Hay toda una disciplina (la jerarquía de información) que dice lo mismo desde otro ángulo: no construyes agentes, construyes la información que ellos leen. Aplicado al codebase: Si el agente no encuentra el “por qué” de una decisión en el código, lo va a inventar.

¿Y la documentación entonces? Tiene su lugar, pero acotado:

Documentar para humanos Hacer el código auto-explicativo
El “por qué” de una decisión de diseño (ADRs, notas) El “qué” y el “cómo”: nombres, estructura, módulos profundos
Convenciones del equipo que el código no puede expresar Reglas que el código sí puede expresar (types, tests, interfaces)
Contexto de negocio y de dominio Lógica de negocio bien encapsulada y testeada
Cuando el código cambia poco Cuando el código cambia mucho (y con IA, cambia mucho)

Cuando implementes con IA, pártelo en vertical

Cuando un agente implementa una feature grande, tiende a ir por capas horizontales: primero el modelo de datos, después los servicios, después el frontend. Se ve ordenado, y hasta parece progreso: cada sesión deja “algo hecho”. Pero al final de la columna horizontal nada funciona de punta a punta, la integración entre capas nunca se probó y los unknown unknowns (las sorpresas que solo aparecen cuando todo se junta) se descubren al final, cuando arreglarlos es carísimo.

Matt Pocock rescata de The Pragmatic Programmer la analogía militar del tracer bullet: en vez de capas, construir slices verticales end-to-end, delgados pero completos, que cortan todas las capas y dejan un rastro visible de que la integración funciona:

“The best way to do it is to break it into tasks that flush out the unknown unknowns really quickly… if you’re integrating with a new kind of service or integrating two things which you haven’t integrated before, then you should do that work first because it’s going to give you feedback on whether your approach is even valid.”

Traduzco la regla: parte la feature en tickets verticales y ataca primero lo más incierto (la integración nueva, el “engine” del que depende todo lo demás), porque es lo que te dice si tu approach siquiera es válido. Matt parte un PRD complejo en cuatro slices; el primero es el motor con tests: si ese motor no funciona, todo lo demás se cae, y es mejor saberlo el día uno que el día veinte.

Esto no es solo técnica de organización: es mantenimiento preventivo. Cada slice vertical que termina deja el sistema en un estado verificable; cada capa horizontal a medio cablear es deuda que alguien (o algún agente) tendrá que descifrar después. Y como los tests son la “luz trazadora” del slice, el código queda con una red de seguridad que además le enseña al siguiente agente cómo se comporta el sistema. Por eso en el flujo de Matt el particionado en vertical slices es un paso explícito (PRD-to-issues) y cada ticket se implementa con TDD.

El lunes: una auditoría de 30 minutos

Si te quedas con una sola acción, que sea esta: agenda 30 minutos y audita si tu agente entiende tu codebase.

  1. Pídele al agente que explique, sin tu ayuda, cómo funciona tu feature más compleja. ¿Llega al módulo correcto? ¿Se pierde?
  2. Cuenta cuántos archivos tuvo que leer para explicar una sola feature.
  3. Busca tus módulos shallow: archivos de menos de 30 líneas que solo existen “para organizar”.
  4. Revisa el último PR generado por IA: ¿el agente tocó cosas que no debía porque no entendió los límites?
  5. Pregúntate si el próximo cambio lo haría un agente nuevo sin romper nada.

La regla es simple: si la IA lo va a tocar, tiene que poder entenderlo.

Y el reframe para cerrar: deja de preguntarte “¿esto funciona?” y empieza a preguntarte “¿esto lo puede mantener un agente (o un humano nuevo) en seis meses?”. Esa pregunta, respondida bien, te ahorra más horas de las que te va a dar cualquier modelo nuevo.

La construcción ya no es el cuello de botella

Durante décadas, el cuello de botella del software fue escribirlo. La IA lo resolvió, y con eso movió el problema a donde siempre estuvo escondido: mantener. Mantener no es limpiar lo que la IA ensucia; es la disciplina de que cada cambio deje el sistema más entendible, no menos. La IA construye rápido; el mantenimiento decide si lo que construyó vale algo en seis meses.

Te dejo la tarea simple: la próxima vez que un agente te entregue código, antes de preguntar si funciona, pregunta si lo vas a poder mantener. Y si la respuesta te incomoda, es una señal de que los cimientos, no el modelo, son los que necesitan atención. Esa es, hoy, la diferencia entre un equipo que aprovecha la IA y un equipo que solo acelera su deuda técnica.


Notas

  • Los deep modules y los módulos shallow vienen de John Ousterhout; si te suenan a “sentido común formalizado”, es porque lo son. Eso no los hace menos importantes: lo importante es que ahora el lector no es solo humano.

Para este artículo me apoyé en

  • PI Agent + Deepseek V4 Flash (para iterar sobre la estructura, la redacción y la revisión de este artículo)
  • Mi Obsidian Vault (para recuperar notas previas de mi conocimiento: la tesis de Matt Pocock, codebase architecture y design concept)

Referencias


Acerca de nosotros

En 23people, somos un grupo de nerds a los que nos gusta lo que hacemos, así que podemos darnos estas licencias de referencias ñoñas. Si quieres conversar sobre mantenimiento de software con IA o necesitas ayuda modernizando sistemas legacy que la IA no logra entender (mira nuestro servicio de Legacy Modernization), escríbenos → https://23people.io