Писать код стало дёшево. Читать его — нет. Поэтому ревью из финальной
формальности превратилось в самый дорогой этап: именно здесь теперь тратится
внимание, и именно здесь всё ломается.
Главная ловушка — код от модели выглядит хорошо. Ровные отступы, осмысленные
имена, комментарии на месте, обработка ошибок присутствует. Человеческий
плохой код видно с первого взгляда; этот — нет. Привычка «выглядит аккуратно,
значит нормально» здесь работает против вас.
Это не случайные ошибки, а повторяющиеся классы. Их стоит проверять всегда,
даже когда «всё очевидно правильно».
Граничные случаи. Пустой список, единственный элемент, null вместо
объекта, ноль в знаменателе, строка из пробелов. Модель пишет happy path
уверенно, а края — по остаточному принципу.
Ошибки, которые проглатываются. try/catch, где в catch пусто или
залогировано и всё. Формально обработка есть, фактически сбой становится
невидимым.
Гонки и повторные запуски. Что будет, если это выполнится дважды
одновременно? А если запрос повторится после таймаута? Идемпотентность —
слепое пятно.
Производительность на объёме. Запрос в цикле, полное чтение файла в
память, вложенный проход по массиву. На десяти записях незаметно, на десяти
тысячах — авария.
Часовые пояса и форматы. Локальное время вместо UTC, наивный разбор дат,
сравнение строк вместо дат. Классика, которая всплывает через полгода.
Тесты, проверяющие ничего. Ассерт на то, что функция вернула не null.
Мок, который повторяет реализацию. Тест, который позеленел после ослабления
условия, — худший из возможных.
Выдуманные API. Метод, которого нет; флаг, которого нет; версия
библиотеки, в которой это ещё не появилось. Проверяется сборкой, но только
если сборка вообще запускалась.
Копия вместо переиспользования. Модель не знала про вашу существующую
функцию и написала пятую почти такую же. Каждая будет чиниться отдельно.
Тихая смена поведения соседей. Просили одно, «заодно» поправили другое.
Смотреть надо весь диф, а не только те файлы, о которых шла речь.
Читать построчно всё — не выйдет, объёмы не те. Работает воронка: сначала
дешёвые проверки, отсеивающие большинство, потом дорогое внимание на
оставшееся.
Ниже — места, где цена ошибки несоизмерима с временем на вычитку.
Здесь «код от модели» не отличается от кода стажёра без доступа: доверия
ноль.
DROP, ALTER ... TYPE,Модель, читающая диф, полезна: она не устаёт, не ленится и хорошо ловит
механическое — забытую проверку, несогласованность, пропущенный случай.
Но у неё есть системная слабость: она не знает, чего вы хотели. Она проверяет
код против самого кода, а не против замысла. Пропущенное требование,
неправильно понятая задача, «сделали не то, но качественно» — вне её
досягаемости.
Полезно: ИИ-ревью до человеческого, чтобы человек не тратил внимание на
механику. Бесполезно: ИИ-ревью вместо человеческого.
Ещё один нюанс: агент, который сам писал код, — плохой ревьюер этого же кода.
Он объяснит, почему всё правильно, теми же рассуждениями, которыми это писал.
Свежая сессия без истории заметно честнее.
Форматирование, порядок импортов, кавычки, длина строк. Это работа линтера и
форматтера. Если такое доходит до человека — чините конфиг, а не комментарии.