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

Техдолг редко начинается с большой архитектурной ошибки. Чаще команда откладывает тесты, копирует похожую логику или оставляет ручную операцию «до релиза», а через несколько месяцев любое изменение в этом месте занимает дни вместо часов. Правильная работа с техдолгом — не отдельный бесконечный проект по уборке, а управляемый процесс: найти источник потерь, оценить его цену, выбрать способ погашения и проверить результат.
Что считать техдолгом, а что — просто плохой задачей
Техдолг — это решение, которое ускорило текущую поставку, но создало будущие расходы: сложность изменений, риск дефектов, ручную работу или ограничения для дальнейшего роста. Термин не означает, что любой старый код нужно переписать. Если участок стабилен, редко меняется и не создаёт риска, его возраст сам по себе ничего не доказывает.
Удобная проверка состоит из трёх вопросов:
- Какая конкретная потеря возникает из-за текущего решения: часы разработки, сбои, ручные операции, задержка релизов?
- Как часто эта потеря повторяется и кто на неё тратит время?
- Можно ли уменьшить потерю изменением кода, тестов, схемы данных, инфраструктуры или процесса?
Если ответов нет, перед вами, скорее всего, не оформленный техдолг, а общее ощущение, что «код некрасивый». Такое ощущение полезно зафиксировать как сигнал для исследования, но не как готовую задачу на переписывание.
Техдолг нужно обсуждать не через эстетику кода, а через цену следующего изменения.
Сноска. «Проценты по техдолгу» — метафора для повторяющихся потерь: дополнительного времени, ошибок и риска. Это не точная финансовая ставка, если команда не измеряет её на своих данных.
Как найти долг в работающем проекте
Не начинайте с полного аудита репозитория. Он быстро превращается в длинный список субъективных замечаний. Ищите места, где бизнес-задачи уже сталкиваются с техническими ограничениями.
Соберите сигналы из работы команды
Источниками могут быть история инцидентов, пул-реквесты, задачи поддержки и комментарии разработчиков. Особенно ценны повторяющиеся формулировки: «нужно менять в пяти местах», «тесты здесь нестабильны», «после релиза проверяем вручную», «никто не знает, почему это работает».
Для каждого сигнала запишите не решение, а наблюдаемую проблему. «Переписать сервис заказов» слишком расплывчато. «Добавление нового статуса требует правок в четырёх обработчиках и ручной проверки двух сценариев» уже позволяет оценить цену.
Разделите долг по типу
- Кодовый. Дублирование, запутанные зависимости, слишком большие функции, отсутствие тестов в зоне частых изменений.
- Архитектурный. Компоненты связаны так, что локальное изменение затрагивает весь сервис или несколько команд.
- Инфраструктурный. Ручные деплои, отсутствие воспроизводимого окружения, устаревшие зависимости, непрозрачное резервное копирование.
- Данных. Неясные правила заполнения, несогласованные идентификаторы, миграции без понятного плана отката.
- Процессный. Релиз нельзя проверить автоматически, знания находятся у одного человека, а критерии готовности меняются по ходу работы.
Границы условны. Например, отсутствие тестов — проблема кода, но её цена проявляется в процессе релизов. В карточке задачи лучше указывать и источник, и место, где возникает потеря.
Как оценить цену, не превращая это в гадание
Точная оценка появляется только из наблюдений. Если данных нет, используйте диапазон и явно помечайте его как гипотезу. Не приписывайте задаче «экономию 30%», если команда её не измеряла.
Минимальная карточка техдолга может содержать:
- Симптом. Что происходит и где это видно.
- Повторяемость. Как часто возникает проблема за спринт, релиз или месяц.
- Цена. Сколько времени уходит, сколько ручных операций выполняется, сколько дефектов или инцидентов связано с зоной.
- Риск без изменений. Что станет хуже при росте нагрузки, числа интеграций или команды.
- Минимальное улучшение. Какое изменение уменьшит проблему, не обещая полного переписывания.
- Проверка результата. Какой показатель должен измениться после работы.
Для повторяющейся ручной операции можно считать затраты так: время одной операции умножается на число повторений и стоимость часа команды. Если стоимость часа внутри компании не используется, оставьте показатель в часах. Это честнее, чем точная сумма без исходных данных.
Три рабочих способа погашать техдолг
Универсального процента времени на техдолг нет. Команда выбирает способ по риску, частоте изменений и близости проблемы к бизнес-результату.
| Подход | Когда подходит | Что выигрываете | Чем платите |
|---|---|---|---|
| Погашать вместе с новой функцией | Долг находится в коде, который всё равно меняется | Изменение сразу окупается рабочей задачей, меньше отдельного контекста | Нужно ограничить объём, иначе задача расползается |
| Выделить отдельную техническую задачу | Проблема блокирует релизы, тестирование или поддержку | Можно сосредоточиться на причине и измерить результат | Бизнес-эффект нужно объяснить заранее, иначе работу отложат |
| Запланировать технический этап | Есть системный риск или несколько связанных узких мест | Команда меняет границы системы последовательно | Потребуется план перехода, совместимость и контроль отката |
Погашайте долг рядом с изменяемым кодом
Это обычно самый безопасный вариант. Если добавляется новый сценарий оплаты, сначала выделите повторяющуюся проверку, добавьте тесты на затронутый контракт и только затем внесите новую ветку. Не нужно переписывать соседний модуль целиком: меняйте ровно ту часть, которая мешает текущей задаче.
Критерий завершения здесь двойной: новая функция работает, а исходная причина задержки уменьшилась. Например, вместо обещания «улучшить слой интеграции» зафиксируйте «новый провайдер добавляется в одном месте, а контракт проверяется автоматическим тестом».
Выносите отдельную работу, когда долг создаёт аварийный риск
Если ручной процесс уже приводит к пропущенным релизам или ошибки невозможно безопасно обнаружить до продакшена, ждать следующей функции не стоит. Сформулируйте задачу через риск: что может произойти, какие системы затронет и какой защитный механизм появится после работы.
Для такой задачи заранее нужны границы. Например, не «перевести деплой на автоматизацию», а «сборка и проверка артефакта выполняются одинаково в тестовом и рабочем окружении; ручным остаётся только подтверждение выката». Если часть процесса останется ручной, это нужно написать прямо.
Делайте этапы вместо большого переписывания
Крупный рефакторинг опасен тем, что месяцы работы проходят без промежуточной проверки. Разбейте его на совместимые шаги: сначала наблюдаемость и тесты на контракт, затем новый путь обработки, потом перевод потребителей и только после этого удаление старого пути.
На каждом этапе должен быть способ отката или хотя бы безопасного возврата к предыдущему поведению. Для схемы данных это может быть обратимая миграция или временная поддержка двух форматов. Детали зависят от СУБД и инструмента миграций, поэтому их нужно сверять с документацией конкретной версии стека.
Что часто ломается
«Перепишем всё, и проблема исчезнет»
Полная замена не отменяет требований, интеграций и неясных правил, из-за которых появился старый код. Перед переписыванием зафиксируйте внешнее поведение: входные данные, ошибки, ограничения и показатели. Иначе команда перенесёт старую проблему в новую структуру.
Техдолг превращают в отдельную очередь без владельца
Список из сотен пунктов не управляется сам. У каждой записи должен быть владелец решения, причина приоритета и дата следующего пересмотра. Если задача больше не влияет на риск или скорость изменений, её можно закрыть как неактуальную.
Команда чинит симптом, но не причину
Добавить таймаут, увеличить лимит или повторить запрос иногда необходимо, но это не всегда устранение долга. После временной меры спросите, какой сценарий привёл к сбою и как обнаружить его раньше. Иначе техническая проблема просто станет менее заметной.
Нет проверки после работы
Рефакторинг без измерения оставляет спор о вкусе. До начала запишите базовое состояние: время сборки, длительность тестов, число ручных шагов, частоту дефектов или время изменения конкретного сценария. После релиза сравните те же показатели при сопоставимых условиях. Если замеров нет, начните с их сбора, а не с обещания улучшения.
Как выбрать следующий шаг
Начните с одной зоны, которая меняется регулярно и уже создаёт измеримую задержку. Зафиксируйте симптом, соберите базовый показатель и выберите минимальное изменение, способное его уменьшить. На ближайшем ревью проверьте не только код, но и результат: стало ли меньше ручной работы, быстрее ли проходит проверка, проще ли добавить следующий сценарий.
После этого настройте регулярный просмотр списка техдолга. В него должны попадать новые записи из инцидентов и ревью, а старые — получать решение: делать сейчас, связать с будущей функцией, принять риск или закрыть как неактуальные. Инвалидация кешей, выбор конкретной СУБД и миграционная стратегия — отдельные темы; здесь важен сам цикл управления долгом.
Проектная работа: От проблемы до защиты: продукт, этапы, вопросы комиссии
Спросить за 15 ₽Источники: TechnicalDebt — Martin Fowler, Google SRE: Engineering Productivity
Частые вопросы
Нужно ли выделять отдельный спринт только под техдолг?
Как доказать руководителю, что техдолг нужно оплачивать сейчас?
Можно ли просто добавить техдолг в беклог и вернуться к нему позже?
Что делать, если команда не успела погасить долг в запланированный срок?
Стоит ли переписывать модуль без тестов перед дальнейшими изменениями?
Как учитывать техдолг при разработке на другой версии фреймворка или библиотеки?
Материал носит информационный характер и подготовлен редакцией «Агентуры». Он не является офертой, рекламой или индивидуальной консультацией. Упомянутые продукты, компании и торговые знаки принадлежат их правообладателям. Перед принятием решений, влекущих юридические или финансовые последствия, обратитесь к профильному специалисту.