Un patrón entre equipos
formando equipos de ingeniería que adoptaron herramientas de codificación de IA en el último año. El primer mes es eufórico. La velocidad se duplica, las funciones se envían más rápido y las partes interesadas están encantadas. Para el tercer mes, una métrica diferente comienza a aumentar: el tiempo que lleva cambiar de forma segura cualquier cosa que se haya generado.
El código en sí sigue mejorando. Modelos mejorados, más correctos, más completos, contexto más amplio. Y, sin embargo, los equipos que generan más código son cada vez más los que solicitan más reescrituras.
Deja de tener sentido hasta que miras la estructura.
Un desarrollador abre un módulo que se generó en una única sesión de IA. Podrían ser 200 líneas, tal vez 600, la longitud no importa. Se dan cuenta de que lo único que entendió las relaciones en este código fue la ventana de contexto que lo produjo. Las firmas de funciones no documentan sus suposiciones. Tres servicios se llaman entre sí en un orden específico, pero el motivo de ese orden no existe en ninguna parte del código base. Cada cambio requiere una comprensión total y una revisión profunda. Ese es el problema de la caja negra.
¿Qué hace que el código generado por IA sea una caja negra?
El código generado por IA no es un código incorrecto. Pero tiene tendencias que rápidamente se convierten en problemas:
Todo en un solo lugar. La IA tiene una fuerte preferencia por los monolitos y por elegir el camino rápido. Solicite “una página de pago” y obtendrá la representación del carrito, el procesamiento de pagos, la validación de formularios y las llamadas API en un solo archivo. Funciona, pero es una unidad. No puede revisar, probar o cambiar ninguna pieza sin ocuparse de ella en su totalidad. Dependencias circulares e implícitas. La IA conecta las cosas en función de lo que vio en la ventana contextual. El servicio A llama al servicio B porque estaban en la misma sesión. Ese acoplamiento no está declarado en ninguna parte. Peor aún, la IA a menudo crea dependencias circulares, A depende de B depende de A, porque no rastrea el gráfico de dependencia entre archivos. Unas semanas más tarde, al eliminar B se rompe A, y nadie sabe por qué. Sin contratos. Los sistemas bien diseñados tienen interfaces escritas, esquemas API y límites explícitos. La IA se salta esto. El “contrato” es cualquier cosa que haga la implementación actual. Todo funciona hasta que necesitas cambiar una pieza. Documentación que explica la implementación, no el uso. La IA genera descripciones detalladas de lo que hace el código internamente. Lo que falta es la otra cara: ejemplos de uso, cómo consumirlo, qué depende de él, cómo se conecta con el resto del sistema. Un desarrollador que lea los documentos puede comprender la implementación, pero aún no tiene idea de cómo usar realmente el componente o qué se rompe si cambia su interfaz.
Un ejemplo concreto
Considere dos formas en que una IA podría generar un sistema de notificación al usuario:
La generación no estructurada produce un solo módulo:
notificaciones/ ├── index.ts # 600 líneas: plantillas, lógica de envío, │ # preferencias de usuario, seguimiento de entrega, │ # lógica de reintento, eventos de análisis ├── helpers.ts # Utilidades compartidas (usadas por… ¿todo?) └── tipos.ts # 40 interfaces, no está claro cuáles son públicas
Resultado: 1 archivo para entenderlo todo. 1 archivo para cambiar cualquier cosa.
Las dependencias se importan directamente. Cambiar el proveedor de correo electrónico significa editar el mismo archivo que maneja las notificaciones automáticas. Las pruebas requieren burlarse de todo el sistema. Un nuevo desarrollador necesita leer las 600 líneas para comprender cualquier comportamiento.
La generación estructurada descompone la misma funcionalidad:
notificaciones/ ├── plantillas/ # Representación de plantillas (funciones puras, comprobables de forma independiente) ├── canales/ # Correo electrónico, push, SMS, cada uno con interfaz declarada ├── preferencias/ # Almacenamiento y resolución de preferencias del usuario ├── entrega/ # Enviar lógica con reintento, depende de los canales/ └── seguimiento/ # Análisis de entrega, depende de la entrega/
Resultado: 5 superficies independientes. Cambia uno sin leer los demás.
Cada subdominio declara explícitamente sus dependencias. Los consumidores importan interfaces escritas, no implementaciones. Puedes probar, reemplazar o modificar cada pieza por sí sola. Un nuevo desarrollador puede comprender las preferencias sin tener que abrir la entrega. El gráfico de dependencia se puede inspeccionar, por lo que no es necesario reconstruirlo a partir de declaraciones de importación dispersas.
Ambas implementaciones producen un comportamiento de ejecución idéntico. La diferencia es enteramente estructural. Y esa diferencia estructural es lo que determina si el sistema aún se puede mantener dentro de unos meses.
El principio de componibilidad
Lo que separa estos dos resultados es la componibilidad: construir sistemas a partir de componentes con límites bien definidos, dependencias declaradas y capacidad de prueba aislada.
Nada de esto es nuevo. Arquitectura basada en componentes, microservicios, microfrontends, sistemas de complementos, patrones de módulos. Todos expresan alguna versión de componibilidad. La novedad es la escala: la IA genera código más rápido de lo que cualquiera puede estructurarlo manualmente.
Los sistemas componibles tienen propiedades específicas y medibles:
Esto es lo que importa: la componibilidad no es un atributo de calidad que se agrega tras generación. Es una restricción que debe existir durante la generación. Si la IA genera un directorio plano sin restricciones, la salida no estará estructurada independientemente de qué tan bueno sea el modelo.
La mayoría de los flujos de trabajo de codificación de IA actuales se quedan cortos en este aspecto. El modelo es capaz, pero el entorno objetivo no le proporciona retroalimentación estructural. Entonces obtienes un código que se ejecuta pero no tiene intención arquitectónica.
Cómo se ve la retroalimentación estructural
Entonces, ¿qué se necesitaría para que el código generado por IA sea componible de forma predeterminada?
Todo se reduce a la retroalimentación, específicamente la retroalimentación estructural del entorno objetivo durante la generación, no después.
Cuando un desarrollador escribe código, recibe señales: errores de tipo, fallas en las pruebas, violaciones de linting, verificaciones de CI. Esas señales limitan la salida hacia la corrección. El código generado por IA normalmente no obtiene nada de esto durante la generación. Se produce en una sola pasada y se evalúa después del hecho, en todo caso.
¿Qué cambia cuando el objetivo de generación proporciona señales estructurales en tiempo real?
“Este componente tiene una dependencia no declarada”, forzando gráficos de dependencia explícitos “Esta interfaz no coincide con las expectativas del consumidor”, haciendo cumplir contratos “Esta prueba falla de forma aislada”, detectando acoplamiento oculto “Este módulo excede su límite declarado”, evitando el desplazamiento del alcance o dependencias cíclicas
Herramientas como Bit y Nx ya proporcionan estas señales a los desarrolladores humanos. El cambio los proporciona durante la generación, para que la IA pueda corregir el rumbo antes de que se produzca el daño estructural.
En mi trabajo en Bit Cloud, hemos integrado este circuito de retroalimentación en el proceso de generación mismo. Cuando nuestra IA genera componentes, cada uno se valida según las limitaciones estructurales de la plataforma en tiempo real: límites, dependencias, pruebas, interfaces escritas. La IA no puede producir un módulo de 600 líneas con acoplamiento oculto porque el entorno lo rechaza antes de comprometerse. Esa es la aplicación de la arquitectura en el momento de la generación.
La estructura tiene que ser una restricción de primera clase durante la generación, no algo que se revise después.
La verdadera pregunta: ¿Qué tan rápido se puede llegar a la producción y mantener el control?
Tendemos a medir la productividad de la IA por la velocidad de generación. Pero la pregunta que realmente importa es: ¿qué tan rápido se puede pasar del código generado por IA a la producción y aún así poder cambiar las cosas la próxima semana?
Esto se divide en algunos problemas concretos. ¿Puedes revisar lo que generó la IA? No solo leerlo, sino revisarlo, de la misma manera que revisarías una solicitud de extracción. ¿Puedes entender los límites, las dependencias, la intención? ¿Puede un compañero de equipo hacer lo mismo?
Entonces: ¿puedes enviarlo? ¿Tiene pruebas? ¿Los contratos son lo suficientemente explícitos como para confiar en él en la producción? ¿O existe una brecha entre “funciona localmente” y “podemos implementar esto”?
Y después de que esté activo: ¿puedes seguir cambiándolo? ¿Puedes agregar una función sin volver a leer todo el módulo? ¿Puede un nuevo miembro del equipo realizar un cambio seguro sin arqueología?
Si la IA le ahorra 10 horas escribiendo código pero dedica 40 a lograr la calidad de producción, o si lo envía rápidamente pero pierde el control un mes después, no ha ganado nada. La deuda comienza el segundo día y se agrava.
Los equipos que realmente se mueven rápido con la IA son los que pueden responder sí a las tres: revisable, entregable y modificable. Eso no se trata del modelo. Se trata de dónde aterriza el código.
Implicaciones prácticas
Para el código que estás generando ahora
Trate cada generación de IA como una decisión límite. Antes de preguntar, defina: ¿de qué es responsable este componente? ¿De qué depende? ¿Cuál es su interfaz pública? Estas restricciones en el mensaje producen mejores resultados que la generación abierta. Le estás dando a la IA una intención arquitectónica, no solo requisitos funcionales.
Para sistemas que ya has generado
Auditoría de acoplamiento implícito. El código de mayor riesgo no es el código que no funciona, es el código que funciona pero que no se puede mantener. Busque módulos con responsabilidades mixtas, dependencias circulares y componentes que no se puedan probar sin ejecutar la aplicación completa. Preste especial atención al código generado en una única sesión de IA. También puede aprovechar la IA para realizar revisiones amplias sobre estándares específicos que le interesen.
Para elegir herramientas y plataformas.
Evalúe las herramientas de codificación de IA en función de lo que sucede después de la generación. ¿Puedes revisar el resultado estructuralmente? ¿Se declaran o infieren dependencias? ¿Se puede probar una sola unidad generada de forma aislada? ¿Puedes inspeccionar el gráfico de dependencia? Las respuestas determinan si llegará rápido a la producción y mantendrá el control, o si llegará rápido y lo perderá.
Conclusión
El código generado por IA no es el problema. El código no estructurado generado por IA sí lo es.
El problema de la caja negra tiene solución, pero no sólo con mejores indicaciones. Requiere entornos de generación que hagan cumplir la estructura: límites explícitos de los componentes, gráficos de dependencia validados, pruebas por componente y contratos de interfaz.
Cómo se ve eso en la práctica: una sola descripción de producto dentro, cientos de componentes gobernados y probados fuera. Ese es el tema de un artículo de seguimiento.
La caja negra es real. Pero es un problema medioambiental, no un problema de IA. Repare el entorno y la IA generará código que realmente podrá enviar y mantener.
Yonatan Sason es cofundador de Bit Cloud, donde su equipo construye infraestructura para el desarrollo estructurado asistido por IA. Yonatan ha pasado la última década trabajando en arquitectura basada en componentes y los últimos dos años aplicándola a plataformas generadas por IA. Los patrones de este artículo provienen de ese trabajo.
Bit es de código abierto. Para obtener más información sobre arquitectura componible y generación de IA estructurada, visite bit.dev.
El propietario de Towards Data Science, Insight Partners, también invierte en Bit Cloud. Como resultado, Bit Cloud recibe preferencia como colaborador.