Logotipo de ConstructiCat
CodeBust.
Explorar la sección ▾

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.

##Signos y síntomas

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 u obsoletas en la versión que tienes instalada realmente: eliminadas — pandas df.append(...) (desaparece en pandas 2.0) y .ix[] (desaparece en 1.0); obsoletas pero aún presentes — ciclos de vida heredados de React, datetime.utcnow() (obsoleto desde Python 3.12), 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().
// 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

##Causas del problema

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), e incluso los modelos comerciales solo alcanzan tasas de éxito de referencia del 48–51 % en 328 problemas condicionados por versión (GitChameleon 2.0, ACL 2026). 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 "la concatenación de cadenas es lo que aparece con más frecuencia en los datos de entrenamiento" y que "MD5 aparece con frecuencia en los ejemplos de hashing de todo su corpus de entrenamiento" (OX Security), y Veracode descubrió que, al elegir entre un método seguro y uno inseguro, los modelos optaron por el inseguro el 45 % de las veces (informe GenAI Code Security 2025 de Veracode).
  • 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 la API de tus versiones. Eno Reyes (Factory) describe al agente como "un gran reconocedor de patrones": "si el código del patrón es bueno, el código que sale es bueno"; sin un ejemplo actual, recurre al promedio de sus datos de entrenamiento (entrevista con Eno Reyes en el blog de Stack Overflow).
  • 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 GitClear de 2025 sobre 211 millones de líneas modificadas (2020–2024) concluyó que las líneas asociadas a la refactorización (líneas «movidas») cayeron del 25 % de las líneas modificadas en 2021 a menos del 10 % en 2024, mientras que las líneas copiadas/pegadas subieron del 8,3 % al 12,3 % en el mismo periodo; 2024 fue el primer año en que las líneas copiadas/pegadas superaron a las movidas, y los bloques con cinco o más líneas duplicadas se multiplicaron aproximadamente por ocho durante 2024 (GitClear 2025). Así, una sola expresión obsoleta se propaga en lugar de corregirse una única vez.
  • 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; en las pruebas de Veracode de 2025, el código generado por IA introdujo vulnerabilidades de seguridad en el 45 % de los casos (Veracode).
  • 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.

##Tratamiento

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: sustituir una API obsoleta por su sucesora soportada es en esencia Sustituir algoritmo, y consolidar las llamadas obsoletas duplicadas en un único ayudante aplica Extraer método contra el Código Duplicado:

// 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.

##Detectado por

  • ESLint (eslint-plugin-n) n/no-deprecated-api — Prohíbe las APIs básicas obsoletas de Node.js (Buffer(), crypto.createCipher, url.parse, etc.)
  • typescript-eslint @typescript-eslint/no-deprecated — Señala el uso de cualquier símbolo marcado como @deprecated en su declaración JSDoc/TS
  • ESLint (eslint-plugin-react) react/no-deprecated — Señala APIs y métodos de ciclo de vida de React obsoletos (componentWillMount, etc.)
  • SonarQube / SonarSource RSPEC-1874 — Informa del uso de código anotado/marcado como obsoleto
  • Ruff pyupgrade (UP) — Detecta y reescribe expresiones idiomáticas de Python anticuadas/superadas a sus equivalentes modernos
  • Dependabot version-updates — Señala versiones de dependencias anticuadas (la faceta de paquetes desactualizados de este olor)