Что такое технический долг
Перейти к содержимому

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

  • автор:

Как избежать ловушки технического долга

//ПОДЛЕЖИТ ИСПОЛНЕНИЮ (шутка!). А теперь серьезно: вы непроизвольно издаете стон, когда видите это? Да, мы тоже.

Dan Radigan

Автор: Dan Radigan

Просмотр тем

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

В начале каждого релиза есть этап, на котором создаются новые функции и (в идеале) выполняются задачи, которые остались невыполненными при последнем релизе (давайте посмотрим правде в глаза: это случается редко). Цикл переходит в стадию разработки альфа-версии, когда каждая функция создана и готова к тестированию. Разработка бета-версии начинается, когда исправлено достаточно багов, чтобы версию можно было продемонстрировать клиентам для получения отзывов. К сожалению, пока команда занята исправлением багов для получения бета-версии, появляются новые баги. Это как бороться с гидрой: исправь один баг, и сразу появятся два новых. Наконец, вы достигаете контрольной точки, когда у вас на руках окончательная версия без неисправленных багов. Чтобы в ней не было неисправленных багов, обычно некоторые известные проблемы устраняют, а остальные (большинство?) откладывают до следующего релиза.

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

Из этой ловушки должен быть какой-то выход.

Agile помогает погасить технический долг

Качество в итеративной разработке обеспечивается за счет Agile, чтобы команда могла выпускать стабильно качественные версии одну за другой. Если функция не соответствует требованиям, она не поставляется. Сложно в это поверить? Секрет в том, чтобы правильно определить (или переопределить) критерии готовности.

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

Главная ветка базы кода должна быть готова к поставке всегда. Это приоритетная задача. Работа над новыми возможностями берет начало в ветке задания, содержащей код этой возможности, а также код автоматических тестов для нее. Когда работа над возможностью завершена и автоматические тесты успешно пройдены, соответствующую ветку можно объединить с главной веткой. Поскольку к качеству предъявляются одинаковые (одинаково высокие) требования на каждой стадии процесса, технический долг удается держать под контролем.

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

Потому что нельзя забывать: чем дольше баги остаются без внимания, тем тяжелее их исправить.

Берем долг команды под контроль

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

Дайте определение

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

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

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

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

Не отводите целые спринты и задания под тестирование

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

Боритесь с багами с помощью автоматизации

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

С чего начать?

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

  • Объясните владельцу продукта, какие реальные последствия несет неконтролируемый рост технического долга. Проверьте оценку сложности будущих пользовательских историй, для выполнения которых нужно погасить существующий технический долг.
  • Используйте модульную архитектуру и четко обозначьте свою позицию по отношению к техническому долгу в новых компонентах или библиотеках в приложении. Когда команда и компания ощутят эффект от следования принципам Agile в процессе работы над этими новыми компонентами, они, несомненно, захотят применить эти принципы и к другим частям кода.
  • Создавайте автоматические тесты! Автоматические тесты и непрерывная интеграция являются лучшей профилактикой багов. При обнаружении бага создайте новый тест, чтобы выявить проблему, а затем устраните ее. Если этот баг появится снова, автоматический тест выявит его раньше, чем с ним столкнутся клиенты.

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

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

Программные системы склонны к накоплению мусора — внутренних недоработок, которые затрудняют дальнейшее изменение и расширение системы по сравнению с идеальным кодом. Технический долг — это метафора, придуманная Уордом Каннингемом. Она объясняет, как воспринимать этот мусор, по аналогии с финансовым кредитом. Дополнительные усилия, необходимые для добавления новых функций, — это проценты по кредиту.

Представьте, что в моей кодовой базе есть модуль путаной структуры. Нужно добавить новую функцию. Если бы структура была ясной, то работа заняла бы четыре дня, но с этим мусором требуется шесть дней. Разница в два дня — это и есть проценты по долгу.

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

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

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

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

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

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

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

Регулярно ведутся дебаты о том, следует ли считать долгом различные виды мусора. Мне кажется, тут полезно учитывать, берётся долг сознательно и разумно — или безрассудно. Так появился квадрат технического долга.

Дальнейшее чтение

Насколько я могу судить, Уорд впервые представил эту концепцию в отчёте для OOPSLA 1992. Она также обсуждалось в вики.

Есть видеозапись, где Уорд Каннингем обсуждает придуманную им метафору.

Дэйв Николетт расширяет взгляд Уорда на технический долг, приводя прекрасный пример того, что я называю разумным преднамеренным долгом.

Несколько читателей предложили другие годные метафоры. Дэвид Панарити назвал некачественную разработку дефицитом программирования. Судя по всему, он начал использовать этот термин несколько лет назад, когда он соответствовал политике правительства; полагаю, теперь это снова актуально.

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

Стив Макконнелл выделил в метафоре несколько хороших моментов. В частности, как уменьшение непреднамеренного долга оставляет больше возможностей намеренно принять долг, когда это полезно. Мне также нравится его формулировка минимальных платежей (которые слишком высоки, чтобы исправить проблемы во встраиваемых системах, но не на сайтах).

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

Эрик Дитрих обсуждает человеческие потери из-за технического долга: сражения в командах, деградация навыков и выгорание.

Правки

Первоначально этот пост был опубликован 1 октября 2003 года. Я полностью переписал его в апреле 2019 года.

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

preview

Что такое технический долг, как он накапливается и что с ним делать.

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

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

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

Основные правила

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

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

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

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

На что обратить внимание

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

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

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

Тестирование

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

Профилирование и мониторинг приложения

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

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

Наличие багтрекинговой системы

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

Наличие архитектурного анализа проекта

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

Наличие перспективного анализа проекта

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

Контроль версионной актуальности и совместимости используемых решений

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

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

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

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

Таким образом для борьбы с техническим долгом необходимо регулярно (лучше всего на ежедневной основе) искать проблемные места, внедрять инструмента контроля и профилирования, планировать изменения и обновлять кодовую базу. Самое главное – стараться сдерживать рост технического долга и оставлять его максимально небольшим.

Что такое технический долг и как с ним бороться

Что такое технический долг и как с ним бороться

В этой заметке я хочу рассмотреть понятие технического долга в разработке продуктов и работу с ним с точки зрения СTO, Технического директора или другого человека кто несет ответственность за разработку и находится в непосредственном контакте с бизнесом.

Определение и некоторые причины возникновения

Для начала давайте определимся с понятием «Технический долг» и познакомимся с некоторыми возможными причинами его возникновения.

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

Причин возникновения техдолга может быть несколько:

  1. Сроки и давление: Когда «сроки горят», разработчики могут сократить усилия над оптимизацией и качеством кода.
  2. Отсутствие ресурсов: Недостаток времени, бюджета или квалифицированных специалистов может привести к неоптимальным решениям.
  3. Недостаточное понимание: Иногда разработчики могут не до конца понимать последствия своих технических решений.
  4. Профессиональное развитие и пересмотры решений: Профессиональное развитие разработчиков и пересмотры ранее реализованных задач, включая замену участков кода на более эффективные библиотеки, также могут стать причинами появления технического долга.
  5. Отсутствие структуры и стандартов: Если в команде отсутствуют четкие стандарты кодирования и архитектурные рекомендации, это может привести к созданию неоптимального кода.

Управление и минимизация технического долга

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

С точки зрения главного технического специалиста (СTO, Технического директора, руководителя разработки), я разделяю работу с техдолгом на два типа по своей направленности:

  1. условно внешняя работа, направленная на взаимодействие с владельцами бизнеса и теми кто ответственен за развитие продукта;
  2. внутренняя — работа направленная на построение и оптимизацию процессов разработки внутри подразделения разработки.

Внешняя работа

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

Вот несколько подходов, которые можно использовать СTO для успешного сотрудничества:

  1. Прозрачность и общение: Открытое общение между разработкой и ответственными за продукт – ключевой фактор. Важно обсуждать понятие технического долга, его важность, последствия и риски с обеих сторон. Вы, как ответственный за разработку, обязаны объяснять бизнесу, как накопление технического долга может повлиять на будущее развитие и стабильность продукта.
  2. Обучение и понимание: Объясняйте ответственным за продукт, как технический долг влияет на качество и развитие продукта. Помогает также показать, как устранение технического долга может сэкономить время и ресурсы в будущем.
  3. Общие цели: Помимо функциональности, продукт также должен быть стабильным, безопасным и поддерживаемым. Вы, как руководитель разработки, и ответственные за продукт должны совместно определять ключевые технические аспекты, которые необходимы для достижения общих целей.
  4. Приоритизация в задачах: Добивайтесь включения задач по устранению технического долга в список задач по развитию продукта и позволяйте команде разработки регулярно выделять время на эту работу. Оценивайте влияние каждой задачи на продукт и его будущее развитие.
  5. Итеративный подход: совместно с продуктом придите к соглашению о внедрении практики постепенного рефакторинга и улучшения кода. Это позволит сбалансировать процесс разработки и устранения технического долга.
  6. Участие в принятии решений: Включайте представителей обеих сторон в принятие решений о том, какие задачи будут приоритетными. Это поможет достичь баланса между добавлением новой функциональности и устранением технического долга.
  7. Мониторинг и измерения: Введите практику учета технического долга, используя метрики и инструменты для оценки качества кода. Это позволит обеим сторонам видеть, какие усилия требуются для его устранения.

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

Работа внутри подразделения

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

Ниже я приведу несколько советов, как можно настроить или улучшить работу с техническим долгом внутри разработки.

  1. Оценка и приоритизация. Первым шагом идентифицируйте технический долг. Это можно сделать путем аудита кодовой базы, ревью кода, общения с разработчиками. После этого важно приоритизировать задачи на основе их влияния на продукт и степени сложности.
  2. Использование средств управления задачами (очевидный для нашего времени совет, но мало ли). Добавляйте задачи, связанные с устранением технического долга, в систему управления задачами (например, Jira, Trello). Это позволит избежать потери информации, следить за их выполнением, назначением ответственных и отслеживанием прогресса.
  3. Регулярные код-ревью. Введите практики регулярных код-ревью если у вас еще этого нет. Это поможет выявлять технический долг на ранних этапах разработки. Коллективный обзор кода способствует обмену опытом и повышает качество кода.
  4. Автоматизированные тесты. Создавайте и поддерживайте автоматизированные тесты. Это позволит быстро выявлять регрессии и ошибки при внесении изменений в код, а также поможет избежать накопления технического долга в будущем.
  5. Внимание к архитектуре. Регулярно обновляйте и модернизируйте архитектуру продукта. Это вам поможет избежать накопления устаревшего кода и улучшит его масштабируемость и поддерживаемость.
  6. Рефакторинг. Регулярно вносите изменения в код с целью улучшения его качества, читаемости и эффективности. Рефакторинг позволит постепенно устранять технический долг без серьезных перерывов в разработке.
  7. Обучение и обмен опытом. Проводите регулярные технические митапы, внутренние семинары и обучение. Эти мероприятия помогают повысить знания и навыки команды.
  8. Четкие стандарты и рекомендации. Установите стандарты кодирования и архитектурные рекомендации. Это позволит создавать единообразный и качественный код.

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

Заключение

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

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

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

#techdebt #dechnicaldebt

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *