Всем привет! Меня зовут Владимир Касаткин, и я работаю бэкенд-разработчиком в компании ivi.ru, в команде “UX”. Цель этой статьи — показать, как мы уменьшили объём клиентской разработки, но при этом увеличили количество проводимых A/B-тестов.

Раньше вся продуктовая разработка была разбита на большие направления (“платформы”): бэкенд, Smart TV, iOS, Android, веб. При этом фичи пилились достаточно долго (по полгода), а побочным эффектом были заметные различия внешнего вида и функционала одной и той же фичи на разных платформах.

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

Постановка задачи

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

  • хотим добавить много новых блоков, поэтому система должна полностью управлять структурой выдачи на клиентах;
  • хотим иметь возможность таргетировать выдачу;
  • хотим иметь возможность проводить A/B-тесты выдачи.

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

Заодно мы смогли побороть старую проблему на главной странице, где рекомендации были не согласованы друг с другом.

Часть главной страницы

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

  • вначале запрашивался список подборок;
  • потом запрашивалось содержимое каждой подборки по отдельности.

Схема запросов

Из-за этого рекомендательная система старалась сделать каждую подборку максимально релевантной, и на первых позициях оказывался один и тот же контент. Так происходит из-за большого пересечения контента в подборках между собой. Ведь любой новый фильм может входить сразу в несколько подборок, например: “Новинки 2020”, “Претенденты на Оскар”, “Лучшая режиссура” и так далее. То есть пользователь мог видеть несколько новых фильмов почти во всех блоках на одной странице.

Варианты реализации

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

Вариант 1 — внедрить GraphQL, и пусть клиенты сами разбираются что куда рисовать. Главный минус: мы никогда не работали с GraphQL, все команды могут потратить уйму времени на выяснение нюансов. А ещё всё API придётся строить с нуля и при этом бесконечно поддерживать старое API для старых клиентов.

Вариант 2 — отдавать полотно, содержащие в себе все ответы всех команд, которые клиенты запрашивали раньше по отдельности, с минимальной обёрткой. Это почти как GraphQL, но без GraphQL.

Мы начали разработку второго варианта и столкнулись с тем, что бекенд не справлялся. Клиентам требуется такой объём информации, что собрать её всю в одной команде крайне тяжело. Время ответа новый команды API составляло 1.5 сек для страницы из 15 блоков по 20 единиц контента в каждой.

Есть и нюанс производительности клиентов. Если отдавать всё сразу, то размер ответа для одной страницы из 15 блоков будет весить примерно 3 Мб. Старые Smart TV не могут переваривать столько данных за раз “by design”, а пагинация страницы пачками по 1-2 блока приводит к схеме “отдельный запрос на каждый блок”.

Вариант 3 — Server Driven UI. В предыдущем варианте у нас есть конечное описание фичей, которые понимает клиент. Что если мы захотим добавить новый абзац текста, или какую-нибудь хитрую кнопку в левом верхнем углу? Мы не управляем вёрсткой, мы не можем внедрить ещё один “такой же” объект, но в другое место на экране. У нас есть только конечный набор вариаций.

Об этом есть хорошие выступления от OZON: (1) и (2). Но мы не пошли этим путём, потому что у нас были жёсткие временные ограничения.

#ui #ux

Между дизайн-системой и Server Driven UI
1.10 GEEK