Steven
Steven6 мин. чтения

Анатомия доведения ПО до совершенства: как код-ревью поймало то, что не смогли тесты

На протяжении всей серии 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
Надёжность