Вы когда нибудь задумывались о том, как в условиях мультикомандной разработки современного продукта избежать задержек из-за синхронизации команд? Далее я поделюсь опытом такой разработки на примере нашей команды Циан.Финансы. Деталями вертикального подхода к разработке и почему мы работаем именно так. Привет, меня зовут Игорь Михайлюк, я ведущий разработчик в команде Циан.Финансы. Мы занимаемся развитием финансовых сервисов на платформе Циан. Наша команда присоединилась к Циан в мае 2018 года в полном составе из 18 человек. С самого начала команда строилась по принципам, по которым работают многие крупные IT компании, в том числе и Pivotal. История команды началась в декабре 2016 года Основные принципы, принятые в нашей команде: Для того, чтобы четче понимать, как соответствовать этим принципам, а также чтобы не наступать на грабли, мы прошли обучение в Pivotal University, после этого мы очертили круг технологий, которые позволяли нам придерживаться принципов, и добиваться отличных бизнес результатов. Прежде всего мы выбрали облачную платформу, поначалу это был Cloud Foundry затем и Kubernetes. На этих платформах мы почувствовали все преимущества cloud native подхода к разработке. В нашей команде было в разные моменты от 10 до 12 DevOps инженеров, которые занимаясь разработкой микросервисов, практически не сталкивались с такими распространенными проблемами в командах более 3 человек, как конфликты при обновлении из git репозитория, долгие споры и согласования merge request, споры о том, на какой технологии делать тот или иной микросервис. Как мы все наверняка знаем, что такие споры, сваливаясь в холивары, не дают позитивного результата. Практически весь фокус инженеров был отдан на реализацию бизнес логики, проверку гипотез, путем быстрого создания прототипов и  а/б экспериментов, анализа мнения фокус групп.  Работая в таком режиме, мы также избавились от эффекта испорченного телефона, когда бизнес объясняет идею аналитику, аналитик, пропустив ее через себя — объясняет разработчику, тот поняв опять же по-своему реализует, и отдает тестировщику, который со слов аналитика также понимает все по-своему. В итоге таких взаимодействий естественно возникает потребность в большом объеме согласований и документации. Благодаря нашему подходу мы избавляемся от этой проблемы. Такой подход к разработке, где команда полностью отвечает за все уровни разработки: front, back, база данных, инфраструктура на которой будет исполняться код в проде. Вот как выглядит разработка ипотечного маркетплейса https://www.cian.ru/ipoteka/  
Рис. 1. Вертикальные команды Циан.Финансы На текущий момент в компании выстроен процесс CI/CD, микросервисный подход к разработке, и активно идет работа по сокращению времени поставки фич в прод. Подробнее о текущем процессе коллеги уже писали тут. Благодаря этому процессу удалось добиться хороших результатов по сокращению багов в проде. Обеспечить отличный процесс code-review. Также у команд получалось релизиться относительно независимо друг от друга. Знания о продукте распространяются с хорошей скоростью. Если присмотреться, то в этом процессе есть точки кросс-командной синхронизации, такие, например, как code review. Когда процесс подходит к этой точке, необходимо привлечение членов других команд, а следовательно, процесс доставки кода притормаживается. Нарушается ритм поставки изменения, допустим, если нам нужно обеспечить 4 изменения в день, то 4 раза нам придется отвлекать членов других команд от их текущих задач, что зачастую просто невозможно. В случае, когда мы говорим только о back-end разработке, например о каком либо SaaS решении, которое предоставляет API, избежать точек кросс-командной синхронизации возможно благодаря микросервисной архитектуре. Но как быть, если помимо back части команде для работы в вертикальной парадигме, необходимо активно менять и front? Одним из способов организовать такую работу является подход микрофронтэндов. Описание подхода находится здесь: https://micro-frontends.org/. Не буду пересказывать в чем суть подхода, про это можно почитать на сайте технологии или тут. Вторая статья чуть потяжелее из-за технических деталей, но в общем дает понятие о технологии и о тех проблемах, которая она решает. Первый, самый распространенный, вариант микрофронтендов в Циан применяется уже давно. Технически, каждая страница отвечающая за тот или иной функционал реализуется своим микросервисом, который выполняется каждый в своем контейнере. А входной nginx занимается связыванием всех этих фронтов в одну целостную структуру. Также если смотреть на карточку объявления в списке найденных объектов — она также была реализована отдельным микросервисом, который в процессе формирования выдачи интегрировался. Это позволяло оперативно менять карточку не затрагивая структуру выдачи. Данный подход показал свою эффективность и позволил устранить многие точки кросс-командной синхронизации и ускорить доставку кода в ПРОД.  В чем же отличие релизного подхода в разных командах Циан? Большинство команд используют в своей работе описанный выше процесс CI/CD. В этом варианте за процесс выкатки, управлением ресурсами, отслеживанием работоспособности и т.д. отвечает команда администраторов. Естественно, ни о каком доступе и контроле за инфраструктурой со стороны разработчика в этом случае речи не идет. Выстроенная инфраструктура довольно сложная штука, чтобы бесконтрольно орудовать в ней. Ведь изменения сделанные для одного микросервиса могут драматически сказаться на всей системе. В команде Циан.Финансы мы используем более глубокий вертикальный подход к разработке, который подразумевает в том числе исполнение и поддержку написанных микросервисов. Это позволяет использовать потенциал нашей команды на 100%.  У нас свой репозиторий кода, своя система доставки микросервисов, своя инфраструктура исполнения кода, свой MQ, своя аналитическая система, каждый devops т.к. он самостоятельно отвечает за работоспособность своей части системы: имеет доступ к инфраструктуре, может создать свой процесс CI/CD такой, какой будет подходить именно его микросервису. Если для реализации функциональности нужна своя БД или допустим CDN, то это ответственность DevOps-а, который делает задачу.  В итоге видим, что ритм, с которым реализуются фичи в команде Циан.Финансы, отличается от основного ритма разработки. Если копнуть глубже, то два микросервиса, которые написаны разными инженерами могут отличаться всем, начиная от языка или технологии, на котором они созданы (typescript vs javascript, React vs Custom Elements), и заканчивая тем, как микросервис оказывается на проде. Например, часть наших микросервисов исполняется на Cloud Foundry развернутой внутри сети Циан. А другая — в Kubernetes, который нам предоставляет публичное облако. Часть микросервисов написано на Java, другая на Node.js, есть сервисы на Kotlin и Python. Да и во фронте нет ограничений. Микрофронты есть и на React (даже с привлечением Next.js) или preact, есть Svelte, да и на чистом JS с кастомными элементами немало.  Все это для того, чтобы как можно быстрее доставить работающую фичу в прод и проверить ее эффективность, а не тратить часы и дни на споры о том, что лучше React или Angular. И не ломать голову, как в рамках выбранного стека реализовать то, что на чистом js реализуется за пару часов. Не спорить о том, сколько ставить пробелов в начале строки, и не вылизывать ts-lint код, который, возможно, не принесет результатов совсем.  Нашим первым подходом к микрофронтендам был вариант с отдельным доменом третьего уровня fin.cian.ru Мы писали микросервис, который полностью выполнял работу от и до. Начиная от отрисовки экранных форм и заканчивая сохранением данных в БД и интеграцией с банками — партнерами. Затем, при  помощи простого reverse proxy, мы стали частью портала Циан. И все точки входа в наш сервис были ссылками на наш домен. Этот этап позволил решить все технические и административные вопросы, как развернуть процесс разработки, отличающийся ритмом от основного, как релизить свои фичи без согласования с остальными командами, как следить за работоспособностью, как интегрироваться с внутренними сервисами Циан. Как сопровождать свои микросервисы.  В итоге за 4 месяца мы запустили ипотечный маркетплейс на Циан, который позволял заполнить заявку на ипотеку прямо на сайте Циан и получить предложения 10 банков, выбрать лучшее. При этом, т.к. пользователь заполнял анкету, он получал не рекламные, а реальные предложения. Дальше захотелось дать больше возможностей нашим пользователям, которые получили предложения от банков и путешествуют по страницам Циан в поисках недвижимости своей мечты. И вот тут уже отдельной страницы на домене третьего уровня не достаточно. Дело в том, что нам нужно было встроиться в страницу Циан, которая разработана и поддерживается другой командой Циан. Помимо этого, нужно не просто встраиваться, но и получать информацию о том, какое объявление мы показываем, и информацию о пользователе, который к нам зашел. Первое, что мы сделали — это кредитный калькулятор под ценой объекта недвижимости.  После нажатия на ссылку пользователь мог ввести свои параметры кредита  Фича было воспринята пользователями на ура. По словам пользователей, очень удобно, когда актуальный ежемесячный платёж находится рядом с ценой. А т.к. процентные ставки в банках отличаются и зависят от множества факторов (новостройка, вторичка, площадь, регион и т.д.), то рассчитать правильный платеж и показать пользователю — хорошая идея. Но тут мы натыкаемся на то, как нам организовать разработку, чтобы при этом сохранить свой ритм релизов и не привлекать членов других команд каждый раз, когда нам надо выкатить изменение? В итоге мы договорились о следующем: Для контроля качества мы использовали автоматические тесты, которые контролировали работу микрофронтенда, как отдельно, так и встроенными на целевые страницы.  Конечно у нас возникла проблема того, что при совмещении двух web приложений на одной странице увеличивался размер кода этой страницы. Для примера: основная страница написана на React. Соответственно она тянет за собой все зависимости. В случае, если это одно приложение на странице — проблемы нет. Размер бандла оптимизируется под необходимые требования по загрузке и тормозов нет. Но вот мы захотели добавить на эту страницу еще одно приложение. Если оно так же написано на React, то мы получим двойную загрузку необходимых библиотек, и соответственно, ухудшение метрик производительности.  В принципе мы видели 2 пути.  В обоих подходах есть свои плюсы и минусы. При использовании общих библиотек мы получили бы сильно связанный код микрофронта с кодом целевой страницы. То есть нам необходимо было бы организовать механизм отслеживания изменений в коде целевой страницы и, если бы мы обнаружили изменение версий библиотек — менять их у себя, что неприемлемо. Ведь такое изменение — это критически срочная задача, т.к. без ее решения перестанет работать функционал на проде, а значит надо бросать все и фиксить зависимости. В итоге с увеличением количества микрофронтов и мест, где они встраиваются вся наша небольшая команда занималась бы устранением конфликтов в зависимостях, а не разработкой нового функционала. К тому же фиксация на общих библиотеках только одной страницы тут же делает невозможными переиспользования на других страницах.  Поэтому мы выбрали второй вариант. Одной из первых библиотек был preact: он прекрасно вписался и не рушил метрики загрузки страниц. Как же нам обеспечить необходимый уровень качества при встраивании? В Циан, как и практически везде есть несколько сред, где развернуты версии продукта: DEV, STAGING, PROD. Не будем останавливаться на том, для чего это нужно. Думаю мы все не раз с этим сталкивались.  Как же организовать интеграционное тестирование микрофронта в случае, когда у нас несколько сред исполнения кода. Мы пришли к такой схеме  Рис. 2. Микрофронтенд (виджет) разрабатывается на DEV среде абсолютно независимо от целевой страницы. Как только основной функционал готов — мы выкатываем его на STAGE. С этого момента команда целевой страницы может приступить к интеграции микрофронта у себя на DEV. Как только разработка завершена. микрофронт уезжает на PROD, но при этом он до сих пор не виден в продакшене целевой страницы. Целевая страница же переезжает на STAGE где проходит тестирование уже с встроенным микрофронтом. После успешного тестирования целевой страницы на STAGE она переводится в PROD, После чего начинается полноценное использование микрофронта. Такая схема размещения своего контента на страницах команд, с отличным от нашего релизного цикла, прекрасно подошла и для размещения контента Циан на сайтах партнеров. Вот уже полгода в работе находится проект Витрина Недвижимости от Циан. В рамках которой мы помогаем нашим партнерам (сайтов банков, и не только) без существенных усилий со своей стороны разместить у себя на сайте базу недвижимости от Циан. Дополнив ее своими сервисами, например, если мы говорим о банках — ипотекой.  В случае с партнером — говорить о совмещении релизного процесса вообще не приходится. Он абсолютно разный. Тем не менее подход микрофронтенда позволяет довольно успешно развивать встраиваемые приложения на любых площадках. Тут важное слово — развивать. Однократная интеграция не столь трудна, но если мы хотим постоянно вносить изменения, нам необходимо найти подход, который не требует усилий со стороны партнера для внесения этих изменений. Микрофронтенд отлично решает эту задачу. Благодаря ему мы можем настроить свои микро приложения так, чтобы быть максимально полезными пользователям и партнерам.  Такие размещения не новость для рынка web разработки. Мы знаем о yandex картах и о подобных им сервисах. Ведь Яндекс или YouTube не согласовывают каждый баг фикс с тысячами сайтов, где интегрированы микро приложения этих компаний. Что мы получаем в итоге: подход микрофронтендов, как он описан на сайте источнике, работает. Он действительно позволяет команде, которая отвечает за определенный проект, максимально сосредоточиться на нем, не сбивая свой ритм разработки на синхронизации с другими командами. А главное обеспечивает подход с вертикальной ответственностью команды за разработку фичи. Начиная от front и заканчивая разворачиванием микросервиса на любой удобной облачной платформе.  Немного хотелось бы остановится на экономической части описанного подхода. За предоставленные данные спасибо Дмитрию Камалдынову — директору нашего бизнес-юнита. Мы рассмотрим как применение наших практик позволяет при одинаковых ресурсах выводить больше фич за одну единицу времени.  Для простоты объяснения мы полагаем, что в команде работают идеальные сотрудники, у них одинаковая производительность (то есть за одно и то же время они выполняют один и тот же объем работ). В реальном мире это, конечно, не так, но может быть скомпенсировано отношениями внутри команды. Члены команды, помогая друг другу, уравнивают производительность, у кого-то она снижается, но у других — повышается.
 
Итак, какие же вводные мы имеем: Существует такой важный параметр разработки как Velocity команды. Для простоты можно определить его как количество нововведений, внедренных командой за определенный период времени (например месяц). Цель владельца продукта — минимальными затратами обеспечить максимальную Velocity продукта, верно определять приоритеты развития, таким образом, чтобы максимальная Velocity достигнутая ИТ командой  в конечном итоге превратилась в profit продукта или увеличила индекс потребительской лояльности (NPS). Т.к. мы ограничены размерами команды, рассмотрим варианты формирование ИТ команды, а так же как меняется velocity при применении виджетов и подхода high performance employee. Это классический вариант разработки, когда каждый член команды занимается только фронтом, или только бэком. Без использования микрофронта. В этом варианте мы получаем Velocity равной 2, то есть за условный месяц выводим 2 горизонтальные фичи, которые требует изменения front+back одновременно. При этом получаем распределение инженеров как на картинке, где цифра — количество инженеров занятых в соответствующей области.  
Рис. 3. Затраты 8 членов команды ИТ: для вывода фичи 2 инженера на фронте, по 2 на приложениях и 2 на бэке. Виджеты — не применялись, HPE — не применялись Давайте теперь рассмотрим, как изменится наша velocity при добавлении варианта с виджетами на фронте. В этом варианте мы делаем единый фронт для всех трех платформ, при этом с платформами мы интегрируемся по web-view. Из-за того, что мы уменьшили объем работ в приложениях (осталась только интеграция web-view) освободилось 2 человека, которые могут взять на себя работы по фронту и бэку. Таким образом мы увеличиваем количество фич, которые команда может вывести за условный месяц.  
Рис. 4. Затраты 8 членов команды ИТ: для вывода фичи 3 инженера на фронте, по 1 на приложениях и 3 на бэке. Применяются виджеты, HPE  — не применялись Попробуем еще ускорить нашу команду, при этом в команде у нас есть high performance employee, которые разбираются во всех стеках разработки и готовы этим заниматься. В этом случае мы выносим интеграцию web view виджетов как часть разработки фронта. А т.к. эта задача одноразовая и требует в дальнейшем лишь незначительной поддержки мы можем говорить, что стоимость разработки на 2 фронтовых платформах равна нулю, и оба освободившихся инженера могут быть переведены на фронт и бэк соответственно. И мы получаем Velocity 4, что в 2 раза больше, чем при классическом варианте 1.  
Рис. 5. Затраты 8 членов команды ИТ: для вывода фичи 4 инженера на фронте + поддержка в приложениях и 4 на бэке. Применяются виджеты и HPE Такую обширную тему как микрофронты в разработке просто невозможно охватить в одной статье. Поэтому в следующей статье мы поговорим о технологиях и инструментах, которые используем. Например Custom Elements Следите за новыми статьями в нашем блоге. Ведущий разработчик