Выплачиваем технический долг с пользой для бизнеса
Решать, как развивать продукт, довольно непросто. Нужно учитывать десятки разных факторов, и некоторые из них — непредсказуемые. Часть решений явно или косвенно принимается технической командой, в том числе стратегия по работе с техническим долгом. Тема эта старая, сложная, мало кого оставляет равнодушным — этим и интересна.
Мне повезло увидеть данную проблему со стороны девелопмента, менеджмента и бизнеса, и я благодарна всем, кто вел со мной длинные споры и обосновывал свою точку зрения. Я считаю, что подход, основанный на всеобщих интересах, работает лучше всего. Хотя на практике не совсем очевидно, как его выработать.
Митинг
Менеджмент (радостно): мы согласовали все детали и запускаем новую фичу!
Девелопмент (недовольно): у нас устарела либа для отрисовки графиков, ужасная сортировка в старом модуле. И мы уже полгода не можем привести в порядок структуру проекта, после того как маркетингу срочно понадобилось переименовать тему.
QA (озабоченно): не работает апгрейд с AmEx картами и не применяются кастомные темы, это нужно забрать в следующий milestone.
На таких митингах кажется, что у всех разные цели. Бизнес уже наступал на грабли инвестиций в девелопмент без видимого результата. Тимлид знает, что накопленные костыли рано или поздно выстрелят ему в ногу. А QA на прошлой неделе 10 минут рассказывал на ретроспективе «what we should start doing», после того как ключевые юзеры зарепортили баги напрямую CEO.
Для многих команд крайне важно качество продукта, и когда им в очередной раз отказывают выделить время на рефакторинг, они теряют энтузиазм и мотивацию. Звучит знакомо?
— Знаешь, мне надоело. Не хотят поддерживаемый продукт — буду делать, как скажут, сами пусть потом разбираются, когда станет проще с нуля все переписать.
— Я так не могу, мне стыдно, что в продукте такой код. У меня в субботу будет время, пойду наведу порядок, хотя бы где успею.
— Тима очень настаивала, мы выделили один спринт под рефакторинг, смогли согласовать с клиентом, но вчера после демо он остался недоволен и попросил сфокусироваться на business priorities.
Мы за все хорошее
То, что кажется разными проблемами, на самом деле является одной и той же. И бизнес, и QA хотят, чтобы как можно меньше значимых юзеров встретили баги. Бизнес заинтересован развивать продукт с наименьшими затратами и как можно быстрее. Девелопмент заинтересован иметь качественный codebase, который легко поддерживать и куда можно наращивать фичи без опасения наткнуться на хрупкий, загадочный и немасштабируемый legacy. Что соответствует бизнес-целям тоже:
- меньше значимых юзеров — значит, что баг становится проблемой, когда касается большого процента target audience (в основном это те, кто приносит прибыль или потенциально может ее принести);
- наименьшими затратами = легко поддерживать = наращивать фичи, только речь идет не об абстрактной фиче, а о том, что уйдет в работу в ближайшее время.
На примере одного беклога
Давайте посмотрим на практике (баги техническим долгом не считаются, но часто фигурируют где-то рядом, поэтому глянем и на них). В беклоге лежит:
Issue | Description |
update PrettyCharts library | Либа, которую используют для отрисовки графиков, устарела на две версии. |
an error when trying to setup custom theme | У всех юзеров, которые пытаются настроить кастомный UI, прилетает 500 с сервера, и настройки не сохраняются. |
payment fails when upgrading with AmEx card | Не проходит апгрейд, если карточка — AmEx. |
apply new sorting logic to the old module | В новых модулях сделали элегантную сортировку, а в старом оставили изначальное корявое решение, сделанное наспех. |
duplicate folders theme and theme_golden | Когда-то тема в приложении была одна, потом добавились другие темы, и дефолтную переименовали в Golden. В коде часть файлов от нее осталась лежать в папке theme, часть перенеслась в theme_golden. |
Все айтемы заслуживают внимания, баги серьезные. В соответствии с best practices либы надо вовремя обновлять, сортировка должна быть consistent везде, а с папками вообще фейспалм. Окей.
В то же время все айтемы сами по себе никому не мешают до тех пор, пока кто-то не столкнется с проблемой. Например, коряво реализованная сортировка в старом модуле становится проблемой, когда в этой части кода надо что-то менять. То же — с багами: наличие бага само по себе не страшно, все зависит от контекста — в каком случае он попадается юзерам и как много людей его встретят.
Добавляем к нашим айтемам контекст и описываем, почему это проблема.
Issue | Description | Context |
update PrettyCharts library | Либа, которую используют для отрисовки графиков, устарела на две версии. | В последней версии либы лучше производительность и есть два новых типа графиков. Если нужен будет экспорт ежедневных отчетов, старая либа с ним не справится. |
an error when trying to setup custom theme | У всех юзеров, которые пытаются настроить кастомный UI, прилетает 500 с сервера, и настройки не сохраняются. | Фича доступна только платным юзерам. По статистике, из платных юзеров 10% пробуют ставить кастомный UI. |
payment fails when upgrading with AmEx card | Не проходит апгрейд, если карточка — AmEx. | Применимо для платных юзеров, чьи подписки созданы до 2019 года. Таких 1%. |
apply new sorting logic to the old module | В новых модулях сделали элегантную сортировку, а в старом модуле оставили изначальное корявое решение, сделанное наспех. | В старом модуле сортировка работает очень медленно, если записей больше 5000. Добавить сортировку по еще одному столбцу очень сложно. |
duplicate folders theme and theme_golden | Когда-то тема в приложении была одна, потом добавились другие темы, и дефолтную переименовали в Golden. В коде часть файлов от нее осталась лежать в папке theme, часть перенеслась в theme_golden. | В эти папки приходится заглядывать в среднем два раза в неделю каждому фронтэндщику, и уходит лишних 20 минут, потому что непонятно, что где искать. |
Дальше узнаем, что по роадмапе нужно делать:
- onboarding for corporate clients;
- generate annual reports in the old module, use CoolAPI.
И возвращаемся к нашему митингу, где мы решаем, что дальше делаем. Помним, что бизнес хочет побыстрее, для этого девелоперам нужна поддерживаемость, и все хотят, чтобы как можно меньше значимых юзеров встретили баги.
Issue | Description | Context | Decision |
update PrettyCharts library | Либа, которую используют для отрисовки графиков, устарела на две версии. | В последней версии либы лучше производительность и есть два новых типа графиков. Если нужен будет экспорт ежедневных отчетов, старая либа с ним не справится. | С текущей производительностью проблем нет, новые типы графиков и ежедневные отчеты пока не нужны. Старая либа не будет ни для кого головной болью. (Конечно, если апдейт — дело получаса, он просто берется и делается, но, допустим, это не наш случай) |
an error when trying to setup custom theme | У всех юзеров, которые пытаются настроить кастомный UI, прилетает 500 с сервера, и настройки не сохраняются. | Фича доступна только платным юзерам. По статистике, из платных юзеров 10% пробуют ставить кастомный UI. | 10% платных юзеров — повод задуматься, но это не core feature, юзерам работать баг не мешает, продукт они не забросят, разочарованные в саппорт писать не будут, и QA тоже может быть спокоен. Однако в роадмапе есть onboarding for corporate clients, а все корпоративные клиенты будут использовать кастомные темы, поэтому нужно чинить. |
payment fails when upgrading with AmEx card | Не проходит апгрейд, если карточка — AmEx. | Применимо для платных юзеров, чьи подписки созданы до 2019 года. Таких 1%. | Очень маленькая вероятность, что кто-то попадет на этот баг, и даже если это произойдет, саппорт может сделать апгрейд вручную. Можно оставлять как есть. |
apply new sorting logic to the old module | В новых модулях сделали элегантную сортировку, а в старом модуле оставили изначальное корявое решение, сделанное наспех. | В старом модуле сортировка работает очень медленно, если записей больше 5000. Добавить сортировку по еще одному столбцу очень сложно. | Максимальное количество записей у текущих пользователей — 3000, добавления сортировки по еще одному полю в планах нет. Фича generate annual reports с сортировкой не связана. Значит, с проблемой тоже никто не столкнется. |
duplicate folders theme and theme_golden | Когда-то тема в приложении была одна, потом добавились другие темы, и дефолтную переименовали в Golden. В коде часть файлов от нее осталась лежать в папке theme, часть перенеслась в theme_golden. | В эти папки приходится заглядывать в среднем два раза в неделю каждому фронтэндщику, и уходит лишних 20 минут, потому что непонятно, что где искать. | С проблемой сталкиваются регулярно, поэтому здесь можно явно выиграть в скорости и поддерживаемости (если наведение порядка не потребует месяца, конечно). |
По закрытии этих айтемов бизнес получает свой профит, потому что починили критический баг для corporate clients onboarding и сэкономили 5 часов девелопмента ежемесячно.
Контекст для рефакторинга/багфикса
При обсуждении важности айтемов спрашивайте себя (и других):
- каких компонентов/фичей касается;
- какую конкретно проблему создает текущая реализация;
- какое преимущество дает переделка (например, будет легче вносить изменения, или можно будет переиспользовать код, или вынести в отдельный компонент, и тогда добавление новой такой же сущности будет занимать минуту);
- планируется ли в ближайшее время разработка в этих компонентах;
- какого сегмента пользователей коснется (скажем, нужна оптимизация под мобильные устройства, а с мобильных сидят только пользователи из региона Х, и они не являются target audience);
- для багов — как часто встречается, для какого use case, есть ли workaround.
Рассматривать подобные задачи вне контекста не имеет смысла: можно получить результат, который никому не будет нужен. Скажем, ребята по своей инициативе и в нерабочее время рефакторят кусок приложения, действительно качественно приводят все в порядок, хотят всех приятно удивить и ожидают как минимум благодарности, а их никто не хвалит, потому что сделанная работа на данном этапе никому не была нужна. Как если бы вам бригада на даче клеила обои и заодно решила пол в сарае покрасить, а вы как раз думали, то ли сносить сарай, то ли погреб там рыть.
Проблема аутсорса, как и некоторых in-house команд, в том, что каждый видит свою версию сарая. Бизнес может не делиться планами, девелопмент может о них не спрашивать, и даже если информация о планах всем доступна, могут быть неоднозначности и разные трактовки. Прояснив планы, можно прорабатывать варианты, от которых выиграют все.
«Продаем» рефакторинг
Зная контекст и бизнес-цели на ближайшее время, девелопменту становится просто «продать» рефакторинг. И, с другой стороны, зная, какой именно impact будет от рефакторинга, менеджмент может выставить правильный приоритет. Грубо говоря, мы что-то улучшаем не для его самоулучшения, а чтобы упростить дальнейшее развитие продукта.
Например, «продадим» апдейт фреймворка, который займет существенное время (если апдейт быстрый, то он обычно делается без вопросов):
А. We need to update the framework because the longer we use the old one, the harder it will be to update it in the future. Ценности для бизнеса нет.
В. We need to update the framework. The new version has the methods to receive data in X format and this will allow us to sent instant messages to the customers. Also the performance of pdf exports will improve by 20%. Если бизнесу важны мгновенные сообщения и скорость экспорта, то апдейт фреймворка у вас «купят».
В варианте А девелоперы обычно поднимают вопрос long-term поддерживаемости. Многие в своей практике сталкивались с продуктами, где обновлять зависимости/рефакторить было уже проблематично, и на ранней стадии было бы проще. Если есть аргументы, что апдейт однозначно понадобится потом, поэтому лучше сделать его сейчас, то нужно их приводить, и вариант сводится к чему-то наподобие В.
Если это просто с запасом «на будущее», то высокий риск ненужного результата. Будущее может не наступить (проект не взлетит). Будущее может быть другим (появится другой более интересный фреймворк). Будущему может хватить и старого фреймворка для своих нужд, и в части случаев действительно придется обновлять фреймворк, уже когда слишком много на него завязано. Если на момент принятия решения вероятность последнего исхода или мала, или неизвестна, то ресурсы на него не выделят, потому что будут более приоритетные задачи, которые решают реальные и видимые на тот момент проблемы.
TL;DR
Мы всегда стремимся оптимизировать все вокруг нас, избавляемся от рутины, перекладываем принятие решений на роботов, упрощаем процессы. А еще нам нравится, когда мы делаем что-то значимое, мы не хотим копать «от забора и до обеда», а хотим что-то построить и хвастаться этим. В нашей абстрактной работе потерять фокус и контекст очень просто. Информации много, мы постоянно переключаемся между разными ее уровнями и, к сожалению, можем упустить из виду ценное.
- Само наличие legacy или багов не страшно: важно понимать, что из этого является реальной проблемой на данный момент.
- Понимая бизнес-приоритеты и направление развития продукта, можно «продать» нужный рефакторинг/багфикс, от чего выиграют обе стороны. Бизнес получит быструю разработку, девелопмент — легко поддерживаемый продукт, а ключевые кастомеры будут иметь smooth experience.
- Возвращайтесь к тому, что именно улучшится предлагаемым изменением. Важно ли это?
- Если вы владелец бизнеса, делитесь своими планами с командой как можно чаще. Это поможет принимать более подходящие архитектурные решения и избежать накопления технического долга, а при его наличии — выплатить самый критический.
- Если вы менеджер, добывайте и делитесь информацией о планах и о контексте рефакторинга/багфикса, но сначала сами убедитесь, что поняли, о чем речь =)
- Если вы девелопер, спрашивайте о том, что сейчас важно продукту, помогайте сделать технический долг видимым и облегчайте понимание правильного контекста.