---
title: "Устаревший или вышедший из употребления паттерн"
type: "ai-smell"
slug: "deprecated-pattern"
url: "http://localhost:3000/ru/ai-smells/deprecated-pattern.md"
category: "Сопровождение"
description: "ИИ-ассистенты уверенно выдают API, библиотеки и идиомы, которые были актуальны несколько лет назад, но теперь объявлены устаревшими, удалены или вытеснены, потому что их параметрическое знание заморожено на моменте обучающего среза, а старый паттерн по-прежнему статистически наиболее распространён в их корпусе."
---
# Устаревший или вышедший из употребления паттерн

> ИИ-ассистенты уверенно выдают API, библиотеки и идиомы, которые были актуальны несколько лет назад, но теперь объявлены устаревшими, удалены или вытеснены, потому что их параметрическое знание заморожено на моменте обучающего среза, а старый паттерн по-прежнему статистически наиболее распространён в их корпусе.

## Signs and Symptoms

Ревьюер распознаёт этот запах, когда сгенерированный код _работает_, но соответствует стилю двух- или трёхлетней давности учебника: он вызывает API, о которых фреймворк теперь предупреждает, закрепляет старые мажорные версии или тянется к легаси-идиомам вместо современной stdlib/синтаксиса. Характерные признаки:

* **Предупреждения об устаревании при установке/сборке/выполнении**, которые модель проигнорировала (`DeprecationWarning`, `[DEP0005]`, `componentWillMount is deprecated`).
* **Идиомы, предшествующие текущему базовому уровню языка**: `var` вместо `const`/`let`, колбэки/цепочки `.then()` там, где кодовая база использует `async/await`, `require()` в ESM-проекте, `moment.js` вместо `Intl`/`Temporal`/date-fns.
* **Вызовы библиотек, удалённые в той версии, что у вас фактически установлена**: pandas `df.append(...)` / `.ix[]`, легаси-методы жизненного цикла React, `datetime.utcnow()`, Node `new Buffer()`, `url.parse()`.
* **Легаси-настройки безопасности по умолчанию**, доминирующие в старых обучающих данных: хеширование MD5/SHA1, `crypto.createCipher`, сырой SQL из конкатенации строк.
* **Переизобретение того, что платформа теперь поставляет** (самописные `deepClone`, `groupBy`, UUID) вместо `structuredClone`, `Object.groupBy`, `crypto.randomUUID()`.

```js
// Сгенерировано ИИ: компилируется, но каждая строка — теперь устаревший паттерн
const crypto = require('crypto');                 // ESM-проект использует import

const buf = new Buffer(userInput);                // Buffer() устарел с Node 6
const id  = crypto.createHash('md5')              // MD5 устарел для любого применения в безопасности
              .update(token).digest('hex');
const cipher = crypto.createCipher('aes-256-cbc', key);  // API удалённого пути, слабый KDF

request(apiUrl, (err, res, body) => { /* ... */ });      // 'request' не сопровождается с 2020 года

```

## Reasons for the Problem

**Почему модели это порождают**

* **Устаревание из-за обучающего среза.** Параметрическое знание LLM заморожено на моменте среза, но библиотеки продолжают развиваться. Измеряющие это исследования обнаруживают **долю использования устаревших API в 25–38 %** по восьми Python-библиотекам в дополнениях LLM ([Wang et al., ICSE 2025](https://dl.acm.org/doi/10.1109/ICSE55347.2025.00245)), а даже самые передовые модели набирают лишь **48–51 %** в генерации с учётом версии ([GitChameleon 2.0](https://openreview.net/pdf?id=wtqdcVfJUN)). На момент вывода нет осведомлённости об API/версиях в реальном времени.
* **Частота следующего токена благоприятствует старому способу.** Корпус содержит _годы_ легаси-кода, поэтому статистически наиболее вероятным дополнением часто оказывается устаревшее. OX Security отмечает, что модели по умолчанию выбирают конкатенацию строк и MD5/SHA1 именно потому, что те «чаще всего встречаются в обучающих данных», а Veracode обнаружила, что при наличии выбора модели выбирают небезопасный/легаси-вариант **примерно в 45 % случаев** ([OX Security](https://www.ox.security/blog/vibe-coding-security/)).
* **Нет контекста репозитория.** Модель обычно не знает, какую мажорную версию вы на самом деле установили, что закреплено в вашем lockfile или что `lib/hash.ts` уже существует, — поэтому не может нацелиться на _вашу_ поверхность API. Формулировка Stack Overflow: агент — «отличный распознаватель паттернов… хороший код на входе, хороший код на выходе»: не имея актуального примера, он откатывается к среднему по своим обучающим данным ([интервью с Рейесом](https://stackoverflow.blog/2026/02/04/code-smells-for-ai-agents-q-and-a-with-eno-reyes-of-factory/)).
* **Поощрение за «чтобы работало» + угодничество.** Модели оптимизируют код, который правдоподобно компилируется и удовлетворяет запросу, а не «использует текущий, поддерживаемый путь». Устаревший вызов всё ещё работает _сегодня_, поэтому выглядит корректным.

**Чем это вредит**

* **Сопровождаемость / поломка с бомбой замедленного действия.** «Устарело сегодня» означает _удалено в следующем мажоре_: код работает, пока обновление незаметно его не сломает, и такие паттерны копипастят, а не рефакторят. Анализ 211 млн строк от GitClear показывает, что доля копипастных строк выросла с **8,3 % до 12,3 %**, тогда как доля отрефакторенных («перемещённых») строк упала с **24,1 % до 9,5 %** за 2020–2024 годы, при этом дублирующихся блоков стало примерно в 8 раз больше, — так что единичная протухшая идиома распространяется, вместо того чтобы быть исправленной один раз ([GitClear 2025](https://www.gitclear.com/ai%5Fassistant%5Fcode%5Fquality%5F2025%5Fresearch)).
* **Корректность.** Вытесненные API часто имеют тонко отличающуюся семантику (`utcnow()` возвращает «наивный» datetime; легаси-методы жизненного цикла срабатывают в другое время), порождая баги, которые проходят беглую дымовую проверку.
* **Безопасность.** Устаревшая криптография (MD5, `createCipher`) и устаревшие версии пакетов несут известные CVE, которые модель никогда не сверяет ни с одной базой уязвимостей, — ключевой фактор вывода о том, что _большинство_ сгенерированного ИИ кода поставляется хотя бы с одной уязвимостью.
* **Нагрузка на ревью и техдолг.** Каждое вхождение — это отдельная ручная правка, а поскольку паттерн дублируется, а не централизуется, издержки нарастают по всей кодовой базе.

## Treatment

**Тактики ревью и промптинга**

* **Укажите версии в промпте или контексте.** «Мы на React 19, pandas 2.2, Node 22 (ESM) — используй только API, актуальные в этих версиях.» Подтяните актуальную документацию в контекст (docs-MCP / Context7) вместо доверия параметрической памяти.
* **Принудите прогон инструментов.** Потребуйте, чтобы модель прогнала линтер, проверку типов и `npm outdated` / `pip list --outdated`, а затем исправила каждое предупреждение об устаревании, прежде чем объявлять готово. Предупреждения об устаревании — самый дешёвый возможный детектор; не позволяйте их игнорировать.
* **Требуйте переиспользования вместо переизобретения.** «Используй существующий хелпер в `lib/hash.ts`; не пиши хеширование вручную.» Укажите на канонический модуль, чтобы модель не сгенерировала легаси-версию заново (Дублирование кода).
* **Кодмоды вместо ручных правок.** Для системных обновлений запускайте официальные кодмоды/модернизаторы, а не просите модель переписать вручную: `npx @next/codemod`, кодмоды React, правила `pyupgrade`/Ruff `UP`. Они детерминированы и полны.

**Рефакторинг** — по сути это _Замена алгоритма_ / замена устаревшего API, а сведение дублированных протухших вызовов в один хелпер применяет _Извлечение функции_ против _Дублирования кода_:

```js
// До — API устаревших/удалённых путей
const buf    = new Buffer(userInput);
const id     = crypto.createHash('md5').update(token).digest('hex');
const cipher = crypto.createCipher('aes-256-cbc', key);

// После — актуально, поддерживается, безопасно для криптографии
import crypto from 'node:crypto';

const buf    = Buffer.from(userInput);                 // безопасный конструктор
const id     = crypto.createHash('sha256').update(token).digest('hex');
const iv     = crypto.randomBytes(16);                 // явный IV
const cipher = crypto.createCipheriv('aes-256-cbc', key, iv);
// (для паролей используйте argon2/bcrypt — а не сырой хеш)

```

Для зависимостей эквивалентное исправление — поднять закреплённую версию и дать кодмоду мигрировать места вызовов, а затем перекрыть будущий дрейф в CI (правило линтера ниже + политика Dependabot/Renovate), чтобы модель не могла незаметно вновь ввести старый паттерн.

## Detected by

- **ESLint (eslint-plugin-n)** `n/no-deprecated-api` — Запрет устаревших core-API Node.js (Buffer(), crypto.createCipher, url.parse и т. д.) (https://github.com/eslint-community/eslint-plugin-n/blob/master/docs/rules/no-deprecated-api.md)
- **typescript-eslint** `@typescript-eslint/no-deprecated` — Помечает использование любого символа, отмеченного @deprecated в его JSDoc/TS-объявлении (https://typescript-eslint.io/rules/no-deprecated/)
- **ESLint (eslint-plugin-react)** `react/no-deprecated` — Помечает устаревшие API React и методы жизненного цикла (componentWillMount и т. д.) (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)` — Сообщает об использовании кода, аннотированного/помеченного как устаревший (https://rules.sonarsource.com/java/RSPEC-1874/)
- **Ruff** `pyupgrade (UP) rules` — Обнаруживает и переписывает устаревшие/вытесненные идиомы Python в современные эквиваленты (https://docs.astral.sh/ruff/rules/#pyupgrade-up)
- **Dependabot** `version-updates` — Помечает устаревшие версии зависимостей (грань «протухшего пакета» этого запаха) (https://docs.github.com/en/code-security/dependabot/dependabot-version-updates/about-dependabot-version-updates)
