Технический долг. Кому и что я должен?

Давайте представим Васю — сферического программиста в вакууме. Вася работает в хорошей компании.

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

Что же такое технический долг?

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

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

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

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

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

Разновидности технического долга

  1. Осознанный (умышленный) — программист отказывается от гибкости кода или от покрытия кода тестами, выигрывая время.
  2. Неосознанный — неопытность программиста в использовании конструкций языка программирования или применении фреймворков и платформ.
  3. Технологический — затягивание с обновлением версии платформы и фреймворков.
  4. Архитектурный — необходимость переработки архитектуры под новые требования.

Причины технического долга

  1. Давление бизнеса. Когда бизнес заставляет выкатить фичи раньше, чем они будут полностью доделаны. В этом случае в коде появляются заплатки и костыли, которые скрывают недоделанные части проекта.
  2. Отсутствие понимания последствий технического долга. Когда бизнес не понимает, что технический долг имеет «проценты» — в виде замедления темпа разработки, по мере накопления долга. Из-за этого слишком сложно выделить время команды на рефакторинг, так как руководство не видит в этом ценности.
  3. Отсутствие борьбы с жёсткой связанностью компонентов. Когда проект напоминает монолит, а не связь отдельных модулей. В этом случае любые изменения одной части проекта затрагивают другие. Командная разработка затруднена, так как сложно изолировать участки работы отдельных людей.
  4. Отсутствие тестов. Отсутствие немедленной обратной связи поощряет быстрые, но рискованные исправления (читай «костыли»), иногда прямо на продакшене. Эффекты от этого бывают катастрофические. Например: невинный хот-фикс рассылает тестовое письмо по всей базе клиентов или удаляет реальные данные клиентов в базе данных.
  5. Отсутствие документации. Замедляет введение новых людей в проект. Может полностью остановить разработку, если ключевые люди покидают проект.
  6. Отсутствие взаимодействия между членами команды. Когда база знаний не распространяется по организации, люди работают с устаревшим пониманием процессов и знаний о проекте. Положение усугубляется, когда младшие разработчики неправильно обучаются их наставниками.
  7. Долговременная одновременная разработка в нескольких ветках. Может вызвать накопление технического долга, который необходимо восполнить при слиянии изменений воедино. Чем больше изменений, которые сделаны изолировано, тем больше итоговый технический долг.
  8. Отложенный рефакторинг. Требования к проекту постоянно изменяются и в определённый момент может стать очевидным, что части кода устарели, стали громоздкими и должны быть переработаны под новые требования. С другой стороны, программисты проекта каждый день пишут новый код, работающий с устаревшими частями. Поэтому, чем дольше задерживается рефакторинг, тем больше зависимого кода придётся перебирать в будущем.
  9. Отсутствие контроля за соблюдением стандартов. Каждый участник проекта пишет код так, как считает правильным (читай «так, как он писал на прошлом проекте»). В итоге код проекта превращается в салат из стилей кодирования, затрудняя понимание всем членам команды.
  10. Отсутствие компетенции. Когда разработчик просто не умеет писать качественный код.

Когда же можно брать технический долг?

  1. Стратегическое видение проекта позволяет ценой долга получить оперативный отклик заказчика и сформировать требования. Например: стремление захватить рынок или создать прототип.
  2. Быстрая отгрузка системы важнее «чистого» кода («исправим позже»). Например: реакция на изменения законодательства.
  3. «Одноразовый» код не требующий выплат. Например: проекты принципиально не предполагающие поддержку.

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

Принятие   

Отклонение

✓  Временное ускорение

✗  Замедление разработки

✗  Утрата гибкости и усложнение изменений

✓  Упрощение будущих изменений

✗  Неконтролируемый и грязный код низкого качества

✓  Поддержание качественной кодовой базы

✗  Чрезмерная специализация разработчиков

✓  Небольшие затраты времени на изучение кода

✗  Вероятно «Техническое банкротство» — неизбежная потребность в полном переписывании продукта ✓  Отсутствие «Технической инфляции» — технологического отставания от индустрии

Жизненный цикл технического долга

Размер технического долга — показатель качества ПО.

 Стандарт ISO 9126 (iso 25010)

Как погашать технический долг?

На уровне релиза (долгосрочная перспектива):

  1. Закладывайте время на работу с техническим долгом.
  2. Анализируйте ваш технический долг.
  3. Устанавливайте рабочие соглашения в команде.
  4. Выделяйте время на образование.

На уровне итерации (среднесрочная перспектива):

  1. Поддерживайте высокий уровень покрытия тестами.
  2. Контролируйте накладные расходы, вызванные техническим долгом.
  3. Насколько вы удовлетворены от работы с вашим кодом?
  4. Учитывайте зависимости между разными составляющими технического долга.
  5. Проводите ретроспективы.
  6. Создавайте истории по работе с техническим долгом.
  7. Используйте непрерывную интеграцию.

На уровне истории пользователя (краткосрочная перспектива):

  1. Просматривайте чужой код.
  2. Практикуйте парное программирование.
  3. Придерживайтесь стандартов кода.
  4. Сделайте технический долг видимым.

 Подведем итоги

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