domingo, 30 de marzo de 2025

De StackOverflow a ChatGPT: El Arte de Pegar sin Pensar

 Es curioso cómo apenas en Agosto del año pasado critiqué duramente la práctica de copiar código de páginas de internet para pegarlo dentro del proyecto y ahora parece haberse vuelto una práctica obsoleta en favor de generar el copiarlo de ChatGPT.

Esta práctica hereda muchos de los problemas que ya mencioné anteriormente, y dado que no quiero que me califiquen de holgazán por copiar y pegar algo de ChatGPT para una entrada de mi blog, voy a copiar y pegar algo que escribí en otra entrada de mi blog:

  • Copiar y pegar sin entender lo que se está haciendo puede ser una oportunidad desaprovechada para aprender algo y mejorar como desarrollador.
  • Es fácil pasar por alto varios detalles si simplemente se copia y pega, la mente es una experta en engañarnos haciéndonos creer que leyó algo cuando no fue así. El tener que teclearlos forza a asegurarse de que se está leyendo con detenimiento todo (un tip que me dieron en un grupo de escritores es que para revisar un escrito es buena idea leerlo en voz alta, así evitas saltarte cosas accidentalmente).
  • Si en tu programa hay código que no entiendes, en el momento que tengas que hacerle cambios no vas a saber qué hacer.
  • El código escrito dentro de respuestas a preguntas(como en Stackoverflow o incluso el que es escrito por bots de chats) tiene el propósito de ser un código fácil de entender y auto-contenido.
    No tiene como prioridad ser eficiente, ni versatil, ni mucho menos acoplarse al proyecto que estés desarrollando (es decir, seguir su estilo de código, usar las funciones que ya se hayan escrito, y separarse en varias funciones/clases si es pertinente).
    Sería como estar escribiendo una novela, preguntar en un chat de Whatsapp por inspiración, y copiar y pegar directamente los mensajes en lugar de entender lo que dicen y escribir esas ideas siguiendo el tono y narrativa presentes en la novela.
    No hay que olvidar que nuestro código está escrito para ser leido tanto por programas(compiladores/interpretes) como por humanos.
Afortunadamente, la lista de inconvenientes es más corta que la de copiarlos de una página. Sin embargo, esta vez no vengo a disuadirlos de usar LLMs para programar, sino que vengo a decirles cómo usarlos efectivamente para evitar caer en los inconvenientes antes mencionados.

El Contexto lo es Todo

Si simplemente le preguntas a un LLM cómo hacer tal o cual cosa, lo más probable es que te genere un fragmento de código bastante genérico y hasta parecido a un tutorial. Con todos los síntomas de código copiado de Stackoverlow (sin seguir las convenciones del proyecto, reinventando la rueda, haciendo muchas cosas de manera ineficiente, con un montón de comentarios redundantes, etc.).
También he escuchado a bastante gente decir de manera categórica que el código generado por LLMs es in-mantenible, y que para hacer código de calidad mejor mantenerse alejado de los LLMs.
La clave aquí es que el LLM puede generar buen código si sabes cómo pedirselo y para ello hay que darle contexto.
Recomiendo usar alguna extensión de VSCode como Github Copilot o similar, pero incluso sin extensión estos consejos van a servir:
  • Primero que nada, si tienes algún documento sobre linemientos de código en el proyecto, o un archivo de Lint, adjúntalo al prompt.
  • Si hay algún archivo dentro del proyecto que implemente algo parecido, también adjúntalo, e indica dentro del texto del prompt que se base en ése ejemplo.
  • Adjunta los principales archivos de dependencias dentro del proyecto que se puedan necesitar para la tarea en cuestión.
  • Sé muy específico en la tarea que estás pidiendo, recomiendo tener una biblioteca de prompts modificables para el proyecto en cuestión, con cada prompt de longitud de alrededor de media página.

Avanza en Pasos Pequeños

Muchos LLMs tratan de resolver todo el problema cuando se los planteas e implementan demasiados pasos en una sola respuesta.
Sé insistente en que hay que avanzar en pasos pequeños, primero pidiendo algo básico y luego conforme vaya funcionando irle agregando más capas/versatilidad, tal como lo harías si estuvieras escribiendo todo el código tú mismo.
Esto tiene exactamente el mismo efecto que al programar sin la asistencia de un LLM: si haces más cosas sin probar ni experimentar, hay más puntos en los que puede fallar.

No Olvides las Pruebas Unitarias

Una vez que tengas un código funcional, si lo escribiste con ayuda de un LLM es bastante probable que en la conversación tenga suficiente contexto para escribir pruebas unitarias.
Aprovecha eso y pídele pruebas unitarias, asegurate de escribir en las instrucciones que priorice verificar funcionalidad en lugar de implementación y que prefiera fakes en lugar de mocks.
También puedes ir un paso mas allá y preguntarle que fakes le serviría tener para las pruebas y pedirle que los genere(para posteriormente pedirle que genere las pruebas usando dsos fakes).
Al revisar las pruebas unitarias ten mucho cuidado de que no esté usando demasiados mocks y de que realmente esté probando algo (aplica la prueba de comentar bloques de código que debería estar probando a ver si falla alguna de las pruebas generadas).
Las pruebas unitarias para código generado por LLM son aún más importantes que las generadas para código escrito por uno mismo, debido a las razones que expondré a continuación.

Pídele Refactorizar

Una vez que el código esté funcionando, observalo con atención y pídele al LLM que refactorice las partes que no te gusten, si tienes pruebas unitarias esto se va a volver algo bastante sencillo. Sólo corre las pruebas luego de cada refactorización y observa que sigan funcionando.

Borra los Comentarios Innecesarios

Además de los comentarios redundantes (que le deberías de pedir a los LLMs que los omitan salvo que estén escribiendo pruebas), los LLMs a veces dejan comentarios para decir qué partes del código cambiaron, y la gran mayoría de las veces no son algo que a tus compañeros de equipo les importe y mas que ayudarles los puede confundir, así que bórralos antes de subir el código al repositorio.

Genera Documentación

Una vez que el modelo ya entendió y generó lo que querías que generara, hay que aprovechar y pedirle que genere documentación en un markdown. El esfuerzo de realizar este último paso es casi nulo y sus beneficios son inmensos.
Además de ayudarte a ti mismo y al resto del equipo a entender el código, también vas a poder incluir el archivo de documentación en el contexto las proximas veces que le pidas al LLM que genere código.
Por último, después de pedirle que genere documentación, hay que pedirle que busque alucionaciones en la documentación recién generada. Es sorprendente lo bien que funciona pedirle esto último.

¿Hay que Entender el Código Generado?

Hay que entender a gran escala como funciona el proyecto, cuales son las responsabilidades de cada una de las clases y además asegurarse de que las clases no se están saliendo de las responsabilidades que les corresponden, pero hay algunos casos en los que no considero tan necesario conocer los detalles del código:
  • Pruebas unitarias. Mientras pasen la prueba de fallar si introduces intencionalmente errores y sigan los lineamientos, no veo ningún detrimento en obviar los detalles. Después de todo, las pruebas unitarias no son dependencia de nada.
  • Herramientas internas. Las fallas de herramientas internas no suelen ser tan catastróficas como la de código en producción, por lo cual a veces vale la pena asumir el riesgo de que haya errores. Sobre todo si se trata de cosas como un script escrito en un lenguaje con el que no estás familiarizado y que no vas a usar después.
  • Cierto tipo de Refactorizaciones. Así como en algunas refactorizaciones no es necesario entender todo el código (sólo estar seguro que la funcionalidad no cambia), lo mismo aplica al hacer refactorizaciones con asistencia de un LLM.
  • Prototipos que no van a llegar a producción. Igual que con las herramientas internas, si esto no va a llegar al cliente en ése estado, puede valer la pena sólo probarolo para prototipear.

¿Es esto Vive Coding?

Recién se volvió viral y hasta polémico este Tweet

There's a new kind of coding I call "vibe coding", where you fully give in to the vibes, embrace exponentials, and forget that the code even exists. It's possible because the LLMs (e.g. Cursor Composer w Sonnet) are getting too good. Also I just talk to Composer with SuperWhisper so I barely even touch the keyboard. I ask for the dumbest things like "decrease the padding on the sidebar by half" because I'm too lazy to find it. I "Accept All" always, I don't read the diffs anymore. When I get error messages I just copy paste them in with no comment, usually that fixes it. The code grows beyond my usual comprehension, I'd have to really read through it for a while. Sometimes the LLMs can't fix a bug so I just work around it or ask for random changes until it goes away. It's not too bad for throwaway weekend projects, but still quite amusing. I'm building a project or webapp, but it's not really coding - I just see stuff, say stuff, run stuff, and copy paste stuff, and it mostly works.

...y admito que de repente lo hago para generar front end de herramientas internas o para experimentos personales, pero como ya dije anteriormente, para código de producción no sería tan laxo.
Me hizo algo de gracia lo de "embrace exponentials", cuando estudiaba con matemáticos llegue a imaginar que bailaba con la función exponencial... sí... sé que suena raro, pero eso es lo que causa apreciar la belleza matemática. Aunque tengo que admitir que no me agrada del todo esta otra connotación, pero bueno, ¡abracemos exponenciales!







No hay comentarios.:

Publicar un comentario

De StackOverflow a ChatGPT: El Arte de Pegar sin Pensar

 Es curioso cómo apenas en Agosto del año pasado critiqué duramente la práctica de copiar código de páginas de internet para pegarlo dentro ...