Últimamente hablo bastante con gente que no es programadora. No tocan Drupal, ni les hace falta. Están montando sus proyectos con otras tecnologías a base de vibe coding, pidiéndole a la IA lo que necesitan y probando a ver qué sale. Y con más frecuencia de la que esperaba, la conversación acaba en el mismo sitio.
"Le pedí que me hiciera una cosa y me la hizo. Pero por el camino tocó otra que no le había pedido, y una tercera se ha descuajeringado. Ahora no funciona igual que antes, va peor y salen errores."
Casi siempre viene seguido de la frase que más me preocupa: "esto es un no parar, cuando arreglo una cosa se rompe por otro lado".
Al principio, eso sí, todo iba bien. Pedían una funcionalidad, la IA la hacía, la probaban por encima y adelante. No hay un día concreto en el que el proyecto se estropee, ni un cambio culpable. Es una acumulación, y por eso cuesta tanto verla venir.
La rana no nota el agua
Seguramente conoces la historia (es más fábula que biología, pero sirve). Si metes una rana en agua hirviendo, salta. Si la metes en agua templada y vas subiendo el fuego poco a poco, no se da cuenta hasta que ya no puede salir.
Con una web pasa lo mismo. Ningún proyecto nace hecho un desastre. Al principio hay una idea más o menos clara, una estructura que tiene sentido y un código que encaja con lo que el cliente pidió. Pero el cliente sigue pidiendo cosas. Un campo nuevo aquí, una excepción para un rol concreto allá, una integración con un CRM que no estaba en el plan inicial.
Cada una de esas peticiones, por separado, es un grado más. Un if dentro de un hook que ya tenía otros tres. Un servicio que empieza a hacer cosas que no le tocan. Una función copiada y pegada con un pequeño cambio porque refactorizar la original llevaba más tiempo. Nada de eso hace saltar ninguna alarma, porque la web sigue funcionando.
El código tiene que ir evolucionando al mismo ritmo que el proyecto. Si las necesidades han cambiado y la arquitectura sigue siendo la del primer día, cada funcionalidad nueva entra a presión. Hasta que un día te das cuenta de que tocar cualquier cosa da miedo.
Ventanas rotas y ropa en el suelo
La otra metáfora que me gusta es la de las ventanas rotas. Si tienes un edificio impecable y se rompe una ventana, la arreglas cuanto antes, porque desentona con todo lo demás. Pero si el edificio ya tiene la mitad de las ventanas rotas, una más no llama la atención. Ni siquiera la ves como un problema nuevo.
Con una habitación pasa algo parecido. Si está ordenada, intentas mantenerla así. Si el suelo ya está lleno de ropa, la siguiente camiseta va al suelo también. Total, apenas se nota.
En el código es igual. Cuando tienes un proyecto con una lista de deuda técnica que no cabe en una pantalla, con bugs conocidos que llevan meses ahí y warnings que nadie lee, la siguiente cosa mal hecha no te escandaliza. La apuntas en la lista (con suerte) y sigues. Esa lista no se acaba nunca, porque siempre hay algo más urgente.
Lo veo mucho en proyectos que heredo. Casi nunca es que el equipo anterior fuera malo. Es que nadie arregló la primera ventana, y a partir de ahí todo tiende a ir a peor.
La IA hace de ventilador
Con la IA todo esto va más rápido.
Un agente, cuando trabaja sobre tu proyecto, mira lo que ya hay e intenta seguir el mismo patrón. Es lo que tiene que hacer, respetar las convenciones del código existente. El problema es que no distingue entre una convención y un vicio. Si tu código está limpio, va a generar código limpio. Si está lleno de mierda, hace de ventilador y la reparte por todas partes.
En Drupal se ve enseguida. Si tu módulo custom tiene un .module de dos mil líneas con la lógica de negocio metida en hooks, llamadas a \Drupal::service() en cualquier sitio y consultas SQL a pelo, la IA va a añadir la siguiente funcionalidad exactamente así. Si en cambio tienes servicios con inyección de dependencias, interfaces claras y los hooks haciendo de simple pegamento, lo normal es que siga ese camino.
Y no hablamos de un poco de código malo de vez en cuando. La IA genera mucho código y muy rápido, así que multiplica lo que ya hubiera. Lo que antes tardaba años en estropearse ahora se estropea en meses. Muchas veces sin que nadie mire si lo que añade afecta a la seguridad, a la performance o a lo mantenible que va a ser dentro de medio año.
Mejor sobre algo que ya funciona
Hay algo que le he oído contar a varias personas y que encaja con todo esto. En vez de pedirle a la IA "móntame un programa que haga tal cosa", cogen un proyecto open source consolidado y bien mantenido que haga algo parecido, y le piden que lo modifique para adaptarlo a lo que necesitan. Y según cuentan, el resultado es bastante mejor.
Tiene lógica. Cuando la IA lo hace todo desde cero, el principio suele ir bien, pero en cuanto el proyecto crece un poco empieza a ser difícil de mantener y aparecen fallos por todas partes. Si partes de una base sólida, pensada por gente que sabía lo que hacía y con años de correcciones encima, lo que la IA construya sobre ella también suele salir bastante sólido. Es lo mismo de antes: la IA copia lo que ve.
También influye lo que la IA no sabe. Cuando modifica algo, no tiene todo el contexto de a qué afecta ni de por qué está hecho de una forma y no de otra. En un proyecto maduro, buena parte de esas decisiones ya están tomadas, y bien tomadas, así que hay menos margen para estropearlo. En un castillo de arena que se va levantando sobre la marcha, cualquier cambio puede tirar una parte que nadie sabía que dependía de otra.
Los que trabajamos con Drupal lo vivimos cada día sin pensarlo mucho. No empiezas desde cero, empiezas sobre un core y unos módulos que llevan años rodando. Esa base es la que te permite trabajar con IA de forma bastante estable y añadir funcionalidades sin romper otras partes del proyecto. Siempre que lo que construyas encima no la eche a perder, claro.
Parches sobre parches
Con la gente que hace vibe coding suele pasar lo mismo. Algo falla, se lo cuentas a la IA, la IA reescribe un trozo y te da un parche. Funciona. Al rato falla otra cosa, otro parche. Y así hasta tener un castillo de naipes aguantado con pinzas, donde el menor golpe tira todo abajo.
Aquí entra un concepto que me parece clave, la agilidad del cambio. Es lo fácil (o difícil) que resulta cambiar algo en tu proyecto sin que se rompa nada más. Un proyecto con buena agilidad del cambio tiene cada responsabilidad en su sitio, no repite la misma lógica en cinco lugares y, cuando modificas algo, sabes qué más puede verse afectado. Un proyecto sin ella es justo lo que me cuentan esas personas: pides una cosa y se te rompen otras dos.
El código duplicado es probablemente lo que más se la carga. Y la IA duplica muchísimo, porque le resulta más fácil escribir una función nueva parecida que entender la que ya existe y extenderla. Arreglas un bug en una copia y las otras cuatro siguen rotas, y ni siquiera sabes que existen.
En estos casos, otro parche no arregla nada. Lo que toca es parar, mirar el proyecto con perspectiva y refactorizar una buena parte para que tenga sentido con lo que es hoy, no con lo que era el día que empezó.
Ya sé lo que me vais a decir: "pues pídele a la IA que haga la refactorización". Se puede, claro. Pero estamos en las mismas. Si no sabes qué arquitectura necesita el proyecto, ni puedes revisar si la refactorización que te propone tiene sentido, has cambiado un montón de parches pequeños por un parche enorme. Alguien tiene que saber distinguir cuándo lo que ha hecho la IA está bien, y la IA sola no lo sabe.
"Esto me lo hago yo con IA"
Hay una conversación que cada vez es más habitual. Un cliente te pide presupuesto para una funcionalidad, se lo pasas y la respuesta es algo como: "uf, es muy caro, por este precio me lo hago yo con IA".
Es una respuesta legítima, pero en ese momento me gusta hacer una pregunta. Imagina que los dos usamos IA. Cuatro horas cada uno, la misma funcionalidad. Cuando terminemos, ¿qué versión crees que estará mejor implementada, con menos bugs y más pulida? ¿La de alguien que lleva años programando, sabe qué pedirle a la herramienta y ve si lo que ha salido está bien o mal? ¿O la de alguien que no sabe muy bien qué está mirando y cruza los dedos?
Y eso suponiendo que tardemos lo mismo, que no suele ser el caso. Yo ya tengo un flujo montado, sé dónde suele meter la pata la IA y sé qué tengo que revisar. Quien empieza de cero va a tardar bastante más en llegar a algo parecido, y probablemente no sepa si ha llegado.
Muchas veces el cliente lo ve en cuanto se lo planteas así. Si es una funcionalidad importante, de las que tienen que ir bien, la cuenta sale sola: puestos a pagar IA igualmente, le compensa pagar a alguien que tardará menos y le entregará algo mejor hecho. Y quien ya sabía programar, con la IA, va mucho más rápido que antes, así que la diferencia en vez de reducirse ha crecido.
Ojo, no digo que nadie sin experiencia deba usar IA para programar. Para un prototipo, una herramienta interna o algo que si se rompe no pasa nada, adelante. El problema aparece cuando ese prototipo acaba siendo la web de la que depende un negocio.
Firmar el código
Hace poco, hablando de todo esto, salió el concepto de firmar el código, y me gustó mucho.
Da igual si lo has escrito a mano, si lo ha generado un agente o si es una mezcla de las dos cosas. Cuando haces el merge de algo que va a producción, estás poniendo tu firma. Estás diciendo que eso tiene tu nivel de calidad y que respondes por ello. La herramienta con la que hayas llegado hasta ahí es lo de menos.
Y eso cambia la forma de trabajar con IA. Si vas a firmar algo, lo revisas. No aceptas un diff de ochocientas líneas porque los tests estén en verde (ya escribí sobre por qué los tests en verde no bastan). Si no entiendes lo que ha hecho, no lo firmas. Si ha duplicado lógica, le pides que la unifique antes de seguir.
Quien hace vibe coding sin saber programar no puede firmar su código, porque no sabe qué está firmando. No lo digo como reproche, simplemente no tiene con qué evaluarlo.
Lo que intento hacer yo
No tengo ningún truco, pero sí unas cuantas costumbres.
Intento arreglar las ventanas en cuanto se rompen. Cuanto más limpio está un proyecto, más fácil es que siga limpio, y más probable es que lo que genere la IA sea decente. Por eso dedicar tiempo a tener una base sana no me parece un lujo, sino lo que hace que trabajar con IA salga a cuenta.
Tampoco me fío de acordarme de mirar. En Drupal eso significa PHPCS con los estándares de Drupal, PHPStan a un nivel razonable, tests y algo que me dé una foto del estado general del site. Yo uso Audit como bucle cerrado, para que los agentes no puedan dar una tarea por terminada si empeora las métricas. No sustituye a revisar, pero quita mucho ruido.
La refactorización la meto en el presupuesto o en la planificación, con su tiempo asignado. Si el proyecto ha crecido en una dirección que no estaba prevista, la arquitectura tiene que acompañar, y si espero a que haya un hueco, el hueco no llega.
Y todo lo que genera la IA lo reviso como si lo hubiera escrito un junior con mucha prisa. Porque en la práctica es un poco eso.