Привет, Хабр! Я Федор Щудло, team lead и fullstack-разработчик. Всего я в разработке 15 лет, из них 11 в роли team lead.

Три года назад я сменил работу и занялся проектом, состояние которого можно описать кратко: ему 25 лет.

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

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

Как результат, разработка шла с большими накладными расходами (все делали долго), и с высокими рисками (выкатили и разломали прод). А команда при этом работала на износ.

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

В чем соль проблемы

Когда мы сняли все «низко висящие фрукты» , перед нами встал вопрос: «А что же делать дальше?». Проблема была не в том, что мы не знали, что делать. Наоборот, сделать можно было очень много всего. Но каждое изменение требовало серьезных вложений, поэтому было трудно выбрать самое важное.

И в принятии этого решения нам очень помогли DORA-метрики.

Краткий экскурс в DORA-метрики

DevOps Research and Assesment (DORA) это девятилетнее исследование подходов к разработке ПО в тысячах компаний из самых разных отраслей. Его задачей было найти подтвержденные корреляции между принятыми в компании практиками разработки ПО и успехом компании на рынке.

Наиболее полно исследование описано в книге Accelerate: The Science of Lean Software and DevOps: Building and Scaling High Performing Technology Organizations, которую я рекомендую прочитать, если вам интересна тема эффективности разработки ПО. Здесь же я лишь кратко перескажу суть.

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

Список практик, значимо влияющих на успех компании согласно DORA research
Список практик, значимо влияющих на успех компании согласно DORA research

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

Throughput-метрики:

  • Deployment frequency: как часто команда релизит свою систему.

  • Commit delivery lead time: время, за которое сделанный коммит “доезжает” до прода.

Stability-метрики:

  • Deployment failure rate: процент релизов, закончившихся поломкой.

  • Mean time to recovery: среднее время на восстановление после поломки.

Участвовавшие в исследовании компании были поделены на 4 категории: Low/Medium/High performers и Elite. По метрикам составили “бенчмарк”, позволяющий оценить вашу компанию относительно индустрии в целом.

Таблица позаимствована из State of DevOps Report 2019
Таблица позаимствована из State of DevOps Report 2019

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

Примечание: после приобретения DORA компанией Google, была добавлена пятая метрика - Reliability. Но в данной статье я буду придерживаться модели из книги Accelerate, поскольку там хорошо описана связанность и значимость именно четырех метрик.

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

Чем DORA-метрики лучше?

  1. DORA-метрики сбалансированы. Если повышать throughput нездоровыми способами (например, заставлять команду часто релизить несмотря на плохо реализованный конвейер поставки), то просядут метрики stability. И наоборот.

  2. DORA-метрики исключают индивидуальную оценку сотрудников, что способствует созданию здоровой blameless-культуры. Также эти метрики значимо коррелируют с выгоранием сотрудников.

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

Возвращаемся к нашему проекту

Итак, мы реализовали сбор DORA-метрик из нашей CI системы (Jenkins) и визуализировали их в Grafana. Вот что мы увидели спустя месяц:

DORA-метрики для нашего проекта за первый месяц их сбора
DORA-метрики для нашего проекта за первый месяц их сбора

Согласно бенчмарку DORA мы перформили лучше, чем 57% компаний в технологической индустрии. Релизили мы раз в два дня - уровень high performers (зеленый цвет). Commit delivery lead time и mean time to recovery были на уровне medium performers (желтый цвет).

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

Чтобы понять значение этих цифр на практике, представьте себя разработчиком на подобном проекте. Допустим, при выполнении задачи вы увидели возможность сделать небольшое улучшение: удалить (вроде бы) мертвый код или обновить зависимость. При этом вы понимаете, что:

  • Ваше изменение поедет на прод через полторы недели, когда вы уже будете погружены в другую задачу.

  • С вероятностью 25% релиз развалится. Совсем не факт, что из-за ваших изменений, но это еще придется выяснить.

  • На починку прода уйдет 29 часов. То есть, буквально, день и ночь.

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

Причем со временем ситуация будет становиться только хуже, сама собой. Если мы боимся изменять код, то он будет все больше обрастать недочетами, его будет все сложнее понимать, и будущие изменения от этого станут еще сложнее. В системном мышлении такое состояние известно как «порочный круг» (vicious cycle). Если это продолжается годами, то результат печальный — полная потеря контроля над кодом (lost ownership).

Однако, порочный круг можно превратить в «круг процветания» (virtuous cycle): чем легче нам делать небольшие изменения, тем чаще мы их делаем и тем проще их будет делать в дальнейшем.

Теперь стало очевидно, куда нам вложиться в первую очередь — в стабильность и простоту конвейера поставки.

Как выглядел наш конвейер поставки

Наш проект состоит из 14 сервисов, которые разрабатываются и поставляются более или менее идентично. На картинке ниже отображены ветки в git и конвейеры в CI, через которые проходил код от разработки до релиза:

Конвейер поставки до внесенных изменений
Конвейер поставки до внесенных изменений

Главный изъян такого pipeline — это многократное повторение идентичных шагов: сборка, юнит-тесты и e2e-тесты. И самым узким местом были именно e2e-тесты.

Вообще наши e2e-тесты великолепны — это создание четырех кластеров-реплик production, на которых в параллельном режиме запускается 3500 тестов, покрывающих все значимые сценарии.

Однако, у них были (и отчасти остались) существенные минусы:

  • Время выполнения варьировалось от 30 до 90 минут. 

  • В один момент времени можно делать только один прогон тестов.

  • e2e-тесты флакуют. Метрики показали, что в худшие периоды падал каждый второй запуск, а в среднем каждый четвертый.

  • Тесты было трудно дебажить и чинить. Метрики показали, что в среднем на починку уходило 5 дней.

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

С описанным выше конвейером нам потребуется: создать 14 pull requests, пройти 14 сборок с e2e-тестами (с учетом падений нам понадобится ~28 запусков). Каждый запуск это 30-90 минут. Итого ~4 рабочих дня. Далее, те же действия для веток develop и master - еще ~8 дней. И, наконец, 14 релизов — ещё полдня. Итого, ~12 рабочих дней непрерывной, совершенно не интеллектуальной работы. Конечно, можно срезать углы и сразу запушить в master. Но это все равно 28 запусков e2e-тестов и ~4 дня прежде чем критический фикс попадет на прод.

Как лечить подобные проблемы прекрасно описано в книгах (например, в канонической Continuous Delivery: Reliable Software Releases through Build, Test, and Deployment Automation). 

Вот что мы сделали: 

  • Максимально упростили и автоматизировали deployment pipeline, добавили возможность выкатывать хоть 1, хоть все 14 сервисов за раз. Собственно, релизит теперь Slack bot, а задача человека просто поставить несколько галочек, чтобы выкатить нужные сервисы и разослать уведомления с release notes.

  • Покрыли health check-ами и alert-ами все критические сценарии, чтобы обнаруживать проблемы сразу при релизе. Это помогло быстрее локализовывать и устранять проблемы.

  • Переписали пайплайн e2e-тестов, чтобы он создавал релизные артефакты для всех 14 сервисов сразу (все равно они тестировались вместе). Теперь в develop и в master вместо 14-28 прогонов e2e-тестов на каждую ветку нужно 1-2 прогона. Это радикально снизило нагрузку на наш главный bottleneck - e2e-тесты.

  • Избавились от ветки develop и начали сливать сразу в master. Так мы сэкономили на 14 слияниях и еще снизили нагрузку на e2e-тесты.

  • Раньше в feature branches e2e-тесты запускались по умолчанию. Мы отключили это, но оставили возможность запустить e2e-тесты при необходимости. С командой мы договорились, что, если в master попадают изменения, ломающие e2e-тесты, то мы не только чиним e2e, но и закрываем этот сценарий unit-тестами в конкретном сервисе. Далее мы 3 месяца следили по метрикам, не упала ли стабильность от такого решения. Она не упала. Так мы еще снизили нагрузку на e2e-тесты.

Вот как выглядит наш конвейер поставки теперь:

Теперь для устранения той же уязвимости в log4j нужно сделать 14 pull requests, получить 14 зеленых сборок (без e2e-тестов это в среднем 4 минуты). Далее сливаем в master и один раз получаем зеленые e2e-тесты (с поправкой на частоту падения это 2 запуска — стабильностью тестов мы еще не занялись). И, наконец, 1 релиз для всех 14 сервисов.

Итого 3-4 часа вместо исходных 2-3 недель. Позже мы прикрутили renovate и подобные обновления стали занимать вообще считанные минуты времени разработчика, но это уже отдельная история.

Описанные изменения мы запускали последовательно в течение января 2023 года. И, как вы можете видеть по графикам ниже, начиная с февраля 2023 ситуация изменилась кардинально: 

Deployment frequency. Декабрь 2022-Декабрь 2023
Deployment frequency. Декабрь 2022-Декабрь 2023
Commit delivery lead time. Декабрь 2022-Декабрь 2023
Commit delivery lead time. Декабрь 2022-Декабрь 2023
Deployments failure rate. Декабрь 2022-Декабрь 2023
Deployments failure rate. Декабрь 2022-Декабрь 2023
Mean time to recovery. Декабрь 2022-Декабрь 2023
Mean time to recovery. Декабрь 2022-Декабрь 2023

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

Вот как выглядят наши метрики теперь, по сравнению с исходными:

DORA-метрики за первый месяц их сбора
DORA-метрики за первый месяц их сбора
DORA-метрики за последние полгода
DORA-метрики за последние полгода

Согласно бенчмарку DORA, теперь мы перформим лучше чем 94% компаний.

Почему это метрики изменившие проект полностью?

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

Разумеется, у нас все еще осталось немало проблем. Но теперь есть уверенность, что мы до всего доберемся, это лишь вопрос времени. 

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

И метрики поставки это не единственное, что стало лучше. Например, время от первого коммита в feature branch до слияния в master за три года сократилось с 9 до 1.5 дней. Думаю, это многое говорит об изменениях в сопровождаемости кода и качестве инструментов. Если же вы верите в скорость закрытия задач как в ценную метрику, то теперь мы выполняем задачи в среднем за 4 дня. Раньше это было 11 дней.

А еще теперь мы можем вещи, которые раньше было трудно даже представить. Например, всего за 4 месяца мы истребили копившийся годами долг по security и выкатили 400 релизов (внимательный читатель мог заметить по графику deployment frequency, что в ноябре и декабре у нас было по 100+ релизов в месяц). И даже при такой интенсивности релизов мы не зацепили ни одного пользователя.

Вместо заключения

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

Если вы захотите повторить описанный опыт, то вот репозиторий с таблицами (Postgres) и Grafana-дашбордом для DORA-метрик, которые используем мы. Правда реализовать заполнение таблиц данными из CI-системы вам придется самим. Эта часть не обобщается. Или, вы можете взять инструмент Four Keys, продвигаемый командой DORA, если он вам подходит больше.

Но прошу вас: прочтите книгу Accelerate, если хотите получить пользу от этих метрик. В ней описано гораздо больше, чем я смог упомянуть в одной статье. Например, книга предостерегает от “токсичного” использования DORA-метрик: превращения их в ОКР, сравнения команд и тому подобных действий. Также, я очень рекомендую вам посмотреть доклад Брайана Финстера How to Misuse DORA DevOps Metrics.

Комментарии (12)


  1. omgiafs
    12.01.2024 10:57

    Это всё замечательно, но, копируя Дороти Маха из "Револьвера" Гая Ричи, бизнес спрашивает: "Что это даёт мне?"


    1. fshchudlo Автор
      12.01.2024 10:57
      +3

      Я показывал эти метрики нашему CTO и нашему CEO (по сути статья написана из материалов, которые я показывал им). Оба ответили, что ценность качественного конвейера поставки теперь очевидна и дали добро на дальнейшие работы по его прокачке.

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

      И, например, security упомянутый в статье, и до которого мы раньше никак не могли добраться, имеет вполне материальное выражение. Внешние аудиторы выставляют security rating нашей компании и это:

      1. Имидж нашего продукта перед клиентами

      2. Имидж компании перед инвесторами

      3. Прямое влияние на стоимость страховки от security-рисков.


  1. dph
    12.01.2024 10:57
    -1

    Хм, но DORA метрики, на самом деле, ни с чем не коррелируют (там исследование не может ничего доказать, так как сделано некорректно).
    Реально я вижу переход к относительно современной модели бранчевания, но этот подход очевиден уже при первом взгляде на старую модель. Зачем тут DORA?

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


    1. fshchudlo Автор
      12.01.2024 10:57
      +2

      А вы можете более развёрнуто рассказать, в чем некорректность исследования? Ну или ссылкой поделиться.

      По поводу модели бранчевания как главной причины - не совсем. Главным изменением было снятие избыточной нагрузки на e2e-тесты, как на главный bottleneck.

      Ну и касательно очевидности. Вы знаете, когда все позади, и когда мы говорим только о применённом решении, то и правда кажется очевидным. Но так не было "внутри событий". У этого феномена даже отдельное название есть - hindsight bias, это одно из когнитивных искажений. Из-за него же человечество никогда не увидит объективных учебников истории, например.

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

      И вот тут как раз DORA-метрики и спасают, потому что они помогают в нужную сторону посмотреть, найти за какую ниточку начать вытягивать. И найти общий язык с окружением, чтобы за нужную ниточку всем вместе и потянуть.


      1. dph
        12.01.2024 10:57

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

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

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


        1. fshchudlo Автор
          12.01.2024 10:57

          Замечания справедливы, но для меня они не списывают ценность исследования в ноль.

          Проблема представительности свойственна любым большим исследованиям. Но какие есть разумные альтернативы?

          По поводу "корреляция не значит каузация" - это верно. Но есть ли (и возможны ли) исследования, подтверждающие причинно-следственную связь, а не корреляцию, для качественных показателей, тем более в таких сложных процессах, как разработка ПО?

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

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

          Принимать решения имея в арсенале цифры+ориентиры+собственный опыт это лучше, чем принимать решения, имея только собственный опыт.


          1. dph
            12.01.2024 10:57

            Хм, проблемы представительности как раз не представляют особой проблемы. Достаточно просто собирать данные не в режиме "пришлите кто-нибудь", а через обращения в компании согласно статистическим данным (хотя бы по размеру и по отраслям), впрочем есть и куча других подходов. Верификацию-то уж точно стоило бы сделать. Как и глубинные интервью хотя бы с некоторыми компаниями (лучше с каким-то представительным количеством). Но ничего из этого не делалось, так как, кажется, цели сделать что-то обоснованное - не ставилось.
            Проверку каузации вполне можно сделать - например посмотреть, как меняется доходность в компаниях с резким изменением метрик (причем тоже с разным размерами и из разных отраслей). Скорее всего финансовые показатели при этом не изменятся.
            (Кстати, так как больше всего делилось данными люди из крупных компаний, где реально скорость доставки имеет смысл и легче обеспечиваются - то корреляция выглядит очевидной. Но понятно, что доставку 10 релизов в день в компании в 10 человек нет смысла делать. Впрочем, кажется, там и успех компаний считали абсолютные, а не в привязке на сотрудника, что уже совсем бессмысленно).
            И да, конечно индексы счастья или коррупции - бесполезны и не дают никакой полезной информации и не обладают никакой прогностической силы.

            Опираться на свой опыт - да, есть смысл!


  1. DizzyJump
    12.01.2024 10:57
    +2

    Спасибо, что поделились опытом. Полезная пища для размышлений.


  1. AndrewSu
    12.01.2024 10:57

    ~28 запусков). Каждый запуск это 30-90 минут. Итого ~4 рабочих дня.

    Какая-то странная арифметика. Сборка только в рабочее время идёт?


    1. fshchudlo Автор
      12.01.2024 10:57

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


  1. botyaslonim
    12.01.2024 10:57

    Отказ от develop в многосервисной архитектуре? Это как?
    У вас в работе 25 задач в одном спринте, допустим. 10 из них деплоятся в прод вместе, 8 других тоже вместе, а остальные 7 вообще хотфиксы. Что вы делаете?


    1. fshchudlo Автор
      12.01.2024 10:57

      У нас (теперь) нет спринтов и мы просто катим задачу на прод как только она готова. Ну или закрываем feature flag-ом и все равно катим, но такое бывает довольно редко. В такой схеме в develop, как в буфере перед релизом, просто нет необходимости. Сделали - релизим, стараемся в continuous delivery.

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

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