Эта статья отчасти написана с помощью ИИ. Отчасти. В этом и заключается проблема.
Угадай, кто написал код
Ниже — три пары функций. В каждой одна написана человеком, другая сгенерирована ИИ. Задача: определите, где код ИИ. Ответы — после каждого блока.
Важно: не подглядывайте!
Пара #1 — функция валидации email
Вариант А:
Вариант Б:
👉 Показать ответ
Вариант А — ИИ. Выдают его:
- Подробный docstring с Args и Returns — человек в реальном проекте так не пишет
- Комментарий # RFC 5322 compliant — попытка выглядеть «правильно»
- Проверка длины local_part и domain — ИИ добавляет edge cases, о которых никто не просил
- Идеально структурированный код без единой живой черты
Вариант Б — человек. Короткий, прагматичный, без лишних слов. Да, regex не идеальный — зато написан за 30 секунд и решает задачу.
Пара #2 — функция получения данных из API
Вариант А:
Вариант Б:
👉 Показать ответ
Вариант Б — ИИ. Признаки:
- Кастомный exception UserFetchError — откуда он взялся? ИИ генерирует код, предполагая, что всё вокруг уже идеально устроено
- logger.error — ИИ всегда добавляет логирование, даже если логгер нигде не объявлен
- data.get('user', {}) вместо data['user'] — безопасно, но безмолвно глотает ошибку
Вариант А — человек. Комментарий # TODO: добавить retry логику когда-нибудь — это настоящий боевой код. «Надеюсь там всегда есть 'user'» — вы это тоже писали, не отрицайте.
Пара #3 — обработка конфигурационного файла
Вариант А:
Вариант Б:
👉 Показать ответ
Вариант Б — ИИ. И это самый показательный пример. Смотрите:
- Огромный docstring с перечислением каждого exception — это документация ради документации
- required_keys включает secret_key — откуда? ИИ дополнил список «по логике», которой нет в задаче
- raise json.JSONDecodeError(...) — перехватить исключение только чтобы перебросить то же самое. Зачем?
- encoding='utf-8' — явно, правильно, никто так не делает в реальном проекте без причины
Вариант А — человек. assert вместо raise ValueError — не best practice, но честно. Комментарий # в json иногда строка приходит — это реальный баг из реального продакшена.
Так в чём, собственно, проблема
То, что вы только что делали — анализировали стиль, искали паттерны, чувствовали «это слишком правильно» — ваш ИИ-ревьюер не умеет.
Claude написал код → CodeRabbit его проверил → всё зелёное → отлично, пускаем в продакшн.
Проблема не в плохом коде. Проблема в том, что ИИ пишет код, который подозрительно хорошо выглядит: есть docstrings, типизация, обработка edge cases. А то, что UserFetchError нигде не определён, что secret_key добавлен из воздуха, что data.get('user', {}) будет отлаживаться три часа — ИИ-ревьюер это упускает. Потому что он обучен на том же.
Это архитектурная проблема: синтетика проверяет синтетику.
И как же быть?
Три вещи, которые реально работают:
- Не убирать человека из ревью критических участков. ИИ хорошо ловит очевидное — опечатки, неиспользуемые импорты, простые race conditions. Архитектурные и логические ошибки — нет.
- Тестировать ИИ-ревьюер на намеренно сломанном коде. Возьмите пять реальных багов из вашего прошлого, дайте ИИ их поревьюить. Сколько он нашёл? Это ваш реальный coverage. Мы провели этот эксперимент на пяти реальных багах из продакшена. Результат: ИИ-ревьюер нашёл 2 из 5. Оба — простые: неиспользуемая переменная и отсутствие проверки на null. Три пропущенных — логическая ошибка в расчёте, race condition при параллельных запросах и неправильный порядок миграций. Все три требовали понимания контекста.
- Разделять «написано правильно» и «делает правильное». ИИ отлично проверяет первое. Второе — всё ещё ваша работа.
А теперь главный вопрос: сколько из трёх пар вы угадали с первого раза?