Bricks: новый подход к управлению интерфейсами
В Авито приходится много работать с разметкой страниц на сайте и экранах мобильного приложения, чтобы оперативно менять интерфейс под запросы пользователей. Часто даже мельчайшие изменения занимают значительное время, так как требуют работы с кодом и привлечения разработчиков. Чтобы оптимизировать процессы, мы решили создать платформу Bricks и управлять интерфейсами Авито с её помощью.
Я — Алексей Ивасюта, тимлид команды Bricks. В статье расскажу, почему мы решили создать этот визуальный конструктор, и объясню, как он помогает решить проблемы управления разметкой.
Какие существуют подходы к управлению интерфейсами
Предположим, перед нами стоит следующая задача.
Есть карточка объявления в блоке рекомендаций на странице поиска. Нам нужно выделить цену объявления синим цветом и поставить её на первую позицию. Задача синтетическая, поэтому не имеет значения, какие за этим стоят цели. Допустим, мы выяснили, что такое отображение сильно повышает конверсию.
Классический подход к изменению разметки страницы
Как будет решаться подобная задача, если мы используем классические инструменты разработки?
Десктопную и мобильную версии сайта меняет Frontend-разработчик.
Он пишет код на CSS, TypeScript или HTML, оформляет Pull Request, проходит тестирование и Code Review и деплоит код в продакшен. Это достаточно быстрый способ, так как после деплоя изменений сразу все пользователи получат актуальную версию разметки. В крайнем случае им нужно будет обновить страницу или повторно зайти на сайт.
Минус такого подхода в том, что для любых изменений в интерфейсе нужно привлекать разработчика.
Мобильное приложение обновляет iOS- или Android-разработчик.
Он также пишет код, проходит тестирование и Code Review, собирает новую версию приложения, которую позже опубликуют в магазинах. Чтобы увидеть изменения, пользователю нужно скачать новый релиз и обновить приложение.
Такой подход к обновлению тянет за собой ряд проблем.
Во-первых, Авито не может проконтролировать, чтобы все пользователи разом перешли на новую версию. Иногда этого приходится ждать годами.
Во-вторых, поддержка старых версий приложения раздувает API, поэтому внутри приложения остаётся много лишнего кода и ветвлений в зависимости от версий. Всё это сильно усложняет разработку и тестирование и приводит к появлению различных багов.
Альтернативный подход к изменению разметки страницы
Чтобы решать подобную проблему, уже давно был придуман подход Backend-Driven UI. Это означает, что вся информация о разметке приходит на клиент с сервера и конфигурируется на сервере. Обычно разметка описывается определённой структурой в виде JSON, где перечисляется, какие блоки должны присутствовать на странице, какие цвета, кнопки, тексты и прочее.
Чтобы имплементировать подход Backend-Driven UI в Авито, мы разработали движок рендеринга Beduin. Он умеет принимать разметку с сервера на клиентах в определённом формате и правильно её рендерить. Подробно об этом можно прочитать в отдельной статье.
Beduin решает несколько главных проблем:
Вся разметка возвращается с сервера, поэтому при её обновлении она меняется сразу у всех пользователей даже в мобильных приложениях без необходимости их обновлять.
Все клиенты используют один-единственный инструмент для рендеринга, поэтому проще обучать сотрудников и внедрять изменения.
Однако у этого подхода тоже есть слабые стороны:
Управление разметкой перекладывается на бэкенд-разработчиков, так как теперь её нужно описывать в сервисах на go через специальную библиотеку, а такого происходить не должно. Бэкенд-инженеры не должны заниматься вёрсткой, даже если она выполняется на сервере.
Чтобы поправить разметку, всё ещё нужно вносить правки в коде и деплоить микросервис, который отвечает за её предоставление клиенту. Мы же хотим иметь такой инструмент, который позволит вносить изменения без участия программистов и написания кода.
Резюмируя, можно сказать, что вышеописанные подходы к управлению интерфейсами подразумевают большую работу с кодом и отвлекают разработчиков от более важных и сложных задач. Чтобы объединить преимущества и искоренить недостатки других фреймворков, мы в Авито придумали платформу Bricks и внедрили её в рабочие процессы.
Что такое Bricks и почему мы её используем
Bricks — это платформа, которая базируется на принципах подхода Backend-Driven UI и позволяет управлять интерфейсами при помощи независимых и переиспользуемых виджетов.
В нашей платформе есть несколько основных сущностей, из которых всё состоит.
Шаблон
Основная агрегирующая сущность платформы Bricks, входная точка для определения правил отображения интерфейса. Шаблон описывает поведение и отображение страницы на сайте или экрана в приложении. Он позволяет удобно управлять частью интерфейса, определять ответственных за него, конфигурировать платформу и ещё много чего.
Виджет
Это минимальная единица интерфейса, которая добавляется в макет. А ещё это отдельный и переиспользуемый элемент, который можно настраивать независимо от других элементов. Он может представлять собой маленький компонент, например кнопку, либо большой и сложный кусок интерфейса со своей внутренней логикой.
Макет
Он существует только в рамках шаблона и описывает то, какие виджеты, в какой последовательности и с какими данными должны быть отрисованы на шаблоне. Макеты обеспечивают версионируемость изменений, поэтому каждое сохранённое изменение в макете создаёт его новую числовую версию.
После того, как версию макета сохранили, её можно опубликовать в production. Это означает, что при успешной валидации и публикации Bricks начнёт отдавать клиентам последнюю опубликованную версию макета, если явно не запрашивается иная.
Благодаря версионированию можно мгновенно переключиться на более раннее состояние макета, если возникнет такая потребность. Также оно позволяет хранить полную историю изменений, что дает большой простор для реализации различных полезных инструментов.
Источник данных
Это абстракция над микросервисами Авито, которая позволяет подключать к макету RPC-ручки этих микросервисов, настраивать их и использовать для обогащения разметки данными.
Взаимодействие с Bricks выглядит так: пользователь заходит в платформу с простым интерфейсом, вносит изменения в макете и публикует его новую версию. Если новый макет не нравится или в нём нашлась ошибка, можно легко откатиться к предыдущей версии.
Изменения вступают в силу мгновенно: не нужно заново деплоить приложение или взаимодействовать с кодом. Поэтому работать с Bricks может любой специалист, не владеющий навыком разработки, например контент- или продакт-менеджер.
Когда клиентское приложение хочет отрисовать страницу, оно приходит за данными в определённый микросервис. Тот посылает запрос в bricks-composition — главный сервис Bricks, который отвечает за разметку. Вместе с запросом микросервис передаёт и контракты шаблона — данные, которые нужны, чтобы отрендерить этот шаблон. При создании шаблона пользователь сам определяет контракты и может обогащать разметку переданными данными.
Если к макету подключены источники данных, то bricks-composition самостоятельно отправит запросы в соответствующие сервисы оптимальным образом, а полученными данными обогатит разметку.
После обработки всех запросов bricks-composition преобразует разметку в формат Beduin и возвращает её в качестве результата вызова. Микросервис, который обращался в Bricks, передаёт полученную разметку клиентскому приложению. Клиент, в свою очередь, передаёт JSON рендер-движку Beduin, который уже непосредственно производит отрисовку на экране.
Вот что умеет bricks-composition:
определять актуальную версию макета для конкретного шаблона;
получать конфигурацию макета;
обогащать макет данными из параметров шаблона;
обогащать макет данными через источники данных;
резолвить зависимости и менять разметку в рантайме в зависимости от полученных данных;
генерировать разметку в Beduin-формате.
Как Bricks решает проблемы категоризации
Мы в Авито хотим кастомизировать страницы и экраны так, чтобы категории и даже микрокатегории отличались друг от друга разметкой. Предположим, у нас есть очень сильно упрощённое дерево категорий, в котором три узла: «Транспорт», «Недвижимость» и «Личные вещи».
Нам нужно, чтобы изменения в разметке для категории «Транспорт» никак не затрагивали категорию «Недвижимость». А микрокатегории вроде «Посуточной аренды» тоже имели особенный вид, и изменения в них оставались точечными.
Bricks поддерживает категоризацию, то есть даёт возможность создавать кастомную разметку для отдельных микрокатегорий и не затрагивать соседние. При этом позволяет выделять общие переиспользуемые части, которые будут одинаковыми во всех категориях.
Как мы адаптируем разметку с учётом зависимостей
Авито стремится управлять отображением страниц и экранов в зависимости от наступления определённых событий и при соблюдении определённых условий.
Например, нужно, чтобы страница объявлений по-разному отображалась для пользователей, которые:
разместили больше 10 объявлений;
имеют статус PRO-продавца;
установили версию приложения 145 и выше;
участвуют в A/B-тесте.
В этих вариантах прослеживается три типа зависимостей, которые поддерживает платформа Bricks:
Зависимость от данных.
Зависимость от версии приложения.
Зависимость от A/B-тестов.
Добавление механики зависимостей позволяет гибко менять отображение страниц при разных условиях.
Что там с производительностью и стабильностью
При таком подходе к формированию разметки Bricks становится критически важной зависимостью, поэтому к платформе выставляются достаточно жёсткие требования по производительности и стабильности.
Так как скорость формирования разметки напрямую влияет на скорость отрисовки страниц и экранов, мы усиленно искали способы ускорить этот процесс. В результате сейчас разметка для достаточно большого шаблона без источников данных формируется со скоростью до 20 мс. Если же к шаблону подключены источники данных, то время увеличивается на время ответа самого медленного из них. В среднем это около 50 мс.
Помимо этого, мы обеспечиваем стабильность сервиса на уровне 99,99, чтобы транзитивно не влиять на стабильность сервисов-потребителей.
Что в итоге
Создание платформы Bricks помогло нам внедрить новый подход к управлению разметкой. В результате сейчас множество изменений даже для мобильных приложений можно производить прямо в интерфейсе нашей платформы без необходимости писать код и релизить новые версии приложений.
Впереди у нас ещё очень много работы и грандиозные планы, о чём мы вам обязательно расскажем в следующих статьях.