Прогнозування дефектів у коді: де ламається якість
Дефект майже ніколи не виглядає як збій у момент появи. Правка на п'ять рядків проходить рев'ю, зелений набір тестів і реліз, а спливає через кілька ітерацій — у модулі, який формально ніхто не чіпав.
Вартість виправлення дефекту зростає з кожним етапом: у гілці це аналіз залежностей і повторний прогін перевірок, після релізу — відкат, відновлення стану й пошук причини.
Головні втрати виникають не в коді, а в рішеннях про нього. Рев'ю дивиться на зміну ізольовано, статичний аналіз ловить стиль і типові шаблони, тести підтверджують те, що й так було покрито.
Питання «де дефект імовірний просто зараз» залишається без відповіді: зазвичай це ділянки, де зійшлися висока зв'язність, часті правки та слабке покриття.
Прогнозування дефектів у коді закриває саме цю прогалину — модель з AUC-ROC понад 0,85 ранжує файли й модулі за ймовірністю помилки, і увага рев'юерів іде туди, де вона окупається.
Пізнє виявлення помилок б'є по передбачуваності випуску. Регресія після релізу — це не один інцидент, а зсув усього конвеєра: команда починає перестраховуватися, подовжує прогін, додає ручні приймання і гальмує постачання. Чим довше дефект живе непоміченим, тим ширше коло змін, які доведеться переперевіряти разом із ним.
Нижче розбираємо, як влаштована така система: які сигнали вона читає з історії репозиторію, як вбудовується в рев'ю і що показує команді до того, як ризик стане інцидентом.
Що дає модель: вимірюваний ефект на рев'ю та релізах
Ефект моделі вимірюється не відчуттям «стало чистіше», а трьома числами: скільки часу йде на розбір однієї правки, яка частка помилок доходить до користувача і скільки людино-годин з'їдає перевірка коду.
До впровадження ми знімаємо ці показники на вашому репозиторії за зіставний період, після — порівнюємо на тому самому наборі правил і з тим самим складом команди.
Швидкість перевірки правок зростає завдяки пріоритизації. Модель позначає фрагменти, де ймовірність дефекту вища, і рев'юер починає розбір із них, а не читає зміну цілком.
На типових правках час розбору скорочується в півтора-два раза; ефект тримається, поки поріг спрацювання налаштований під ваш стиль коду й не тоне в хибних сигналах.
Раннє виявлення дефектів змінює клас відмов. Підказки надходять на етапі, коли правка ще в гілці: розіменування порожніх значень, необроблені винятки, помилки в межах умов, забуті гілки обробки.
Такий дефект коштує правки в один рядок, а той самий дефект у релізі перетворюється на інцидент із розбором причин і відкатом версії.
Витрати праці на перевірку коду знижуються, але не до нуля — мета в тому, щоб увага команди йшла на логіку та проєктні рішення, а не на механічні пропуски. Частина зауважень формулюється до обговорення, тому розбір починається з готовим списком питань, а не з читання навмання.
Цільовий поріг якості фіксуємо заздалегідь — метрика AUC-ROC не нижче 0,85 на вашому стеку. Якщо на реальних даних він не тримається, модель дообучаємо до заміру ефекту: інакше прогнозування дефектів перетворюється на шум, і підказки просто перестають відкривати.
Варіанти впровадження: конвеєр, рев'ю, ручний прогін
Модель одна, а режимів її використання три — і саме режим визначає, що команда робить із прогнозом.
Автоматичний контроль під час збірки перетворює оцінку на блокувальний гейт, підказки під час рев'ю залишають рішення людині, офлайн-прогін дає звіт по гілці, не впливаючи на загальний конвеєр.
| Варіант | Коли підходить | Обмеження |
|---|---|---|
| Автоматичний контроль під час збірки | Регулярні релізи, потрібен жорсткий поріг: збірка падає, якщо ймовірність дефекту в змінених файлах вища за задану | Хибні спрацювання гальмують постачання, а за надто високого порогу зміни починають протягувати в обхід |
| Підказки під час рев'ю | Рев'юери перевантажені, важливо розставити пріоритет перевірки й не витрачати увагу на очевидні ділянки | Нічого не блокує: ефект тримається на дисципліні рев'юерів, а не на процесі |
| Офлайн-прогін гілки | Ризиковані зміни, великий рефакторинг, аудит перед злиттям | Запуск на вимогу — у звичайному потоці захисту від пропущеного дефекту немає |
Загальні обмеження
Модель спирається на історію репозиторію: на нових модулях і рідкісних типах змін упевненість нижча, а на масовому рефакторингу зростає частка хибних спрацювань.
Поріг добираємо не за загальною метрикою якості, а за часткою хибних спрацювань на ваших даних, тому перший місяць режим працює в спостереженні: рахуємо точність, дивимося підтверджені й відхилені спрацювання, і лише потім вмикаємо блокування.
Етапи впровадження: від аудиту репозиторію до передачі
Порядок робіт тут жорсткий, і він не збігається з порядком «поставили модель — подивилися на метрику».
Прогнозування дефектів спирається на історію правок: якщо розмітка зібрана з випадкових змін, шумні злиття потрапляють у навчальну вибірку й якість упирається в стелю, яку потім не підняти жодним налаштуванням. Тому починаємо з даних і перевірок, а пороги виставляємо останніми.
- Аудит репозиторію — рахуємо глибину історії, частку злиттів і автоматичних правок, зв'язність із трекером задач, доступність гілок за потрібний період. На виході — карта того, на яких файлах і авторах даних достатньо, а де ознак не вистачить.
- Розмітка історії правок — фіксуємо правило: дефектом вважаємо зміну, яку пізніше виправляли окремою правкою або задачею з ознакою помилки. Автоформат, перейменування й масові заміни виключаємо, інакше модель вчиться на косметиці.
- Схема перевірок — збираємо ознаки зміни та контексту: розмір і розкид правки по файлах, щільність минулих виправлень, свіжість модуля, покриття тестами. Валідацію ріжемо за часом, а не випадково, — інакше модель підглядає майбутнє.
- Навчання й контроль якості — модель вчиться на минулих релізах і перевіряється на пізніших. Цільовий орієнтир — розділення дефектних і чистих правок на рівні понад 0,85 за площею під кривою, за окремого контролю частки пропусків.
- Налаштування порогів спрацювання — вибираємо дві межі: м'яка дає попередження в рев'ю, жорстка блокує злиття. Пороги добираємо за числом хибних спрацювань на сотню правок, щоб перевірка не гальмувала роботу команди.
- Приймання — прогін на правках останніх тижнів, звірка з ручним рев'ю та розбір розбіжностей. Дивимося, які дефекти ловимо, які втрачаємо і чому.
- Передача — доступи, регламент перенавчання на нових даних, документація з розмітки та порогів. Команда замовника може змінювати правила без нас.
Що залишається в репозиторії після впровадження
Впровадження закінчується не показом працюючої моделі, а набором артефактів у репозиторії замовника. Усе, що впливає на поведінку системи, лежить у контролі версій поруч із кодом — конфігурації, схеми перевірок, звіти про якість.
Тоді результат відтворюваний без нас: нова команда читає документацію й продовжує з того самого місця.
- Конфігурація перевірок — поріг спрацювання, охоплення шляхів, винятки для згенерованого коду й словників. Змінюється правкою в репозиторії, без перезбірки моделі.
- Схема інтеграції — де вбудовується перевірка: локальний прогін перед надсиланням змін, серверна перевірка в запиті на злиття, режим «лише попередження» на період обкатування.
- Звіт про якість моделі — метрики на відкладеній вибірці (AUC-ROC, повнота й точність на робочому порозі), розбивка за типами дефектів і компонентами, перелік відомих обмежень.
- Набір підтверджених спрацювань — історія прийнятих і відхилених зауважень, на якій модель дообучається всередині контуру замовника, без вивантаження коду назовні.
- Документація — опис підготовки даних і ознак, порядок дообучення та перевірки якості, інструкція з локального запуску.
- Регламент супроводу — періодичність перегляду порогу, порядок розбору хибних спрацювань, точки контролю дрейфу й план відкату на попередню версію моделі.
Кейс: як знизилася частка дефектів до релізу
Завдання було одне: зробити так, щоб про дефекти дізнавалися на рев'ю, а не після релізу. До старту ми зняли базові метрики на історії проєкту за кілька місяців — це дало точку відліку, а не відчуття «стало краще».
Дивилися чотири величини: частка дефектів, знайдених до релізу, повнота виявлення на відкладеній вибірці, число хибних спрацювань на сто перевірок і години команди, що йдуть на ручне рев'ю за спринт.
| Метрика | До впровадження | Після |
|---|---|---|
| Дефекти, знайдені до релізу | 44% | 79% |
| Повнота виявлення | 0,61 | 0,87 |
| Хибні спрацювання на 100 перевірок | 34 | 8 |
| Години на ручне рев'ю за спринт | 61 | 37 |
Завдяки чому отримано результат
Основний приріст дала не сама модель, а ознаки з історії репозиторію: частота правок у файлі, розмір зміни, зв'язність модулів, авторство й результат минулих перевірок.
Модель навчена на розмітці реальних дефектів і налаштована так, щоб сигнал надходив у Merge Request до апруву — через GitLab та його перевірки в конвеєрі збірки.
Окремо ми дібрали поріг: зниження хибних спрацювань з 34 до 8 на сто перевірок прибрало головну причину, через яку такі системи вимикають за місяць.
Звільнені години рев'юери витрачають на архітектурні обговорення та складні зміни, а не на вичитку однотипних правок. Модель дообучається на підтверджених і відхилених спрацюваннях, тому повнота виявлення не деградує зі зростанням кодової бази.
Чим навчена модель відрізняється від статичних правил?
Статичні правила — умови, написані руками: «файл довший за N рядків», «цикломатична складність вища за поріг», «код змінено, тести не зачеплено».
Так працює, наприклад, SonarQube: той самий набір перевірок застосовується до кожної правки, а пороги виставлені експертом під стан репозиторію на момент налаштування.
Правила не змінюються разом із проєктом. Поріг складності, розумний для моноліту, дає потік хибних спрацювань на розбитій на модулі системі; стиль команди зміщується, і перевірка, яка ловила справжні дефекти, починає спрацьовувати на рефакторингах. Попередження перестають читати — сигнал зникає.
Модель вчиться на історії правок конкретного репозиторію. Мітка береться звідти ж: правка, після якої в тій самій ділянці коду незабаром ішов виправний коміт, вважається дефектною.
Ознаки — розмір зміни, число зачеплених файлів, частота правок модуля, наявність тестів поруч зі зміненим кодом.
На виході — ймовірність дефекту для кожної правки й налаштовуваний поріг в одному місці. Перед релізом поріг піднімають, і на перевірку йдуть верхні 5-10% змін за ризиком; у звичайному режимі опускають і дивляться ширше. У набору правил такої ручки немає: перевірка або спрацьовує, або ні.
Різниця видна в часі: правила застарівають мовчки, модель дообучається на свіжій історії, а якість вимірюється на відкладеній вибірці — AUC-ROC від 0,85 на даних самого замовника. Падіння метрики помітно раніше, ніж попередження перестануть читати.
Одне не скасовує друге: правила залишаються швидким фільтром і частиною ознак, модель розставляє пріоритети.
Технічні сумніви: якість розмітки та хибні спрацювання
Розмітка надходить із різних джерел: правила статичного аналізу, історія інцидентів, правки рев'юерів — і помітна частина прикладів суперечить сама собі.
Один рев'юер позначає знахідку як критичну, інший закриває її мовчки, і модель вчиться на цій розбіжності, відтворюючи її вже в прогнозах.
Тому до навчання ми зводимо розмітку до єдиного регламенту: опис класів, спірні випадки в окрему категорію, перетин вибірок між розмітниками й замір їхньої узгодженості.
Друге питання — довіра до цифр. Метрики рахуємо на відкладеному зрізі, який не брав участі в навчанні, і окремо фіксуємо рівень хибних спрацювань на кожну сотню знахідок, бо саме шум у звітах визначає, чи користуватимуться ними.
Третій — контроль дрейфу якості: стиль коду й правила рев'ю змінюються, тому розподіл ознак і частку підтверджених знахідок звіряємо регулярно, а не один раз на прийманні. Стек і правила з SonarQube підключаємо як джерело сигналу, а не як готову відповідь.
Як перевірити якість моделі, якщо розмітка неоднорідна?
Тримаємо контрольну вибірку, розмічену двома незалежними інженерами, і рахуємо узгодженість між ними — це верхня межа, вище якої модель у принципі не підніметься. Конфліктні приклади виносимо на арбітраж і не пускаємо в навчання до рішення.
Метрика рахується лише на відкладеній частині, інакше отримуємо красиву цифру, яка розсипається на першому ж релізі.
Який рівень хибних спрацювань прийнятний?
Поріг задаємо не «в середньому», а за ціною помилки в конкретному процесі: пропущений дефект на критичному модулі й зайва позначка в тестах коштують різного. Орієнтир, який узгоджуємо на старті — частка підтверджених знахідок і передбачуване число хибних на сотню.
Якщо звіт перетворюється на шум, команда перестає його відкривати, і система вмирає раніше, ніж окупиться.
Що буде, коли стиль коду й розмітка зміняться?
Закладаємо моніторинг дрейфу з першого дня: стежимо за розподілом вхідних ознак і часткою знахідок, які розробники підтверджують.
За відхилення від базової лінії запускаємо перенавчання на свіжому зрізі й звіряємо метрики з попередньою версією — відкат на минулу модель залишається доступним у будь-який момент.
Обговоримо задачу: що потрібно від вас для старту
Щоб повернутися з оцінкою термінів і планом робіт за вашим репозиторієм, нам потрібні ввідні нижче. Прогнозування дефектів у коді будується на тому, як дефекти виникали раніше, — тому спираємося на вашу історію, а не на загальні правила з документації.
- Зріз репозиторію або доступ на читання: історія правок за рік-два, гілки, теги релізів. На короткій історії модель не відрізняє небезпечну зміну від рутинної.
- Журнал інцидентів і трекер задач зі зв'язкою «правка — дефект — виправлення». Це основа розмітки: без неї вчити систему нема на чому.
- Звіти конвеєра збірки й тестів: які перевірки падали, де ламалося частіше, скільки тривала збірка.
- Ваше визначення дефекту й критичні класи помилок: обробка винятків, робота з ресурсами, межі значень, конкурентний доступ.
- Поточний процес рев'ю: скільки правок на тиждень, хто їх дивиться, скільки часу проходить до виявлення помилки.
- Обмеження щодо даних і доступів: що не можна виносити за периметр, де допустимо навчати модель, хто бачить звіти.
- Критерії приймання: за якою метрикою вважаємо результат досягнутим і куди вбудовуємо підказки — до коміту або коментарем до запиту на злиття.
Із цим набором ми повертаємося з планом: схема розмітки, склад ознак, точки інтеграції та протокол приймання на відкладеній вибірці. Опишіть задачу й надішліть доступ — назвемо терміни й обсяг робіт.







