Рефакторинг без отрыва от производства: пьеса в трех частях
Мы записали историю от Алексея Катаева, руководившего разработкой интерактивной платформы для обучения английскому - основного продукта Skyeng. Эту платформу давным-давно начали писать еще основатели на JQuery и пятом PHP, а сейчас она живет на четвертом Symfony и восьмом Angular. За все это время ее ни разу не переписывали с нуля.
— Леша! Давай перепишем все с нуля! Здесь уже отрефакторить ничего нельзя! — С таким предложением ко мне приходят Дима и Катя, это мои разработчики.
— Ну так а что ж вы не рефакторили все это время?
— Это все Глеб. Глеб заставляет нас каждый день пилить фичи и говорит, что на рефакторинг нет времени.
И, естественно, предложение Димы и Кати отклоняется. Но проблема остается!
Глава первая, где мы договариваемся с Глебом
Мы вместе с Димой и Катей отправляемся говорить с Глебом. Поскольку у нас в Skyeng разработчики разбросаны по всему миру и работают удаленно, встречаемся мы в Hangouts.
— Глеб! — Говорят Дима и Катя. — Если мы будем и дальше быстро пилить фичи и не будем рефакторить, у нас будет плохой код!
— Ну и что, что плохой? Зато он приносит деньги, — парирует Глеб.
Не получилось. Ладно, пробуем зайти с другой стороны:
— Глеб! Если мы будем быстро катить фичи, то в конце концов наш проект ждет катастрофа!
— Ооо, быстро катить фичи? — Оживляется Глеб. — Да! Я как раз хотел на этой неделе проверить 10 гипотез; они должны принести много денег.
Вот такой у нас Глеб, все у него только деньги на уме. За это его и ценят, собственно. Коли так, попробуем задеть его за живое:
— Глеб! Если мы не будем рефакторить, мы не сможем быстро проверять гипотезы и впиливать твои прекрасные новые фичи, должные принести много денег. Если мы не будем рефакторить, стабильность нашего проекта упадет, у нас будет куча багов, мы начнем терять деньги. Глеб! Скоро мы не сможем нанимать классных разработчиков, мы будем тратить на их поиск кучу денег, а они будут приходить и говорить “да не хочу я работать с вашим плесневелым легаси!”. А если уйдут Дима и Катя, это вообще будет катастрофа.
Но это не все: перед тем, как мы пошли к Глебу, я дал Диме и Кате почитать книгу “Договориться можно обо всем!” Гэвина Кеннеди. Они знают, что мало просто напугать Глеба, надо выдвинуть конкретное предложение:
— Глеб! Давай будем тратить на рефакторинг 20% времени! Только в этом квартале, а в следующем, когда разберемся с основными проблемами, - всего 15%! А взамен мы предлагаем тебе Изолированные Костыли™!
— Окей, — наконец говорит Глеб. — 20% мы можем себе позволить, особенно если благодаря этому мы не будем терять деньги.
Почему у нас получилось?
- мы договаривались, а не жаловались;
- мы искали общий язык, зашли с важной для Глеба стороны;
- мы выдвинули конкретное предложение.
Глава вторая, где мы учимся рефакторить без отрыва от выкатывания фич
— Ну что, Дима и Катя, теперь у нас 20% времени на рефакторинг!
Но Дима и Катя почему-то в задумчивости:
— А что же мы будем делать с фичами, которые не докатились, что же делать с критичными багами, которые срочно нужно фиксить?..
Уходят думать и возвращаются с предложениями:
— Давайте откусим 20% от квартала одним блоком и будем в это время сфокусированно рефакторить, — предлагает Дима.
— Погоди, Глеб ни за что на это не пойдет. Он скажет: “Как мы можем остановить производство наших фич и проверку гипотез?” А вариант отложить это на конец квартала не сработает, там всегда найдется, что делать, плюс времени, конечно, не останется.
— Ну тогда давайте включим в оценку, — предлагает Катя. — Типа, задачу делать десять часов, рефакторить еще шесть, скажем, что оценка - 16 часов.
— Катя! Тогда мы будем рефакторить только какие-то мелочи и не сможем сделать крупный рефакторинг. Кроме того, если мы будем говорить Глебу, что у этой задачи time to market 16 часов, а не 10, мы будем обманывать Глеба. Вот тебе, Катя, книга Сэма Харриса “Ложь”, в ней говорится о том, что в долгосрочной перспективе говорить правду всегда выгоднее. Твой вариант тоже не катит!
Что же остается?
Остается рефакторить параллельно с разработкой. И для сначала понять
Сколько времени выделять на рефакторинг
Допустим, мы посчитали часы, вычли отпуска, перемножили на разработчиков и получилось у нас условные 100 часов разработки в месяц. Значит ли это, что теперь мы 20 из них будем тратить на рефакторинг?
Нет.
Не все время разработчика уходит на, собственно, программирование. Поскольку у нас есть ворклоги, мы можем точно сказать, что примерно треть тратится на общение, ревью, стендапы и прочую подобную муть, и лишь две трети - на саму разработку. При этом разработка - не только работа над продуктом, это также фиксы багов и, собственно, рефакторинг. В результате получается, что теперь мы на рефакторинг можем выделить 13 часов из ста, это и будут те самые 20%, обещанные Глебу.
Итак, Катя и Дима взяли задачу, рефакторили честные 13 часов в начале месяца, а потом отправились привычно тестировать гипотезы и выкатывать фичи. Наступил конец месяца, и что? Как всегда, что-то где-то зафакапилось, приходит Глеб:
— Что-то вы много рефакторите, не успеваете работать над продуктом, давайте отменять.
Чтобы этого не происходило, мы написали бота Арсения. Он контролирует, сколько фактически времени с начала месяца у нас ушло на рефакторинг.
Окей, мы определились, когда рефакторить. Теперь надо решить,
Что именно рефакторить
Катя и Дима предлагали нам переписать все с нуля.
— Нет, ребят, переписывать с нуля мы не будем.
— Почему?
— А потому, что у нас есть принцип 2.15:
— Мы будем бороться с техническим долгом.
— А что такое технический долг? — Для них это что-то непонятное, размытое. — Давай мы просто будем видеть какую-то проблему и сразу ее исправлять.
— Нет, это нам не подходит. Мы тогда вообще не будем видеть света в конце тоннеля, ведь у нас бесконечное число проблем.
— Ну давай ты составишь нам список самых критичных, будем работать с ними!
Проблема в том, что код я давно уже не пишу, поэтому смутно представляю себе, какие там в нем на самом деле проблемы. А кто представляет? Конечно, разработчики - Катя с Димой! Пусть сами их и перечисляют.
Делаем доску в Трелло и говорим:
— Народ, пусть каждый напишет сюда карточки с проблемами, которые видел: костыли, кривые решения, старые библиотеки, старые API и т.д.
Когда я впервые провел такое в команде биллинга, то получил примерно такие карточки:
Ввели соглашение писать карточки в определенном формате:
- Проблема, которую решаем;
- Профит, который получим;
- Если есть, возможное решение.
Дальше собираемся на встречу и обсуждаем, что с этим всем делать: это у нас называется рефакторинг-митап. Ищем максимально высокоуровневые решения, создаем тикеты в Jira - есть у нас специальный тип таких тикетов refactoring task.
Получаем сотню тикетов, но глупо же начинать их разрешать по очереди. Надо как-то приоритезировать. И здесь нам опять помогут разработчики: Дима с Катей лучше всех знают, где у них максимально болит. Проводим среди них опрос, где просим оценить каждый тикет по шкале от 1 до 5: 5 = нужно фиксить прямо сейчас, 1 = когда-нибудь в следующей жизни.
В результате мы получаем конкретный список тикетов и точную оценку технического долга в часах. Если такие митапы проводить раз в квартал, можно видеть, как растет или уменьшается технический долг, наблюдать динамику.
Итак, нам потребовалось:
- Понять, что рефакторить надо параллельно. Раз в квартал или обманом (завышением оценки) - плохие варианты;
- Прежде чем бороться с проблемой, ее надо формализовать;
- Приоритезировать: не прыгать на коня и скакать шашка наголо, а сперва найти самые больные места.
Глава третья, где мы учимся делать так, чтобы больше никогда не рефакторить
Опять пришли Дима с Катей:
— Леша! Кажется, мы попали в какой-то бесконечный водоворот. Мы пилим фичи - рефакторим, пилим фичи - рефакторим, и нет из этого никакого выхода.
Ну что же, дело за малым: осталось научиться писать безупречный код. Это помогут сделать образование и обмен опытом. Мы пробовали много способов и нашли несколько более-менее рабочих.
Пицца-клуб. Совершенно элитный закрытый vip-клуб, члены которого должны прочитать книгу, сделать по ней презентацию на пять минут для своей команды и за это получить пиццу с доставкой на дом. Филонишь? Тебя ждет страшное наказание: исключение из vip-клуба!
Education Day. В советских НИИ это называлось “библиотечным днем”: выделяем разработчику целый оплаченный день, даем список статей (или выбирает сам), он их читает и по итогам публикует обзор - что получил, чему обучился, рекомендует ли команде. Эдакий полу-выходной. Наш опыт говорит, что это действительно работает.
Таблички. Я люблю таблички.
— Здравствуй, команда, напиши мне в этой табличке, насколько каждый из вас разбирается в приеме платежей, поиске сотрудников и расчете зарплат:
Определив с помощью таблички автобусные факторы для каждой части проекта, мы пишем документацию, проводим мини-доклады, снимаем видосики, т.е. те, кто разбирается, рассказывают тем, кто не очень. Это быстро закрывает проблему, и теперь все более-менее разбираются во всем, становятся причастны ко всему проекту, а не к каким-то его отдельным участкам.
Технические ревью. Маленькие групповые обсуждения - где разработчики собираются и вместе решают, что делать с такой-то задачей и такой-то проблемой. Во-первых, это дает нам более крутые решения, чем если бы просто тимлид говорил: “Это делаем так, а вот это - эдак” или делегировал конкретному человеку, чтобы тот по вечерам изобретал костыли. Во-вторых, после обсуждения решения мы получаем более точную оценку, а разработчик чувствует себя более замотивированным, причастным.
Боты. Мы автоматизировали процесс технического ревью. У нас есть бот Джейк: каждое утро он собирает задачи на разработку и проводит опрос “Кто хочет обсуждать вот эту задачу”. Голосуют “за” те, кто шарит в задаче, разбирается в теме, либо им просто очень интересно поучаствовать. Количество участников ограничено четырьмя, потом формируется расписание и проводятся встречи.
Соглашения. Мы поняли, что только конвенций и код-стайла недостаточно, поэтому разработали соглашения, эдакие технические принципы. Например, в одной из команд - 16 принципов, которые позволяют не спорить, не делать все по-своему и потом разгребать, а, однажды согласившись, писать более-менее одинаковый код.
Эпилог
Итак, Дима с Катей счастливы, потому что мы:
- разобрались с Глебом;
- нашли время на рефакторинг;
- поняли, что нам нужно рефакторить
- и как сделать так, чтобы рефакторить нужно было меньше.
Можно подумать, что теперь наш проект на 100% идеален. Но на деле, всегда есть место техническому долгу. Однако, теперь мы о нем в курсе, потому что на него у нас есть карточка, и мы полностью контролируем ситуацию. Когда-нибудь доберемся и до него.