Запахи ИИ-кода.
Повторяющиеся проблемы в коде, написанном ИИ-ассистентами: как их распознать, почему модели их создают, как их исправить и какие правила статического анализа их обнаруживают.
ИИ-ассистент оборачивает код в лишние функции, классы или интерфейсы, добавляющие слой косвенности, не скрывая никакой сложности и не давая переиспользования, — абстракции, которые лишь пробрасывают вызов к единственной точке вызова.
При написании нового кода ИИ-ассистенты склонны вставлять или заново выводить слегка подправленную копию уже существующей логики вместо того, чтобы вызвать или извлечь общую функцию, поэтому дублированный код растёт с каждой новой задачей.
ИИ-ассистенты почти никогда не перестраивают существующий код: они навешивают на то, что уже есть, новые ветки, параметры-флаги и обёртки, поэтому функции и условные операторы всё растут, а рефакторинг — переработка, поддерживающая здоровье кодовой базы, — незаметно исчезает.
Модель вручную пишет самописный код для того, что уже делает стандартная библиотека, имеющаяся зависимость или хелпер уже в репозитории, — добавляя дублированную, хуже протестированную логику вместо вызова того, что уже есть.
Сгенерированный ИИ код, который вызывает функции, методы, параметры, ключи конфигурации или пакеты, выглядящие правдоподобно, но не существующие в той версии библиотеки, от которой вы зависите.
ИИ-ассистенты склонны генерировать код, который обрабатывает только успешный, корректный случай — пропуская валидацию ввода, обработку ошибок, проверки на null/пустоту и краевые случаи — поэтому код работает в демо и ломается в продакшене.
ИИ-ассистенты выдают функциональный код, который молча опускает средства защиты, которые человек добавил бы по привычке — валидацию ввода, авторизацию, кодирование вывода, работу с секретами — потому что "оно компилируется и возвращает 200" выглядит как готово.
Комментарии, которые являются артефактами генерационного диалога — пересказанные промпты, пошаговый нарратив, чат-ремарки и заглушки-эллипсисы вроде `// ... rest of the code here`, закоммиченные в исходники вместо настоящей документации.
ИИ-ассистенты раздувают простую логику комментариями, пересказывающими каждую строку, пошаговыми пояснениями, защитными «лестницами» проверок на null и многословными выражениями там, где хватило бы идиомы или существующего хелпера, — число строк растёт, а поведения не прибавляется.
ИИ-ассистент даёт новому коду обобщённые заглушки-имена или новое соглашение, игнорируя существующие идентификаторы и доменный словарь репозитория, что подрывает читаемость и плодит дублирующиеся, неверно описанные понятия.
Сгенерированный ИИ код, который тихо игнорирует устоявшиеся соглашения репозитория — переизобретает вспомогательные функции, выбирает не ту библиотеку и использует не принятое в проекте именование и обработку ошибок — из-за чего кодовая база дрейфует к обобщённому, усреднённому по интернету стилю.
ИИ-ассистенты уверенно выдают API, библиотеки и идиомы, которые были актуальны несколько лет назад, но теперь объявлены устаревшими, удалены или вытеснены, потому что их параметрическое знание заморожено на моменте обучающего среза, а старый паттерн по-прежнему статистически наиболее распространён в их корпусе.
ИИ-ассистенты подстраховываются от сбоев, которые не могут произойти, оборачивая уже безопасный код в избыточные проверки на null, мёртвые охранные условия и всеохватные блоки try/except, добавляющие сложность без добавления безопасности.
ИИ-ассистенты вшивают зависящие от окружения значения — URL, порты, пути, тайм-ауты, ключи и магические числа — прямо в логику вместо чтения их из конфигурации или окружения, потому что литерал является наиболее вероятным следующим токеном, а модель не знает о вашем существующем слое конфигурации.