Каждое переписывание должно было стать последним

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

Я ошибся три раза подряд, каждый раз с полной уверенностью. То, что я ошибался, раздражало. Но говорить я на самом деле хочу о полной уверенности, потому что это было одно и то же повторяющееся ощущение, и я ни разу не распознал его как предупреждение.

«На этот раз всё правильно»

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

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

Почему переписывание всегда выглядит лучше

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

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

Цена, которую я продолжал платить

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

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

То, что лежит в основе: преждевременная абстракция

Настоящим двигателем всей этой перестройки была ошибка в том, как я думал о дизайне. Я продолжал переписывать, потому что продолжал пытаться найти правильную структуру прежде, чем по-настоящему понимал задачу. Я относился к правильной абстракции как к чему-то, что я могу сесть и спроектировать верно заранее, будь я только достаточно умён.

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

Когда переписывание действительно того стоит

Я не хочу утверждать, что переписывания всегда неправильны. Иногда дизайн искренне не может растянуться туда, куда тебе нужно его довести, и эволюционировать его на месте обошлось бы дороже, чем начать заново. Различие, которое я в конце концов научился проводить, касается источника порыва.

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

Решение: гни на месте, пока действительно не сможешь

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

Бóльшую часть времени дискомфорт, который заставляет тебя хотеть начать заново, — это информация, а не приговор. Это код говорит тебе, где ему больно — и это ровно то знание, которое ты выбросил бы, перестраивая с нуля.

Уверенность и была подсказкой

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

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

— Никаких сигналов, никакой доходности, не инвестиционный совет.