Cuando la IA empieza a escribir código

Durante mucho tiempo, programar significaba escribir cada línea uno mismo.

Buscar la sintaxis correcta. Leer la documentación. Probar. Equivocarse. Volver a intentarlo. Entender por qué aquel punto y coma olvidado había decidido arruinar la mañana.

Luego llegaron los asistentes de IA.

Primero como autocompletados inteligentes.

Una línea sugerida. Una función terminada. Un import adivinado. Una docstring propuesta.

Después se volvieron capaces de generar bloques enteros, corregir errores, explicar código, proponer pruebas, refactorizar una función e incluso encargarse de una pequeña tarea completa.

Hoy, para muchos desarrolladores, la pregunta ya no es:

¿Puede la IA ayudar a programar?

La pregunta pasa a ser:

¿Cómo programar con IA sin perder el control de lo que estamos construyendo?

Porque la IA no cambia solo la velocidad de escritura.

Cambia el gesto mismo del desarrollo.


El desarrollador no necesariamente escribe menos: trabaja de otra manera

Decir que la IA “programa por nosotros” es demasiado simple.

A veces sí, escribe mucho.

Pero eso no significa que el desarrollador desaparezca.

Su papel se desplaza.

Antes, una gran parte del trabajo visible consistía en escribir el código directamente.

Con la IA, una parte creciente del trabajo consiste en:

  • definir la necesidad;
  • encuadrar la petición;
  • dar el contexto correcto;
  • limitar el perímetro;
  • revisar la propuesta;
  • detectar efectos secundarios;
  • ejecutar pruebas;
  • analizar errores;
  • corregir;
  • validar;
  • decidir si el resultado es aceptable.

El gesto se vuelve menos lineal.

Ya no hacemos simplemente:

pensar → escribir → probar.

Hacemos más bien:

encuadrar → generar → revisar → probar → corregir → validar.

No es necesariamente más simple.

Es diferente.

Y a veces es más exigente de lo que parece.

Porque la IA puede producir rápido.

Pero producir rápido no es comprender correctamente.


El código generado no es código validado

Esta es la regla más importante.

El código generado no es código validado.

Una IA puede escribir una función limpia. Puede corregir un error visible. Puede proponer un parche coherente. Puede producir una prueba que parece razonable. Incluso puede explicar su trabajo con mucha seguridad.

Pero eso no demuestra que el código sea bueno.

Un código generado puede:

  • funcionar en un ejemplo simple;
  • romper un caso límite;
  • modificar un comportamiento vecino;
  • ignorar una restricción de negocio;
  • añadir una dependencia inútil;
  • esquivar el problema real;
  • producir una solución demasiado amplia;
  • eliminar una seguridad;
  • pasar las pruebas existentes pero fallar en uso real;
  • parecer limpio mientras desplaza la deuda técnica.

Esto es especialmente cierto en proyectos ya existentes.

En un pequeño script aislado, la IA puede ser espectacular.

En una aplicación real, con historia, arquitectura, módulos, datos, restricciones, interfaz, pruebas, empaquetado y producción, el riesgo cambia de naturaleza.

El código no es solo texto.

Es una pieza viva dentro de un sistema.

Y a los sistemas no siempre les gusta que les injerten una respuesta brillante encontrada en treinta segundos.


El verdadero trabajo: dar el marco correcto

Con la IA de código, el prompt no es una fórmula mágica.

Es una especificación.

Cuanto más vaga es la petición, más improvisa la IA.

Y una IA improvisando en una base de código puede convertirse rápidamente en un becario con demasiado café y acceso al botón “modificar todos los archivos”.

Un buen marco debe decir:

  • cuál es el problema observado;
  • dónde se produce;
  • qué debe corregirse;
  • qué no debe tocarse;
  • qué archivos están implicados;
  • qué pruebas deben pasar;
  • qué comportamiento esperado debe verificarse;
  • qué tipo de informe se pide;
  • qué pruebas o evidencias son necesarias.

La frase:

Corrige este bug.

es demasiado vaga.

Una mejor petición se parece más a:

Corrige únicamente el problema observado en este módulo. No modifiques el comportamiento de los demás módulos. No hagas refactorización. Añade o adapta pruebas específicas si es necesario. Indica la lista de archivos modificados, la causa identificada, la corrección aplicada y los comandos ejecutados.

Menos glamuroso.

Mucho más útil.

La IA programa mejor cuando se le quitan las malas libertades.


A la IA le encanta ampliar el perímetro

Una de las grandes trampas de los asistentes de IA es su tendencia a “mejorar” lo que no se les ha pedido.

Se informa de un problema de visualización.

Propone un rediseño. Se pide una corrección específica.

Renombra funciones. Queremos un bugfix.

Reestructura un componente. Pedimos una validación.

Añade una capa de abstracción con un nombre muy serio, porque aparentemente el mundo necesitaba un ManagerServiceCoordinator.

A veces la mejora es pertinente.

Pero a menudo aumenta el riesgo.

En un proyecto real, cada cambio tiene un coste:

  • coste de revisión;
  • coste de pruebas;
  • coste de comprensión;
  • coste de mantenimiento;
  • coste de posible regresión;
  • coste mental para el desarrollador.

Programar con IA exige entonces una disciplina sencilla:

Corregir el defecto preciso observado, sin tocar lo demás.

No por miedo a mejorar.

Sino porque un buen cambio debe ser proporcional al problema.

Un parche limpio no es el que cambia más cosas.

Es el que resuelve el problema con el menor daño posible.


Los modelos de IA no reemplazan la arquitectura

Los modelos de código progresan rápido.

Pueden leer archivos, proponer modificaciones, entender errores, escribir pruebas, generar componentes y crear scripts.

Pero no reemplazan una visión de arquitectura.

Una arquitectura no es solo “dónde poner el archivo”.

Es comprender las responsabilidades.

¿Quién decide? ¿Quién muestra? ¿Quién guarda? ¿Quién valida? ¿Quién llama a quién? ¿Qué parte debe permanecer estable? ¿Qué parte puede evolucionar? ¿Qué dependencia es aceptable? ¿Qué deuda técnica es peligrosa?

Una IA puede ayudar a formular esta arquitectura.

Puede documentarla.

Puede proponer una versión más clara.

Pero si el ser humano no sabe qué quiere proteger, la IA puede producir muy rápido una solución seductora y mal situada.

El código puede funcionar.

Luego, tres semanas después, descubrimos que un módulo depende de otro que nunca debería conocer.

Y entonces, por supuesto, todo el mundo empieza a mirar sus zapatos.


Programar con IA exige más pruebas, no menos

Otra trampa consiste en creer que la IA reduce la necesidad de pruebas.

Es lo contrario.

Cuanto más rápido se genera código, más importantes se vuelven las pruebas.

¿Por qué?

Porque la IA acelera la producción de posibilidades.

Puede generar diez soluciones antes de que hayamos terminado de entender la primera.

Sin pruebas, juzgamos por impresión.

Con pruebas, juzgamos por comportamiento.

Las pruebas no lo garantizan todo.

Pero obligan a formular una expectativa.

Transforman una impresión en verificación.

Un buen flujo de trabajo con IA debe incluir:

  • pruebas unitarias;
  • pruebas específicas sobre el bug;
  • verificación del comportamiento esperado;
  • controles de no regresión;
  • lectura de logs;
  • prueba manual si la interfaz está implicada;
  • validación del artefacto final cuando el tema toca empaquetado o producción.

La IA puede escribir pruebas.

Pero hay que verificar que esas pruebas prueben realmente algo.

Una prueba generada puede ser bonita, verde e inútil.

Verde no siempre significa “validado”.

A veces solo significa:

La prueba confirma exactamente lo que el código ya hace, incluso cuando ese comportamiento es malo.

Pequeña obra maestra del absurdo moderno.


El informe de la IA debe convertirse en prueba, no en relato

Cuando una IA termina una tarea de código, le encanta explicar.

Dice lo que ha corregido. Dice que todo está bien. Dice que las pruebas pasan. Dice que el problema está resuelto.

Muy bien.

Pero en un proyecto serio, un informe no basta.

Hacen falta pruebas.

Un buen informe debe contener:

  • archivos modificados;
  • causa identificada;
  • corrección aplicada;
  • pruebas ejecutadas;
  • resultados exactos;
  • límites restantes;
  • lo que no se ha probado;
  • riesgos posibles.

Sin eso, obtenemos un relato.

No una validación.

Y un relato puede ser falso.

Incluso cuando está muy bien escrito.

Con la IA, hay que aprender a pedir pruebas concretas:

¿Qué comando has ejecutado? ¿Qué prueba ha pasado? ¿Qué archivo ha cambiado? ¿Qué comportamiento se ha verificado? ¿Qué queda sin probar?

No es desconfianza gratuita.

Es higiene de proyecto.


Las ganancias reales existen

No hay que caer en el exceso contrario.

La IA puede ayudar de verdad a desarrollar.

Puede ahorrar tiempo en:

  • funciones repetitivas;
  • scripts utilitarios;
  • generación de pruebas básicas;
  • lectura de errores;
  • documentación;
  • docstrings;
  • migraciones simples;
  • refactorizaciones encuadradas;
  • comprensión de un archivo antiguo;
  • comparación de soluciones;
  • traducción de una idea en estructura de código.

También puede ayudar a desbloquearse mentalmente.

Cuando estamos cansados, la IA puede proponer una primera pista.

Cuando nos perdemos en un bug, puede reformular el problema.

Cuando ya no vemos una arquitectura, puede ayudar a cartografiarla.

En esos casos, se convierte en una verdadera compañera.

No porque lo sepa todo.

Sino porque hace aparecer algo que podemos examinar.

Y a veces, tener algo que criticar ya es mucho mejor que quedarse mirando una pared.


Las falsas ganancias también existen

Pero también hay ganancias que no lo son realmente.

La IA puede producir rápidamente un parche que después exige una hora de revisión.

Puede generar una prueba que pasa pero no protege nada.

Puede corregir un síntoma en lugar de la causa.

Puede proponer una solución más compleja que el problema.

Puede crear una dependencia inútil.

Puede transformar una corrección de cinco líneas en una modificación de seis archivos.

Puede dar la impresión de que avanzamos cuando en realidad producimos sobre todo trabajo de verificación.

El coste oculto del código generado por IA suele estar ahí:

no es el tiempo de generación, es el tiempo de recuperación.

Así que hay que medir la ganancia real.

No solo:

La IA ha producido algo en treinta segundos.

Sino:

¿Esto me acerca realmente a un resultado fiable?

Si la respuesta es no, la IA no ha acelerado.

Ha desplazado el trabajo.


El desarrollador también se convierte en editor

Programar con IA se parece cada vez más a un trabajo de edición.

No solo escribir.

Sino elegir.

Cortar. Rechazar. Corregir. Ensamblar. Reordenar. Simplificar. Pedir otra versión. Conservar una línea. Tirar el resto.

El desarrollador ya no es solo “quien teclea el código”.

Se convierte en quien dirige la producción de código.

Esa posición es poderosa.

Pero exige un verdadero nivel de exigencia.

Un mal editor lo acepta todo.

Un buen editor sabe decir:

No. Demasiado amplio. Demasiado arriesgado. Fuera de tema. No está suficientemente probado. Demasiado abstracto. Vuelve al problema real.

Programar con IA no es soltar el teclado.

A veces es sujetar la dirección con más firmeza.


El peligro para los principiantes

La IA puede ser maravillosa para aprender.

Puede explicar un error, dar ejemplos, reformular una noción, comparar dos enfoques y proponer ejercicios.

Pero también puede ser peligrosa para principiantes.

¿Por qué?

Porque un principiante todavía no siempre sabe reconocer una mala respuesta.

Puede copiar código sin entenderlo. Puede aceptar una arquitectura frágil. Puede creer que una prueba verde basta. Puede acumular soluciones que no sabrá mantener. Puede progresar en apariencia y perder comprensión profunda.

La IA no debe convertirse en una muleta permanente.

Para aprender a programar con ella, a veces conviene pedirle:

  • explícame por qué;
  • dame una versión simple;
  • muéstrame el error;
  • propón un ejercicio;
  • compara dos soluciones;
  • señala los riesgos;
  • no me des directamente la respuesta;
  • guíame paso a paso.

La IA puede ser profesora.

Pero hay que pedirle que enseñe, no solo que resuelva.


El peligro para los desarrolladores experimentados

Los desarrolladores experimentados tampoco están a salvo.

Su trampa es distinta.

Saben detectar muchos errores.

Pero pueden verse tentados a ir demasiado rápido.

Pueden dar demasiado contexto. Aceptar una corrección plausible. Dejarse seducir por una arquitectura bien nombrada. Olvidar un caso límite. Subestimar el coste de revisión. Multiplicar prompts hasta perder el hilo.

La IA puede dar una sensación de superpoder.

Y a veces lo es.

Pero un superpoder sin protocolo suele acabar como deuda técnica con capa.

El desarrollador experimentado debe entonces usar la IA como multiplicador.

No como excusa para relajar el método.

Cuanto más potente es el modelo, más claro debe ser el marco.

Cuanto más crítica es la tarea, más sólida debe ser la prueba.

Cuanto más cerca está el código de producción, menos hay que creer sin verificar.


Un buen flujo de trabajo para programar con IA

Un flujo simple puede evitar muchos daños.

Describir el problema real

Antes de pedir una corrección, escribir el problema observado.

No solo el error.

El comportamiento esperado. El comportamiento actual. El contexto. El módulo implicado. Los límites.

Reducir el perímetro

Decir explícitamente qué no debe modificarse.

A menudo es tan importante como decir qué hay que corregir.

Pedir un análisis antes del parche

No empezar por:

Corrige.

Empezar por:

Analiza la causa probable y propón un plan corto antes de modificar.

Eso evita a veces parches impulsivos.

Corregir de forma específica

Una vez clara la causa, pedir una corrección limitada.

Sin refactorización.

Sin mejora global.

Sin limpieza fuera de tema.

Probar

Ejecutar las pruebas útiles.

No necesariamente toda la catedral en cada microcorrección.

Pero sí lo suficiente para demostrar que el comportamiento esperado se mantiene.

Revisar

Mirar el código modificado.

Aunque las pruebas pasen.

Sobre todo si pasan demasiado fácilmente.

Validar

Para una interfaz, probar visualmente.

Para un build, probar el artefacto final.

Para producción, verificar en condiciones reales.


Elegir el modelo adecuado para programar

No todos los modelos merecen el mismo uso.

Un modelo premium puede justificarse para:

  • arquitectura compleja;
  • bug crítico;
  • refactorización profunda;
  • análisis multiarchivo;
  • seguridad;
  • rendimiento;
  • validación de release;
  • bloqueo en producción.

Un modelo más ligero puede bastar para:

  • reformular un comentario;
  • docstrings;
  • pequeño script;
  • generación de ejemplos;
  • explicación simple de un error;
  • limpieza local;
  • primer borrador de prueba.

El buen modelo no es siempre el más caro.

Es el que corresponde al riesgo.

Usar un modelo costoso para una tarea simple puede vaciar un presupuesto sin mejorar el resultado.

Usar un modelo demasiado débil para una tarea crítica puede costar aún más en errores.

La buena pregunta es entonces:

¿Qué nivel de inteligencia, contexto y validación merece esta tarea?

Ni más.

Ni menos.


Lo que la IA no debe decidir sola

Algunas decisiones deben seguir siendo humanas.

Por ejemplo:

  • cambiar una arquitectura;
  • añadir una dependencia;
  • eliminar un comportamiento existente;
  • modificar un sistema de licencias;
  • tocar la seguridad;
  • cambiar un formato de datos;
  • modificar una lógica de pago;
  • romper una compatibilidad;
  • validar una release;
  • declarar un bug resuelto.

La IA puede aconsejar.

Pero no debe decidir sola.

Cuanto más largas son las consecuencias de una decisión, más explícita debe ser.

Con la IA, el peligro no es solo el error.

Es el error silencioso.

La pequeña modificación que pasa en un parche, parece razonable y se convierte en problema tres semanas después.

El buen desarrollador no vigila solo lo que escribe la IA.

Vigila lo que supone.


Conservar el placer de entender

En medio de todo este método, no hay que olvidar algo sencillo: programar también es comprender.

Hay un placer particular en ver iluminarse un sistema.

Un bug que parecía absurdo se vuelve lógico. Una arquitectura borrosa se vuelve legible. Una función demasiado larga recupera su forma. Una prueba que falla por fin cuenta algo. Una idea se convierte en herramienta.

La IA puede acelerar ese momento.

Pero también puede robarlo si delegamos demasiado rápido la parte más interesante.

El objetivo no es solo producir código.

El objetivo es construir una relación más clara con el sistema.

Una IA útil no debería convertirnos en operadores de prompts.

Debería ayudarnos a ser mejores lectores, mejores arquitectos, mejores testers, mejores creadores.


Escribir menos, entender más

Programar con IA no significa dejar de programar.

Significa que el código ya no siempre se escribe de la misma manera.

A veces escribimos directamente. A veces guiamos. A veces revisamos. A veces rechazamos. A veces pedimos una variante. A veces retomamos todo a mano. A veces usamos la IA para comprender, no para producir.

El desarrollador del mañana no será necesariamente quien teclee más rápido.

Será quien sepa:

  • formular un problema;
  • encuadrar una herramienta;
  • leer una respuesta;
  • detectar un error;
  • probar una hipótesis;
  • proteger una arquitectura;
  • validar un resultado;
  • conservar la responsabilidad.

La IA puede escribir líneas.

Pero no debe escribir por nosotros la comprensión del sistema.

Ahí sigue estando el corazón del oficio.

No en cada carácter tecleado.

Sino en la capacidad de saber qué hacemos, por qué lo hacemos y qué aceptamos dejar entrar en nuestro código.

Al final, programar bien con IA no es escribir menos para pensar menos.

Es escribir menos para entender más.