Ускоряем запуск продуктовых фичей

Всем привет! Меня зовут Айдар Шайфутдинов, я присоединился к команде Яндекса три года назад. За это время запускал разные продуктовые проекты в Такси и Самокатах. Сейчас занимаюсь разработкой клиентского продукта Самокатов.

О чём эта статья?

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

Почему нам так важна скорость запусков?

Для ответа на этот вопрос давайте посмотрим на причинно-следственную цепь.

  • В продукте почти все запуски — это проверка гипотез.
  • При этом по субъективной статистике около 80% гипотез не развиваются по итогам эксперимента.
  • Соответственно, большáя часть нашей с вами работы как разработчиков оказывается ненужной спустя какое-то время.

Не знаю, как для вас, но для меня это довольно некомфортный факт, и хочется с этим что-то сделать. И тут как будто есть два варианта:

  1. Лучше выбирать гипотезы
     
    Это сложно. Потому что, во-первых, субъективно, а во-вторых, разработчик не всегда может повлиять на выбор продуктовых гипотез.
  2. Быстрее проверять гипотезы
     
    Это уже более объективно — один и тот же проект можно сделать за месяц или за две недели, и разработчик на это обычно может повлиять.

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

Инструменты ускорения

О чём мы думаем, когда говорим про ускорение? Обычно это какое-то облако инструментов и методов:

  • челлендж продуктовых идей и гипотез, технических проработок, сроков;
  • трейд-оффы;
  • итеративный дизайн;
  • срез углов;
  • универсальные решения, например Backend-driven UI;
  • платформенные решения (динамические конфиги, эксперименты, API Gateway и тд).

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

В чём тогда проблема?

Тут предлагаю читателю остановиться и ответить на два вопроса:

  1. Был ли у вас за последний год хотя бы один проект, который вы сделали, но он так и не запустился? Не там, где вы проверили гипотезу, и она не полетела, а когда вы именно делали-делали что-то — а в результате не запустили ничего.
  2. А было такое, что после очередного запуска вы смотрели назад и понимали, что часть фичей/работы — иногда бо́льшую! — можно было не делать, запуститься раньше, и от этого ничего особо не поменялось бы?

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

Помимо того, что мой ответ на оба вопроса — «да», по моему субъективному опыту я не помню ни одного крупного проекта, запуск которого ретроспективно нельзя было бы ускорить.

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

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

Цель

Отсюда и вырисовывается цель (куда хочется прийти), которую я формулирую для себя и своих команд:

  • Запускать проекты быстрее, не делая ненужное в моменте.
  • Не делать проекты в стол.

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

Пример 1. Меню Самокатов

Сейчас самокатами в Яндекс Go никого не удивишь, но давайте перенесемся в лето 2021 года. Незадолго до запуска к нам приходит продакт-менеджер и говорит, что в приложении Яндекс Go нужно сделать меню для самокатного экрана.

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

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

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

В целом идея ясна, на этом этапе вступаем мы — разработчики: задаем уточняющие вопросы продакту, чтобы сформулировать для себя продуктовый контекст задачи — по сути, что и зачем мы делаем:

Разработчик: «Нам важно поддержать все кнопки в меню сразу или нет?»
Продакт: «Самые важные — „Сканировать“ и „Поддержка“. Остальные — nice to have, но можно и позже сделать».

Разработчик: «Как будем запускать? Сразу на всех или через A/B-тест?»
Продакт: «Сразу на всех, потому что этих точек входа больше нигде нет, да и мы не запущены еще, поэтому A/B нам тут не нужен».

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

Вариант 1. Сделать всё сразу

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

Понятно, что нужно добавить http endpoint, — например, воспользоваться сервисом, который реализует паттерн API Gateway (). Внутри него мы будем получать разные кнопки из разных источников:

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

Предварительная экспертная оценка разработчика на реализацию: две недели на клиенте и три недели на бэкенде. Но это не единственный вариант.

Вариант 2. Сделать только кнопки сканирования и поддержки

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

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

Оценка: три недели на бэкенде превращаются в одну, на клиенте остается так же две недели, потому что в этом месте мы используем backend-driven UI, и клиенты просто отображают то, что возвращает бэкенд.

На этих примерах мы видим, почему так важна практика описания альтернатив:

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

Вариант 3. Вариант 2 без разработки на бэкенде

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

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

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

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

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

В итоге получили оценку: две недели на клиенте, ноль на бэкенде.

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

Чтобы ответить на этот вопрос, давайте посмотрим на общий контекст запуска Самокатов.

Это версия роадмапа запуска Самокатов для второго варианта реализации. Здесь видно, что критическим путем является бэкенд, а запуск запланирован на пятую неделю.

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

Для сравнения давайте посмотрим на роадмап для первого варианта, где делаем всё и сразу, — тут мы вместо четвертой недели запустились бы на седьмой (запуск не уместился на картинке выше).

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

Чему мы научились на этом примере

Какие навыки разработчика помогли ускорить запуск:

  • Навык задавать вопросы продакту и получать продуктовый контекст.
  • Навык описания альтернативных вариантов реализации с опорой на технический и продуктовый контексты одновременно.
  • Как следствие, у нас получилось срезать углы в альтернативных вариантах реализации, оставляя возможности развития (итеративность).

Какие инструменты помогли ускорить запуск:

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

Резюмируем плюсы и минусы выбранного решения:

Плюсы:

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

Минусы:

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

Пример 2. Повышенный кешбэк на любимый маршрут

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

Немного контекста: в некоторых тарифах Такси уже есть кешбэк для подписчиков Плюса. Идея в том, чтобы в рамках эксперимента дать пользователю возможность выбрать любимый маршрут, например «работа — дом», и давать на поездки по этому маршруту повышенный кешбэк — скажем, не 10%, а 20%.

Есть гипотеза, что это может долгосрочно увеличить активность пользователей в супераппе в целом. Чтобы проверить эту гипотезу, запустим A/B-тест на небольшой процент пользователей и посмотрим на метрики.

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

  1. Во-первых, надо уметь добавлять любимый маршрут. У нас уже есть раздел адресов, давайте туда же добавим точку входа на добавление любимого маршрута. Выбираешь точки А и Б, сохраняешь — тут всё понятно.
  1. Во-вторых, нужно уметь изменять и удалять маршрут, если пользователь добавил не то или передумал.
    При этом есть важная деталь: после первой успешной поездки по выбранному маршруту нужно его фиксировать и блокировать изменения на один месяц, чтобы пользователь не мог менять любимый маршрут перед каждой следующей поездкой и на каждую их них получать повышенный кешбэк.
  1. Также надо уметь отображать это всё в интерфейсе, а когда пользователь выбирает точки А и Б, и они совпадают с любимым маршрутом, — явно отображать повышенный кешбэк и начислять его после поездки.

В целом понятно, задаем уточняющие вопросы продакту:

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

Разработчик: «Обязательно ли делать точку входа в любимый маршрут на главном экране?»
Продакт: «Очень хотелось бы, чтобы на видном месте была».

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

Вариант 1

Реализовать добавление и получение маршрута несложно. У нас уже есть сервис адресов, нужно добавить в БД новую табличку с маршрутами и два http endpoint-а для добавления и получения маршрута. На бэкенде это одна неделя. На клиенте — две.

Дальше нужно научиться изменять и удалять маршрут — после первого шага это тривиально: таблица с маршрутами уже есть, нужны лишь два новых endpoint-а для удаления и изменения. Это полнедели на бэкенде и неделя на клиенте.

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

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

  • получать любимый маршрут пользователя из сервиса адресов;
  • сверять точки А и Б любимого маршрута с текущими (с точностью до определенного радиуса);
  • если поездка по любимому маршруту — запоминать это в сервисе адресов;
  • добавлять дополнительную логику в endpoint изменения и удаления, чтобы проверять, может ли пользователь менять любимый маршрут.

При этом, чтобы маршрут нельзя было менять через удаление (удалил-добавил), будем делать soft delete ().
С учетом этих доработок оценка увеличилась до полутора недель на бэкенде и клиенте.

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

  • из динамического конфига получаем пользователей, на которых включен эксперимент;
  • сверяем выбранные точки А и Б с любимым маршрутом пользователя из сервиса адресов;
  • если это любимый маршрут пользователя — показываем кешбэк до и во время поездки и начисляем после.

Оценка: одна неделя на бэкенде.

По итогам проработки у нас получился такой роадмап с запуском на шестой неделе.

Спойлер.

И всё бы хорошо, но эта фича так и не попала в прод.

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

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

Вариант 2 (гипотетический)

Мысленно возвращаемся к обсуждению с продактом в самом начале:

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

Как будто бы это ограничение нам всё сильно усложнило с самого начала — и на этапе проработки, и на этапе реализации. И можно было почелленджить это продуктовое требование, используя технический контекст, который у нас есть, например:

Разработчик: «Ограничение на изменение маршрута сильно усложняет нам изменение и удаление маршрута (плюс одна неделя). Может быть, лучше отложим это на вторую итерацию разработки фичи, а для проверки гипотезы запустимся без ограничений?

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

Если бы нам удалось убедить в этом продакта, то получился бы вот такой роадмап:

На этом роадмапе запуск планируется на четвертой неделе, с учетом того что в первой итерации мы делаем только кор-функционал фичи: добавить, получить и изменить маршрут без ограничений, показать и начислить кешбэк, а всё остальное откладываем на вторую итерацию:

  • ограничения на изменение и удаление;
  • шорткат на главном экране.

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

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

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

Инструменты здесь использовали те же самые: динамические конфиги и существующую инфраструктуру (в данном случае — начисления кешбэка). Без этого реализовать эту фичу было бы сложнее.

Основные мысли и выводы

Хочется еще раз подсветить основные мысли и выводы, которые хотелось проиллюстрировать примерами выше.

  1. Скорость проверки гипотез как основная метрика полезного действия продуктовой команды. Можно не ставить это во главу угла, но точно может быть полезно иногда смотреть на работу команды сквозь эту призму.
  2. Без продуктового контекста разработчику сложно влиять на сроки. Важно понимать, какие требования значимы, а какими можно пренебречь, для этого надо общаться с продактом и челленджить требования.
  3. Некоторые навыки разработчика и инструменты помогают ускорять запуски системно. Можно использовать их как чек-лист в своих проектах и иногда сверять часы: точно ли мы всё из этого делаем или снова наступаем на те же грабли?

Ну и финальная мысль — рефлексировать полезно.

Желаю вам побольше рефлексировать над своими проектами и иногда задавать себе вопрос: «А можно ли было в нашем последнем проекте запуститься раньше?»

Другие публикации

  • 📹
  • mobile
  • Такси

Yet another Flutter DI