Проверка кода, сгенерированного ИИ-ассистентами: какие ошибки повторяются чаще всего и как встроить их отлов в разработку

Проверка кода, сгенерированного ИИ-ассистентами: какие ошибки повторяются чаще всего и как встроить их отлов в разработку

изображение: grok

ИИ-ассистенты заметно снизили стоимость написания кода. Разработчик может за несколько минут получить реализацию функции, набор изменений сразу в нескольких файлах или даже значительную часть новой возможности продукта. Но стоимость проверки этого кода не снизилась автоматически: человеку по-прежнему нужно понять, что именно изменено, соответствует ли решение требованиям и не создаёт ли оно новых дефектов.

Из-за этого меняется баланс всего процесса разработки. Узкое место постепенно перемещается от написания кода к проверке изменений. Поэтому для руководителя разработки важен уже не вопрос, насколько быстро ИИ способен генерировать код, а другой: способен ли весь процесс разработки пропустить через себя возросший поток изменений без такого же роста ошибок, переделок и технического риска.

Главная проблема ИИ-кода — его правдоподобность

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

Типовые ошибки такого кода можно свести к нескольким группам. ИИ может использовать несуществующий или устаревший программный интерфейс, подобрать неподходящую библиотеку или воспроизвести уже небезопасный способ решения задачи. Он может правильно реализовать штатный сценарий, но ошибиться при пустом значении, на границе диапазона, при сбое внешней системы или при неожиданном вводе пользователя. Наконец, отдельная функция может быть написана вполне корректно, но не учитывать устройство всей системы: дублировать существующую логику, обходить принятые ограничения или создавать уязвимость при взаимодействии с другими компонентами.

Такие ошибки опасны именно тем, что далеко не всегда видны при беглом просмотре. Код компилируется, выглядит аккуратно и может успешно проходить простые тесты. Поэтому увеличение объёма сгенерированного кода означает не просто увеличение числа строк, которые необходимо прочитать, — оно увеличивает объём правдоподобного кода, требующего содержательной проверки.

Нельзя масштабировать машинную генерацию только человеческим вниманием

Очевидный ответ — тщательнее проверять код, созданный ИИ. Но именно человеческое внимание в такой модели становится самым дорогим и плохо масштабируемым ресурсом.

Если разработчик начинает производить изменения значительно быстрее, а пропускная способность проверки остаётся прежней, система получает один из двух результатов: либо изменения дольше ждут проверки, либо сама проверка становится более поверхностной. В реальной разработке обычно проявляются оба эффекта.

Поэтому ИИ не устраняет узкое место, а переносит его. Код становится дешевле создать, но доказать его корректность всё ещё нужно.

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

ИИ позволяет масштабировать не только создание кода, но и его проверку

Одних привычных автоматических тестов для этого недостаточно. Нужна полноценная система проверки поведения: модульные тесты для отдельных частей программы, интеграционные — для взаимодействия компонентов и сквозные — для проверки пользовательского сценария от начала до конечного результата.

Здесь ИИ сам становится частью решения. Если раньше создание большого количества сквозных тестов часто считалось слишком дорогим, то теперь ассистенты могут помогать генерировать и их. Сквозной тест обычно проще основной логики приложения, но при этом способен проверить именно конечное поведение системы, а не отдельную функцию в изоляции.

Для критичных участков полезно дополнять обычные тесты мутационным тестированием. Его смысл состоит в том, чтобы намеренно вносить небольшие ошибки в программу и проверять, обнаружит ли их существующий набор тестов. Это позволяет оценить уже не количество тестов и не процент покрытия строк, а способность тестов действительно замечать изменение поведения.

Параллельно должны автоматически работать проверки, которые вообще не требуют человеческого анализа: статический анализ безопасности исходного кода, анализ состава открытого кода и зависимостей, поиск секретов, проверка запрещённых или уязвимых конструкций, а также обязательные правила допуска изменений в основную ветку.

В результате получается простой принцип: машина проверяет формализуемые свойства и поведение программы, человек — её смысл.

Дополнительные проверки не обязательно замедляют выпуск продукта

На первый взгляд такой подход противоречит самой идее ускорения разработки. Чем больше проверок выполняется перед включением изменения в основную ветку, тем больше времени занимает прохождение каждого отдельного изменения.

Но время прохождения одной сборки и время получения качественного результата — не одно и то же.

Ошибка, обнаруженная через несколько минут после написания кода, исправляется разработчиком, который ещё помнит контекст задачи. Та же ошибка после выпуска продукта запускает новый цикл: её нужно обнаружить, локализовать, поставить задачу, восстановить контекст, исправить код, снова проверить изменение, провести повторное тестирование и выпустить новую версию.

Поэтому автоматические проверки могут немного увеличить время одного прохода, но одновременно резко сократить объём повторной работы.

Быстрее написать — ещё не значит быстрее поставить.

Если команда благодаря ИИ начинает закрывать условно в три раза больше задач, но значительная часть последующей работы уходит на исправление дефектов в уже выпущенном коде, реальный рост производительности оказывается намного меньше красивой цифры в отчёте. Считать нужно не количество произведённых изменений, а количество изменений, которые дошли до эксплуатации и не потребовали последующей переделки.

Именно поэтому качество, встроенное непосредственно в процесс разработки, является не противоположностью скорости, а одним из её условий.

ИИ становится новым драйвером РБПО

Здесь развитие ИИ напрямую пересекается с практиками разработки безопасного программного обеспечения — РБПО.

Раньше статический анализ, контроль состава открытого кода, проверка зависимостей, защищённые ветки и обязательные проверки перед включением изменений нередко воспринимались разработчиками прежде всего как дополнительные требования информационной безопасности. То есть как необходимые ограничения, которые приходится выполнять ценой некоторого усложнения процесса. ИИ меняет эту экономику.

Те же самые механизмы начинают решать уже не только задачу безопасности. Они становятся способом автоматически фильтровать растущий поток изменений до того, как на их проверку будет потрачено дорогое человеческое внимание. РБПО из дополнительного защитного контура постепенно превращается в инфраструктуру масштабирования самой разработки.

Поэтому распространение ИИ-ассистентов можно рассматривать как один из драйверов внедрения РБПО в повседневный процесс разработки. Чем больше кода способна производить команда, тем важнее автоматически доказывать его минимально необходимые свойства ещё до включения в продукт.

Такой контур можно выстроить и средствами GitFlic: использовать статический анализ безопасности кода, анализ состава открытого кода, автоматические тесты и другие контрольные проверки, защищать основные ветки и разрешать включение изменений только после выполнения заданных условий и необходимых согласований. При правильной настройке GitFlic такой процесс позволяет покрыть до 90% требований ГОСТ к РБПО и одновременно использовать одни и те же механизмы не только для выполнения требований безопасности, но и для контроля качества растущего потока изменений.

В конечном счёте организации не требуется отдельный процесс для «кода от ИИ». Более полезно вообще отказаться от деления изменений на написанные человеком и машиной.

Значение имеет другое деление: проверенное изменение или непроверенное.

Устойчивое преимущество от ИИ получает не та организация, которая научилась генерировать больше кода, а та, чей процесс разработки способен пропустить через себя больший поток изменений без пропорционального роста дефектов, переделок и технического риска.

Максим Козлов, технический директор GitFlic (входит в “Группу Астра”)

Группа Астра
Автор: Группа Астра
ГК «Астра» (ООО «РусБИТех-Астра») — один из лидеров российской IT-индустрии, ведущий производитель программного обеспечения, в том числе защищенных операционных систем и платформ виртуализации. Разработка флагманского продукта, ОС семейства Astra Linux, ведется с 2008 года. На сегодня в штате компании более 1000 высококвалифицированных разработчиков и специалистов технической поддержки.
Комментарии: