Технический долг
Технический долг (также известен как цифровой долг, техническая задолженность, долг проектирования[1] или долг кода) — это дефицит или скрытая стоимость будущей доработки, необходимой для поддержания качества продукта. Технический долг возникает в процессе разработки программного обеспечения, когда принимается решение в пользу более быстрой и простой, но менее оптимальной и не полностью завершённой реализации, вместо более качественного и проработанного решения, требующего больших затрат времени и сил, однако не создающего дополнительных проблем в будущем[2].
Аналоги
По аналогии с финансовым долгом[3], если технический долг не «погашается», с течением времени накапливаются «проценты» — дополнительные затраты и усложнения, которые со временем всё сильнее препятствуют внесению изменений и развитию системы. Неустранённый технический долг увеличивает энтропию программного обеспечения и стоимость последующих доработок. Как и финансовый долг, техническая задолженность не всегда является злом и в ряде случаев необходима — например, при создании прототипов или проверке концепций. Однако некоторые специалисты отмечают, что метафора «технический долг» порой приводит к недооценке этого явления и недостаточной приоритизации его устранения[4][5].
В процессе внесения изменений в исходный код часто возникает необходимость координированных изменений в смежных модулях, документации или даже других системах. Неоконченные изменения становятся техническим долгом — до его устранения он продолжает «обрастать» процентами, осложняя дальнейшее развитие проекта. Хотя термин «технический долг» зародился в разработке программного обеспечения, он находит применение и в других сферах.
Причины возникновения
К распространённым причинам технического долга относят:
- Постоянное развитие и многократные изменения проекта ведут к устареванию ранее реализованных решений, не соответствующих современным стандартам.
- Недостаточно чёткая постановка задачи, запуск разработки при ещё не до конца определённых требованиях или даже без какой-либо формализации требований. Делается для ускорения старта, но зачастую приводит к необходимости последующих доработок.
- Давление со стороны бизнеса, когда нужно как можно скорее выпустить программный продукт до завершения всех необходимых работ и изменений, что создаёт технический долг[6][7].
- Отсутствие процессов и/или недостаточное понимание самой идеи технического долга в организации, из-за чего руководящие решения не учитывают долгосрочные последствия.
- Жёсткая связанность компонентов, когда модули не выделены и не обеспечивается гибкость для перестройки ПО под новые требования бизнеса.
- Отсутствие комплексных тестов, провоцирующее быстрое и потенциально рискованное устранение ошибок «костылями».
- Недостаточная документированность: когда код создаётся без сопроводительных описаний, а работа по их созданию откладывается, формируя дополнительную задолженность.
- Отсутствие сотрудничества между командами, когда не происходит обмена знаниями, страдает эффективность бизнеса, либо начинающие программисты не проходят должного обучения.
- Разработка параллельно в нескольких ветках порождает дополнительные обязательства по интеграции: чем больше изолированных изменений, тем выше технический долг, связанный со слиянием (merge).
- Откладываемая рефакторизация: по мере изменения требований становится ясно, что части кода требуют переработки, но если откладывать её, долг растёт[7].
- Несоответствие отраслевым стандартам и пренебрежение широко используемыми технологиями (framework–ами), что усложняет последующую интеграцию и удорожает техническое обслуживание[6].
- Недостаток знаний у разработчиков о том, каким должен быть качественный код.
- Отсутствие «хозяина» кода: при передаче разработки на аутсорсинг внутри компании может возникнуть потребность пересмотра или переписывания результата — это становится новым долгом.
- Слабое технологическое лидерство и принятие стратегических решений без оценки технических последствий.
- Внесение срочных изменений в последний момент, на которые, как правило, не хватает времени и ресурсов для грамотной реализации, тестирования и документирования.
Возникновение и устранение технического долга
Кеннет Рубин описывает стадии существования технического долга в аспектах его обнаружения и ликвидации:[8]
- Обнаруженный случайно технический долг — долг, о существовании которого команда не знала до тех пор, пока не столкнулась с ним непосредственно в ходе работ: например, при добавлении новой функции старое неэффективное решение обнаруживается в коде, написанном бывшими сотрудниками.
- Известный технический долг — долг, признанный и зафиксированный командой, но пока не решённый.
- Технический долг в работе — долг, внесённый в бэклог и поставленный в план доработок.
Последствия
«Проценты» по техническому долгу — это дополнительные издержки, связанные с необходимостью регулярного обслуживания или устранения накопленных проблем в программном обеспечении. Такими издержками могут стать постоянные поддержки, рост количества обращений пользователей, потеря производительности и удорожание дальнейшей доработки из-за снижения качества кода. Чем дольше откладывается устранение технической задолженности, тем она значительнее возрастает, и тем дороже её погашение в будущем, особенно если система продолжает развиваться. Погашение задолженности происходит через выполнение отложенных, требуемых для устранения проблем работ.
Технический долг — одна из главных причин срывов сроков проектов: трудно точно оценить объём скрытой и незавершённой работы (т.е. долга), связанный с каждым новым изменением, так как неопределённость нарастает по мере накопления долга. Когда долг превышает доступное время, проект не успевает к сроку. Для предсказуемости выпуска команду рекомендуют ограничивать количество параллельно находящихся в работе задач, чтобы сдерживать рост незавершённых работ (долга).
Если критерием выпуска продукта служит только готовность задекларированных функций, проект может быть выведен в продакшн с существенным техническим долгом. В дальнейшем любая доработка, вынужденная погасить этот долг, может повлечь риски для бизнеса: прерывание работы, финансовые потери и юридические проблемы при нарушении SLA. В этом смысле выпуск проекта с непогашенным техническим долгом можно рассматривать как «увеличение процентной ставки» по задолженности, а снижение этой ставки возможно только при отключении либо полном переписывании системы.
В своей книге «Рефакторинг к шаблонам» сходный аргумент относительно «долга проектирования» приводит и Дж. Кериевски[9].
К видам работ, откладываемых и тем самым увеличивающих технический долг, относят документирование, подготовку тестовых сценариев, доработку незавершённых фрагментов кода, исправление предупреждений компиляторов и результатов статического анализа. Другие факторы долга — несистематизированные знания в организации и слишком запутанный для модификации код.
Грейди Буч также отмечал схожесть между развитием городов и эволюцией сложных программных систем — во многом из-за технического долга и пренебрежения рефакторингом.
В открытом ПО откладывание отправки изменений обратно в оригинальный проект (upstream) также рассматривается как форма технического долга.


