[Перевод] Стратегии выплаты технического долга

image

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

Эта метафора остаётся подходящей и для разработки ПО; кроме того, она содержит в себе намёки на возможные стратегии, которые можно использовать для выплаты технического долга.

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

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

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


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

Плюсы:

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

Минусы:
  • Начинают возникать конфликты слияния, поскольку сотрудники вносят более крупные объёмы архитектурных изменений.
  • При таком хаосе и нестабильности может быть сложно определить, что что-то сломалось, если отсутствует хорошее покрытие тестами.
  • Только из-за того, что вы работаете над техническим долгом, инциденты с поддержкой никуда не деваются. Без сотрудников, способных помочь с переносом обращения за поддержкой на более высокие уровни, работе с техническим долгом гарантированно будет мешать поддержка.

Выделенные Capacity для выплаты технического долга


В такой модели agile-команда резервирует определённое количество поинтов или процент от общей capacity спринта для выплаты технического долга на постоянной основе. Например, в каждом спринте команда может брать 5 сторипоинов разнообразной работы по выплате долга.

Плюсы:

  • Это гарантирует, что выплата техдолга является частью постоянной культуры организации
  • Текущая работа над техническим долгом может предотвратить необходимость более интенсивной работы в будущем.

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

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


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

Плюсы:

  • Частично сохраняется тот настрой, который присутствует в спринтах, выделенных для выплаты технического долга.
  • Благодаря тому, что другие люди продолжают активно работать над стандартными задачами, руководителям проекта не нужно приостанавливать деятельность по проекту
  • Перерывы на поддержку необязательно прерывают работу над техническим долгом
  • Этот вариант позволяет выплачивать за один спринт более крупные части технического долга

Минусы:
  • БОльшие объёмы сосредоточенной на техническом долге работ всё равно могут вызывать значительные конфликты слияний, хотя риск и не так велик
  • Работу сотрудника, занимающегося техническим долгом, с большой вероятностью всё равно будут прерывать и перекидывать его на другие задачи при необходимости дополнительной capacity

Выплата технического долга после завершения работы


В такой модели при планировании разработчиками работы они вносят в план подчистку соседнего кода и выплату обнаруживаемого технического долга, уже находящегося в области работы. Это соответствует принципу бойскаутов: всегда оставляй стоянку (кодовую базу) чище, чем она была до тебя.

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

Похожая концепция приведена в книге Малкольма Глэдуэлла The Tipping Point, где приводится пример с метро Нью-Йорка. Управление городского транспорта выяснило, что если отцеплять вагоны метро, очищать их от граффити и обеспечивать постоянное отсутствие граффити, то можно сэкономить на эффекте разбитых окон, при котором люди считают, что состояние вагонов никого не волнует и уровень преступности может увеличиваться. Сокращая количество «зайцев» и граффити, управление могло также снизить количество насильственных преступлений в метро.

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

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

Плюсы:

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

Минусы:
  • Нет особых возможностей внесения крупных изменений, влияющих на всю систему
  • Вызывает «инфляцию» сторипоинтов из-за того, что с каждым тикетом нужно проделывать дополнительную работу. Это снижает объём работы, который можно выполнить в каждом спринте.


Выше я рассказывал о стратегии выплаты технического долга путём постепенной замены частей системы, как в мысленном эксперименте с кораблём Тесея, но что если этого недостаточно? Что если у вас нет времени заменять всё ПО часть за частью и вам нужно внести более радикальные изменений?

Вот несколько идей, которые могут вам помочь:

Разбиение приложения на более мелкие приложения


При такой методологии мы разбиваем монолитное приложение на мелкие приложения. Часто такой подход дополняется предметно-ориентированным программированием (Domain Driven Design) и/или микросервисами, но основной его смысл заключается в том, что если приложение слишком объёмно для замены, его можно разделить на меньшие части, замена которых реалистична, после чего можно заменять каждую часть, одну за другой.

Также эту схему можно реализовать с помощью шаблона Strangler Application Мартина Фаулера, при котором создаётся новое приложение, получающее те же запросы, что и старое, и осуществляющее вызовы к легаси-системам, пока для каждой из них не будет готова современная замена.

Плюсы:

  • Позволяет стратегически управлять наиболее важными аспектами переписывания без необходимости брать на себя тяжесть всего проекта по переписыванию кода
  • Уменьшение частей приложения уменьшает вероятность полного переписывания кода в будущем

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

Прототипирование приложений в резервной capacity


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

Действуя по этому шаблону, я очень успешно перенёс JavaScript-приложения на TypeScript, в том числе тратя на это время вне работы (не то, чтобы это было обязательно, но я решил сделать так) и ожидая вывода онлайн сред регрессивного тестирования.

Плюсы:

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

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

Полный переход к новому приложению


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

Плюсы:

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

Минусы:

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


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

© Habrahabr.ru