урок 4 из 16

Починка: найти причину, а не признак

Воспроизводить поломку четырьмя вопросами и сокращать воспроизведение, находить место делением пополам, отличать признак от причины и собирать починку в порядке «красный тест — минимальная правка — проверка руками — запись причины».

17 мин чтения · 4 главы ·4 задания ·домашняя работа

Воспроизведение — половина работы

Пришла жалоба: «отчёт показывает не те суммы». Первое побуждение — открыть код отчёта и начать читать. Второе, с агентом, — описать ему жалобу и попросить починить. Оба ведут к одному результату: правка, про которую неизвестно, помогла ли она.

Починка начинается не с кода, а с воспроизведения. Пока поломка не повторяется у вас по требованию, чинить нечего — и не потому, что нельзя догадаться, а потому, что нечем проверить исправление.

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

Жалоба почти никогда не содержит того, что нужно. Она содержит впечатление. Превратить впечатление в шаги помогают четыре вопроса.

ВопросЗачем он
у когоправа, настройки, роль — половина поломок только у части людей
когдадата, время, что было перед этим, повторяется ли
на каких данныхконкретный документ, номер, период — не «в отчёте», а «в этом»
что именно вместо чегоожидалось 1200, получено 1150 — а не «неправильно»

Четвёртый вопрос — самый важный и самый редко заданный. «Неправильные суммы» — это может быть и ноль вместо числа, и число другого порядка, и число, отличающееся на копейку. Это три разные поломки с тремя разными причинами, и до ответа на этот вопрос вы не знаете, какую из них чините.

Дальше воспроизведение сокращают. Жалоба звучит как «зашёл в раздел, выбрал период, нажал сформировать, открыл вкладку, нажал печать — не те суммы». Половина шагов к делу не относится. Убирайте по одному и проверяйте, повторяется ли: обычно от семи шагов остаётся два, и эти два и есть поломка.

Сокращённое воспроизведение стоит того же, что и полное, а работать с ним в разы легче: меньше мест, куда смотреть, и проще объяснить другому — в том числе агенту.

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

И последнее правило главы, которое экономит больше всего времени: записывайте воспроизведение сразу, как нашли. Через час вы будете помнить его неточно, а «работало, а теперь не работает, и я не помню, что делал» — самый дорогой вид починки из всех.

Сужение: делим пополам

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

весь путь: запрос → расчёт → сохранение → отчётданные на входе верны?данные на выходе верны?до расчёта вернопосле расчёта невернопричина внутри расчёта — сужаем дальшевопрос на каждом шаге один: верно ли здесь? — да или нет
Каждая проверка отсекает половину. Десять шагов хватает, чтобы найти место в тысяче.

Делите путь пополам. Данные проходят через цепочку: пришли, посчитались, сохранились, показались. Вопрос на каждом шаге один: верно ли здесь? Ответ «да» отсекает всё до этого места, ответ «нет» — всё после.

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

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

Инструменты деления простые и все доступны: напечатать значение в подозрительном месте, посмотреть, что в базе, прогнать кусок отдельно с известными данными, заглянуть в журнал. Выбор между ними — вопрос удобства, а не принципа.

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

Про агента здесь важное: сужение можно вести вместе с ним, и это заметно быстрее. Он хорош в том, чтобы по описанию «вот здесь верно, вот здесь неверно» назвать все места, где данные меняются между этими двумя точками. Это механический обход кода, и он делает его быстро и полно.

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

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

Признак и причина

Место найдено. Теперь самое ответственное место починки: отличить признак от причины.

Признак: в отчёте стоит нольправка признака:правка причины:«если ноль — не показывать»«курс не найден — берём вчерашний»жалоба ушла,данные по-прежнему неверныданные верны,и в журнале видно, что курс не пришёлпроверка простая: объясняет ли правка, откуда взялся признак
Правка признака гасит жалобу и оставляет причину. Она вернётся другим признаком.

Разберём на живом примере. В отчёте в колонке «сумма в рублях» стоит ноль. Место нашли: функция пересчёта по курсу возвращает ноль, потому что курс на эту дату не найден.

Правка признака: «если сумма ноль — не показывать строку». Жалоба уходит. Данные по-прежнему неверны, просто их больше не видно, и через месяц кто-то сверит итоги и не сойдётся.

Правка причины: «курс на дату не найден — берём последний известный и помечаем в журнале». Данные верны, и, что важнее, видно, что курс не пришёл, — то есть настоящая беда (обмен курсов сломался) становится заметной.

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

Есть более коварный случай — причина лежит на уровень глубже, чем кажется. Курс не найден, потому что обмен не отработал; обмен не отработал, потому что упал по таймауту; таймаут потому, что чужой сервис отвечает медленно раз в месяц. Где здесь остановиться?

И третье, про агента, потому что здесь его вклад неоднозначен. Агент склонен чинить признак, и это не его недостаток, а следствие постановки: ему говорят «в отчёте ноль, почини», и самый прямой способ убрать ноль — убрать ноль.

Лечится это формулировкой поручения. Не «почини, чтобы не было нуля», а «вот место, где появляется ноль; объясни, откуда он там берётся». Объяснение проверяется, и из него уже видно, где настоящая причина.

Хорошая проверка перед тем, как принять правку: попросить назвать, что именно было не так — одним предложением, без кода. Если предложение получается вида «значение оказывалось нулевым, и мы его теперь скрываем» — перед вами правка признака, и это видно сразу.

Починка целиком

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

ШагЧто делается
1. тест, который падаетпроверка, воспроизводящая поломку — до правки
2. правка причиныминимальная, только то, что относится к делу
3. тест проходити старые тоже — проверка, что не сломали соседнее
4. проверка рукамитот же путь, которым шёл человек из жалобы
5. записьчто было не так, одним предложением

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

Второй шаг — минимальная правка. Соблазн причесать соседний код по дороге велик, особенно когда агент уже предложил. Не стоит: смешав починку с улучшением, вы теряете возможность откатить одно без другого, а если после выкладки что-то пойдёт не так, придётся выбирать между «откатить починку» и «разбираться под нагрузкой».

Замеченное по дороге записывается отдельной задачей. Это не отговорка: записанное действительно делается, а сделанное вместе с починкой — увеличивает риск обоих.

Четвёртый шаг — руками, тем же путём. Тест проверяет то, что вы придумали проверить. Человек шёл другим путём: через свой раздел, со своими правами, на своих данных. Пройти его путь занимает две минуты и ловит то, чего нет ни в одном тесте, — например, что вы починили в одном месте, а тот же расчёт есть и во втором.

Про агента в починке общая раскладка такая.

ШагКто делает
воспроизведениевы: у него нет данных и прав
гипотезы, от чего зависитон предлагает, вы проверяете
сужениевы делите, он ищет между точками
отличить признак от причинывы: спрашиваете объяснение и проверяете его
тест, который падаетон пишет, вы убеждаетесь, что он красный
правкаон пишет, вы читаете
проверка рукамивы: путём человека из жалобы

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

Способ не попасться простой: не принимать правку, пока не можете назвать причину одним предложением. Не «код стал правильным», а «данные приходили без курса, и пересчёт отдавал ноль». Если предложение не складывается — причина не найдена, сколько бы кода ни было написано.

Задания урока

Каждое проверяется сразу: ответ сверяется с эталоном, и на неверный вариант приходит разбор.

  1. Расставьте шаги починки по порядку.средне
  2. «У меня не воспроизводится» — значит, поломки нет.средне
  3. Разложите правки на починку признака и починку причины.средне
  4. Тест на поломку пишут после правки: так понятнее, что проверять.сложно

Практика и материалы по теме курса

Пройти урок с проверкой заданий Курс «Codex: продукты и практика» открыт и бесплатен, прогресс сохраняется.
Открыть курс