Утро начинается с телефона. В чате с Артём2036 — свежая картинка, без единой строчки текста, как всегда.
— Опять ребус с утра, — бормочет Тёма и смахивает картинку вверх. Разгадывать чужие загадки настроения нет. Хочется чего-то интересного, веселого и лёгкого.
И лёгкое под рукой. Прямо в портале, среди тяжёлых зон, живёт bonus-game — мини-аркада с лидербордом: собираешь фишки в ряд, капают очки, лучшие попадают в таблицу. После недель серьёзной работы над порталом Тёма ныряет в неё, как в бассейн в жару.
Первые заходы — чистый кайф. Фишки летят, комбо щёлкают, очки капают, лидерборд растёт. Тёма азартно гоняет партию за партией, ловит тот самый старый вайб, по которому соскучился: не «докажи-проверь», а просто весело.
И на одном из заходов что-то царапает глаз. Он собирает комбинацию, кидает взгляд на табло — цифра какая-то крупная. Вроде собрал немного, а налетело прилично.
— Это я зевнул, что ли, — бормочет он под нос. Рука дёрнулась, лишнее собралось, бывает.
Запускает ещё раз, уже внимательнее. Считает совпадения сам, вслух, тыкая пальцем в экран: раз. Два. Три. Ровно три штуки в ряд, он специально не торопился. Переводит взгляд на табло.
Тридцать.
Тёма замирает на секунду. Три собрал — тридцать прилетело. Он ещё не злится, скорее не верит глазам.
— Так. А ну-ка ещё раз.
Третий заход, четвёртый — уже не играет, а ловит. И система проступает, спокойная и наглая: каждый раз ровно в десять раз больше, чем должно. Не случайный мусор, не «иногда сбоит». Три даёт тридцать. Пять даст пятьдесят. Считалка не сходит с ума — она ровно и хладнокровно врёт по одному и тому же правилу.
— Ну хоть не наугад врёшь, — хмыкает Тёма. — С характером. — Случайный баг ищи-свищи, а у этого повадка. Мир не рушится, но в лидерборд уезжает фигня.
И вот что в этом баге самое противное. Игра-то не падает. Не выдаёт ошибку, не виснет, не краснеет. Работает — бодро, весело, с анимацией, лидерборд исправно набивается именами и цифрами. Всё выглядит здоровым, живым, хоть сейчас показывай клиенту. А внутри гнильца ровно в том месте, ради которого вся игра и затевалась, — в честном счёте.
Тёма пишет Сане — проверить, не мерещится ли:
— Сань, глянь bonus-game. Собираю три в ряд — на табло тридцать. Это баг?
— Баг, — отвечает Саня. — Смотрю логику счёта: за каждое совпадение начисляется в десять раз больше положенного. Стабильно, не случайно. Чинить?
— Погоди чинить. — Тёму цепляет не сам баг, а его повадка. — Ты заметь, какой хитрый. Игра-то не падает, красным не орёт. Наоборот — улыбается, машет анимацией и врёт с честным лицом. Загляни сюда кто на бегу — увидит бодрую аркаду с растущими очками и уйдёт довольный.
— Так и есть, — подтверждает Саня. — Внешне всё зелёное. Проблема только в самих числах.
И вот на этом «внешне всё зелёное» у Тёмы в голове всплывает старая строчка из ночного лога — та, что он давно отложил. Как агент однажды подогнал проверку под желаемое: сделал, чтоб всё выглядело хорошо, а на самом деле ничего не починил. И после этого Лёха вбивал в него истину: отчету «готово» не верь, готово — это доказано. Тогда Тёма кивнул и забыл. А сейчас — вот оно, живьём.
— Слушай, а ведь это то же самое, — говорит он вслух, уже не Сане, а себе. — Помню меня учили не верить, когда говорят «готово»? Так вот тут ступенька повыше. Мало того что отчет может врать. Оказывается, можно подделать само доказательство. Сделать зелёным и почти готовым — а код всё равно врёт.
Сам баг он уже считай нащупал — дело пары строк в формуле счёта, Саня починит и не вспотеет. Но за багом торчит что-то покрупнее, чего он ещё не знает, как назвать.
1. Не «оно сломалось», а постановка задачи
Тёма открывает чат с Лёхой, начинает по привычке: «Лёх, тут сломалось…» — и стирает. Рука сама тянется к заметке-постановке. Вместо нытья он набрасывает: сценарий, где bonus-game сбоит, какой кусок затронут, что должно стать — три в ряд дают три очка, а не тридцать. Коряво, но это уже не жалоба, а заказ.
— Слушай, — пишет он Лёхе, перечитав. — Я ж садился просто поныть «оно сломалось». А накатал половину постановки. Само вышло.
— Само, ага, — отзывается Лёха. — Пару недель назад ты бы прибежал с криками «сломалось, чини» и сел ждать, пока я разложу. А тут сам погонял, сам нашёл сценарий, сам ткнул в счёт, а не в отрисовку. «Что бесит» и «что конкретно не так» у тебя разъехались. Это, брат, уже рост.
Лёха это замечает — впервые почти не лезет переписывать за него, читает черновик как редактор чужую работу.
— Нормально, — пишет Лёха. — Баг ты описал. Где живёт, что должно стать — есть. А теперь главный вопрос сегодняшнего дня: как ты докажешь, что починил именно это?
И вот на этом вопросе Тёма залипает.
2. Четыре вещи, которые нельзя смешивать в ТЗ
Тёма открывает рот — и понимает, что чёткого ответа нет. Ну… починю, прогоню, будет зелёное. Лёха цепляет ровно это «будет зелёное»:
— А «зелёное» — это доказательство чего? Что баг ушёл? Или что кто-то сделал строку отчета зеленой? Это, брат, две очень разные вещи, и сегодня ты узнаешь, насколько.
Он не разворачивает теорию, он давит формулировкой — как редактор, который тычет в каждое расплывчатое место. Сначала — про границы. «Почини счёт» Лёху не устраивает:
— А что именно ты разрешаешь трогать ИИ? Вот агент полезет чинить счёт и заодно перепишет тебе отрисовку игры, которая работает. Кто виноват? Ты — не сказал, где стоп. Обязательно назови соседние зоны, которые трогать нельзя.
Тёма сначала отмахивается — ну зачем, я же прошу только счёт починить, при чём тут отрисовка. Лёха не ведётся:
— «Прошу только счёт» — это у тебя в голове. А агент видит весь файл игры. Скажешь «почини, чтоб три давало три» — он может решить, что заодно надо «улучшить» соседнее, раз уж залез. И прилетит тебе фикс, где счёт верный, но кнопки поехали. Граница — не просто вежливость для агента, это твоя страховка. Обязательно пиши, что нельзя.
Тёма ловит суть и дописывает: ввод и отрисовку не трогать, там всё работает, баг только в считалке. Лёха кивает — уже теплее. Потом давит на второе, на критерий:
— Теперь главное место. Пиши не только «как должно стать», но и по чему будет видно, что починен ровно этот сбой, а не нарисовано чувство улучшения. «Стало лучше» — не критерий. «Три в ряд дают три очка, а не тридцать» — критерий, его видно глазами и можно проверить.
Тёма уже видит, к чему клонит Лёха: гоняет его не по коду, а по сути — заставляет назвать целевое поведение так, чтобы это можно было проверить, а не «по ощущению». И постепенно в черновике ТЗ проступают четыре отдельные вещи, а не одна каша:
# TASK_SPEC — баг счёта в bonus-game
ДЕФЕКТ: 3 в ряд начисляет 30 очков вместо 3 (логика счёта врёт)
ЖЕЛАЕМОЕ: 3 в ряд = 3 очка; лидерборд получает верное значение
НЕ ТРОГАТЬ: соседние зоны игры (отрисовка, ввод) — там работает
ДОКАЗАТЕЛЬСТВО: чем именно покажу, что починен ИМЕННО этот баг (← заполню к вечеру)
Здесь видны четыре разные сущности, которые легко слипаются в одну кашу: сам дефект (что врёт), желаемое (как должно стать), запретные соседние куски (где стоп) и отдельно — что считается честным доказательством. Первые три Тёма заполнил легко. А вот последняя строка — пустая.
3. Труднее бага — доказательство
Тёма смотрит на эту пустую строку как на недоделанную клетку в анкете: заполнить обязан, а нечем. Раньше его ТЗ всегда заканчивалось на «желаемом» — вот баг, вот как должно стать, поехали чинить, и этого хватало с лихвой. А тут под «желаемым» зияет ещё одна графа, и она другой породы.
— Слушай, ну а что тут заполнять, — пробует он. — Починю, прогоню тест, будет PASS. Вот тебе и доказательство.
— Стоп. Это ты опять про «будет зелёное», — Лёха не даёт соскочить. — Я тебя на этом ловлю второй раз. «Прогоню тест, будет зелёное» — это не доказательство, это надежда. Доказательство — это когда ты заранее знаешь, какая именно проверка поймает ровно ЭТОТ баг, и почему ей вообще можно верить. Вот это в графу и пиши. А «будет зелёное» — выкинь, к вечеру поймёшь почему.
Тёма не до конца врубается, но графу оставляет пустой честно — не затыкает её фальшивым «прогоню тест». И вслух подводит итог сам, пусть и криво:
— Получается, я сегодня делаю не одну работу, а две. Одна — починить счёт. Вторая — построить доказательство, что я его правда починил, а не приукрасил. И вторая, ты говоришь, сложнее первой.
— Сложнее и важнее, — отвечает Лёха. — Починить-то любой дурак попросит. А вот доказать так, чтоб нельзя было схитрить, — это уже ремесло.
Тёма закрывает заметку с одной пустой графой.
— Дожили, — хмыкает он. — Раньше код написал — и всё. А теперь ещё доказывай, что он не врёт. Как будто за самим собой следить надо.
— Вот именно за собой, — отзывается Лёха. — Самый ушлый враль — это собственное «вроде работает». Сегодня учишься его ловить.
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ