СТЕК ТЕХНОЛОГИЙ
Company
ПРОЕКТЫ
ОТЗЫВЫ
КОМАНДА
КАК МЫ РАБОТАЕМ
ОБСУДИТЬ ПРОЕКТ

Технический долг на проекте в веб-студии — что это, откуда он берётся и можно ли его погасить

bg
17 октября 2024

Технический долг на проекте в веб-студии — что это, откуда он берётся и можно ли его погасить

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

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

Что такое технический долг и легаси, и как он возникает

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

Техдолг проще всего понять на аналогии с ремонтом.

Вы въезжаете в квартиру и быстро ставите проводку там, где удобно сейчас, не выравниваете стены, тянете удлинители. Кажется, что жить можно! Но с каждым месяцем передвинуть розетки и вообще что-то поменять становится дороже, удлинители наращиваются удлинителями, и в итоге нужен не мелкий ремонт, а капитальный, который в разы сложнее и дороже.

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

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

Отдельным видом техдолга является легаси-код (от англ. legacy — наследство).

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

Если нести бремя техдолга команда вызвалась сама, то легаси-код достался ей от ранее поддерживавших проект предшественников или прошлой эпохи технологий. Это не всегда плохой код, но на вопрос «А что если нам нужно изменить это завтра?» он точно отвечает плохо.

Как разработчики понимают, что на проекте есть техдолг? 

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

Скорость и стабильность работы проекта

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

Код и архитектура

  • Нарушен базовый принцип DRY (Don’t Repeat Yourself — «Не повторяйся»): одна и та же логика дублируется в десятках мест. Изменение требует правки всех копий.
  • Появляются «божественные объекты» (God Object) и «спагетти-код» — огромные модули или функции на сотни строк, которые знают и делают слишком много.
  • Код сложно читать даже его авторам. В нём используются «магические числа» (например, if (user.status == 5)), смысл которых никто не помнит.
  • Команда боится трогать определённые части системы. Никто не уверен, как они работают и что от них зависит. Это святыни, и за стабильность их работы остаётся только помолиться.

Работа команды

  • Невозможно быстро добавить на проект нового разработчика. Если только единичные ветераны проекта знают, как устроена система, погружение в неё новых людей может занять месяцы.
  • Рефакторинг постоянно откладывается до лучших времён, которые всё никак не наступят.
А что говорит о том, что основа проекта — это легаси?

  • Технологический стек устарел. Проект использует фреймворки и библиотеки, которые уже не поддерживаются, или версии, отставшие на несколько лет.
  • В проекте лежат «мёртвые» зависимости. Их репозитории помечены как архивные. Попытка обновить их грозит крахом всей системы.
  • Код был написан под давно изменившиеся требования. Теперь непонятно, зачем почему всё сделано именно так.
  • Удаление кода опаснее, чем его добавление. Никто не знает, где и как он может использоваться.
  • Документация либо отсутствует, либо полностью расходится с реальностью. Работа на таких неповоротливых проектах зачастую вызывает у членов команды спорные чувства.

Как команда реагирует на технический долг

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

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

В первую очередь это постоянное раздражение из‑за неудобств: код, который приходится править, сопротивляется каждому изменению. Сильные разработчики вместо созидания вынуждены заниматься бесконечным ремонтом и заматывать протечки скотчем там, где система прогнила и пора всё менять. Код пишется одной рукой, потому что другая зажала фигу в кармане: «Зачем делать хорошо? Всё равно потом переделывать. Главное — попасть в оценку». Минус мотивация, минус смысл в работе, минус профессионализм.

Но что растёт, так это техдолг. Техдолг и страх быть инициатором эффективных и полезных изменений.

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

А что, если технический долг не должен влиять на команду? Ведь решение о его погашении принимает клиент. Но сначала ему важно понять, что от техдолга не уйти, стоимость поддержки будет увеличиваться с усложнением системы, а продуктивность команды — снижаться с ростом костылей и времянок. Чтобы этого не было, нужны регламентированные процессы устранения техдолга.

К каким последствиям приводит наличие технического долга

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

Что может вызвать технический долг, если на него закрывать глаза:

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

Анти-кейс из нашей практики.

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

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

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

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

Если клиент готов к переменам, он получит:

  • Безопасность. Новые версии библиотек, фреймворков и CMS защищены от значительного количества способов взлома.
  • Предсказуемость. Добавление новой функции не приведёт к поломке старых.
  • Скорость реакции на рынок. В проект с читаемым кодом, написанным по актуальным стандартам, проще и дешевле внедрять новые функциональные возможности, не отставать от конкурентов, а в перспективе даже обгонять их.
  • Доступность программистов. Живой язык популярнее мёртвого, потому и проще найти тех, кто на нём говорит (в нашем случае — пишет). Чем больше людей будут разбираться в проекте, тем ниже шанс, что он зависнет с уходом одного носителя сакрального знания.
  • Проще продать бизнес. На что-то популярное и доступное спрос выше, чем на антиквариат.
  • СЕО сможет фокусироваться на бизнесе, а не технических проблемах. Это в комментариях не нуждается.

Кейс про друида, о котором мы упомянули в четвёртом пункте.

Нам достался сервис, которым 10 лет занимался один-единственный человек. Он хорошо прокачал навыки работы с PostgreSQL, Vue.js и Nuxt прежде чем оставить проект и унести все знания о нём с собой — никакой документации и доступов к внешним системам он не составлял. То, чему он посвятил 10 лет, мы постигли за гораздо меньший срок, чем гордимся.

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

О порядке работы с техническим долгом

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

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

Этап 1: Разведка и погружение

1. Поиск «носителя знаний»:
  • Найти в истории репозитория (git blame) последнего активного разработчика или тимлида.
  • Связаться с ним. Цель: понять историю принятия решений, «подводные камни» и особенности деплоя. (Если контакт невозможен — переходим к шагу 2).
2. Локальный запуск и первичная диагностика:
  • Клонировать репозиторий.
  • Попытаться запустить проект согласно README.md (если его нет — это уже технический долг).
  • Зафиксировать ошибки сборки/запуска. Цель: понять, насколько проект «боеспособен» и сколько времени нужно, чтобы просто заставить его работать локально.
3. Анализ зависимостей (Dependency Audit):
  • Проверить файлы манифестов (например, package.json, requirements.txt, pom.xml, go.mod).
  • Проверить безопасность текущих решений (команды типа npm audit, safety check, OWASP Dependency Check).
  • Выявить устаревшие или критические уязвимые пакеты. Зафиксировать, какие из них можно обновить без изменения кода (patch-версии и некоторые minor-версии).
4. Архитектурный осмотр:
  • Беглый просмотр кода. Определить паттерны и стиль (ООП, функциональный, спагетти-код).
  • Понять структуру: есть ли разделение на слои (UI, бизнес-логика, данные) или все в одном файле.

Этап 2: Инвентаризация и планирование

1. Определение границ (Boundary Detection):
  • Четко определить, какую функциональность проекта мы вообще собираемся трогать. Что требует изменений (новые фичи), а что должно работать "как есть"?
  • Составить карту «зон изменений». Отметить самые запутанные и критически важные участки кода.
2. Быстрые победы (Low-hanging fruits):
  • Выполнить обновление того, что обновляется безопасно (см. п. 3 Этапа 1).
  • Закоммитить эти изменения отдельно. Это улучшит безопасность сейчас и уменьшит объем долга в будущем.
3. Составление поэтапного плана обновлений:
  • Разработать дорожную карту приведения проекта к современным стандартам.
  • Пример: Версия 1.0 (текущая) -> Обновить библиотеку X до LTS-версии -> Переписать модуль Y на новый фреймворк -> Версия 2.0.
4. Согласование:
  • Показать план руководству/заказчику. Объяснить риски (например, уязвимости) и выгоды (скорость разработки новых фич в будущем). Получить approval на временные затраты.

Этап 3: Создание «защитного периметра»

1. Документирование текущего поведения:
  • Если нет тестов, их нужно написать на ключевой функционал перед его изменением (Characterization Tests).
  • Задача тестов — не проверить корректность логики (мы можем ее не знать), а зафиксировать текущее поведение системы.
2. Автоматизация проверок:
  • Внедрить линтеры и форматтеры (хотя бы для изменяемых файлов), чтобы не тратить время на обсуждение стиля кода при код-ревью.

Этап 4: Рефакторинг и разработка

1. Правило бойскаута (Оставляй место стоянки чище, чем ты его нашел):
  • Вносишь изменения в функцию? Отрефактори её (переименуй переменные, разбей на подфункции).
  • Критическое правило: Улучшаем только то, что трогаем. Не пытайтесь переписать весь монолит сразу — это провалится.
2. Микро-шаги:
  • Изменения должны быть очень маленькими, чтобы их можно было легко откатить.
  • Принцип: 1 коммит = 1 логическое изменение.
3. Тотальное тестирование:
  • После каждого маленького изменения запускать тесты (ручные/автоматические).
  • Сравнивать результат с "эталонным" поведением, задокументированным на Этапе 3.

Этап 5: Интеграция и стабилизация

1. Ревью кода:
  • Даже правки легаси должны проходить ревью. Вторая пара глаз поможет заметить сломанную совместимость.
2. Непрерывная интеграция (CI):
  • Настроить автоматический прогон тестов при каждом коммите.
3. Постепенный выкат изменений на prod-сервер:
  • Если возможно, выкатывать изменения на прод поэтапно (feature flags, канареечные релизы).

Заключение. О перспективном «завтра» вместо компромиссного «сегодня»

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

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

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

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