Технический долг

Технический долг (также известен как цифровой долг, техническая задолженность, долг проектирования[1] или долг кода) — это дефицит или скрытая стоимость будущей доработки, необходимой для поддержания качества продукта. Технический долг возникает в процессе разработки программного обеспечения, когда принимается решение в пользу более быстрой и простой, но менее оптимальной и не полностью завершённой реализации, вместо более качественного и проработанного решения, требующего больших затрат времени и сил, однако не создающего дополнительных проблем в будущем[2].

Аналоги

По аналогии с финансовым долгом[3], если технический долг не «погашается», с течением времени накапливаются «проценты» — дополнительные затраты и усложнения, которые со временем всё сильнее препятствуют внесению изменений и развитию системы. Неустранённый технический долг увеличивает энтропию программного обеспечения и стоимость последующих доработок. Как и финансовый долг, техническая задолженность не всегда является злом и в ряде случаев необходима — например, при создании прототипов или проверке концепций. Однако некоторые специалисты отмечают, что метафора «технический долг» порой приводит к недооценке этого явления и недостаточной приоритизации его устранения[4][5].

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

Причины возникновения

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

  • Постоянное развитие и многократные изменения проекта ведут к устареванию ранее реализованных решений, не соответствующих современным стандартам.
  • Недостаточно чёткая постановка задачи, запуск разработки при ещё не до конца определённых требованиях или даже без какой-либо формализации требований. Делается для ускорения старта, но зачастую приводит к необходимости последующих доработок.
  • Давление со стороны бизнеса, когда нужно как можно скорее выпустить программный продукт до завершения всех необходимых работ и изменений, что создаёт технический долг[6][7].
  • Отсутствие процессов и/или недостаточное понимание самой идеи технического долга в организации, из-за чего руководящие решения не учитывают долгосрочные последствия.
  • Жёсткая связанность компонентов, когда модули не выделены и не обеспечивается гибкость для перестройки ПО под новые требования бизнеса.
  • Отсутствие комплексных тестов, провоцирующее быстрое и потенциально рискованное устранение ошибок «костылями».
  • Недостаточная документированность: когда код создаётся без сопроводительных описаний, а работа по их созданию откладывается, формируя дополнительную задолженность.
  • Отсутствие сотрудничества между командами, когда не происходит обмена знаниями, страдает эффективность бизнеса, либо начинающие программисты не проходят должного обучения.
  • Разработка параллельно в нескольких ветках порождает дополнительные обязательства по интеграции: чем больше изолированных изменений, тем выше технический долг, связанный со слиянием (merge).
  • Откладываемая рефакторизация: по мере изменения требований становится ясно, что части кода требуют переработки, но если откладывать её, долг растёт[7].
  • Несоответствие отраслевым стандартам и пренебрежение широко используемыми технологиями (framework–ами), что усложняет последующую интеграцию и удорожает техническое обслуживание[6].
  • Недостаток знаний у разработчиков о том, каким должен быть качественный код.
  • Отсутствие «хозяина» кода: при передаче разработки на аутсорсинг внутри компании может возникнуть потребность пересмотра или переписывания результата — это становится новым долгом.
  • Слабое технологическое лидерство и принятие стратегических решений без оценки технических последствий.
  • Внесение срочных изменений в последний момент, на которые, как правило, не хватает времени и ресурсов для грамотной реализации, тестирования и документирования.

Возникновение и устранение технического долга

Кеннет Рубин описывает стадии существования технического долга в аспектах его обнаружения и ликвидации:[8]

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

Последствия

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

Технический долг — одна из главных причин срывов сроков проектов: трудно точно оценить объём скрытой и незавершённой работы (т.е. долга), связанный с каждым новым изменением, так как неопределённость нарастает по мере накопления долга. Когда долг превышает доступное время, проект не успевает к сроку. Для предсказуемости выпуска команду рекомендуют ограничивать количество параллельно находящихся в работе задач, чтобы сдерживать рост незавершённых работ (долга).

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

В своей книге «Рефакторинг к шаблонам» сходный аргумент относительно «долга проектирования» приводит и Дж. Кериевски[9].

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

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

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

Примечания