07 февр. 2025 г.·8 мин чтения

Решение о переписывании ПО: проверьте порыв за 2 недели

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

Решение о переписывании ПО: проверьте порыв за 2 недели

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

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

Такой отклик естественен, но это всё равно лишь отклик. Боль говорит о том, что команде тяжело. Доказательства объясняют почему. Это не одно и то же.

Команде может быть очень плохо по причинам, которые мало связаны с самим кодом. Могут постоянно меняться продуктовые требования. Уйти может один сильный инженер. Тестирование может быть слабым. В бэклоге могут лежать старые решения, о которых уже никто не помнит. Если всё это назвать «плохой архитектурой», можно принять дорогое решение о переписывании ПО только на эмоциях.

Один плохой спринт особенно обманчив. Спринты срываются по разным причинам:

  • срочный дедлайн заставил пойти на упрощения
  • рискованная функция затронула слишком много частей сразу
  • вопросы поддержки отвлекли инженеров от плановой работы
  • неясные требования привели к переделкам

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

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

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

Что собирать в ближайшие две недели

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

Используйте реальную работу, а не догадки. Если баг не превратился в тикет, не считайте его. Память превращает один болезненный сбой в «у нас всё время всё ломается», и именно так команды уговаривают себя на переписывание, которое потом не могут оправдать.

По той же причине измеряйте сроки выполнения с чёткими точками начала и конца. Начинайте, когда кто-то просит изменение или создаёт тикет. Заканчивайте, когда это изменение попадает в продакшн. Не меняйте определения в середине окна, иначе цифры потеряют смысл.

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

Сделайте сбор простым:

  • Считайте баги только из системы тикетов
  • Фиксируйте сроки выполнения для каждого выложенного запроса
  • Записывайте каждый обходной путь, который команда использовала для релиза
  • Используйте одно фиксированное окно в 10 рабочих дней для всех трёх метрик

Короткое окно важнее, чем думает большинство команд. Если вы сравниваете один плохой месяц, одну праздничную неделю и один крупный запуск, вы сравниваете не кодовую базу. Вы сравниваете хаос.

Если хотите добавить ещё одну деталь, указывайте рядом с каждым пунктом влияние. Баг затронул клиента? Обходной путь занял 20 минут или полдня? Такая маленькая деталь помогает отделить раздражающую помеху от дорогой помехи.

К концу двух недель у вас должен быть небольшой, даже скучный набор фактов. И это хорошо. Он даёт команде что-то более надёжное, чем фрустрация.

Как отслеживать количество багов без лишней рутины

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

Используйте тот трекер, с которым команда и так работает каждый день. Если они уже ведут задачи в GitLab issues, оставьте их там. Если используют другую доску, оставайтесь на ней. Инструмент менее важен, чем одно правило: каждый баг проходит через одно и то же место с одним и тем же небольшим набором полей.

Поля делайте простыми:

  • серьёзность: низкая, средняя или высокая
  • статус: открыт, исправлен или открыт снова
  • область: вход, биллинг, админка, поиск, API или другой участок продукта
  • дата открытия и дата закрытия

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

Серьёзность должна совпадать с тем языком, которым команда уже пользуется. Если люди естественно говорят «мелкое раздражение» или «блокирует релиз», просто сопоставьте это с тремя понятными метками и двигайтесь дальше. Сложные системы оценки выглядят красиво, но большинство команд бросает их уже к третьему дню.

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

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

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

Как измерять сроки выполнения так, чтобы команда доверяла цифрам

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

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

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

Плановую работу и срочные исправления нужно держать в разных корзинах. Горячий фикс сломанного checkout flow идёт быстро, потому что команда бросает всё остальное. Запланированная фича проходит обычные этапы ревью, тестирования и релиза. Если смешать их, среднее число расскажет ложную историю.

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

Сравнение не менее важно, чем время. Сравнивайте похожие задачи с похожими задачами. Однострочное исправление текста не должно стоять рядом со сменой платёжного потока или миграцией базы данных. Разбейте данные на грубые группы: маленький багфикс, среднее продуктовое изменение и крупная backend-задача.

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

Что обычно показывают обходные решения

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

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

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

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

Паттерны, которые обычно важны

Короткий список помогает, когда вы просматриваете последние две недели:

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

Простой двухнедельный процесс, которому может следовать команда

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

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

Хороший ритм важнее идеального формата:

  1. В первый день договоритесь, что считается багом, когда начинаются и заканчиваются сроки выполнения и что вы называете обходным решением.
  2. Каждый день каждый разработчик добавляет короткие заметки в таблицу. Одной строки на пункт достаточно.
  3. Записывайте факты. Пишите «баг в платеже, нашли в понедельник, исправили в среду, патч в двух файлах» вместо «платежи — катастрофа».
  4. Встречайтесь два раза в неделю по 20 минут. Смотрите на повторы, а не на мнения.
  5. В конце второй недели напишите короткое резюме и проведите одну встречу для решения.

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

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

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

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

Быстрые проверки перед тем, как сказать «да» переписыванию

Сначала стабилизировать поставку
Если релизы постоянно срываются, получите практичный план по коду, процессу и ответственности.

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

Используйте несколько простых проверок, прежде чем одобрять что-то большое.

  • Посмотрите, где появляются баги. Если они постоянно приходят из одного и того же модуля, checkout flow или фоновой задачи, у вас может быть одна повреждённая зона, а не весь продукт, который нужно заменять.
  • Смотрите на маленькие изменения, а не на большие проекты. Если правка текста, правило цен или небольшое изменение API всё равно занимают дни, проблема может быть в слабых границах, плохих тестах или неясной ответственности.
  • Считайте обходные решения. Когда команда каждую неделю добавляет ещё один ручной шаг, feature flag, исключение или одноразовый скрипт, код начинает сопротивляться обычной работе.
  • Проверьте, у кого вся карта в голове. Если один инженер знает рискованные файлы, порядок деплоя и старые крайние случаи, у команды есть не только проблема кода, но и проблема знаний.
  • Смотрите, что происходит после релиза. Если каждое исправление создаёт новые побочные эффекты, более долгий QA или страх отката, систему становится всё труднее менять.

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

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

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

Реальный пример небольшой продуктовой команды

У команды из семи человек был один проблемный участок: старый billing-модуль, который отвечал за планы, скидки, prorations и время выставления счетов. Большая часть продукта работала стабильно. Billing — нет.

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

Команда перестала спорить о том, «плохой» ли код на ощущение, и 14 дней фиксировала, что происходит. Они увидели, что пять из восьми багов, зарегистрированных за этот период, были связаны с billing, хотя на billing приходилась лишь небольшая часть общего инженерного времени.

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

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

К концу двух недель решение о переписывании ПО стало гораздо уже. Переписывать весь продукт не требовалось. Команда решила заменить только rules engine для billing, где начиналось большинство багов и задержек, а customer portal, invoices и админские экраны пока оставить как есть.

Это решение снизило риск. Они могли протестировать новый billing-core за старым интерфейсом, переносить по одному ценовому сценарию за раз и не затягивать в проблему остальную часть продукта, которая эту проблему не создавала.

Ошибки, которые ведут к неверному решению

Нужен нейтральный взгляд CTO
Привлеките опытного Fractional CTO, чтобы оценить баги, сроки выполнения и рискованные модули.

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

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

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

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

Помогает простой чек:

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

Последний пункт важнее, чем команды готовы признать. Переписывание не исправит размытые тикеты, слабый code review, отсутствие владельцев или привычку сливать код поздно в пятницу. Все эти проблемы почти сразу переезжают в новую кодовую базу.

Если команда не может назвать, что именно изменится в повседневной работе, переписывание, скорее всего, просто история, которой люди объясняют себе желание сбежать от раздражения.

Что делать после этих двух недель

Соберите заметки, баги и данные о поставке в одном месте и сведите выбор к трём вариантам: оставить как есть, доработать или заменить. Если команда не может назвать вариант одной фразой, данные всё ещё слишком размыты.

Хорошо работает простое разделение:

  • Оставьте как есть, если боль реальна, но ограничена, и команда всё ещё может выпускать изменения без ежедневной драмы.
  • Дорабатывайте, если одни и те же части снова и снова тормозят людей, но у продукта всё ещё есть рабочее ядро.
  • Заменяйте только если данные показывают, что текущий код блокирует обычную работу, создаёт повторяющиеся баги и сопротивляется небольшим исправлениям.

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

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

Запишите решение и причину простыми словами. Хорошая заметка короткая: «Мы дорабатываем billing flow, потому что он дал 40% времени на исправления и три из пяти повторяющихся обходных решений». Это даёт команде конкретную точку, к которой можно вернуться позже.

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

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

Хорошее решение о переписывании ПО обычно кажется людям менее драматичным и более маленьким, чем они ожидают. И это часто хороший знак.