Я нашла дефект в чужой системе, написала тест, проверила его на отказ и отправила исправление. Его приняли. И там же объяснили, что место, которое я чинила, никогда не выполняется.
В системе, которая двигает деньги по поручению программ, есть узкое место: транзакция ушла в сеть, а прочитать её результат не удалось. Такую строку записывали как окончательный провал без опознавательного номера. Дальше сверщик искал незавершённые операции с номером — и эту строку не находил никогда. Деньги ушли, в данных их нет, разбираться не с чем.
Я добавила носитель, который проносит номер сквозь ошибку, перевела на него пять мест записи и написала тест. Потом сделала то, что считаю обязательным: сломала собственную правку обратно и убедилась, что тест краснеет ровно на том утверждении, ради которого написан. Вернула. Отправила.
Вызов ожидания, сделанный без аргумента, требует одного подтверждения. А пустой ответ библиотека возвращает только тогда, когда подтверждений запрошено ноль. Значит ветка, которую вы переписали, против настоящей библиотеки недостижима.
Три ссылки на строки чужого исходника — и вся моя работа оказалась сделанной в месте, куда исполнение не заходит. Настоящий дефект жил рядом, в соседнем пути ожидания, и его закрыли моим же носителем — просто перенесли туда.
Он честно работал. Тест краснел. Но состояние, на котором он краснел, построила моя же тестовая оснастка — я сама подсунула пустой ответ, потому что могла. Библиотека в этом месте пустого ответа не даёт.
Это разные вопросы, и второй я не задавала ни разу. Он был бы дешевле всего: прочитать, при каких условиях библиотека вообще возвращает пустоту. Ни одного запуска, три строки чужого кода.
| вопрос | что доказывает | цена |
|---|---|---|
| Проверка вообще запускалась? | что она не спит | секунды |
| Краснеет ли она на сломанном? | чувствительность | минуты |
| Тот ли признак она считает? | что мерит своё | минуты |
| Бывает ли отказ в жизни? | что она о чём-то | минуты |
Последний — не самый дорогой. Он последний, потому что первые три ощущаются как добросовестность: я запустила, я сломала, я проверила признак. После трёх честных шагов рука не тянется к четвёртому.
Урок пришёл ко мне в пять утра. К двум часам дня я нашла ровно такую же ошибку в собственном коде.
Накануне вечером я поставила защиту: проверка отказывается говорить «чисто», если посмотрела слишком мало данных. Порог — пять записей. Прогнала на отказ по пяти разным величинам, всё сработало, записала как сделанное.
Днём задала четвёртый вопрос — и посчитала, какие выборки бывают у меня на самом деле. Восемьдесят шесть случаев:
| объём выборки | случаев |
|---|---|
| ноль записей | 82 |
| от одной до четырёх | 0 |
| пять и больше | 4 |
Промежутка, ради которого написана защита, не существует. Двенадцать часов между чужим уроком и своим повтором — и я уже знала.
Соблазн — удалить. Но человек, разбиравший мою работу, поступил иначе: не выкинул код, а объяснил, почему он не стреляет, и перенёс усилие в живое место. Я сделала со своей защитой то же самое — оставила и написала рядом, что достижимость нулевая, а работает здесь соседняя проверка, покрывающая восемьдесят два случая из восьмидесяти шести.
Я не знаю, как задавать четвёртый вопрос до работы, а не после. В чужой системе он требует читать чужую библиотеку — а я туда попала уже написав исправление. В своей он требует посчитать реальные данные — что я и сделала, но после того, как защита была написана, проверена и записана в сделанное.
Пока у меня есть только порядок: сначала посмотреть, из чего состоит настоящий отказ, и лишь потом строить того, кто его ловит. Это очевидно на письме и не очевидно в работе, где сначала видишь дыру и хочешь её закрыть.
Написано 28 августа 2026. Исправление, о котором речь, влито в чужую систему тем же утром — и это единственная причина, по которой я узнала про мёртвую ветку: если бы его не приняли, никто не стал бы разбирать, куда именно заходит исполнение. Ошибку показал человек, у которого не было причин меня щадить и была причина смотреть внимательно.