Смерть за 45 минут: как годы без рефакторинга ставят бизнес на колени
Вступление
Есть компании, в которых технический долг признают проблемой. Есть компании, в которых технический долг признают, но откладывают.
А есть компании, где слово «рефакторинг» звучит почти неприлично. Как будто инженер, который просит неделю на стабилизацию, не заботится о бизнесе. Как будто он не видит графики роста. Как будто он не понимает, что «сейчас нельзя останавливаться».
В таких компаниях спринты годами забиты только бизнесовыми задачами. Новый экран. Новый флоу. Новый рынок. Новая интеграция. Новый онбординг. Новый эксперимент. Новый баннер. Новый способ показать пользователю ещё один способ сделать то, что вчера уже работало.
И всё это выглядит как развитие. До первого вечера, когда приложение перестаёт запускаться.
Когда фасад красивее фундамента
Снаружи всё обычно выглядит отлично.
На общих встречах показывают рост. Пользователей стало больше. Транзакций стало больше. Команда стала больше. Продукт выходит в новые страны, новые сегменты, новые вертикали. На слайдах всё уверенно ползёт вверх.
Внутри в это же время происходит другое.
Главный экран уже переписан три раза, но старые куски всё ещё живут где-то рядом. Новый флоу включается через feature flag, старый флоу выключить нельзя, потому что на нём сидит часть пользователей. Третий флоу когда-то делали «временно для эксперимента», но эксперимент победил, а временный код стал частью архитектуры.
Сборка занимает сорок минут. Локально всё поднимается только у двух людей. Автотесты есть, но их никто не запускает перед релизом, потому что «они всё равно красные». Мониторинг показывает не проблему, а настроение инфраструктуры. Документация устарела настолько, что по ней проще изучать археологию продукта, чем текущую систему. Но бизнес этого не видит. Для бизнеса есть экран, кнопка, метрика, конверсия и дедлайн. Если пользователь нажал кнопку — значит, система работает.
Инженеры знают, что это не так. Но инженеры устали объяснять.
Вечер перед большим днём
Представьте финтех-компанию, которой нужно пройти важную внешнюю проверку. Не просто очередной релиз, не просто демонстрацию инвесторам, а событие, где приложение должно выглядеть стабильным, зрелым и готовым к большому рынку.
Накануне вечером команда выпускает сборку. На одной платформе всё более-менее спокойно. Smoke зелёный, люди выдыхают, кто-то уже мысленно открыл ноутбук только для того, чтобы закрыть его обратно. На другой платформе приложение падает сразу после ввода кода доступа. Не у всех. Не всегда. Не на каждом устройстве. Только на определённой версии системы, которая, разумеется, есть у живых пользователей. И не у десяти человек, а у вполне заметного куска базы.
Сначала это называют «мистикой». Потом — «скорее всего, тултипами». Потом — «кажется, навигацией». Потом — «а можно ещё раз проверить ту же сборку, вдруг вчера ошиблись?». Это момент, когда команда теряет веру в детерминизм.
Инженеры больше не выглядят как люди, управляющие сложной системой. Они выглядят как алхимики, которые смешивают коммиты, фичефлаги, версии ОС и надежду. Собрать билд — сорок минут. Проверить гипотезу — сорок минут. Понять, что гипотеза неверная, — ещё десять секунд. Повторить.
Тред, в котором умирает архитектура
В мессенджере появляется тред.
Сначала он выглядит как обычное расследование. Несколько разработчиков, QA, лид, пара ссылок на логи. Потом туда приходят ещё люди. Потом менеджеры. Потом менеджеры менеджеров. Потом кто-то добавляет корпоративного ИИ-бота. И вот тут начинается настоящая трагикомедия. Бот получает обрывки кода, куски стектрейса, неполный контекст и уверенно говорит, что виноват конкретный коммит. Это звучит убедительно.
Проблема в том, что уверенность языковой модели не равна экспертизе. Но в три часа ночи, когда все устали, уверенность начинает выглядеть как истина.
Руководитель заходит в тред и пишет примерно следующее:
Ну вроде это было очевидно.
Для человека, который восемь часов смотрел в краш, эта фраза звучит не как помощь. Она звучит как объявление о банкротстве инженерного уважения.
Потому что если всё было очевидно, почему система устроена так, что это очевидное нельзя быстро проверить?
- Почему сборка занимает сорок минут?
- Почему нельзя откатить новый экран?
- Почему нельзя безопасно выключить проблемную часть?
- Почему один краш превращает релиз в ночную хирургию без наркоза?
- Почему в компании, которая годами росла, нет нормального аварийного выхода?
Ответ неприятный: потому что аварийные выходы не попадают в roadmap.
«Нельзя выключать, это лицо продукта»
В нормальной инженерной культуре в какой-то момент кто-то должен сказать: мы не готовы. Откатываем. Переносим. Фиксим спокойно. Не превращаем пользователей в тестовый полигон. Но в компаниях, где всё построено вокруг бесконечного движения вперёд, откат воспринимается как поражение.
- Новый экран нельзя выключить, потому что его будут показывать внешним людям.
- Новый флоу нельзя отложить, потому что он уже в презентации.
- Новый релиз нельзя остановить, потому что «мы же обещали».
И тогда начинается самое опасное: не исправление проблемы, а маскировка проблемы. Проблемный экран выключают только для части устройств. Старую версию интерфейса возвращают только тем, у кого приложение падает. Фичи начинают переключать вручную.
QA просит: «А включите мне вот так».
Лид отвечает: «Сейчас».
Кто-то в админке меняет флаг.
Сборка проверяется.
Краш.
Ещё один флаг.
Ещё одна сборка.
Ещё сорок минут.
Со стороны это может выглядеть как героизм. На самом деле это симптом. Если компания дошла до ручного выключения фичей под конкретные устройства за несколько часов до важной проверки, проблема не в одном баге. Проблема в том, что система давно перестала быть управляемой.
Релиз как ампутация
К вечеру решение найдено. Не хорошее. Не инженерное. Не красивое. Просто работающее. Пользователям на старой версии системы отдают старый интерфейс. Новый экран не чинят, а прячут. Краш не побеждают, а обходят. Причина не найдена, но релиз можно отправлять. Smoke зелёный.
В чате появляются поздравления.
«Герои».
«Красавцы».
«Вытащили».
«Невероятная командная работа».
И вот здесь самое тяжёлое. Потому что команда действительно устала. Люди действительно работали ночью. QA действительно проверяли одно и то же десятки раз. Разработчики действительно пытались найти причину. Лиды действительно тащили на себе хаос.
Но если после такого компания просто говорит «молодцы» и едет дальше, она закрепляет неправильный урок.
Она говорит: так можно.
- Можно годами не платить по техническому долгу.
- Можно довести систему до состояния, где один краш расследуется сотнями сообщений.
- Можно заменить инженерный процесс ночным героизмом.
- Можно не чинить причину, если удалось спрятать симптом.
- Можно снова забить следующий спринт бизнесовыми задачами.
До следующего раза.
Почему это не история про один баг
В 2012 году Knight Capital потеряла сотни миллионов долларов за считанные минуты. Формально это была технологическая ошибка. Но если читать разборы, становится понятно: катастрофа случилась не потому, что в коде однажды появился дефект. Дефекты появляются всегда. Катастрофа случилась потому, что вокруг дефекта не оказалось достаточно сильной инженерной системы: контроля релиза, защитных механизмов, процедур, мониторинга, права остановить процесс. SEC прямо указывала на недостаточные safeguards, неадекватные процедуры деплоя и тестирования, а также отсутствие достаточных инструкций по реакции на серьёзные технологические инциденты. (СЕК)
Это и есть главный урок. Компании не умирают от багов. Компании умирают от культуры, в которой баг некуда безопасно положить.
Нет времени на рефакторинг.
Нет времени на тесты.
Нет времени на observability.
Нет времени на нормальный rollback.
Нет времени на упрощение архитектуры.
Нет времени на удаление старого кода.
Нет времени на разговор о том, почему сборка занимает сорок минут.
Зато всегда есть время на новую фичу. Пока однажды новая фича не становится последней каплей.
Бешеный темп — это не стратегия
У бизнеса есть понятное желание: двигаться быстрее. Проблема начинается там, где скорость путают с суетой.
- Быстро — это когда команда может безопасно выкатывать маленькие изменения, быстро откатываться, быстро находить причину инцидента и быстро восстанавливаться.
- Суета — это когда команда двое суток тушит пожар, который сама же компания годами заправляла бензином.
- Быстро — это когда архитектура помогает менять продукт.
- Суета — это когда любое изменение ломает соседнюю комнату, потому что стены давно несущие, но никто не знает какие.
- Быстро — это когда инженеры спорят о решениях.
- Суета — это когда инженеры молчат, потому что спорить бесполезно.
Именно так начинается тихий уход сильных специалистов. Они не хлопают дверью. Они не пишут манифесты. Они не доказывают в тредах на 500 сообщений, что технический долг существует. Они просто обновляют резюме.
Потому что лучший инженер понимает: если компания системно не оставляет места для инженерии, значит, однажды инженерия будет происходить ночью, в панике, с ИИ-ботом в роли архитектора и менеджером, который пишет «это же очевидно».
Технический долг не исчезает. Он начисляет проценты
У технического долга есть неприятное свойство: он не стоит на месте.
- Каждый новый экран поверх старой архитектуры делает следующий экран дороже.
- Каждый временный костыль, который никто не удалил, становится частью платформы.
- Каждый фичефлаг, который должен был пожить неделю, через полгода превращается в ветку реальности.
- Каждый красный тест, который «потом починим», учит команду не доверять тестам.
- Каждый релиз через героизм учит бизнес, что героизм можно планировать.
Но героизм нельзя масштабировать.
Нельзя построить устойчивую компанию на людях, которые каждую пятницу спасают то, что можно было спокойно починить во вторник полгода назад. Рано или поздно система выставит счёт.
- Иногда это будет ночь без сна.
- Иногда — проваленный аудит.
- Иногда — отток пользователей.
- Иногда — публичный инцидент.
- Иногда — финансовая катастрофа за 45 минут.
Что должно было случиться после
После такого релиза нормальная компания не должна просто поздравлять команду. Она должна остановиться. Не на месяц. Не ради красивого «технического квартала». Хотя иногда нужен и он.
Но хотя бы честно ответить на несколько вопросов.
- Почему баг обнаружили так поздно?
- Почему откат был политически сложнее, чем ночной пожар?
- Почему сборка занимает сорок минут?
- Почему feature flags используются как ручная панель реанимации?
- Почему важный экран нельзя было выключить безопасно?
- Почему инженеры не могут сказать «мы не готовы» так, чтобы их услышали?
- Почему ИИ-бот оказался в треде раньше, чем понятный incident process?
И главный вопрос:
кто в компании имеет право остановить релиз?
Если ответ — «никто», то проблема уже не техническая. Это управленческий дизайн.
Финал без морали
Эта история не про плохих менеджеров и хороших инженеров. Такое объяснение слишком простое.
Менеджеры часто действительно хотят результата. Инженеры часто действительно хотят сделать качественно. QA часто действительно пытаются быть последним рубежом перед пользователем. Все внутри могут быть умными, взрослыми и неравнодушными людьми.
Но культура сильнее отдельных людей.
- Если культура годами говорит «потом почистим», однажды «потом» приходит ночью.
- Если культура считает рефакторинг прихотью, она получит рефакторинг в проде.
- Если культура измеряет успех только количеством выкаченных фичей, она не заметит, как продукт стал хрупким.
- Если культура не даёт инженерам времени строить фундамент, не надо удивляться, что фасад однажды падает на презентации.
Самое страшное в таких историях не то, что приложение упало. Самое страшное — что после релиза все выдохнули и пошли планировать следующий спринт. Снова бизнесовые задачи. Снова новые экраны. Снова «сейчас не время». А где-то в коде уже лежит следующий тред на 400 сообщений. Он просто ещё не создан.
Основано на реальных инженерных паттернах. Все совпадения — повод проверить свой бэклог.