Каждому разработчику знакома ситуация, когда реализация новой возможности в системе занимает большое количество времени, но релиз уже близко, а тимлид или менеджер проекта пятый раз за день задают уже надоевший вопрос: “Ну когда будет готово?”. И тогда встает непростой выбор — сделать все правильно и не уложиться в сроки релиза или реализовать минимально работающий, но не идеальный с точки зрения технического решения, функционал. Очевидно, что в большинстве случаев будет выбран второй вариант, так как релиз и предоставление результата клиентам здесь и сейчас важнее чистоты кода и архитектуры системы. Но проходит несколько месяцев, и вот уже старое не идеальное техническое решение мешает реализации другого функционала. И дальше такие решения будут накапливаться в огромный ком. Разбираясь с этой проблемой, очень важно сделать правильные выводы и выбрать нужное решение. От этого решения будет зависеть дальнейшая судьба всего проекта. В данной статье мы постараемся разобраться с природой технического долга и посоветовать пути его устранения.
Природа технического долга
Само понятие технического долга впервые ввел Уорд Каннингем (Ward Cunningham), разработчик технологии wiki и один из создателей экстремального программирования. В 1992 г. в своей статье он сформулировал это понятие в виде метафоры финансового долга: так же, как и при финансовом займе, разработчики могут получить дополнительные средства здесь и сейчас за счет использования быстрых и не оптимальных технических решений, но неизбежно будут расплачиваться за них при дальнейшей разработке, в независимости от того, как будет выплачен этот долг — постепенными выплатами процентов или одним платежом.
Но если проблема технического долга была описана еще 25 лет назад и встречается практически на любом проекте, почему еще нет методики управления проектами, которая позволяла бы избежать само появление технического долга? Ответ кроется в самом понятии проекта. Одним из ключевых отличий проекта от других видов деятельности является уникальность конечного продукта. Там где уникальность, там и непредсказуемость, и именно она порождает изменения на проекте и вносит трудности в первоначальное проектирование системы.
Конечно, можно попытаться построить архитектуру, предусматривая возможные изменения, но здесь команда столкнется с таким понятием как “кошелёк Миллера”: правилом, при котором в кратковременную память человека можно «положить» одновременно не более девяти «монет». А если количество элементов превышает это значение, то
Можно попытаться делить компоненты на более мелкие, чтобы уложиться в этот “кошелек”, но сложности от этого меньше не станет, да и количество абстракций при таком подходе будет расти с катастрофической скоростью. А как известно, любую проблему можно решить путём введения дополнительного уровня абстракции, кроме проблемы слишком большого количества уровней абстракции.
Другие команды предпочитают вообще отказываться от первоначального проектирования, максимально стараясь использовать по ходу разработки универсальные инструменты. С одной стороны, это проще, чем пытаться предсказывать изменения и на первых этапах система будет получаться достаточно гибкой к изменениям. Но со временем, сложность системы, согласно второму правилу Лемана, неизбежно будет расти, она станет менее гибкой, и могут возникнуть изменения, идущие вразрез с текущей архитектурой. В этом случае разработчики будут также тратить больше времени на решение архитектурных проблем.
Так или иначе, неизбежность изменений на проекте провоцирует появление технического долга.
Как определить, что на проекте есть проблема технического долга
Важнейшим показателем того, что на проекте есть проблема с техническим долгом, это, конечно же, сам код. Прежде всего, стоит сказать об особенности написания кода. Дело в том, что написание и чтение кода — два совершенно разных процесса. Когда разработчик пишет код, он сосредоточен лишь на контексте задачи. Но изменение отдельного участка кода влияет на общую картину происходящего. В свою очередь, прежде чем изменять написанный код, нужно иметь представление не только о конкретном участке, но и обо всей картине в целом. Но при чтении, границы контекстов, в рамках которых был написан код, стираются на общем представлении. Такая разница между чтением и написанием кода генерирует дополнительную сложность, которая прямым образом влияет на его качество.
На что следует обратить внимание:
- Участки кода, которые часто подвергаются изменениям. Скорее всего эти участки требуют серьезной доработки.
- Большое количество пометок FIXME и TODO и малое количество комментариев в коде должно насторожить. Современные IDE имеют встроенную поддержку работы с такими метками, так что это один из самых быстрых и надежных способов распознавания слабых мест в системе.
- Отсутствие тестов. Без них у разработчиков нет уверенности в том, что их изменения не нарушат работу системы. Команда относится к коду, не покрытому тестами как к карточному домику, стараясь избегать лишних, а порой необходимых, изменений.
- Отсутствие документации. Ситуация схожа с предыдущем пунктом. Отсутствие регламентированной информации заставляет разработчика самому додумывать картину происходящего, и есть вероятность, что у него сложится неверное представление о системе. Ситуация усугубляется тем, что в подавляющем большинстве случаев на проекте работают разработчики разного уровня подготовки и компетенции. А различие в понимании кода еще сильнее усложняют процессы чтения и написания кода.
- Устаревшие технологии и инструменты разработки. Любая библиотека или модуль обновляется, а поддерживать старые версии со временем становится все сложнее и затратнее.
- Отсутствие стандартов разработки. Каждый разработчик делает что и как он хочет.
Методы устранения технического долга
- Как и при лечении любой болезни, самый первый шаг к выздоровлению — это признание себя больным. Действительно, в первую очередь каждый участник проекта, от заказчика до разработчика должен признать проблему нарастания технического долга. Не так давно я стал тимлидом на одном крупном проекте, который достался нам в наследство, и работа по техническому долгу на нем никогда не велась. Копаясь в огромном количестве задач, я постоянно натыкался на задачи по устранению технического долга, которые создавались разными людьми в разное время, но так и не были реализованы. Это говорит о том, что попытки справиться в одиночку с технически долгом сравнимы с боем с ветряными мельницами. Очень важно, чтобы участники проекта осознавали эту проблему, ведь ее решения требуют исключительно системного подхода.
- Используйте гибкие методологии разработки (Agile). Основная суть методик состоит в разбиении разработки на небольшие, изолированные итерации длиной от одной до четырех недель. Таким образом обходится ограничение “кошелька Миллера”, ведь теперь в каждой итерации нужно работать только с ограниченным потоком информации, в котором легче управлять сложностью, и соответственно, техническим долгом.
- Введите общий и понятный всем регламент по работе с техническим долгом. Создайте бэклог, в котором будут находиться задачи на его выплату. И при добавлении нового функционала или при планировании следующей итерации уделяйте время на выполнение этих задач. Можно попробовать выделить время только на выполнение этих задач, но тогда разработка нового функционала зависнет, и скорее всего, вы столкнетесь с непониманием со стороны бизнеса. В своем проекте мы решили выделять 20%-30% времени от очередной итерации на погашение технического долга.
- Создайте метрики, по которым будет удобно следить за выполнением технического долга. Такие метрики индивидуальны для каждого проекта. Например, для своего проекта мы выделили такие метрики, как процент покрытия тестами и документацией, соответствие кода с принятыми Style Guides и сложность разворачивания системы на локальном окружении разработчика. Некоторые из метрик собираются автоматически, некоторые только субъективно каждым разработчиком. Важно, чтобы эти метрики были доступны всем, каждый участник видел прогресс и был согласен с ним.
Заключение
Проблема технического долга весьма актуальна на данный момент, и для каждого проекта требуется индивидуальный подход к проблеме его устранения.
Не стоит бояться выплат, ведь если принять правильную стратегию, то технический долг станет той силой, которая будет заставлять развиваться ваш проект. Именно работа с техническим долгом показывает уровень зрелости как самого проекта, так и команды, которая над ним трудится.
Автор: SSul