La fiebre por los asistentes de código basados en modelos de lenguaje (LLM) ha transformado la velocidad a la que escribimos software. Herramientas como GitHub Copilot, ChatGPT o agentes de codificación autónomos permiten generar decenas de líneas de código en segundos. Sin embargo, esta velocidad ha traído consigo una “ilusión de productividad”: escribir más líneas de código no se traduce necesariamente en resolver mejor los problemas.
A medida que delegamos más tareas mecánicas a la Inteligencia Artificial, un factor emerge como el verdadero cuello de botella de la ingeniería moderna: el contexto. Sin un contexto completo, tanto a nivel funcional como técnico, la IA está ciega.
1. Las dos caras del contexto: funcional y técnico
Los modelos de lenguaje no poseen un modelo mental de tu aplicación ni comprenden las intenciones de tu negocio; simplemente predicen el siguiente token más probable basándose en su entrenamiento. Por ello, el desarrollador debe actuar como el guardián del contexto en dos frentes indispensables:
El contexto funcional (el dominio de negocio)
Representa el por qué y el para quién del software. Incluye las reglas del negocio, el comportamiento esperado por el usuario y los objetivos estratégicos.
- El riesgo: Si no acotamos funcionalmente a la IA, esta generará flujos de código genéricos que a menudo contradicen las reglas del negocio real. Por ejemplo, al diseñar un sistema de checkout, la IA puede escribir un código técnicamente correcto pero que ignore la normativa fiscal de un país específico o las reglas internas de cancelación y reembolso de la empresa.
El contexto técnico (la arquitectura y el entorno)
Representa el dónde y el cómo del software. Comprende las limitaciones de infraestructura, deudas técnicas específicas, integraciones heredadas (legacy) y las políticas de seguridad del stack.
- El riesgo: Sin este contexto, la IA tiende a importar librerías redundantes o proponer soluciones incompatibles con la plataforma actual (por ejemplo, sugiriendo arquitecturas pesadas en memoria para entornos serverless con restricciones estrictas de inicio en frío). Como señala el revelador Informe de GitClear (2024), el desarrollo asistido por IA está provocando una tasa de duplicación de código y rotación de base de datos preocupantes, precisamente por la falta de un entendimiento holístico de la base de código existente.
2. La física del software no cambia en la era de la IA
Es fácil dejarse llevar por la facilidad con la que una IA genera un script, pero los problemas fundamentales de la ingeniería de software siguen siendo exactamente los mismos de siempre. La física de sistemas no se ha reescrito:
- Escalabilidad y Rendimiento: La IA destaca escribiendo código que “funciona” a nivel unitario, pero a menudo ignora la complejidad algorítmica. Es común ver cómo genera bucles ineficientes o la clásica consulta N+1 en bases de datos relacionales, problemas bien analizados en clásicos como Designing Data-Intensive Applications de Martin Kleppmann.
- Seguridad: Los modelos de IA han sido entrenados con millones de repositorios públicos, muchos de los cuales contienen vulnerabilidades históricas. Un riguroso estudio de la NYU (2021) demostró que cerca del 40% del código generado por asistentes basados en IA presentaba fallos de seguridad comunes de la lista OWASP Top 10, como inyecciones de dependencias o falta de sanitización de inputs.
- Concurrencia e Integridad: La IA tiende a ignorar las condiciones de carrera (race conditions) y no suele estructurar transacciones ACID robustas por sí misma, a menos que el desarrollador le indique explícitamente cómo manejar el aislamiento y los bloqueos en base de datos.
- Punto Único de Fallo (SPOF): La IA suele codificar para el camino feliz (happy path). Diseñar la tolerancia a fallos mediante patrones circuit breaker, límites de reintento con retroceso exponencial (exponential backoff) y fallbacks sigue siendo una decisión arquitectónica humana indispensable.
3. Pruebas de aceptación: la red de seguridad definitiva
En este nuevo paradigma, ¿cómo validamos que el código generado por una IA es correcto y no introduce efectos colaterales indeseados? La respuesta tradicional sigue siendo la más fuerte: los tests de aceptación.
Las pruebas de aceptación (a menudo expresadas en lenguajes estructurados como Gherkin bajo metodologías BDD) formalizan el contexto funcional en un conjunto de pruebas ejecutables.
- Especificación viva: Un test de aceptación define con precisión matemática el comportamiento esperado del sistema antes de escribir el código de producción. Podemos alimentar a la IA con este test para que genere el código necesario para superarlo.
- Prevención de regresiones: Debido a que los LLM actualizan código de forma fragmentada, es habitual que la corrección de un bug en un endpoint rompa de manera silenciosa una regla de negocio en otro módulo del sistema. Como indica Martin Fowler en su clásico Refactoring, contar con una suite de pruebas robusta es el único habilitador real para realizar cambios continuos con confianza. Los tests de aceptación actúan como esa barrera infranqueable ante regresiones generadas por la velocidad de la IA.
4. La responsabilidad técnica: definir el “cómo”
Delegar el código no significa delegar la arquitectura. Decidir si tu sistema debe utilizar una Arquitectura Hexagonal, seguir principios de Domain-Driven Design (DDD) o estructurarse bajo un patrón MVC clásico es una decisión que el ingeniero humano debe tomar.
Cuando decides la arquitectura y la documentas mediante guías claras en tu espacio de trabajo (por ejemplo, mediante archivos de configuración de agentes y reglas de código en el proyecto), logras que la IA se ciña a tus principios de diseño (Clean Architecture de Robert C. Martin). Dejas de recibir código desordenado y empiezas a recibir piezas que encajan como bloques de lego en tu sistema.
Conclusión: del programador al “ingeniero de contexto”
La sintaxis del lenguaje de programación se ha vuelto un ‘commodity’. El valor diferencial del ingeniero de software hoy en día no reside en memorizar APIs o escribir líneas de código con rapidez, sino en la capacidad de orquestar el contexto:
- Modelar el problema de negocio con precisión (contexto funcional).
- Diseñar la arquitectura y restricciones que mitigarán la escalabilidad, la concurrencia y la seguridad (contexto técnico).
- Validar con tests de aceptación para blindar el software contra regresiones.
La IA es un copiloto espectacular, pero el piloto sigue siendo quien decide la ruta, anticipa la tormenta y asegura que el avión aterrice en el destino correcto.