← Все статьиНаписать

Технический долг: как он копится и когда проект пора переписать

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

Пост, на основе которого написана статья: На чём сделать сайт и приложение сейчас: что изменилось с ИИ

Откуда взялся термин

Метафору придумал Уорд Каннингем, автор первой вики. В 1992 году он выступал на конференции OOPSLA с отчётом о системе WyCash для управления портфелями ценных бумаг и сравнил первую версию кода с займом. Немного долга ускоряет разработку, если его быстро возвращают через рефакторинг. Опасность начинается, когда долг не отдают: каждая минута работы с не вполне верным кодом становится процентами.

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

Метафора прижилась, потому что её понимает бизнес. Слово «рефакторинг» директору ничего не говорит. Фраза «мы платим проценты по кредиту, который взяли полгода назад» объясняет, почему простая доработка вдруг стоит две недели.

Что такое долг в коде простыми словами

Тело долга — работа, которую нужно сделать, чтобы привести код в порядок. Проценты — лишнее время на каждую новую задачу, пока порядка нет.

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

Виды долга: квадрант Фаулера и не только

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

БезрассудныйРазумный
Осознанный«На проектирование нет времени»«Выпускаем сейчас, последствия знаем и разберём после релиза»
Неосознанный«А что такое слои?»«Теперь понятно, как надо было сделать»

Где ещё прячется долг

  • Архитектурный: границы модулей проведены неудачно, и любая доработка задевает полсистемы.
  • Тестовый: тестов нет или они проверяют не то, что важно бизнесу.
  • Документационный: знания о системе живут в головах двух человек.
  • Долг зависимостей: устаревшие версии фреймворка, библиотек и языка.
  • Инфраструктурный: ручной деплой, нет мониторинга, окружения на серверах отличаются.

Почему долг копится

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

Остальные причины знакомы любому руководителю разработки.

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

Как ИИ-агенты ускоряют рост долга

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

Отдельная ловушка — тесты. Агенты любят подгонять тесты под текущее поведение кода и игнорировать требования. Зелёная сборка в таком случае ничего не гарантирует, поэтому тесты, написанные агентом, я перепроверяю руками.

Что снижает риск: типизация, документация в коде и рядом с ним, конвенции в именах и структуре, тонкая нарезка на слои, чтобы агент получал весь нужный контекст. И файл Agents.md, написанный вручную, примерно на 150 строк: в нём правила, которые агент сам из кода не выведет.

Как измерять и управлять долгом

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

Инструменты статического анализа вроде SonarQube оценивают долг как время на исправление найденных проблем. Цифра условная, но тренд по ней полезен: если за квартал оценка выросла вдвое, разговор с бизнесом становится предметным.

  • Сколько времени уходит на типовую задачу сейчас и полгода назад.
  • Какую долю спринта съедают баги и срочные исправления.
  • Как часто правка в одном модуле ломает другой.
  • Насколько устарели фреймворк и ключевые библиотеки.
  • Сколько людей в команде могут уверенно менять каждый модуль.

Как отдавать долг без остановки разработки

  • Вести реестр долга в том же трекере, где лежат задачи, с оценкой и последствиями.
  • Закладывать в каждый спринт фиксированную долю времени на долг, а не ждать «свободного месяца».
  • Следовать правилу бойскаута: оставлять модуль чуть чище, чем он был до правки.
  • Перед правкой старого кода покрывать тестами то место, которое меняешь.
  • Обновлять зависимости по расписанию, мелкими шагами.

Когда проект пора переписать

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

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

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

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

Вопросы и ответы

Что такое долг в разработке простыми словами?

Это работа, которую отложили ради скорости. Пока её не сделали, каждая новая задача стоит дороже — это и есть проценты по долгу.

Всегда ли долг — это плохо?

Нет. Осознанный долг ради быстрого запуска нормален, если команда знает, где он, и договорилась, когда его отдавать. Опасен долг, о котором никто не знает.

Как ИИ-агенты влияют на долг в проекте?

Они ускоряют и разработку, и накопление костылей: агент копирует паттерны из кода и любит подгонять тесты. Помогают типизация, конвенции, тесты с ручной перепроверкой и Agents.md, написанный вручную.

Когда проект дешевле переписать?

Когда правки ломают соседние модули, людей со знанием кода не осталось, а доработка стоит дороже нового модуля. Даже тогда я бы переносил функции постепенно, а не останавливал всё на год.