---
title: "Patrón anticuado u obsoleto"
type: "ai-smell"
slug: "deprecated-pattern"
url: "http://localhost:3000/es/ai-smells/deprecated-pattern.md"
category: "Mantenimiento"
description: "Los asistentes de IA emiten con total seguridad APIs, bibliotecas y expresiones idiomáticas que eran actuales hace años pero que ahora están obsoletas, eliminadas o superadas, porque su conocimiento paramétrico está congelado en una fecha de corte del entrenamiento y el patrón antiguo sigue siendo el estadísticamente más común en su corpus."
---
# Patrón anticuado u obsoleto

> Los asistentes de IA emiten con total seguridad APIs, bibliotecas y expresiones idiomáticas que eran actuales hace años pero que ahora están obsoletas, eliminadas o superadas, porque su conocimiento paramétrico está congelado en una fecha de corte del entrenamiento y el patrón antiguo sigue siendo el estadísticamente más común en su corpus.

## Signs and Symptoms

Un revisor reconoce este olor cuando el código generado _se ejecuta_ pero se ajusta al estilo de un tutorial de hace dos o tres años: llama a APIs sobre las que el framework ya advierte, fija versiones mayores antiguas o recurre a expresiones heredadas en lugar de la biblioteca estándar/sintaxis moderna. Señales reveladoras:

* **Advertencias de obsolescencia en la instalación/compilación/ejecución** que el modelo ignoró (`DeprecationWarning`, `[DEP0005]`, `componentWillMount is deprecated`).
* **Expresiones idiomáticas anteriores a la base actual del lenguaje**: `var` en lugar de `const`/`let`, cadenas de callbacks/`.then()` donde la base de código usa `async/await`, `require()` en un proyecto ESM, `moment.js` en lugar de `Intl`/`Temporal`/date-fns.
* **Llamadas a bibliotecas eliminadas en la versión que tienes instalada realmente**: pandas `df.append(...)` / `.ix[]`, ciclos de vida heredados de React, `datetime.utcnow()`, `new Buffer()` de Node, `url.parse()`.
* **Valores de seguridad heredados por defecto** que dominan los datos de entrenamiento antiguos: hashing MD5/SHA1, `crypto.createCipher`, SQL concatenado en crudo con cadenas.
* **Reinventar lo que la plataforma ya incluye** (`deepClone`, `groupBy`, UUID hechos a mano) en lugar de `structuredClone`, `Object.groupBy`, `crypto.randomUUID()`.

```js
// Generado por IA: compila, pero cada línea es un patrón ya obsoleto
const crypto = require('crypto');                 // el proyecto ESM usa import

const buf = new Buffer(userInput);                // Buffer() obsoleto desde Node 6
const id  = crypto.createHash('md5')              // MD5 obsoleto para cualquier uso de seguridad
              .update(token).digest('hex');
const cipher = crypto.createCipher('aes-256-cbc', key);  // API de ruta eliminada, KDF débil

request(apiUrl, (err, res, body) => { /* ... */ });      // 'request' sin mantenimiento desde 2020

```

## Reasons for the Problem

**Por qué los modelos lo producen**

* **Desactualización por la fecha de corte del entrenamiento.** El conocimiento paramétrico de un LLM queda congelado en su fecha de corte, pero las bibliotecas siguen evolucionando. Los estudios que lo miden encuentran una **tasa de uso de APIs obsoletas del 25–38 %** en ocho bibliotecas de Python dentro de las terminaciones generadas por LLM ([Wang et al., ICSE 2025](https://dl.acm.org/doi/10.1109/ICSE55347.2025.00245)), e incluso los modelos más avanzados solo alcanzan un **48–51 %** en la generación condicionada por versión ([GitChameleon 2.0](https://openreview.net/pdf?id=wtqdcVfJUN)). No existe conciencia en tiempo real de la API ni de la versión durante la inferencia.
* **La frecuencia del siguiente token favorece la forma antigua.** El corpus contiene _años_ de código heredado, así que la terminación estadísticamente más probable suele ser la obsoleta. OX Security señala que los modelos recurren por defecto a la concatenación de cadenas y a MD5/SHA1 precisamente porque esos "aparecen con mayor frecuencia en los datos de entrenamiento", y Veracode descubrió que los modelos eligen la opción insegura/heredada el **\~45 % de las veces** cuando se les da a elegir ([OX Security](https://www.ox.security/blog/vibe-coding-security/)).
* **Sin contexto del repositorio.** Normalmente el modelo no sabe qué versión mayor tienes instalada realmente, qué fija tu lockfile, ni que `lib/hash.ts` ya existe, así que no puede apuntar a _tu_ superficie de API. Como lo plantea Stack Overflow: un agente es "un gran reconocedor de patrones… buen código entra, buen código sale"; sin un ejemplo actual, recurre al promedio de sus datos de entrenamiento ([Reyes Q&A](https://stackoverflow.blog/2026/02/04/code-smells-for-ai-agents-q-and-a-with-eno-reyes-of-factory/)).
* **Recompensa de "hazlo funcionar" + adulación.** Los modelos optimizan para que el código compile de forma plausible y satisfaga la petición, no para que "use la vía actual y soportada". La llamada obsoleta todavía funciona _hoy_, así que parece correcta.

**Por qué resulta perjudicial**

* **Mantenibilidad / rotura como bomba de tiempo.** Obsoleto hoy significa _eliminado en la próxima versión mayor_: el código funciona hasta que una actualización lo rompe en silencio, y estos patrones se copian y pegan en lugar de refactorizarse. El análisis de 211 millones de líneas de GitClear muestra que las líneas copiadas/pegadas subieron del **8,3 % al 12,3 %** mientras que las líneas refactorizadas ("movidas") cayeron del **24,1 % al 9,5 %** entre 2020 y 2024, con bloques duplicados multiplicándose \~8 veces, de modo que una sola expresión obsoleta se propaga en vez de corregirse una sola vez ([GitClear 2025](https://www.gitclear.com/ai%5Fassistant%5Fcode%5Fquality%5F2025%5Fresearch)).
* **Corrección.** Las APIs superadas suelen tener una semántica sutilmente distinta (`utcnow()` devuelve un datetime naive; los ciclos de vida heredados se disparan en momentos distintos), produciendo errores que superan una prueba rápida de humo.
* **Seguridad.** La criptografía obsoleta (MD5, `createCipher`) y las versiones de paquetes anticuadas arrastran CVE conocidos que el modelo nunca contrasta con ninguna base de datos de avisos: un motor central del hallazgo de que la _mayoría_ del código generado por IA se entrega con al menos una vulnerabilidad.
* **Carga de revisión y deuda técnica.** Cada aparición es una corrección manual independiente y, como el patrón está duplicado en lugar de centralizado, el coste se acumula por toda la base de código.

## Treatment

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

* **Indica las versiones en el prompt o el contexto.** "Usamos React 19, pandas 2.2, Node 22 (ESM): emplea solo APIs vigentes en esas versiones." Incorpora la documentación actual al contexto (un MCP de documentación / Context7) en lugar de fiarte de la memoria paramétrica.
* **Obliga a una pasada de herramientas.** Exige que el modelo ejecute el linter, el verificador de tipos y `npm outdated` / `pip list --outdated`, y luego corrija cada advertencia de obsolescencia antes de darlo por terminado. Las advertencias de obsolescencia son el detector más barato posible: no dejes que se ignoren.
* **Exige reutilización en lugar de reinvención.** "Usa el ayudante existente en `lib/hash.ts`; no implementes el hashing a mano." Apunta al módulo canónico para que el modelo no regenere una versión heredada (Código duplicado).
* **Codemods en lugar de ediciones manuales.** Para actualizaciones sistemáticas, ejecuta los codemods/modernizadores oficiales en lugar de pedir al modelo que reescriba a mano: `npx @next/codemod`, los codemods de React, las reglas `pyupgrade`/`UP` de Ruff. Son deterministas y completos.

**La refactorización**: en esencia es _Sustituir algoritmo_ / reemplazar-API-obsoleta, y consolidar las llamadas obsoletas duplicadas en un único ayudante aplica _Extraer función_ contra _Código duplicado_:

```js
// Antes — APIs obsoletas o de ruta eliminada
const buf    = new Buffer(userInput);
const id     = crypto.createHash('md5').update(token).digest('hex');
const cipher = crypto.createCipher('aes-256-cbc', key);

// Después — actuales, compatibles y sensatas en seguridad
import crypto from 'node:crypto';

const buf    = Buffer.from(userInput);                 // constructor seguro
const id     = crypto.createHash('sha256').update(token).digest('hex');
const iv     = crypto.randomBytes(16);                 // IV explícito
const cipher = crypto.createCipheriv('aes-256-cbc', key, iv);
// (para contraseñas, usa argon2/bcrypt, no un hash en crudo)

```

Para las dependencias, la corrección equivalente es subir la versión fijada y dejar que el codemod migre los puntos de llamada, y luego bloquear la deriva futura en CI (la regla de lint anterior + una política de Dependabot/Renovate) para que el modelo no pueda reintroducir el patrón antiguo en silencio.

## Detected by

- **ESLint (eslint-plugin-n)** `n/no-deprecated-api` — Prohíbe las APIs básicas obsoletas de Node.js (Buffer(), crypto.createCipher, url.parse, etc.) (https://github.com/eslint-community/eslint-plugin-n/blob/master/docs/rules/no-deprecated-api.md)
- **typescript-eslint** `@typescript-eslint/no-deprecated` — Señala el uso de cualquier símbolo marcado como @deprecated en su declaración JSDoc/TS (https://typescript-eslint.io/rules/no-deprecated/)
- **ESLint (eslint-plugin-react)** `react/no-deprecated` — Señala APIs y métodos de ciclo de vida de React obsoletos (componentWillMount, etc.) (https://github.com/jsx-eslint/eslint-plugin-react/blob/master/docs/rules/no-deprecated.md)
- **SonarQube / SonarSource** `RSPEC-1874 ("@Deprecated" code should not be used)` — Informa del uso de código anotado/marcado como obsoleto (https://rules.sonarsource.com/java/RSPEC-1874/)
- **Ruff** `pyupgrade (UP) rules` — Detecta y reescribe expresiones idiomáticas de Python anticuadas/superadas a sus equivalentes modernos (https://docs.astral.sh/ruff/rules/#pyupgrade-up)
- **Dependabot** `version-updates` — Señala versiones de dependencias anticuadas (la faceta de paquetes desactualizados de este olor) (https://docs.github.com/en/code-security/dependabot/dependabot-version-updates/about-dependabot-version-updates)
