Хабрахабр

Будь как Мунк, или пару слов о техническом долге

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

Три года назад я пришел в Dodo Pizza в качестве Chief Agile Officer и стал помогать командам создавать процессы и внедрять инженерные практики. image
За 8 лет IT-команда Dodo Pizza выросла с 2 разработчиков, обслуживающих одну страну, до 80 человек, обслуживающих 12 стран. Кроме того, обнаружилось, что когда несколько команд работают над одним продуктом, сложно заставить их поддерживать высокое качество кода. Зачастую эти внедрения было слишком медленными.

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

Background

Dodo Pizza – это компания-киборг, которая продает пиццу. Наш бизнес основан на платформе Dodo IS, которая управляет всеми бизнес-процессами: приём заказов, приготовление пиццы, управление запасами, управление людьми (менеджмент) и многое-многое другое. Всего за 8 лет мы выросли с 2 разработчиков, обслуживающих одну пиццерию, до 80+ разработчиков, обслуживающих 498 пиццерий в 12 странах мира.

Было небольшое покрытие unit-тестами, API/UI-тестов не было вовсе. Три года назад Dodo IS была монолитом, содержащим 1 миллион строк кода. Все об этом знали или хотя бы догадывались. Само качество кода было разочаровывающим. Мы даже нарисовали диаграмму «будущей» архитектуры, но, честно говоря, так ничего и не сделали, чтобы приблизиться к ней. В мечтах о светлом будущем мы раскалывали монолит на дюжину сервисов и переписывали самые отвратительные части системы.

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

Shit happens

В 2018 году команда маркетинга запустила нашу первую федеральную рекламную кампанию на ТВ с бюджетом 100 млн. рублей. Это было грандиозное событие для Dodo Pizza. IТ-команда тоже хорошо подготовилась к кампании. Мы автоматизировали и упростили наш деплой – теперь с помощью одной кнопки в TeamCity мы могли развернуть монолит в 12 странах. С помощью тестов производительности мы провели анализ уязвимостей. Мы сделали все возможное, но всё равно облажались.

Мы получали от 100 до 300 заказов в минуту. Рекламная кампания была потрясающей. Плохая новость: Dodo IS не выдержала такой нагрузки и умерла. Это была хорошая новость. Система перезагружалась каждые 3 часа. Мы достигли предела вертикального масштабирования и больше не могли обрабатывать заказы. Каждая минута простоя стоила нам десятки тысяч рублей, не считая потери уважения со стороны разъяренных клиентов.

Когда я пришел в Dodo Pizza три года назад, я сразу же начал внедрять инженерные практики. Большинство команд приняли парное программирование, модульное тестирование и DDD довольно быстро. Но не все было так просто. Мне пришлось преодолевать сопротивление разработчиков, продактов и команды саппорта.

Разработчики привыкли думать, что команда, сосредоточенная на одном компоненте, пишет лучший код. В отличие от идей инженерных практик, поначалу не все поддерживали идею feature teams. Еще этот бесконечный поток багов постоянно требовал внимания… Мы выпускали продукт не чаще одного раза в неделю, и каждый релиз занимал довольно много времени, требовал огромного количества ручного регресса и поддержки UI-тестов. Было неясно, как совместить быстрое развитие бизнес-функций с давно назревшим массивным рефакторингом сложной системы. Я пытался исправить это, но изменение процесса шло слишком медленно и фрагментарно.

История падения и подъема

Initial state: монолитная архитектура

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

True story

Монолитная архитектура хороша для начала, потому что она проста. Но она не может выдержать высокую нагрузку, будучи единственной точкой отказа. Однажды все наши рестораны в России перестали принимать заказы из-за сообщения в блоге. Как такое могло случиться?

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

Ранний сбой в 2017 году

14 февраля. Для любителей поздравить друг друга 14 февраля мы делаем специальную пиццу – «Пепперони» в форме сердца. Я навсегда запомню 14 февраля 2017 года, потому что в этот день, когда все пиццерии работали на полную загрузку, Dodo IS начала падать. В каждой пиццерии стоит 4-5 планшетов для управления производством: для какого заказа пиццемейкер раскатывает тесто, кладет ингредиенты, выпекает или отправляет на доставку. На тот момент количество пиццерий достигло 150+, каждый планшет обновлялся несколько раз в минуту. Все эти запросы создали такую огромную нагрузку на базу данных, что она перестала выдерживать и начала отказывать. Dodo IS умерла во время пика продаж. А ведь впереди был напряженный праздничный сезон: 23 февраля, 8 Марта, 1 и 9 Мая. Во время этих праздников мы ожидали еще большего роста заказов.

Зная наши планы роста и предел нагрузки, которую мы можем выдержать, мы выяснили, как долго мы можем оставаться в живых. День, когда ты умрешь. Каково это — жить, зная дату своей смерти? Предполагаемая дата Армагеддона ожидалась примерно через полгода: в августе–сентябре 2017.

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

Некоторые улучшения после года

За год мы заметно выросли:

  • Мы автоматизировали и ускорили процесс деплоя до 4-5 часов
  • Наконец-то мы начали распиливать монолит: трекер и TV-борды были вынесены на отдельный сервис со своей собственной базой данных
  • Мы начали отделять кассу доставки — второй компонент, создававший высокую нагрузку
  • Переписали систему аутентификации пользователя и устройства

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

Провал во время Федеральной рекламной кампании. Второй кризис доверия

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

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

Система снова падала и перезагружалась каждые 3 часа. Под нагрузкой Федеральной маркетинговой кампании мы снова легли. Наш бизнес терял десятки миллионов рублей.

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

Вынесенные уроки

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

  • Единый бэклог продукта
  • Полностью кросс-функциональные и кросс-компонентные команды
  • Парное и моб программирование
  • Настоящая непрерывная интеграция (CI) – интеграция кода 12-ю командами в одну ветку
  • Упрощенная работа с ветками (trunk-based development)
  • Частые релизы: непрерывный деплой для микросервисов, релиз каждый день для монолита
  • Отказ от отдельной команды QA, эксперты QA являются частью команд разработки

6 практик, которые мы выбрали после кризиса:

1. Сила фокуса. До кризиса каждая команда работала над своим собственным долгом и специализировалась в своей области. Во время кризиса у команд не было конкретных задач, у них была одна большая сложная цель. Например, мобильное приложение и API должны обрабатывать 300 заказов в минуту, несмотря ни на что. Команда берет цель и самостоятельно придумывает, как ее добиться. Команда сама формулирует гипотезы и быстро проверяет их на проде. Команды не хотят быть простыми кодерами, они хотят решать проблемы.

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

Внутренние хакатоны. Мы провели хакатон «500 ошибок». 2. Целью было сохранить логи в чистоте. Все команды дружно очистили логи и удалили причины 500 ошибок на сайте и в API. Когда логи чисты, новые ошибки хорошо видны, вы можете легко настроить пороговые значения для оповещений.

Раньше у нас был полный бэклог багов, некоторые из них болтались там в течение многих лет. Еще один пример хакатона – баги. И каждый день появлялись новые. Казалось, они никогда не закончатся. Мы объединили работу над багами и обычными элементами бэклога.

Политика #zerobugspolicy.

  1. Если баг находится в бэклоге более 3 месяцев, просто удали его. Он провалялся там уже целую вечность, и никто не умер.
  2. Оцени боль, которую причиняют оставшиеся баги клиентам. Оставь только те баги, которые усложняют жизнь большой группе пользователей.
  3. Устрой внутренний хакатон по багам. Мы сделали это за несколько спринтов. Каждый спринт каждая команда брала несколько ошибок и исправляла их. После 2-3 спринтов у нас был чистый бэклог. Теперь можно ввести #zerobugspolicy.
  4. #zerobugspolicy. Если баг попадёт в бэклог, он обязательно будет исправлен. Любой баг в бэклоге имеет более высокий приоритет, чем любой другой элемент бэклога. Но для того, чтобы попасть в бэклог, баг должен быть серьезным. Либо он наносит непоправимый вред, либо затрагивает большое количество пользователей.

3. От проектных групп до стабильной команды. Была забавная история с проектными командами. Во время кризиса мы сформировали экспертные команды людей, которые были наиболее квалифицированными для задачи. После того, как кризис закончился, команды решили продолжить эту практику. Несмотря на то, что эта идея мне совсем не понравилась, мы попробовали. Всего за 2 недели (один спринт), на следующей ретроспективе, команды отказались от этой практики, (это решение меня осчастливило). Если команде не хватает некоторых навыков, они могут постепенно учиться. Но командный дух, поддержка и взаимопомощь формируются очень долго, на это уходят месяцы. Краткосрочные проектные команды постоянно находятся в стадии форминга и шторминга. Вы можете потерпеть это в течение нескольких недель, но не сможете работать так все время.

Нет ручному регрессу. Мы поставили перед собой цель избавиться от ручных регрессий. 4. Но наличие долгосрочной амбициозной цели заставляет думать о шагах, ведущих к цели. Нам потребовалось 1,5 года, чтобы достичь ее.

Мы сделали это в 3 шага.

  1. Автоматизация критического пути.
    В июне 2017 года, мы сформировали команду QA. Задачей команды было автоматизировать регресс наиболее критичного функционала Dodo IS – прием и производство заказов. В течение следующих 6 месяцев новая команда QA из 4 человек покрыла автоматическими тестами весь критический функционал системы. Разработчики фича-команд активно помогали команде QA. Вместе мы написали красивый и понятный доменный язык (DSL), который понимали даже клиенты. Параллельно со сквозными тестами разработчики обвешивали код модульными тестами. Некоторые новые компоненты были переработаны с помощью TDD. После этого мы расформировали команду QA. Бывшие члены команды QA присоединились к командам, работавшим над бизнес фичами, чтобы передать опыто разработки и поддержки автотестов в команды.
  2. Теневой режим.
    Имея автотесты, во время 5 релизов мы делали ручной регресс в теневом режиме. Команды полагались только на автоматическое тестирование, но когда команда решала, что она готова к релизу, мы запускали ручной регресс, чтобы проверить, не пропустили ли наши автотесты какие-либо ошибки. Мы отслеживали, сколько ошибок было поймано вручную и не поймано автотестами. После 5 релизов мы проанализировали данные и решили, что можем доверять нашим автотестам. Никаких серьезных ошибок не было пропущено.
  3. Отказ от ручного регресса.
    Когда у нас было достаточно тестов, чтобы начать им доверять, мы полностью отказались от ручного тестирования. Чем больше мы пишем тестов, тем больше им доверяем. Но это произошло только через 1,5 года после того, как мы начали автоматизировать регрессионное тестирование.

5. Нагрузочные тесты — часть регресса. Во время кризиса мы написали нагрузочные тестоы. Это было совершенно новым для нас опытом. Тем не менее, всего за 2 недели нам удалось создать кое-что с помощью инструментов Visual Studio. Мы использовали их в том числе для генерации искусственной нагрузки на сервер, чтобы найти пределы производительности. Например, если органическая нагрузка на проде составляет 100 заказов/мин, мы добавляли еще 50 заказов/мин с помощью наших тестов, чтобы посмотреть, способна ли система обрабатывать повышенную нагрузку.

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

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

Результаты

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

Если во время весенних каникул 2018 года наши пиццерии не могли работать из-за Dodo IS, то в 2019 году, с ростом от 300 до 498 пиццерий, Dodo IS работает безупречно. В результате этих экспериментов за последний год мы значительно улучшили качество и стабильность Dodo IS. Мы спокойно пережили пик продаж в новом году, во время Второй маркетинговой кампании и весенних праздников.

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

Результаты для бизнеса

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

Результаты для команд

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

  1. Полностью кросс-функциональные и кросс-компонентные команды
  2. Парное/Моб программирование
  3. Continuous Integration – непрерывная интеграция кода 12 команд в одну ветку
  4. Subject Matter Expert в команде
  5. Нет отдельной команды QA, эксперты QA являются частью команд разработки
  6. Замена ручного регресса автотестами
  7. Политика отсутствия багов (#Zerobugspolicy)
  8. Stop the Line в качестве драйвера для ускорения деплоя пайплайна

Чему мы научились

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

  1. Инженерные практики защищают бизнес от кризиса
  2. Не накапливать технический долг. Может стать слишком поздно и стоить слишком дорого
  3. Эволюционные изменения занимают в несколько раз больше времени, чем революционные
  4. Кризис – это не всегда плохо. Используйте кризис для революционных изменений процессов
  5. Тем не менее, длительная эволюционная подготовка требуется заранее
  6. Не применяйте слепо все методы, которые вам нравятся. Некоторые методы ждут своего часа, и когда он придет, команды будут использовать их без сопротивления. Ждите подходящего момента
  7. Со временем команды сами начинают принимать важные решения и реализовывать их. Дайте им благоприятную среду, чтобы попытаться, позвольте потерпеть неудачу и учиться на ошибках

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

Благодарности

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

Ты настоящий лидер компании с подлинной гибкой культурой. Большое спасибо нашему генеральному директору Федору Овчинникову за доверие.

Большое спасибо Дмитрию Павлову, нашему Product Owner'у, моему старому другу и со-тренеру.

Спасибо Александру Андронову и Андрею Моревскому за поддержку.

Вашу помощь трудно переоценить. Большое спасибо Даше Баяновой, нашему первому штатному Scrum-мастеру, которая всегда помогает и поддерживает меня со всей нашей инициативой.

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

Теги
Показать больше

Похожие статьи

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

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

Кнопка «Наверх»
Закрыть