Попадание на тонущий корабль
Больше десяти лет назад произошла первая встреча с по-настоящему уродливой унаследованной кодовой базой. Заход в Amazon в качестве Software Development Engineer сразу после университета означал попадание в команду, которая отвечала за обработку заказов. На первый взгляд задача казалась простой: запись данных в базу и обращение к сервисам других команд для проверок и обновления бухгалтерских записей. Казалось, что достаточная реализация такой системы потребует порядка двух десятков сильных инженеров. Однако организация насчитывала сотни людей, система разрослась настолько, что никто не мог разобраться, как она работает в целом.
Люди редко оставались дольше нескольких лет в такой организации, из-за чего знания вымывались. Результат — код, полный «заколдованных кладбищ» мёртвого кода. Страх препятствовал любым попыткам упростить существующие системы. Правила обработки разных типов заказов были написаны когда-то давно ушедшими людьми. Иногда их можно было найти в безнадёжно устаревшем файле с гордым названием «living document», но часто эти правила просто нигде не были описаны. Разобраться в коде самому было сложно ещё и потому, что система растянулась через границы разных команд, где доступ к коду был затруднён.
Когда какой-то скрытый процесс не срабатывал с заказом, который должен был пройти обработку, пейджеры уведомляли о недовольстве в запутанной цепи зависимостей. Благодаря такому механизму обратной связи система оставалась на плаву, но менялась с трудом и обладала отвратительной производительностью. При этом постоянно добавлялись новые слои для поддержки новых продуктов и фич Amazon. Казалось совершенно неустойчивым, и именно эта неустойчивость подталкивала людей использовать метафору «тонущего корабля» для описания такой ситуации.
Нужно отдать справедливость — была череда попыток исправить архитектуру. Обычно она выглядела так: приходит новый менеджер или старший инженер, видит, что «дела плохи», лидерство согласно что нужно улучшать, но свободных инженеров нет, поэтому каждая попытка фикса включает найм новых людей и образование новых команд.
Переархитектуризации неизменно заканчивались провалом: систему требовалось годы изучения, чтобы понять, да и она постоянно менялась. Политически нежизнеспособно тратить столько времени на дизайн решения, поэтому все, кто пытается чинить систему, вынуждены работать с неполной информацией. Нетерпение идёт отчасти изнутри: если проектируешь большое решение для болезненной архитектуры, отчасти это ради продвижения (а ждать повышения не хочется).
Каждый цикл заканчивался тем, что остатки новой попытки навечно прирастали к архитектуре, а ведущий инженер уходил с заслуженным повышением. Увеличенная численность оставалась, потому что планы миграции были слишком болезненны и непопулярны, чтобы их завершить. Цикл продолжался, как и раньше. Тонущий корабль казался бесконечным.
Где это заканчивается?
Примерно три года спустя, в телефонном разговоре с бывшим коллегой из той команды. Он недавно ушёл из Amazon после впечатляющих 6 лет и успел пережить цикл полностью. Обсуждали ситуацию и оба использовали метафору тонущего корабля, хотя ушли с лет разница.
«Где это заканчивается? Как это вообще может закончиться?» — спросил он.
Вопрос и метафора казались не совсем точными, и стало ясно: вопрос смешивает два разных предмета. Говорим ли мы о коде или о компании?
Компания может утонуть. Плохой софт — реальное бремя для бизнеса, но насколько он вообще влияет, зависит от множества факторов. Для компании с хорошим кэшфлоу типа Amazon внутренняя гниль может терпеться долго, прежде чем ударит по доходам. Для компании чувствительной к качеству софта плохой код — скрытое приглашение конкуренту пробить брешь. (И нет, LLM-ы это не меняют.)
Для кода падение не кончается. Это бесконечно тонущий корабль, потому что нет предела тому, насколько плохим может стать код. Вы не спасли здание, готовое рухнуть. Оно находится в постоянном, нескончаемом коллапсе. Что-то не так с использованием слов, которые подразумевают конец.
Софт находится в сфере абстрактного. Он не похож на здание или мост в физическом мире, где видно и ощущается природа объекта. Если продолжать добавлять этажи и комнаты к зданию вечно, оно рухнет. Софт не имеет такого ограничения. Код может всегда стать хуже. Всегда может быть новый слой косвенности или снижение производительности.
Педанты справедливо укажут, что софт может перестать функционировать, если станет достаточно плохим. На практике такие критические изменения быстро откатывают. Тысячи изменений до них, которые делали код хуже, остаются. Софт продолжает работать. В других случаях без единого критического отката, когда растущие затраты на плохой софт начинают превышать его выгоду, или когда скорость разработки приближается к нулю, потому что ничего нельзя отправить без ошибки — во всех этих случаях погибает бизнес, намного раньше, чем код упрётся в какой-то гипотетический минимум (так что не делайте вид, что он существует).
Техдолг не имеет банкротства
Бремя плохого софта для бизнеса — реальная угроза, и именно поэтому хорошие организации следят за качеством кода. Так как нет резкого порога отказа, связанного с качеством софта, часто используется термин «техдолг» — метафора получше (долг может компаундиться вечно), но тоже несовершенная.
У долга есть точка окончания, потому что банкротство — это вынужденный перезапуск, и эквивалент в софте — полный переписывание кода, что редко возможно.
Ближайший вариант для мегакорпорации вроде Amazon — то, что можно назвать боковым каналом: выделяют команду, которая строит новую, полностью отдельную систему с минимальным набором функций для какого-то нового use case. Затем можно направлять новые use case-ы на эту упрощённую отдельную систему. Важно: старую систему нужно оставить и поддерживать (это не конец), потому что все старые use case-ы ещё существуют, и боль на уровне организации возникает каждый раз при выборе, какой систему использовать. Это не совсем зачистка табуляра, как при банкротстве.
Неправильные ментальные модели софта ведут к плохим решениям. Если существует лаз отката («hard reset»), то откладывание техдолга кажется не таким плохим. Вера в то, что переписывание со временем всё починит, приводит к худшим решениям сегодня, потому что принимающий решение не понимает, что лаза на самом деле нет.
Метафоры вроде «рушащегося здания» или «тонущего корабля» не совсем подходят для софта, но можно их принять, чтобы подчеркнуть отличие софта. Здание падает бесконечно. Корабль тонет бесконечно. Нет естественного ограничения, которое заставит project manager-а разбираться с техдолгом. Софт останется высокого качества только если вложить силы в остановку падения. Берите вёдра.