Logotipo do ConstructiCat
CodeBust.
Explorar a seção ▾

Padrão Obsoleto ou Descontinuado.

Assistentes de IA emitem com confiança APIs, bibliotecas e expressões idiomáticas que eram atuais anos atrás, mas que agora estão descontinuadas, removidas ou substituídas, porque seu conhecimento paramétrico está congelado em um corte de treinamento e o padrão antigo ainda é o estatisticamente mais comum em seu corpus.

##Sinais e sintomas

Um revisor reconhece este smell quando o código gerado roda, mas combina com o estilo de um tutorial de dois ou três anos atrás: ele chama APIs sobre as quais o framework agora emite avisos, fixa versões principais antigas ou recorre a expressões idiomáticas legadas em vez da biblioteca padrão/sintaxe moderna. Sinais reveladores:

  • Avisos de descontinuação na instalação/build/execução que o modelo ignorou (DeprecationWarning, [DEP0005], componentWillMount is deprecated).
  • Expressões idiomáticas que antecedem a base atual da linguagem: var em vez de const/let, cadeias de callbacks/.then() onde a base de código usa async/await, require() em um projeto ESM, moment.js em vez de Intl/Temporal/date-fns.
  • Chamadas de biblioteca removidas ou descontinuadas na versão que você realmente tem instalada: removidas — pandas df.append(...) (removido no pandas 2.0) e .ix[] (removido na 1.0); descontinuadas, mas ainda presentes — ciclos de vida legados do React, datetime.utcnow() (descontinuado desde o Python 3.12), Node new Buffer(), url.parse().
  • Padrões de segurança legados que dominam dados de treinamento antigos: hashing MD5/SHA1, crypto.createCipher, SQL bruto concatenado por strings.
  • Reinventar o que a plataforma agora já fornece (deepClone, groupBy, UUID feitos à mão) em vez de structuredClone, Object.groupBy, crypto.randomUUID().
// Gerado por IA: compila, mas cada linha é um padrão agora descontinuado
const crypto = require('crypto');                 // projeto ESM usa import

const buf = new Buffer(userInput);                // Buffer() descontinuado desde o Node 6
const id  = crypto.createHash('md5')              // MD5 descontinuado para qualquer uso de segurança
              .update(token).digest('hex');
const cipher = crypto.createCipher('aes-256-cbc', key);  // API de caminho removido, KDF fraca

request(apiUrl, (err, res, body) => { /* ... */ });      // 'request' sem manutenção desde 2020

##Causas do problema

Por que os modelos o produzem

  • Defasagem do corte de treinamento. O conhecimento paramétrico de um LLM está congelado em seu corte, mas as bibliotecas continuam evoluindo. Estudos que medem isso encontram uma taxa de uso de APIs descontinuadas de 25–38% em oito bibliotecas Python nas completações de LLMs (Wang et al., ICSE 2025), e, em 328 problemas condicionados à versão, os modelos comerciais atingem taxas de sucesso de base de apenas 48–51% (GitChameleon 2.0, ACL 2026). Não há consciência de API/versão em tempo real no momento da inferência.
  • A frequência do próximo token favorece o jeito antigo. O corpus contém anos de código legado, então a completação estatisticamente mais provável muitas vezes é a obsoleta. A OX Security observa que "a concatenação de strings é o que aparece com mais frequência nos dados de treinamento" e que "o MD5 aparece com frequência em exemplos de hashing em todo o seu corpus de treinamento" (OX Security), e a Veracode descobriu que, diante da escolha entre um método seguro e um inseguro, os modelos escolheram o inseguro em 45% das vezes (relatório GenAI Code Security 2025 da Veracode).
  • Sem contexto do repositório. O modelo geralmente não sabe qual versão principal você realmente instalou, o que seu lockfile fixa, ou que lib/hash.ts já existe — então ele não consegue mirar na API das suas versões. Eno Reyes (Factory) descreve o agente como "um ótimo reconhecedor de padrões": "código bom no padrão significa código bom na saída" — sem um exemplo atual, ele recorre à média de seus dados de treinamento (entrevista com Eno Reyes no blog do Stack Overflow).
  • Recompensa por "fazer funcionar" + bajulação. Os modelos otimizam para código que plausivelmente compila e satisfaz o prompt, não para "usa o caminho atual e suportado". A chamada descontinuada ainda funciona hoje, então ela parece correta.

Por que isso prejudica

  • Manutenibilidade / quebra-bomba-relógio. Descontinuado hoje significa removido na próxima versão principal — o código funciona até que uma atualização o quebre silenciosamente, e esses padrões são copiados e colados em vez de refatorados. A análise de 2025 da GitClear, com 211 milhões de linhas alteradas (2020–2024), constatou que as linhas associadas à refatoração (linhas "movidas") caíram de 25% das linhas alteradas em 2021 para menos de 10% em 2024, enquanto as linhas copiadas/coladas subiram de 8,3% para 12,3% no mesmo período; 2024 foi o primeiro ano em que as linhas copiadas/coladas superaram as movidas, e os blocos com cinco ou mais linhas duplicadas cresceram cerca de oito vezes ao longo de 2024 (GitClear 2025). Assim, uma única expressão obsoleta se propaga em vez de ser corrigida uma única vez.
  • Correção. APIs substituídas muitas vezes têm semântica sutilmente diferente (utcnow() retorna um datetime ingênuo; ciclos de vida legados disparam em momentos diferentes), produzindo bugs que passam por um teste rápido de fumaça.
  • Segurança. Criptografia descontinuada (MD5, createCipher) e versões de pacotes desatualizadas carregam CVEs conhecidos que o modelo nunca confronta com nenhum banco de dados de advisories; nos testes da Veracode de 2025, o código gerado por IA introduziu vulnerabilidades de segurança em 45% dos casos (Veracode).
  • Carga de revisão & dívida técnica. Cada ocorrência é uma correção manual separada e, como o padrão é duplicado em vez de centralizado, o custo se acumula por toda a base de código.

##Tratamento

Táticas de revisão & prompting

  • Declare as versões no prompt ou no contexto. "Estamos no React 19, pandas 2.2, Node 22 (ESM) — use apenas APIs atuais nessas versões." Traga a documentação atual para o contexto (um docs MCP / Context7) em vez de confiar na memória paramétrica.
  • Force uma passagem de ferramentas. Exija que o modelo execute o linter, o verificador de tipos e npm outdated / pip list --outdated, e então corrija todo aviso de descontinuação antes de declarar concluído. Avisos de descontinuação são o detector mais barato possível — não deixe que sejam ignorados.
  • Exija reutilização em vez de reinvenção. "Use o helper existente em lib/hash.ts; não faça hashing à mão." Aponte para o módulo canônico para que o modelo não regenere uma versão legada (Código Duplicado).
  • Codemods em vez de edições manuais. Para atualizações sistemáticas, execute os codemods/modernizadores oficiais em vez de pedir ao modelo que reescreva à mão: npx @next/codemod, codemods do React, regras pyupgrade/Ruff UP. Eles são determinísticos e completos.

A refatoração — substituir uma API descontinuada por sua sucessora suportada é essencialmente Substituir Algoritmo, e consolidar as chamadas obsoletas duplicadas em um único helper aplica Extrair Método contra o Código Duplicado:

// Antes — APIs de caminho descontinuado/removido
const buf    = new Buffer(userInput);
const id     = crypto.createHash('md5').update(token).digest('hex');
const cipher = crypto.createCipher('aes-256-cbc', key);

// Depois — atual, suportado, sensato em segurança
import crypto from 'node:crypto';

const buf    = Buffer.from(userInput);                 // construtor 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 senhas, use argon2/bcrypt — não um hash bruto)

Para dependências, a correção equivalente é elevar o pin e deixar o codemod migrar os pontos de chamada, e então bloquear a deriva futura no CI (regra de lint abaixo + uma política Dependabot/Renovate) para que o modelo não possa reintroduzir silenciosamente o padrão antigo.

##Detectado por

  • ESLint (eslint-plugin-n) n/no-deprecated-api — Proíbe APIs principais descontinuadas do Node.js (Buffer(), crypto.createCipher, url.parse, etc.)
  • typescript-eslint @typescript-eslint/no-deprecated — Sinaliza o uso de qualquer símbolo marcado como @deprecated em sua declaração JSDoc/TS
  • ESLint (eslint-plugin-react) react/no-deprecated — Sinaliza APIs e métodos de ciclo de vida descontinuados do React (componentWillMount, etc.)
  • SonarQube / SonarSource RSPEC-1874 — Relata o uso de código anotado/marcado como descontinuado
  • Ruff pyupgrade (UP) — Detecta e reescreve expressões idiomáticas Python obsoletas/substituídas para equivalentes modernos
  • Dependabot version-updates — Sinaliza versões de dependências desatualizadas (a faceta de pacote obsoleto deste smell)