Los retornos tempranos matan el anidamiento; las constantes con nombre matan los números mágicos
Dos arreglos de treinta segundos hacen legible el código generado por IA. Los retornos tempranos matan el anidamiento; las constantes con nombre matan los números mágicos. Tu asistente adora las pirámides profundas de ifs anidados y los números sin explicación como 3 o 500 — ambos son code smells clásicos, ambos saltan a la vista en un diff, y ambos se arreglan en menos de un minuto.
Por qué el código generado por IA huele así
- Condicionales anidados. El modelo envuelve el camino feliz dentro de cada validación, y la lógica real termina cuatro niveles adentro. El anidamiento es caro para el lector: la métrica de Cognitive Complexity de SonarSource añade explícitamente una penalización por cada nivel de anidamiento, porque cada nivel es una condición más que debes mantener en la cabeza.
- Números mágicos. Un literal numérico cuyo significado no es claro para el lector —
retries < 3,sleep(500),if len(name) > 64. El antipatrón es tan antiguo que las advertencias datan de los manuales de COBOL y FORTRAN de los años 60, y tu asistente lo reproduce constantemente porque los datos de entrenamiento están llenos de él.
Ninguno de los dos es sutil. Encuentras ambos escaneando la indentación y buscando dígitos — sin herramientas.
Arreglo 1: convierte las condiciones en cláusulas de guarda
Una cláusula de guarda verifica primero la condición de fallo y retorna de inmediato, así la lógica principal nunca se anida. Es la refactorización Replace Nested Conditional with Guard Clauses de Martin Fowler, tal cual:
// Before — AI's favorite pyramid
function payAmount(employee) {
let result;
if (employee.isSeparated) {
result = {amount: 0, reason: "SEP"};
} else {
if (employee.isRetired) {
result = {amount: 0, reason: "RET"};
} else {
result = someFinalComputation();
}
}
return result;
}
// After — guard clauses, happy path flat
function payAmount(employee) {
if (employee.isSeparated) return {amount: 0, reason: "SEP"};
if (employee.isRetired) return {amount: 0, reason: "RET"};
return someFinalComputation();
}
Tres líneas de guardas reemplazan dos niveles de anidamiento y una variable result mutable. El lector procesa cada precondición por separado en lugar de rastrear alcances, y la función se lee de arriba abajo como una lista de verificación: sal, sal, haz el trabajo.
Arreglo 2: extrae los números a constantes con nombre
Replace Magic Literal de Fowler (alias: Replace Magic Number with Symbolic Constant) es el movimiento espejo para los datos:
# Before
if attempt < 3:
time.sleep(0.5)
# After
MAX_RETRIES = 3
RETRY_BACKOFF_SECONDS = 0.5
if attempt < MAX_RETRIES:
time.sleep(RETRY_BACKOFF_SECONDS)
El número ahora se explica solo, vive en un solo lugar y aparece en el autocompletado la próxima vez que tú — o tu agente — lo necesiten. Las excepciones son convencionales: 0, 1 y los contadores de bucle como i < count son evidentes y no necesitan nombre.
Reglas prácticas
| Smell | Señal | Arreglo | Tiempo |
|---|---|---|---|
| Anidamiento | 3+ niveles de indentación en una función | Cláusulas de guarda / retorno temprano | ~30s |
| Número mágico | Literal suelto distinto de 0/1/límites de bucle | Constante con nombre al inicio del módulo | ~30s |
| Ambos a la vez | if x > 500: anidado | Primero la guarda, luego nombra el 500 | ~60s |
Movimientos avanzados
- Ponlo en el system prompt. Agrega "prefer guard clauses over nested conditionals; name every non-obvious numeric literal" al archivo de instrucciones de tu asistente (CLAUDE.md, .cursorrules, etc.). Dejas de arreglar el smell después de generar y empiezas a prevenirlo.
- Usa un linter, no el ojo.
no-magic-numbersde ESLint, el checkermagic-value-comparisonde Pylint y la regla de complejidad cognitiva de Sonar detectan esto mecánicamente — conéctalos al CI y el código de la IA queda sujeto al mismo estándar que el humano. - Las constantes son combustible para agentes. Un
DEBOUNCE_DELAY_MScon nombre es un ancla buscable con grep. El siguiente agente que edite el archivo encuentra la intención en el nombre en lugar de adivinar qué significaba300— el código plano y con nombres es más barato de modificar correctamente para los modelos, no solo más fácil de leer para los humanos.
Recursos
- Replace Nested Conditional with Guard Clauses — catálogo de refactoring de Martin Fowler
- Replace Magic Literal — catálogo de refactoring de Martin Fowler
- Replace Magic Number with Symbolic Constant — Refactoring.Guru
- Guard (computer science) — Wikipedia
- Magic number (programming) — Wikipedia
- Whitepaper de Cognitive Complexity — SonarSource (PDF)
¿Construyes con código generado por IA? Yeda AI diseña, audita y entrega sistemas LLM en producción.