La generación de código con LLM puede llevar a una pérdida de confianza
(jaysthoughts.com)- Recientemente, la generación de código basada en LLM se está usando cada vez más entre los desarrolladores
- El código generado automáticamente está aumentando la preocupación por la calidad y confiabilidad del código
- Los desarrolladores experimentan un aumento en la dificultad de mantenimiento de los proyectos debido a la falta de comprensión del código y a verificaciones insuficientes
- La expansión del uso de código no confiable afecta a todo el ecosistema de software
- Se enfatiza la necesidad de preparar medidas para asegurar la confiabilidad junto con el avance tecnológico
Resumen
Jay aborda en su blog el impacto que la reciente tecnología de generación de código basada en LLM (modelos de lenguaje de gran tamaño) está teniendo en el desarrollo de software. Aunque el avance de estas herramientas mejora la eficiencia del desarrollo, al mismo tiempo están surgiendo problemas de confiabilidad y calidad del código.
El auge de la generación de código con LLM
- En el entorno de desarrollo se están expandiendo rápidamente las herramientas de generación automática de código que utilizan LLM
- Ofrecen alta productividad en la implementación de funciones complejas o en tareas de codificación repetitivas
- Tienen la ventaja de permitir la creación rápida de prototipos y de reducir la carga de aprender nuevos lenguajes
Problemas de confiabilidad
- Se presentan casos en los que el código generado por LLM no siempre funciona como se pretende
- La intención interna y la lógica de diseño del código no quedan claras, lo que dificulta el proceso de comprensión y verificación
- Si el proceso de revisión y pruebas es insuficiente, existe la posibilidad de que aparezcan bugs o vulnerabilidades inesperadas
Mantenimiento de proyectos e impacto en el ecosistema
- Surgen problemas de falta de documentación y explicaciones insuficientes sobre el código generado automáticamente
- A los desarrolladores les cuesta entender cómo funciona el código, lo que incrementa la complejidad del mantenimiento
- Existe el riesgo de que se deteriore una cultura de desarrollo de software confiable
Conclusión y propuestas
- La tecnología de generación de código basada en LLM es innovadora, pero asegurar la confiabilidad es una tarea esencial
- Al adoptar código generado automáticamente, se enfatiza la necesidad de reforzar la verificación y realizar revisiones de código sistemáticas
- A largo plazo, es importante establecer estándares para proteger la confianza en el ecosistema informático
1 comentarios
Opiniones en Hacker News
https://archive.is/5I9sB
Funciona incluso en navegadores antiguos y no necesita JavaScript salvo al pasar por CloudSnare.
Un amigo siempre dice que “la innovación ocurre a la velocidad de la confianza”, y desde GPT-3 esa frase me sigue viniendo a la mente.
Verificar es costoso, y el medio clave para reducir ese costo es la confianza. No sé cómo podríamos llegar a confiar en los LLM. Son muy fluidos tanto en código como en lenguaje natural, pero al mismo tiempo entran con gusto en madrigueras fractales que se extienden sin fin, y también muestran conductas que, en una persona, se considerarían maliciosas.
Este nuevo mundo en el que siempre hay que verificar todo es bastante agotador y, francamente, muy lento.
Es demasiado útil como para ignorarlo, y la confianza siempre se construye ladrillo por ladrillo. No hay que olvidar que los humanos, para empezar, tampoco son tan confiables. Como al manejar un auto, la capacidad de producir código con menos bugs en caminos definidos de antemano pronto parece que superará a la de los humanos, y después solo será una disputa de fundamentos para mejorar la complejidad.
En la ciencia, se construye confianza a medida que se avanza.
En el trabajo me pasó algo así, pero de una forma distinta a la que esperaba. Un compañero y yo estábamos bajo presión para mostrar avances, y decidí apresurar la fusión de un refactor bastante grande en el que estaba trabajando. Era un PR en borrador, pero lo fusionamos para mantener el impulso, y la semana siguiente aparecieron algunos bugs en áreas de código no probadas.
Durante la depuración, mi compañero dejó ver que había asumido que yo lo había escrito con IA, y dijo que era frustrante intentar entender a posteriori algo generado por IA. Pero ese código no usó IA. Claro que uso IA para escribir código, pero este lo escribí a mano, pensando cuidadosamente el diseño completo. Los bugs no eran fallas fundamentales del refactor, sino pequeños descuidos al ajustar el código existente a la API modificada.
Al final, poder hablar explícitamente de la tensión con mi compañero terminó siendo una experiencia para construir confianza. Fue una forma bastante suave de enfrentarnos a la fuerza de lo que está ocurriendo. Viéndolo en retrospectiva, me alegra que se resolviera así, y puedo imaginar que en otro entorno laboral podría haberse vuelto mucho más complicado. Hay que tener cuidado.
Hace unos 4 años hice una tontería enorme. Un periódico local publicó un artículo con una afirmación absurda sobre una persona, usando una foto como evidencia principal, y yo le escribí directamente al editor explicando por qué estaba seguro de que la imagen había sido manipulada. Mi razonamiento se basaba en un malentendido mío: interpreté mal que la persona en cuestión había posado con varias personas en un meet-and-greet casi sin cambiar de posición ni postura. El editor se ofendió y me respondió en tono burlón; cuando no di marcha atrás, se dio cuenta de que no era un agitador sino simplemente un tonto, y me compartió el video completo inédito del que provenía la foto. En ese momento me disculpé profundamente y también hice una donación, y durante el año siguiente mi ego quedó apropiadamente reducido.
Antes de enviar el correo, como no quería hacer una acusación falsa, compartí la foto con amigos serenos y les pedí su opinión; como ellos también concluyeron que era muy probable que la imagen hubiera sido manipulada, yo me sentía bastante seguro. Ahora confío implícitamente en ese periódico y en las personas involucradas, pero incluso convencer a una sola persona requirió muchísimo trabajo.
Cuesta entender la premisa. Si confío en que alguien escribe buen código, esa confianza es algo que aprendí porque el código de esa persona funcionó bien, no porque dentro de su cabeza exista algún modelo mental a priori que “produce buen código”.
Si alguien usa un LLM para crear código sin bugs, confiaría en esa persona. Si alguien usa un LLM para crear código lleno de bugs, no confiaría. ¿En qué se diferencia de cuando esa persona hacía código usando solo su propia cabeza?
Por culpa de los LLM, se vuelve muy difícil juzgar de inmediato la calidad del desarrollador que envió un parche mirando solo el código enviado. Si no puedes intuir qué tipo de persona es la otra parte, vuelves a la “confianza cero” y tienes que revisar todo con muchísimo detalle. Es decir, ya no hay “atajos de revisión” seguros, y eso puede ser doloroso en lugares donde el trabajo avanzaba apoyándose en esas señales. Si ya es un equipo competente y de alta confianza, este problema no aplica, y es probable que el concepto en sí les parezca ajeno.
Confío más si el colaborador explica bien los cambios. Confío más si en el pasado hizo un trabajo excelente. Confío más si gestiona bien las unidades de cambio, como commits razonables. Confío más si elige los problemas correctos, por ejemplo arreglar bugs antes de agregar nuevas funciones. Confío más si demuestra que puede mantener el código existente, en vez de simplemente añadir cosas encima. Confío más si contribuye con regularidad.
El problema suele ser un error de comunicación. Para quien hace la tarea, el encargo puede estar claro, pero por los frecuentes reinicios de contexto es difícil garantizar que el LLM también conozca el panorama completo; y si hay ambigüedad, es fácil que haga suposiciones tontas. Creo que la forma en que deep research de 4o pide información adicional antes de hacer algo debería volverse estándar también en la generación de código. Eso podría evitar una montaña de problemas.
Algunos casos son simples: se trata de si esta rutina devuelve o no el valor deseado. Pero otras situaciones son mucho más complejas porque hay que anticipar cómo interactuará con otras partes del sistema y cuáles son los casos límite poco evidentes. En esas situaciones, para escribir código “sin bugs” el autor tiene que entender las implicaciones del código; y si el desarrollador no entiende exactamente qué hace el código escrito por el LLM, tampoco puede entender esas implicaciones. Entonces esa carga pasa al revisor, y aumenta el trabajo del revisor. Esa era la premisa.
Una buena regla práctica es simplemente rechazar el trabajo en el que haya intervenido un LLM e ignorar también la comunicación escrita por un LLM. Aunque una persona use el inglés como lengua extranjera, creo que su inglés “torpe” es mucho mejor que dejar que ChatGPT hable por ella. A medida que los problemas graves de los LLM se vuelvan más claros, creo que este tipo de política se convertirá en el estándar general, y espero que así sea.
Los LLM hacen que cualquier tipo de mal trabajo parezca un trabajo plausiblemente bueno. Por eso es razonable descontar automáticamente el resultado de alguien que usó IA
Hace tiempo, uno de mis parientes resultó ser un estafador. Después de que lo descubrieran, corté contacto y dije que no lo conocía, y él me dijo: “soy la misma persona que conociste durante 10 años”. Yo respondí: “puede ser. Pero recién ahora me doy cuenta de que nunca supe quién era esa persona, y que tampoco podré saberlo en el futuro”
Todos asumimos que las personas en nuestra vida no intentan dañarnos activamente. Cuando esa confianza se rompe, se rompe muy fuerte. Nadie que use IA puede afirmar “este es mi trabajo”, porque no se puede saber si lo es. Quien usa IA tampoco puede afirmar que es un buen trabajo a menos que lo entienda a fondo, y probablemente no lo entienda a fondo. Muchos de mis estudiantes afirmaron haber leído y entendido textos que escribí, pero descubrí que en realidad no era así. ¿Qué pasaría si yo fuera una IA y ellos tomaran mi trabajo y pusieran su propio nombre como autor? No podrían explicar nada, ni defenderlo, ni darle seguimiento. Este problema existía antes de la IA, pero ahora es diez veces peor
Soy alguien que dedicó “más de 10.000 horas” a programar aplicaciones complejas antes de que aparecieran LLM útiles. Durante años, todas las noches me sumergí por completo en documentación y código fuente de otras personas para dominar el full-stack. Al final, esa inmersión me llevó a un burnout grave, deterioró mi salud y sacudió mi matrimonio. Poco después de lanzar una aplicación, tuve que dejarlo todo por completo durante 3 años para recuperarme, y estaba convencido de que nunca volvería a retomarlo
Después de escuchar muchas historias de que los LLM se habían vuelto bastante buenos con el código, volví con cautela frente a la computadora, y ahí mi experiencia se separa mucho de esa preocupación. No puedo estar de acuerdo con la idea de que “quien usa IA no puede afirmar ‘este es mi trabajo’”. Cuando uso un LLM, soy el diseñador y el revisor final. Dirijo la visión, diseño el sistema y reviso cada línea generada por el LLM con una herramienta de diff. Hace poco construí junto con un LLM un modelo de optimización complejo para el motor de cotizaciones de mi negocio. Usar un modelo de optimización real siempre fue la forma “correcta” de hacerlo, pero antes me habría llevado meses de trabajo arduo aprender cada detalle de la biblioteca y leer código de otras personas. Esta vez lo terminé en una semana. ¿Se siente como mi trabajo? Totalmente. Simplemente tuve un asistente incansable y brillante, aunque a veces defectuoso
Mi experiencia también contradice la idea de que el usuario “probablemente no lo entienda a fondo”. Para usar un LLM de forma efectiva en algo no trivial, se necesita una comprensión más profunda de los fundamentos para guiarlo y detectar los errores sutiles que comete con frecuencia. Sin mis años de experiencia, no habría podido dirigir un desarrollo complejo de múltiples módulos, depurar sus resultados ni darme cuenta de que un trabajo que parecía plausiblemente bueno en realidad estaba mal, por ejemplo por un problema N+1
Empatizo con la experiencia como docente. El problema de estudiantes que fingen entender con estas herramientas es real y difícil. En la academia, el objetivo es el proceso de aprendizaje: obtener alguna parte sustancial de esas 10.000 horas. Pero en el mundo profesional, el objetivo son los resultados, y esta es una herramienta nueva y poderosa para conseguir mejores resultados. No sé cómo deberían enseñar los docentes a los estudiantes en esta nueva realidad, pero demonizar el uso de LLM probablemente no sea lo mejor
Para mí, esto no hizo que un mal trabajo se viera bien. Volvió a hacer posible un gran trabajo, y al mismo tiempo me permitió recuperar mi vida. Me devolvió el disfrute del craft del desarrollo de software sin destruirme a mí ni a mi familia, y hoy mi vida está mucho más equilibrada, cosa que agradezco
Para mí ya es así. He leído una cantidad enorme de veces “perdón por haberlo pasado por alto, tienes toda la razón”. Diría que en 8 o 9 de cada 10 veces
Por otro lado, sigo viendo a gente copiar sin pensar código generado por LLM de pago y luego enfurecerse cuando no funciona como esperaban. Por cierto, esa es la mejor opción. Porque es preferible que algo esté claramente roto a que parezca funcionar por fuera
Aun así, los motores de predicción todavía no pueden hacer ingeniería de verdad. Si no les indicas específicamente que usen algo como Python generator, es muy probable que produzcan código que consuma una cantidad enorme de memoria. Lamentablemente, eso no es muy distinto de muchos programadores Python que conozco, pero también es un ejemplo de que los LLM son exactamente tan malos como se dijo. El lado positivo es que hacen que la gente realmente escriba especificaciones más detalladas que una sola línea de “agregar funcionalidad”
Donde los agentes de IA nos resultan más útiles es en código legacy que nadie prioriza. Tenemos un extractor de datos escrito en el milenio anterior, que usa unas 200 coordenadas hardcodeadas para extraer datos de cierto tipo de documento que llega por fax. Como el documento no cambió en unos 30 años, funcionaba bien, pero cambió recientemente, y Copilot tardó unos 30 segundos en corregir las coordenadas. Para una persona probablemente habría sido un día entero de trabajo extremadamente tedioso. Eso sí, no tengo ni idea de cómo nuestra industria piensa formar expertos en la era del vibe coding
Pelear contra los LLM es como orinar contra el viento
Los LLM en su forma actual parecen hacer más productivos a los desarrolladores. Incluso es posible que les den un beneficio mayor a los desarrolladores con menos experiencia que a los desarrolladores expertos. Las mejoras de productividad, quizá mejoras de productividad por múltiplos muy grandes, no se van a abandonar por los obstáculos que pongan quienes se oponen a la tecnología por algún motivo.
Aunque aparezca un ejemplo en el que una nueva herramienta de productividad cause un daño enorme, por ejemplo un bug que deje fuera de servicio a un servicio grande durante bastante tiempo, si esa tecnología aporta una productividad considerable, no se va a detener. El único camino razonable es trabajar con la tecnología y mitigar sus debilidades. Y esas mitigaciones no deben ser un conjunto de reglas que elimine por completo las ganancias de productividad de la nueva tecnología. Las mitigaciones tienen que funcionar junto con la tecnología de una forma que aumente su adopción; de lo contrario, serán esquivadas.
En mi experiencia, quienes afirman con más fuerza que gracias a los LLM se volvieron 10 veces más productivos suelen ser desarrolladores frontend relativamente junior, o desarrolladores de startups en serie que están creando aplicaciones nuevas desde cero una y otra vez. Por supuesto que es un caso de uso completamente válido, pero por eso es fácil que un desarrollador frontend junior y un desarrollador senior de C embebido no se entiendan cuando hablan de mejoras de productividad con IA.
En lugar de decir que lo único razonable es trabajar con la tecnología y mitigar sus debilidades, basta con usarla con más criterio. Por ejemplo, ¿la idea misma de los “agentes” de IA es buena? El reciente incidente de Copilot[0] hizo que MS y la IA parecieran un chiste. Es posible que intentar que la IA trabaje de forma autónoma no sea muy sensato.
Una analogía reciente son blockchain y las criptomonedas. Te gusten o no, viendo el éxito de Coinbase y similares, está claro que blockchain encontró un caso de uso real pero acotado. Pero durante la fiebre cripto había gente diciendo cosas como “vamos a rastrear la cadena de suministro de granos de café con blockchain”. En 2025 suena como un chiste exagerado de Twitter, pero en 2020 IBM realmente intentaba vender algo así[1]. Puede que algún día, al mirar hacia atrás, veamos que los agentes de IA o algunas de las aplicaciones actuales de IA generativa fueron el blockchain para café de esta burbuja.
[0] https://www.reddit.com/r/ExperiencedDevs/comments/1krttqo/my...
[1] https://www.forbes.com/sites/robertanzalone/2020/07/15/big-c...
Pero esto no significa que la combinación modelo/humano satisfaga de forma más efectiva las necesidades del usuario. Significa que produce “más código”. No existe un LLM que entregue un conjunto de cambios que elimine 2000 líneas de código. Por eso se entiende que cuando se dice que “hace más productivos a los ingenieros”, se está hablando de la cantidad de código generado.
Lo planteas como si fuera una dicotomía entre usar LLM o no usarlos, pero el autor habla principalmente de mitigar riesgos. Como analogía: es como si el autor señalara que algunos autos explotaron y dijera que, dado que los caballos de antes no explotaban, antes de poner en marcha la fábrica de pegamento habría que hacer que los autos explotaran menos; y tú parecieras creer que el autor se opone fundamentalmente al desarrollo de los autos.
Incluso ahora siento resistencia a usar GPT, mientras que últimamente mis colegas dicen cosas como “ChatGPT dice que...” o “este código lo hizo ChatGPT”. Me enorgullece escribir el código yo mismo y no usar GPT, pero al mismo tiempo sí uso Google y Stack Overflow. Supongo que también se podría decir que eso es una versión más lenta de GPT.
Creo que al autor se le escapa que actores imperfectos y probabilísticos también pueden construir sistemas deterministas confiables.
No confiaríamos en una herramienta de recolección de basura por la confiabilidad de su autor, sino viendo si, tras pruebas extensas, queda demostrado que hace lo que se pretendía. Es fácil imaginar que la confianza se debilite en el futuro y, como resultado, creo que el desarrollo guiado por pruebas cobrará más impulso. No hay que confiar: hay que verificar.
La pregunta más importante es: ¿quién prueba las pruebas? En el desarrollo tradicional, toda la lógica se implementa dos veces: una en el código y otra en las pruebas. Las pruebas revisan el código y, a la inversa, el código revisa implícitamente las pruebas. Es bastante común que el bug estuviera en las pruebas y no en el código de la aplicación. No podemos confiar ciegamente en las pruebas y esperar hasta que un agente encuentre la forma de replicar el bug de las pruebas en el código.
Tomando el ejemplo de la recolección de basura: claro, quizá algún día un sistema agéntico pueda levantar algo y ajustarlo a golpes con un arnés de pruebas, correcciones de bugs y demás. Pero imagina usar el modelo como el recolector de basura/la herramienta en sí. Por ejemplo, en cada barrido le pasas al modelo la memoria del programa y le indicas que libere los bloques innecesarios. Nunca podrías confiar en que el modelo identifique exactamente los bloques de memoria correctos, y ninguna “parcheada” ni “afinación” lo llevaría hasta ahí.
En abstracciones anteriores como la JVM, si una salida determinista —en este caso, el ensamblador que emite el JIT— está mal, ese bug se parchea y esa abstracción nunca vuelve a tener el mismo defecto. Los LLM no funcionan así. Cuando hablamos de herramientas de desarrollo del pasado que cambiaron por completo la naturaleza de la industria, para mí esta diferencia es crucial. No digo que los LLM no vayan a influir profundamente en la forma de trabajar en el futuro. Solo creo que hemos entrado en territorio completamente desconocido, con muy pocos precedentes históricos.
Tampoco entiendo por qué siempre se presenta que el desarrollo guiado por pruebas cobrará más impulso, como si TDD fuera una bala de plata que arregla todos los problemas de construir software. La cantidad de veces que he visto que, partiendo de pruebas incorrectas, TDD produjo software incorrecto es francamente vergonzosa.
Hay que especificar el resultado, no el proceso. Esperar que un contribuidor entienda un parche es una buena idea.
Pero recomendar o exigir que un junior evite durante un tiempo las herramientas asistidas por LLM durante el onboarding es una idea terrible. El onboarding tiene muchos problemas aleatorios de configuración de entorno, y los LLM suelen ser bastante fuertes en eso. También se trata de ponerse al día con el código y la documentación, y hay excelentes herramientas de búsqueda/resumen de texto que uno podría querer compartir.
Parece bastante obvio que, si eliminas de forma pulida todas las dificultades y complejidades de la vida, no pasará mucho tiempo antes de que, al encontrarte con una dificultad o complejidad, no tengas la menor idea de qué hacer. ¿Solo yo pienso así?
Es la primera vez que oigo hablar del fenómeno que el autor llama acantilado de la IA, en el que un LLM “aproxima algo cercano a la respuesta correcta durante cierto tiempo y luego, con el tiempo, su precisión cae en picada”. ¿A otros les ha pasado?
Los generadores actuales tienden a hacerlo todo más complejo con el tiempo, no más simple. Siempre termino siendo yo quien le pide al LLM que refactorice hacia algo más simple, o quien refactoriza directamente cuando se volvió demasiado complejo para que el LLM lo maneje. Así que, al menos con la generación actual de LLM, si simplemente “le sueltas las riendas al LLM” y dejas que haga lo que quiera, parece bastante inevitable que termine creando un enorme desastre a lo Rube Goldberg, y que tú acabes intentando limpiarlo.
Conectándolo con la idea del artículo: alguien experimentado puede notar pronto que el LLM empieza a arrastrarlo mar adentro y, aunque se aleje un poco, puede encontrar el camino de vuelta a aguas poco profundas. Un principiante queda fuera de su profundidad y perdido en el mar antes de siquiera entender qué ocurrió.
Imagina que como entrada de contexto tienes 10.000 tokens con 99% de acierto. Cada vez que el LLM responde, añade 1000 tokens con 90% de acierto. Después de varias idas y vueltas corrigiendo al LLM, la ventana de contexto queda llena en su mayoría con los restos de la propia salida del LLM. Peor aún: los errores se acumulan. Incluso ese 90% correcto no es más que una extrapolación correcta de una discusión sobre código incorrecto, y el LLM valora más los tokens más recientes. El mismo problema aparece en la prosa.
En los modelos de razonamiento, este problema puede empeorar. Todo el proceso de razonamiento está dentro del contexto, y si el pensamiento se va realmente por una tangente, siembra una semilla venenosa que alimenta la degradación. Sería bueno poder implementar algún tipo de poda de contexto para cortar el contexto irrelevante cuando aparezca. Por ahora, cuando siento que aparece degradación, hago un resumen y paso a una instancia nueva.
Con herramientas agénticas como claude code, codex o gemini cli, el problema es mucho menor. Pueden gestionar su propia ventana de contexto y ejecutar herramientas de desarrollo para hacerse sanity checks.
Este proceso te entrena en el hábito de documentar el estado actual del trabajo para que el nuevo agente pueda ponerse al día.