Steven
Steven5 хв читання

Анатомія доведення ПЗ до досконалості: як код-рев'ю зловило те, що не змогли тести

Упродовж усієї серії GeekBye v2 повторюється те саме: виправлення проходить кожен тест на машині розробника, а потім код-рев'ю доводить, що воно б не спрацювало майже ні в кого. Ось робочий процес за дев'ятьма релізами — ворота рев'ю, відлови на етапі виправлення і дисципліна «протестуй до відвантаження», яка перетворює «у мене працює» на «працює».

Інженерія
Процес
Код-рев'ю
Релізи GeekBye
Анатомія доведення ПЗ до досконалості: як код-рев'ю зловило те, що не змогли тести

За кілька тижнів GeekBye випустило дев'ять релізів — з v2.0.0 по v2.0.11 — і ця серія розповіла історію кожного з них. Прочитайте їх разом, і випливає патерн цікавіший за будь-який окремий баг: знову і знову виправлення проходило кожен тест на машині розробника, а код-рев'ю доводило, що воно б не спрацювало майже в усіх інших.

Цей зазор — між «у мене працює» і «працює» — і є тим місцем, де насправді живе надійність. Ось робочий процес, який його закриває, і покажчик на кожен реліз, який він створив.

Патерн: зелені тести, неправильна відповідь

Ось три найнаочніші випадки із серії, бо вони роблять абстрактне конкретним.

  • У виправленні захоплення на кількох моніторах (v2.0.10) перша реалізація прив'язувала захоплення екрана до вікна-оверлея застосунку. Воно пройшло тестування — на машині розробника з одним монітором. Рев'ю розсудило, де цей оверлей насправді живе (на основному дисплеї, завжди, якщо тільки ви фізично його не перетягнете) і довело, що «виправлення» розв'язалося б назад на неправильний монітор майже в кожного реального користувача. Правильний якір — курсор — вийшов із цього міркування, а не з прогону тесту.
  • У релізі з резервним каналом при блокуванні WebSocket (v2.0.8) рев'ю виявило, що саме той 403, який повертає блокуючий проксі, класифікувався як фатальна помилка автентифікації — тож резервний канал, заради запуску якого функція й існувала, ніколи не міг спрацювати. Функція б відвантажилася, пройшла тести щасливого шляху і не зробила нічого для своєї справжньої аудиторії.
  • У виправленні тайм-ауту простою (v2.0.9) перша версія ставила позначку годинника «ще живий» усередині шляху коду, який частина транскриптів законно пропускає — репліки іншого співрозмовника. Рев'ю спіймало, що майбутня зміна могла б тихо знову ввести рівно той баг, який лагодили, і позначку перенесли в безумовне місце, з тестом, який її там утримає.

Жоден із них не був спійманий запуском коду. Усі вони були спіймані рецензентом, який міркує про те, чому код працює — і знаходить випадок, де він не працює.

Три частини воріт

Робочий процес за серією не мудрований. Це три звички, застосовувані без винятків.

1. Рев'ю міркує про коректність, а не просто запускає код. Тест, що проходить, доводить, що код працює для випадку, про який ви подумали. Рев'ю — це друга, змагальна модель системи, яка питає про який випадок ви не подумали? — другий монітор, корпоративний проксі, транскрипт, що пропускає гілку, клієнт на одну версію позаду. Крок рев'ю в цій серії часто був незалежним рецензентом-агентом, якому доручали спростувати виправлення, а не благословити його. У цій рамці весь сенс: рецензент, який намагається зламати ваше міркування, знаходить діру, повз яку рецензент, що намагається його схвалити, прослизає поглядом.

2. Кожне виправлення поведінки відвантажується з тестом, що пришпилює точний збій. Не тестом, що функція працює — тестом, що цей конкретний баг мертвий. 403 від заблокованого проксі має провалитися в резервний канал; справжній 403 автентифікації — ні. Годинник активності має поставити позначку на транскрипті, який пропускає атрибуцію. Ці тести існують, аби баг не зміг тихо повернутися за пів року, коли хтось рефакторитиме поруч — збій прибитий до підлоги.

3. Збірка нотаризується і перевіряється до відвантаження. Кілька із цих виправлень пройшли від діагнозу до підписаного, нотаризованого, автооновлюваного релізу за один день. Ця швидкість безпечна лише тому, що ворота дисципліновані: діагностика доводить першопричину (реліз із дозволом на мікрофон відвантажив свою діагностику першою), тест пришпилює виправлення, рев'ю спростовує міркування, і лише тоді виходить справжня нотаризована збірка. Строгість — це те, що робить швидкість безпечною, а не те, що з нею розмінюється.

Чому для AI-застосунку це важливіше

Є причина, чому ця дисципліна не підлягає обговоренню саме для інструмента на кшталт GeekBye. Кілька найгидкіших багів у серії були тихо-неправильними, а не гучними падіннями: скриншот, що згодував ШІ неправильний монітор (v2.0.10), транскрипція, зміщена до сміттєвих термінів, так що «speak» вийшло як ім'я (v2.0.11), асистент, що відповідає в неправильному режимі без способу це побачити (v2.0.3 + v2.0.5). Коли ваш застосунок згодовує контекст моделі, неправильний вхід видає впевнено неправильний вихід і ніде жодної помилки. Не можна витестувати вихід зі збоїв, які не кидають винятків. З них треба виміркувати — а рівно для цього й потрібні ворота рев'ю.

Серія, по порядку

Кожен із них — самодостатній розбір одного релізу. Прочитані від початку до кінця, вони — анатомія переведення продукту з «працює» у «заслуговує на довіру».

  1. Чого насправді варта версія 2: 206 комітів чесних станів — v2.0.0. Фундамент: ніколи не показуй стан, який неправда.
  2. День, коли наш застосунок задудосив сам себе — v2.0.1 + v2.0.4. Стартовий затор завантажень, що розтоптав наш власний бекенд, і драбина живучості, яку він змусив.
  3. Спокійне ПЗ: виправлення мерехтіння і чип режиму відповіді — v2.0.3 + v2.0.5. Релізи без функцій, що купували довіру по одній деталі за раз.
  4. Ваш застосунок на Mac забуває доступ до мікрофона за кожного запуску — v2.0.6. macOS App Translocation і відвантаження діагностики до виправлення.
  5. Одна CSS-змінна, п'ять раундів рев'ю і тулчейн Swift, який збрехав — v2.0.7. Рівномірна напівпрозорість і бінарник, що змінив розмір, бо документація розійшлася зі скриптом-енфорсером.
  6. Жива транскрипція, коли фаєрвол блокує WebSocket — v2.0.8. Резервний канал на чистому HTTPS і 403, який сховав би його від нього самого.
  7. Чому ваш AI-нотатник перестає записувати посеред зустрічі — v2.0.9. Таймер простою, що чув лише вас, і падіння, яке могло заблокувати ваш робочий стіл.
  8. Чому запис екрана захоплює не той монітор — v2.0.10. Баг неправильного дисплея і виправлення, яке пройшло на одному моніторі і провалилося б на двох.
  9. Чому AI-транскрипція недочуває технічні терміни — v2.0.11. Зміщення мовлення до вашого словника — і регресія, яка зробила гірше, перш ніж стало краще.

Висновок

Досконалість — не стан, якого досягають; це ворота, які тримають. Дев'ять релізів і ті самі три питання за кожного: про який випадок ти не подумав, чи пришпилений точний збій тестом і чи вийшла насправді справжня підписана збірка? Ніщо з цього не гламурне. Усе це — причина, чому GeekBye v2 відчувається спокійним. Якщо ти будуєш ПЗ — AI чи інше — переносна частина не в якомусь одному виправленні. Вона у звичці ставитися до зеленого набору тестів як до початку суперечки, а не її кінця.

Кожен реліз вище доступний через автооновлення. Про продукт, у який складаються ці виправлення, дивись що нового в GeekBye v2.

Схожі статті

Ваш застосунок для Mac отримує доступ до мікрофона — і забуває його при кожному запуску
Steven
Steven5 хв читання

Ваш застосунок для Mac отримує доступ до мікрофона — і забуває його при кожному запуску

GeekBye попросив доступ до мікрофона, ви його надали, і все запрацювало. Наступний запуск: доступу немає. А в Системних параметрах → Мікрофон застосунок узагалі не з’явився. Винуватцем виявилася функція безпеки macOS, що тихо запускає застосунок зі шляху, який зникає — ось діагноз і виправлення в одне натискання.

macOS
Дозволи
Інженерія
Одна CSS-змінна, п'ять раундів рев'ю та ланцюжок інструментів Swift, що збрехав
Steven
Steven6 хв читання

Одна CSS-змінна, п'ять раундів рев'ю та ланцюжок інструментів Swift, що збрехав

GeekBye v2.0.7 зробив увесь оверлей регульовано напівпрозорим — що звучить як однорядкова зміна CSS і абсолютно нею не було. Справжня історія — про те, що виловило код-рев'ю: дві поверхні, які відмовлялися згасати, панель запису, що виглядала неправильно за тієї самої прозорості, і скомпільований бінарник, який стрибнув на 672 байти, бо наша власна документація підказала рецензенту неправильну версію Swift.

Інженерія
Дизайн
Збірка
Перевірка безпеки, через яку застосунок стало неможливо закрити
Steven
Steven5 хв читання

Перевірка безпеки, через яку застосунок стало неможливо закрити

Автооновлення виявилося найважчою функцією, яку ми будь-коли випускали, — шість релізів за чотири дні, щоб воно перестало ламати застосунок. Найгіршу ваду ми внесли самі, намагаючись бути обережними: 500-мілісекундна «захисна» перевірка, що перетворювала невдале оновлення на процес, який буквально неможливо було закрити.

Інженерія
Electron
Надійність