Всем привет! Меня зовут Саша Швец, я CTO Вертикалей Яндекс Еды, отвечаю за основные вертикали — Ритейл, Ресторанный продукт, Рекламу. В статье расскажу историю о том, как я переводил разработку из функциональной структуры в кросс-функциональную и зачем я это делал. Статья будет полезна CTO и другим руководителям, которые столкнулись с проблемами взаимодействия и роста внутри своей технической команды.
Интро
Идеальный подход мог бы быть таким: брать в команду только fullstack-разработчиков, которые делают сразу и бэк, и весь фронт. Суперудобно: все люди взаимозаменяемые, все они в курсе происходящего, можно вертеть командой как душе угодно. До Яндекса я очень много работал в таких командах. Кое-где встречалось функциональное разделение, но я старался его нивелировать.
В очень больших проектах, таких как Еда, fullstack-команда невозможна, нужны люди разных специальностей, каждый из которых суперпрофи в своей области. При этом для меня всегда было нонсенсом наблюдать, как большие команды порезаны на максимально разобщенные функциональные отделы, то есть бэкендеры, веб- и мобильные разработчики, а также QA сидят по разным углам и друг с другом почти не коммуницируют.
Это теория. Перейдем к нашей истории.
Проблемы функциональной команды
На старте всё было плохо…
В Яндекс я пришел в 2019 году в Суперчек — был в Яндекс Маркете такой проект про каталоги крупнейших ритейлеров. До близкого знакомства с компанией я пребывал в иллюзии, что в Яндексе всегда всё суперпередовое, и уж там-то точно сделаны кросс-команды…
Но в Суперчеке Android-разработка жила отдельно от iOS, бэкенд жил в стороне от них обоих, и все они почти не общались. Со временем людей приходило всё больше — боль становилась совсем невыносимой. Мне же как СТО эту боль приходилось гасить.
В Маркете, где я работал после Суперчека, было получше: использовалось деление на стримы и v-teams. В 2022 году я перешел из Маркета в Еду и, по ощущениям, вернулся в Суперчек, но в гораздо более запущенном виде.
![](/posts/cross-functional-teams-2024-06-28/images/1.jpg)
Летом 2022 года устройство Еды выглядело как на картинке. Во главе стоял СТО, отвечавший за всю Еду, и уже прорастали зачатки вертикалей: отдельно рестораны, отдельно ритейл, отдельно логистика. Я пришел как CTO Ритейла (колонка слева) и управлял двумя командами бэкенда. Виртуально у меня были еще команды веб-, iOS- и Android-разработчиков (справа). Из схемы понятно, что они не подчинялись мне напрямую, а велись своими функциональными лидами.
Основные проблемы организации, которые стали видны почти сразу:
- Распределение ресурсов на проекты шло в формате еженедельного рубилова. Основные заказчики — продакты — еженедельно ссыпали всю разработку в общий котел, а потом забирали оттуда людей на конкретные проекты. Преимуществом для продактов было хорошее горло: чем громче кричишь про важность своего проекта — тем больше шансов заполучить разработчиков. Хаотичное перекидывание людей шло непрерывно, и это негативно влияло на атмосферу в командах.
- Команды не всегда понимали, кто их руководитель. Во время моих визитов разработчики смотрели на меня как на левого персонажа, который вылез непонятно откуда и чего-то от них добивается. Это была лично моя боль.
- Под каждый новый проект формировалась новая команда, и каждый раз требовалась своя система процессов: дейлики, чатики, синки — а это накладные расходы.
- Мало кто понимал, что происходило в команде глобально. Продакты были заняты выбиванием ресурсов, а разработчики наоборот — вообще не были вовлечены в эти процессы и из-за еженедельных изменений перемещались с одного проекта на другой.
…а потом стало хуже
В Еду я пришел летом 2022-го, а уже осенью Яндекс совершил сделку с VK: от нас ушли Новости и Дзен, а к нам перешел Деливери. Я зову этот период «Черная осень двадцать второго», потому что весь Деливери надо было переварить, объединить с Едой и перевести всю пользовательскую базу на технологии Яндекса.
![](/posts/cross-functional-teams-2024-06-28/images/2.jpg)
Сложность заключалась в том, что под капотом у нас были совершенно разные стеки. В нативной разработке всё было еще достаточно понятно: iOS есть iOS, а Android есть Android, даже в ЮАР. Но на бэкенде в Еде всё сделано на C++, а в Деливери — на Go (что забавно, и там, и там был монолитик на PHP). Веб же в Еде был написан на React, а в Деливери — на Vue, причем был заметно слабее развит.
И вот — два огромных бизнеса с разными стеками. Now kiss!
![](/posts/cross-functional-teams-2024-06-28/images/3.jpg)
Рассказ об объединении достоин отдельной статьи. В контексте этого материала важно то, что приход Деливери усугубил все проблемы: число людей удвоилось, и появился отдельный сектор разработчиков Go, как будто до этого разобщенности было мало. Единственное светлое пятно — и нативные команды, и веб-команда полностью перешли под меня.
Нулевое улучшение: «Планнер»
![](/posts/cross-functional-teams-2024-06-28/images/4.jpg)
На старте мы попробовали упорядочить хаос, внедрив инструмент под названием «Планнер», который я принес из Маркета. «Планнер» родился из подручных инструментов: поначалу я размечал, кто чем занимается, в эксельках, а потом мы сделали веб-интерфейс.
Выглядит «Планнер» как диаграмма Ганта, но строчки здесь — не проекты, а люди. Из диаграммы видно и то, каким проектом занят каждый конкретный разработчик, и общая картина занятости. Когда нужно быстро перебросить человека с одного проекта на другой — можно сразу прогнозировать, что из-за этого поедет.
Но «Планнер» это подорожник: добавляет прозрачности, а остальных проблем не решает.
Первое улучшение: кросс-функциональность
![](/posts/cross-functional-teams-2024-06-28/images/5.jpg)
Поэтому мы затеяли глобальную реформу и придумали новую структуру с опорой на продуктовые предпосылки.
Во-первых, весь Ритейл разбили на два домена: работу с покупателями (витрину, слева) и работу с магазинами-партнерами (справа).
Во-вторых, в каждом из этих доменов выделили свои стримы. Например, в домене покупателей это:
- OX — Order Experience, опыт заказа;
- CX — Customer Experience, опыт покупки;
- Growth — стрим роста;
- Search — стрим поиска, всё, что касается поисковой выдачи.
При этом в каждом стриме есть полный набор специализаций разработки. В партнерском домене похожее деление.
Если раньше все общались как попало — были отдельные синки бэкенда, отдельные команды iOS, то теперь получились сплоченные команды, которые не нужно менять каждую неделю, они работают постоянно в одном направлении.
В чём мы выиграли
- Продакты перестали бороться за ресурсы. Каждый продакт обрел свою команду, где приоритетами рулит только он.
- У каждого разработчика появился соло-руководитель, погруженный в его задачи. Не функциональный руководитель, а лид, который действительно понимает, чем человек занят ежедневно и куда он идет.
- Новые команды не создаются каждую неделю, а значит, нет накладных расходов на синхронизацию новорожденных. Каждая команда сработана, у них уже есть свои синки и дейлики.
- У команд появились долговременные горизонты на месяц, на квартал и даже собственные метрики.
- Всё стало предельно прозрачно.
В чём проиграли
- Тимлидам стало сложнее оценивать работу членов своих команд. В кросс-функциональной команде лид по специальности может быть и бэкендером, и фронтендером, и даже iOS- или Android-разработчиком. Понять, чем занят подчиненный другого профиля, он еще может, но оценить качество работы ему уже тяжело.
- Тимлиду сложно растить людей из других специальностей, особенно по хард-скилам. Сеньоров он еще может покоучить менеджерским навыкам, но джунам надо прокачивать именно харды — несовпадение специальностей здесь критично.
Второе улучшение: гильдии
![](/posts/cross-functional-teams-2024-06-28/images/6.jpg)
Мы решили эти проблемы матричной структурой, а именно — вводом гильдий. На схеме видно, что продуктовые команды лежат по горизонтали, а вертикально их прошивают гильдии специальностей. У каждой гильдии в этой системе свои лиды: лид гильдии C++, лид гильдии Android и так далее.
Такая структура хорошо решает проблему роста сотрудников и осознанности их работы. У гильдий есть свои зоны ответственности:
- Онбординг новичков. Если, например, бэкенд-специалист пришел в команду мобильного тимлида, то за его бэкенд-скилы отвечает гильдия. Гильдия может назначить ментора — мы прописали инструкции, как правильно принимать человека на борт.
- Развитие старичков. Лиды гильдий знают, как тянуть вообще всех, независимо от стажа: делятся опытом, подсказывают на код-ревью. Вместе с лидом гильдии в этом процессе участвует и непосредственный руководитель продуктовой команды.
- Общие процессы типа релиза нативного приложения. Понятно, что продуктовый стрим не решает, как залить конкретное приложение в конкретный стор, это определяет гильдия.
- Архитектура и техдолг. Гильдия отвечает за общее качество кода и следит, что мы не копим технический долг, а только уменьшаем его. Наша условная техноквота — 20%, за ее распределением следит гильдия.
- Обмен знаниями. Банальная, но важная штука.
Третье улучшение: платформа и вечность
![](/posts/cross-functional-teams-2024-06-28/images/7.jpg)
В бэкенде, вебе и тестировании есть задачи, которые не свяжешь с продуктовой разработкой и двадцатью процентами техдолга.
Пока команда небольшая, таких задач немного, можно решать их внутри продуктовых стримов. Но годы идут, гильдии растут, и когда объем работ вне клиентского и партнерского доменов становится большим и самостоятельным, у нас появляется третий домен — платформа. Там специалисты по бэкенду или по вебу делают большие стройки, крупные рефакторинги и всё прочее, что точно нужно делать, но в продукт никак не вписывается.
Платформа — уже не кросс-функциональная команда, в ней выделены бэкенд, веб и QA. Но, как вы видите на схеме, мобильной платформы отдельно в Ритейле не появилось, мы используем общую мобильную платформу Еды.
![](/posts/cross-functional-teams-2024-06-28/images/8.jpg)
Это не всё — мы продолжаем расти и после создания платформы. Но если в функциональных командах рост — это боль и масштабирование проблем, то кросс-функциональные команды в процессе могут почковаться: делиться, разрастаться или, наоборот, сливаться в общий стрим.
Что произошло по мере роста у нас:
- от Customer Experience отделилось направление Distribution, и они оба вместе теперь называются Monetization;
- Growth вырос в Strategic Growth, и внутри возникли свои два направления;
- Order Experience с Search объединились в единый сектор ответственности Core.
Структура супермасштабируема: можно идти глубже, почковаться внутри секторов и внутри команд. Растите бизнес, растите продукт, набирайте людей — система умеет работать с этим гладко.
Итоги
В разных подразделениях всё может быть устроено по-своему. И хотя я лично не понимаю, как могут выжить функциональные команды, где-то в Яндексе они работают до сих пор. В Еде же мы распространили опыт кросс-функциональных команд на все вертикали разработки и на ядро продукта.
Иногда кросс-функциональность действительно не нужна — например, если ваша команда занимается отдельной платформой. У нас есть команда интеграций, упрощенно она пишет на Python или Go адаптеры, которые просто заняты трансформингом данных. У таких команд кросс-функциональность только с менеджерами и QA, это нормально.
Для продуктовой же разработки кросс-функциональность — мастхэв. Такая система всегда более слаженна, эффективна и прозрачна, чем функциональная.
Напомню три хинта, которые вам пригодятся, если вы возьметесь за кросс-функциональность:
- нужны вертикальные гильдии, иначе трудно рулить развитием людей и общими процессами платформ;
- возможно, понадобится отдельная специализированная команда для платформы;
- с ростом будьте готовы к тому, что всё будет масшабироваться, почковаться и размножаться.