---
title: "Configuración codificada de forma rígida"
type: "ai-smell"
slug: "hardcoded-configuration"
url: "http://localhost:3000/es/ai-smells/hardcoded-configuration.md"
category: "Mantenimiento"
description: "Los asistentes de IA incrustan valores específicos del entorno —URL, puertos, rutas, tiempos de espera, claves y números mágicos— directamente en la lógica en lugar de leerlos de la configuración o del entorno, porque un literal es el siguiente token más probable y el modelo desconoce la capa de configuración existente."
---
# Configuración codificada de forma rígida

> Los asistentes de IA incrustan valores específicos del entorno —URL, puertos, rutas, tiempos de espera, claves y números mágicos— directamente en la lógica en lugar de leerlos de la configuración o del entorno, porque un literal es el siguiente token más probable y el modelo desconoce la capa de configuración existente.

## Signs and Symptoms

Un asistente de IA tiende a emitir un _literal plausible_ justo donde corresponde una referencia. El código funciona en la demo, así que el smell sobrevive a la revisión a menos que lo busques.

Señales reveladoras:

* **Endpoints, puertos, rutas y tiempos de espera incrustados** esparcidos por la lógica de negocio en lugar de en un módulo de configuración: `http://localhost:3000`, `/tmp/cache`, `5432`, `setTimeout(..., 30000)`.
* **Números/cadenas mágicos** sin constante con nombre: recuentos de reintentos, tamaños de página, límites de tasa, umbrales de funcionalidades.
* **El mismo literal repetido entre archivos** porque el modelo lo regeneró en lugar de importar una constante existente (el patrón de GitClear «copiar/pegar arriba, refactorizar abajo» en miniatura).
* **Credenciales / claves codificadas de forma rígida**: tokens de API, claves de cifrado o cadenas de autenticación `Basic` pegadas desde los datos de entrenamiento.
* **Un `config.ts` / `.env` / objeto de ajustes existente que el nuevo código ignora** por completo.
* **Valores incrustados del entorno**: una URL de desarrollo/staging o un ID de cuenta de pruebas cableado en una ruta que llega a producción.

```ts
// 🚩 Generado por IA: cada parámetro es un literal, con valores de desarrollo incrustados
export async function syncOrders() {
  const res = await fetch("https://api.staging.acme.dev/v1/orders", {
    headers: { Authorization: "Bearer sk_test_4eC39HqLyjWDarjtT1zdp7dc" },
    signal: AbortSignal.timeout(30000),
  });
  const orders = (await res.json()).slice(0, 50); // ¿por qué 50?
  for (let i = 0; i < 3; i++) { /* reintentar 3 veces... ¿por qué 3? */ }
}

```

La línea de Authorization es una coincidencia para gitleaks/Semgrep; la URL, `30000`, `50` y `3` son smells de valores mágicos; y `api.staging.acme.dev` es un valor de desarrollo a punto de llegar a producción.

## Reasons for the Problem

**Por qué lo producen los modelos**

* **Un literal es el siguiente token de mayor probabilidad.** Dado `fetch(`, la terminación más barata que satisface el prompt inmediato es una cadena de URL concreta, no `config.apiBaseUrl`. Resolver una _referencia_ requiere saber que un símbolo existe en otro lugar; emitir un _valor_ no requiere nada. Los modelos optimizan para obtener un fragmento localmente plausible y ejecutable.
* **El corpus de entrenamiento son fragmentos autocontenidos.** Los tutoriales, los ejemplos de README y las respuestas de Stack Overflow incrustan sus valores para que se ejecuten de forma independiente. El modelo aprendió que «el buen código de ejemplo» codifica los valores de forma rígida, lo contrario de la higiene de producción.
* **Sin contexto del repositorio / ventana limitada.** El modelo normalmente no ha leído tu `config/`, tu esquema de entorno ni tu archivo de constantes, así que no puede reutilizarlos. GitClear vincula precisamente esto con el aumento de la duplicación: los asistentes son «menos propensos a proponer la reutilización de una función similar… en parte por el tamaño limitado del contexto», con bloques duplicados de más de 5 líneas multiplicados por unas 8 veces en 2024, mientras que las líneas refactorizadas («movidas») cayeron de cerca del 24 % a cerca del 9,5 %.
* **Servilismo / sesgo de responder al prompt.** Si se le pide «añade una sincronización de pedidos», el modelo entrega algo que funciona _ahora_; externalizar la configuración es andamiaje adicional que no ofrecerá voluntariamente a menos que se le indique.
* **Obsolescencia por el corte del entrenamiento.** Los literales incrustados suelen ser literales _obsoletos_: endpoints antiguos, versiones de API en desuso, puertos por defecto o constantes criptográficas débiles (MD5, claves codificadas de forma rígida). OX Security descubrió que el 62 % del código generado por IA se entrega con problemas y atribuye las claves/secretos/rutas codificados de forma rígida a patrones «aprendidos de bases de código heredadas… \[con\] cero conciencia de que los estándares de seguridad evolucionaron».

**Por qué es perjudicial**

* **Mantenibilidad: cirugía a escopetazos.** Cambiar un tiempo de espera o una URL base implica buscar cada literal duplicado por toda la base de código; si se te escapa uno, el comportamiento diverge en silencio según el punto de llamada.
* **Corrección entre entornos.** Una URL de staging o un ID de cuenta de desarrollo cableado en la lógica acaba en producción; los umbrales mágicos sin nombre se desincronizan de los valores que deberían reflejar.
* **Seguridad.** Los tokens/claves codificados de forma rígida son filtraciones de credenciales: una vez confirmados, viven para siempre en el historial de git. El estudio de código de compilación de arXiv (2601.16839) encontró rutas/URL codificadas de forma rígida y credenciales codificadas de alta gravedad recurrentes en los archivos de compilación generados por IA.
* **Carga de revisión y deuda técnica.** Los revisores deben verificar la procedencia de _cada_ literal. El trabajo sobre smells específicos de la IA (arXiv 2509.20491) señala que los modelos manejan bien los «literales dentro del ámbito», pero tienen problemas con los casos **sensibles al valor**, donde la corrección depende de umbrales que se propagan a través de funciones auxiliares: precisamente los valores codificados de forma rígida que los humanos deben ahora auditar a mano. Según la entrevista de Stack Overflow con Eno Reyes, de Factory, la calidad básica del código es «la única señal» de si los agentes aceleran o _frenan_ a un equipo, y la proliferación de valores codificados de forma rígida erosiona exactamente esa base.

## Treatment

**Tácticas de prompting / revisión**

* **Apunta el modelo hacia tu superficie de configuración:** «Lee `src/config.ts` y `.env.example`; usa `config.*` / `process.env` para cada URL, puerto, tiempo de espera y credencial. No introduzcas literales.» Los modelos incrustan valores porque no saben que el símbolo existe: nómbralo.
* **Prohíbe los valores mágicos de forma explícita:** «Nada de números ni cadenas mágicas: extrae constantes con nombre.» Después haz que ejecute `eslint --rule no-magic-numbers` y un escáner de secretos (gitleaks/Semgrep) y que corrija lo que marquen. Según la guía de Factory, conecta los linters/escáneres al bucle para que el agente se autocorrija en lugar de apoyarse en la revisión humana.
* **Proporciona el esquema del entorno** (zod/envalid/`.env.example`) para que el modelo tenga dónde colocar los valores en lugar de adivinarlos.
* **Inspecciona los nuevos diffs** en busca de `http`, `localhost`, literales de IP, `Bearer ` y dígitos sueltos en los argumentos de las llamadas antes de hacer merge.

**La refactorización**: nombra las maniobras clásicas:

* **Reemplazar número mágico con constante simbólica** para umbrales, recuentos y tamaños.
* **Extraer función / extraer módulo de configuración** para reunir los parámetros en un único lugar tipado y validado.
* **Externalizar al entorno** (12-factor) para todo lo que difiera según el entorno o sea secreto; nunca confirmes secretos.

```ts
// config.ts — fuente de verdad única y validada
import { z } from "zod";
const env = z.object({
  ORDERS_API_BASE_URL: z.string().url(),
  ORDERS_API_TOKEN: z.string().min(1),
  ORDERS_TIMEOUT_MS: z.coerce.number().default(30_000),
  ORDERS_PAGE_SIZE: z.coerce.number().default(50),
  ORDERS_MAX_RETRIES: z.coerce.number().default(3),
}).parse(process.env);
export const config = env;

```

```ts
// ✅ después: referencias, no literales — un único lugar que cambiar, el secreto fuera del código fuente
import { config } from "./config";
export async function syncOrders() {
  const res = await fetch(`${config.ORDERS_API_BASE_URL}/v1/orders`, {
    headers: { Authorization: `Bearer ${config.ORDERS_API_TOKEN}` },
    signal: AbortSignal.timeout(config.ORDERS_TIMEOUT_MS),
  });
  const orders = (await res.json()).slice(0, config.ORDERS_PAGE_SIZE);
  for (let i = 0; i < config.ORDERS_MAX_RETRIES; i++) { /* ... */ }
}

```

Si un secreto ya llegó a un commit, rótalo: eliminar la línea no purga el historial de git.

## Detected by

- **ESLint** `no-magic-numbers` — Prohibir números mágicos (https://eslint.org/docs/latest/rules/no-magic-numbers)
- **SonarSource** `typescript:S109 / java:S109 — "Magic numbers should not be used"` — Números mágicos (https://rules.sonarsource.com/java/RSPEC-109/)
- **SonarSource** `java:S1075 — "URIs should not be hardcoded"` — URI codificadas de forma rígida (https://rules.sonarsource.com/java/RSPEC-1075/)
- **SonarSource** `java:S2068 — "Hard-coded credentials are security-sensitive"` — Credenciales codificadas de forma rígida (https://rules.sonarsource.com/java/RSPEC-2068/)
- **Checkstyle** `MagicNumber` — Comprobación de números mágicos (https://checkstyle.org/checks/coding/magicnumber.html)
- **PMD** `AvoidUsingHardCodedIP` — Evitar direcciones IP codificadas de forma rígida (https://docs.pmd-code.org/latest/pmd_rules_java_bestpractices.html#avoidusinghardcodedip)
- **Bandit** `B105 hardcoded_password_string / B108 hardcoded_tmp_directory` — Contraseñas / directorios temporales codificados de forma rígida (Python) (https://bandit.readthedocs.io/en/latest/plugins/b105_hardcoded_password_string.html)
- **gitleaks** `secret detection (e.g. generic-api-key, regex/entropy rules)` — Escáner de secretos codificados de forma rígida (https://github.com/gitleaks/gitleaks)
- **Semgrep** `generic.secrets / hardcoded-credentials registry rules` — Reglas de secretos/configuración codificados de forma rígida (https://semgrep.dev/r?q=hardcoded)
- **eslint-plugin-no-secrets** `no-secrets/no-secrets` — Detección de cadenas de alta entropía (secretos) (https://github.com/nickdeis/eslint-plugin-no-secrets)
