Prompt engineering · · 7 min de lectura
7 patrones de prompts para generar código
Spec-first, few-shot, test-first y otros cuatro patrones, cada uno con un prompt de ejemplo para generar código.
La calidad del código que produce un modelo no depende de lo bueno que sea el modelo. Depende de lo bien que plantees el problema. El mismo Claude, GPT o Cursor te escupirá un boilerplate mediocre o exactamente lo que necesitas, y la diferencia está en las tres o cuatro frases del principio. Un prompt no es un conjuro, es la especificación de un contrato. Cada hueco que dejas lo rellena el modelo por ti, y siempre lo rellena con la solución “más típica” de su entrenamiento, no con la de tu repositorio.
A continuación, siete patrones que uso a diario. Cada uno incluye su justificación (por qué funciona) y un breve prompt de ejemplo. No son excluyentes entre sí: los mejores resultados salen de combinarlos. Están escritos desde la perspectiva de un desarrollador que trata al modelo como a un junior muy rápido y muy literal.
Patrón 1: spec-first (la especificación antes que el código)
Antes de pedir una implementación, pide un plan. Haz que el modelo describa las firmas de las funciones, los casos límite y el contrato de entrada/salida, y que solo escriba código cuando des tu visto bueno. Funciona porque un modelo que planifica por separado no mezcla las decisiones de diseño con los detalles de sintaxis, y es justo en esa unión donde nacen la mayoría de los errores. Además, obtienes un punto de control: un plan barato de corregir en lugar de un código caro de reescribir.
Ejemplo: Before writing any code, describe in bullet points: the function signature, input and output types, 3 edge cases and the error-handling approach. Then stop and wait for my OK.
En la práctica, el fallo más común es saltarse la sección de “lo que NO vamos a hacer”. Define el alcance negativo de forma explícita: sin él, el modelo añade caché, reintentos y logs que nunca pediste.
Patrón 2: few-shot con las convenciones de tu repo
El modelo no conoce tu estilo hasta que se lo enseñas. Pega 1-2 funciones existentes de tu código y escribe: “sigue exactamente esta convención”. Funciona porque el modelo es excelente imitando un patrón presente en el contexto: se le da mucho mejor “hazlo así” que “sigue nuestra guía de estilo documentada en otra parte”. Nombres, forma de devolver errores, orden de los imports, tests: todo eso lo toma del ejemplo.
Ejemplo: Here is how we write handlers in this project [paste a sample handler]. Write the createInvoice handler in the identical style: same Zod validation pattern, same Result structure, same naming conventions.
Dos buenos ejemplos valen más que diez frases de descripción. Si tienes un archivo ejemplar en el repo, ese es tu mejor prompt.
Patrón 3: test-first (tests que fallan antes que el código)
Invierte el orden: pide primero los tests que describen el comportamiento deseado, y solo después la implementación que los cumpla. Funciona porque los tests son un contrato sin ambigüedad: el modelo no puede cumplir “casi” una aserción. Además, ganas verificabilidad: una vez generado el código, simplemente ejecutas los tests en lugar de leerlo línea por línea.
Ejemplo: First write a test suite for parsePolishDate, including malformed formats and leap years. The tests must start red. Show them to me, and after I approve, write the implementation that passes all of them.
La trampa: cuando la implementación falla, al modelo le gusta “arreglar” el test en lugar del código. Añade: “no cambies los tests sin mi aprobación”.
Patrón 4: restricciones explícitas (stack, cero dependencias nuevas, alcance de archivos)
Di claramente lo que el modelo NO puede hacer. Versión del lenguaje, framework, “ningún paquete nuevo de npm”, “edita solo estos dos archivos”. Funciona porque, por defecto, el modelo recurre a las bibliotecas más populares de su entrenamiento: añadirá lodash, axios o moment aunque tengas fetch nativo y tus propias utilidades. Las restricciones reducen el espacio de soluciones al que encaja con tu repo.
Ejemplo: Constraints: TypeScript strict, React Server Components, no new dependencies (use native fetch), change only the file api/users.ts. Do not touch any config.
El alcance de archivos no es un detalle menor. Sin él, el modelo “arregla de paso” los módulos vecinos y te encuentras con un diff de media pantalla en lugar de uno de cinco líneas.
Patrón 5: rol + formato de salida (“devuelve solo un unified diff”)
Define un rol y fuerza un formato de respuesta exacto. “Eres un revisor”, “devuelve solo un diff”, “nada de prosa fuera del código”. Funciona por dos vías: el rol fija una perspectiva (un revisor busca errores, un arquitecto piensa en los límites del sistema) y un formato de salida rígido elimina el muro de prosa entre el que, de lo contrario, tendrías que abrirte paso. Un diff lo aplicas directamente con git apply; un archivo completo tendrías que compararlo a mano.
Ejemplo: Act as a senior reviewer. Return ONLY a unified diff (git format), no explanations, no fenced block. If no change is needed, return an empty diff.
“Solo el diff” tiene otro efecto secundario: el modelo reescribe el archivo entero con menos frecuencia, porque tiene que mostrar el cambio mínimo. Obtienes PR más pequeños y fáciles de revisar.
Patrón 6: chain-of-thought para la lógica complicada (“razona primero, implementa después”)
Ante un algoritmo no trivial (concurrencia, zonas horarias, parsing a medida), haz que el modelo exponga su razonamiento paso a paso antes de escribir código. Funciona porque el modelo genera token a token: si primero “piensa” el problema en prosa, los tokens de código posteriores se apoyan en un razonamiento correcto y no en la primera asociación. Para un CRUD sencillo es excesivo; para una lógica cargada de casos límite marca una diferencia real.
Ejemplo: This is tricky. First walk through step by step how to handle the summer/winter clock change and zones without DST, list the pitfalls, and ONLY THEN write the implementation.
Extra: cuando el razonamiento es explícito, es fácil señalar el paso equivocado y corregirlo, en lugar de depurar un código terminado y mudo.
Patrón 7: refinamiento iterativo (“critica tu propio código”)
Después de la primera versión, no escribas “arréglalo”. Escribe: “revisa tu propio código como un revisor implacable, enumera los 3 puntos más débiles y luego corrígelos”. Funciona porque el modelo en modo crítico evalúa de forma distinta que en modo generación: ve el manejo de errores que falta, una fuga de recursos o una race condition que se le escaparon mientras “solo escribía”. Es una segunda pasada barata sobre el mismo contexto.
Ejemplo: Put on the hat of a demanding reviewer and find problems in your own code: security, edge cases, performance. List them, then return the corrected version.
Limita las iteraciones a dos o tres. A partir de la tercera ronda, el modelo da vueltas en círculo más a menudo de lo que mejora de verdad; en ese punto es mejor volver al patrón 1 y reescribir la especificación.
Antipatrones que debes evitar
Los tres pecados más comunes. El primero, “hazme una app” sin contexto: obtendrás el esqueleto más genérico que existe. El segundo, volcar todo el repo en el contexto con la esperanza de que “el modelo ya se las arreglará”: la señal relevante se ahoga en el ruido y la calidad cae. El tercero, aceptar código que no entiendes: si no sabes revisar el resultado, ningún prompt te salvará. Un prompt acelera la escritura, pero no te exime de pensar.
TL;DR
Siete patrones: spec-first (el plan antes que el código), few-shot con tus convenciones, test-first (tests en rojo y después el código), restricciones explícitas (stack, cero dependencias nuevas, alcance de archivos), rol + formato de salida (solo el diff), chain-of-thought para la lógica complicada y autocrítica iterativa. Combínalos. La calidad del prompt pesa más que la calidad del modelo: el mismo Claude o GPT te dará boilerplate o exactamente tu código, según cómo plantees el contrato.