Опыт онлайн-кинотеатра Иви
Когда в начале 2017 года мы впервые задумались о создании собственной системы доставки дизайна в код, об этом уже многие говорили и кто-то даже делал. Однако, об опыте построения кроссплатформенных дизайн-систем и по сей день мало что известно, а понятных и проверенных рецептов, описывающих технологии и способы подобной трансформации процесса имплементации дизайна в уже работающий продукт как не было, так и нет. Да и под «компонентами в коде» часто понимают очень разные вещи.
Меж тем компания год от года удваивала штат — нужно было масштабировать отдел дизайна и оптимизировать процессы создания и передачи макетов в разработку. Умножаем всё это на «зоопарк» платформ, которые нужно поддерживать, и получаем подобие вавилонского столпотворения, которое просто не способно «нормально делать» и приносить доход. Развитие платформ часто шло параллельно, и один и тот же функционал мог выходить на разных платформах с лагом в несколько месяцев.
Отдельные наборы макетов для каждой платформы
Традиционно, мы начали с проблем, которые помогла бы решить дизайн-система и сформулировали требования к её проектированию. Помимо создания единого визуального языка, увеличения скорости макетирования и разработки, повышения качества продукта в целом, было жизненно необходимо максимально унифицировать дизайн. Это нужно для того, чтобы развитие функционала стало возможным сразу на всех наших платформах одновременно: Web, iOS, Android, Smart TV, tvOS, Android TV, Windows 10, xBox One, PS4, Roku — не прорабатывая при этом каждую из них в отдельности. И это у нас получилось!
Когда принципиальные договорённости отделов продукта и разработки были достигнуты, мы сели за подбор технологического стека и проработку деталей всего процесса — от макета до релиза. Чтобы полностью автоматизировать процесс передачи дизайна в разработку поисследовали вариант с парсером параметров компонентов прямо из Sketch-файлов с макетами. Оказалось, что находить нужные нам куски кода и извлекать нужные нам параметры — затея сложная и опасная. Во-первых, дизайнерам придётся быть крайне аккуратными в именовании всех слоёв исходника, во-вторых, это работает только для самых простых компонентов, а в-третьих, зависимость от чужой технологии и структуры кода исходного Sketch-макета ставит под угрозу будущее всего проекта. Мы решили отказаться от автоматизации на этом участке. Так в команде дизайн-системы появился первый человек, на вход которому подаются дизайн-макеты, а на выходе — данные, описывающие все параметры компонентов и иерархически упорядоченные по методологии атомарного дизайна.
Дело оставалось за малым: где и как хранить данные, как передавать в разработку и как интерпретировать в разработке на всех поддерживаемых нами платформах. Вечер переставал быть томным… Итогом регулярных встреч рабочей группы, состоящей из дизайнеров и тимлидов от каждой платформы стали договорённости о нижеследующем.
Вручную разбираем визуал на элементы-атомы: шрифты, цвета, прозрачности, отступы, скругления, иконки, картинки и длительности для анимаций. И собираем из этого кнопки, инпуты, чекбоксы, виджеты банковских карт и т. д. Стилям любого из уровней, кроме пиктограмм присваиваем несемантические имена, например названия городов, имена нимф, покемонов, марки автомобилей… Тут условие одно — список не должен исчерпаться раньше, чем закончатся стили — шоу маст гоу он! Семантикой же не стоит увлекаться, чтобы не пришлось добавлять среднюю кнопку между «small» и «medium», например.
Разработчики ушли думать, как хранить и передавать данные, чтобы это подходило всем платформам, а дизайну предстояло спроектировать элементы интерфейса, способные одинаково хорошо выглядеть и эффективно работать на всём парке поддерживаемых устройств.
Ранее мы уже успели «обкатать» большинство элементов дизайна в приложении под Windows 10, которое на тот момент являлось для нас новой платформой, то есть требовалась отрисовка и разработка «с нуля». Рисуя его, мы смогли подготовить и проверить большинство компонентов и понять, какие из них должны были войти в будущую дизайн-систему Иви. Без такой «песочницы» подобный опыт можно было получить только большим числом итераций на уже работающих платформах, а на это потребовалось бы больше года.
Переиспользование одинаковых компонентов на разных платформах уменьшает количество макетов и массив данных дизайн-системы в разы, поэтому дизайну предстояло решить ещё одну задачу, ранее не описанную в практиках продуктового дизайна и разработки — как, например кнопку для телефонов и планшетов переиспользовать на телевизорах? И как в принципе быть с размерами шрифтов и элементов на таких разных платформах?
Очевидно, требовалось спроектировать кроссплатформенную модульную сетку, которая будет задавать нужные нам размеры текста и элементов для каждой конкретной платформы. За точку отсчёта для сетки мы выбрали размер и количество постеров фильмов, которые хотим видеть на том или ином экране и, исходя из этого сформулировали правило построения колонок сетки, при условии — ширина одной колонки равна ширине постера.
Теперь нужно привести к одному размеру макета все большие экраны и вписать их в общую сетку. Apple TV и Roku разрабатываются в размер 1920x1080, Android TV — 960x540, Smart TV, в зависимости от вендора бывают такими же, а бывают 1280x720. Когда приложение рендерится и отображается на экранах Full HD, 960 умножается на 2, 1280 на 1,33, а 1920 выводится как есть.
Опуская скучные подробности, мы пришли к тому, что вообще все экраны, включая телеэкраны с точки зрения элементов и их размеров покрываются одним дизайн-макетом, а все телеэкраны являются частным случаем общей кроссплатформенной сетки, и состоят из пяти или шести колонок, как средний планшет или десктоп. Кому интересны подробности, го в комменты.
Единый UI для всех платформ
Теперь для отрисовки новой фичи нам не нужно рисовать макеты под каждую из платформ, плюс варианты адаптивности для каждой из них. Достаточно показать один макет и его адаптивность для всех платформ и устройств любой ширины: телефоны — 320–599, всё остальное — 600–1280.
Конечно, как бы нам ни хотелось прийти к абсолютно унифицированному дизайну, каждая платформа имеет свои уникальные особенности. Несмотря на то, что и веб, и Smart TV используют стек ReactJS + TypeScript, приложение для Smart TV запускается на устаревших WebKit- и Presto-клиентах, и потому не может использовать общие стили с вебом. А email-рассылки и вовсе вынуждены работать с табличной вёрсткой. При этом ни одна из не-html-платформ не использует и не планирует использовать React Native или какие-то её аналоги, опасаясь ухудшения производительности, так как у нас слишком много кастомных лэйаутов, коллекций со сложной логикой обновления, изображений и видео. Поэтому для нас не подходит распространённая схема — поставлять готовые CSS-стили или React-компоненты. Поэтому мы решили передавать данные в формате JSON, описывая значения в абстрактном декларативном виде.
Декларативность описания также предполагает, что если платформа технически не может использовать какое-либо свойство или его значение, она может его проигнорировать. С точки зрения терминологии мы сделали некое подобие языка эсперанто: что-то взяли из Android, что-то из SVG, что-то из CSS.
В случае если на той или иной платформе потребуется отображать элементы как-то иначе, мы реализовали возможность передачи соответствующей генерации данных в виде отдельного JSON-файла. Например, состояние «в фокусе» для Smart TV, диктует изменение позиции текста под постером, значит для этой платформы данный компонент в значении свойства «отступ» будет содержать необходимые ей 8 поинтов отступа. Хоть это и усложняет инфраструктуру дизайн-системы, зато даёт дополнительную степень свободы, оставляя нам возможность самим управлять визуальной «непохожестью» платформ, а не быть заложниками нами же созданной архитектуры.
Иконографика в цифровом продукте — это всегда объёмный и не самый простой подпроект, часто имеющий отдельного дизайнера. Глифов всегда много, каждый из них имеет несколько размеров и цветов, к тому же платформам они нужны, как правило в разных форматах. В общем, не было повода не завести всё это в дизайн-систему.
Глифы загружаются в векторном SVG-формате, а значения цветов автоматически заменяются переменными. Приложения-клиенты могут получать их уже готовыми к использованию — в любом формате и цвете.
Поверх JSON’а с данными мы написали инструмент для предпросмотра компонентов — JS-приложение, на лету пропускающее JSON-данные через свои генераторы разметки и стилей, и отображающее в браузере различные вариации каждого из компонентов. По сути, предпросмотр является точно таким же клиентом, как и платформенные приложения, и работает с теми же данными.
Понять, как работает тот или иной компонент, проще всего путём взаимодействия с ним. Поэтому мы не стали использовать инструменты, подобные Storybook, а сделали интерактивный предпросмотр — можно пощупать, понаводить, покликать… При добавлении в дизайн-систему нового компонента он появляется в предпросмотре, чтобы платформам было на что ориентироваться при его внедрении.
На основе тех данных, которые в виде JSON поставляются платформам, автоматически формируется документация по компонентам. Описывается перечень свойств и возможные типы значений в каждом из них. После автогенерации информацию можно уточнить в ручном режиме, добавить текстовое описание. Предпросмотр и документация снабжены перекрёстными ссылками друг на друга на уровне каждого компонента, а вся информация, попадающая в документацию, доступна разработчикам в виде дополнительных JSON-файлов.
Ещё одной необходимостью стала возможность со временем заменять и обновлять уже существующие компоненты. Дизайн-система научилась сообщать разработчикам, какие свойства или даже целые компоненты использовать нельзя и удалять их, как только они перестают использоваться на всех платформах. Пока в этом процессе ещё много «ручного» труда, но мы не стоим на месте.
Несомненно, самым масштабным по сложности этапом стала интерпретация данных дизайн-системы в коде всех поддерживаемых нами платформ. Если, например, модульные сетки на вебе не являются чем-то новым, то разработчики нативных мобильных приложений под iOS и Android изрядно попотели, прежде чем придумали, как с этим жить.
Для верстки экранов iOS-приложения мы используем два базовых механизма, которые предоставляет iviUIKit: cвободная компоновка элементов и компоновка коллекций элементов. Мы используем VIPER, и всё взаимодействие с iviUIKit сосредоточено во View, а большая часть взаимодействия с Apple UIKit сосредоточена в iviUIKit. Размеры и расположение элементов задаётся в терминах колонок и синтаксических конструкций, работающих поверх нативных констрейнтов iOS SDK, делающих их более прикладными. Особенно это упростило нам жизнь при работе с UICollectionView. Мы написали несколько настраиваемых обёрток для лэйаутов, в том числе довольно сложных. Клиентского кода получилось минимум и он стал декларативным.
Для генерации стилей в проекте Android мы используем Gradle, превращая данные дизайн-системы в стили формата XML. При этом у нас есть несколько генераторов различного уровня:
После того, как дизайнеры нарисовали новый компонент или переработали существующий, эти изменения попадают в дизайн-систему. Разработчики каждой из платформ дорабатывают свою кодогенерацию, обеспечивая поддержку изменений. После этого его можно использовать в реализации нового функционала, где этот компонент необходим. Таким образом, взаимодействие с дизайн-системой происходит не в реальном времени, а только в момент сборки новых релизов. Такой подход также позволяет лучше контролировать процесс передачи данных и гарантирует работоспособность кода в проектах клиентской разработки.
Скоро год как дизайн-система стала частью инфраструктуры, обслуживающей развитие онлайн-кинотеатра Иви, и уже можно делать кое-какие выводы:
Предпросмотр компонентов дизайн-системы Иви — design.ivi.ru
Когда в начале 2017 года мы впервые задумались о создании собственной системы доставки дизайна в код, об этом уже многие говорили и кто-то даже делал. Однако, об опыте построения кроссплатформенных дизайн-систем и по сей день мало что известно, а понятных и проверенных рецептов, описывающих технологии и способы подобной трансформации процесса имплементации дизайна в уже работающий продукт как не было, так и нет. Да и под «компонентами в коде» часто понимают очень разные вещи.
Меж тем компания год от года удваивала штат — нужно было масштабировать отдел дизайна и оптимизировать процессы создания и передачи макетов в разработку. Умножаем всё это на «зоопарк» платформ, которые нужно поддерживать, и получаем подобие вавилонского столпотворения, которое просто не способно «нормально делать» и приносить доход. Развитие платформ часто шло параллельно, и один и тот же функционал мог выходить на разных платформах с лагом в несколько месяцев.
Отдельные наборы макетов для каждой платформы
Традиционно, мы начали с проблем, которые помогла бы решить дизайн-система и сформулировали требования к её проектированию. Помимо создания единого визуального языка, увеличения скорости макетирования и разработки, повышения качества продукта в целом, было жизненно необходимо максимально унифицировать дизайн. Это нужно для того, чтобы развитие функционала стало возможным сразу на всех наших платформах одновременно: Web, iOS, Android, Smart TV, tvOS, Android TV, Windows 10, xBox One, PS4, Roku — не прорабатывая при этом каждую из них в отдельности. И это у нас получилось!
Дизайн → данные
Когда принципиальные договорённости отделов продукта и разработки были достигнуты, мы сели за подбор технологического стека и проработку деталей всего процесса — от макета до релиза. Чтобы полностью автоматизировать процесс передачи дизайна в разработку поисследовали вариант с парсером параметров компонентов прямо из Sketch-файлов с макетами. Оказалось, что находить нужные нам куски кода и извлекать нужные нам параметры — затея сложная и опасная. Во-первых, дизайнерам придётся быть крайне аккуратными в именовании всех слоёв исходника, во-вторых, это работает только для самых простых компонентов, а в-третьих, зависимость от чужой технологии и структуры кода исходного Sketch-макета ставит под угрозу будущее всего проекта. Мы решили отказаться от автоматизации на этом участке. Так в команде дизайн-системы появился первый человек, на вход которому подаются дизайн-макеты, а на выходе — данные, описывающие все параметры компонентов и иерархически упорядоченные по методологии атомарного дизайна.
Дело оставалось за малым: где и как хранить данные, как передавать в разработку и как интерпретировать в разработке на всех поддерживаемых нами платформах. Вечер переставал быть томным… Итогом регулярных встреч рабочей группы, состоящей из дизайнеров и тимлидов от каждой платформы стали договорённости о нижеследующем.
Вручную разбираем визуал на элементы-атомы: шрифты, цвета, прозрачности, отступы, скругления, иконки, картинки и длительности для анимаций. И собираем из этого кнопки, инпуты, чекбоксы, виджеты банковских карт и т. д. Стилям любого из уровней, кроме пиктограмм присваиваем несемантические имена, например названия городов, имена нимф, покемонов, марки автомобилей… Тут условие одно — список не должен исчерпаться раньше, чем закончатся стили — шоу маст гоу он! Семантикой же не стоит увлекаться, чтобы не пришлось добавлять среднюю кнопку между «small» и «medium», например.
Визуальный язык
Разработчики ушли думать, как хранить и передавать данные, чтобы это подходило всем платформам, а дизайну предстояло спроектировать элементы интерфейса, способные одинаково хорошо выглядеть и эффективно работать на всём парке поддерживаемых устройств.
Ранее мы уже успели «обкатать» большинство элементов дизайна в приложении под Windows 10, которое на тот момент являлось для нас новой платформой, то есть требовалась отрисовка и разработка «с нуля». Рисуя его, мы смогли подготовить и проверить большинство компонентов и понять, какие из них должны были войти в будущую дизайн-систему Иви. Без такой «песочницы» подобный опыт можно было получить только большим числом итераций на уже работающих платформах, а на это потребовалось бы больше года.
Переиспользование одинаковых компонентов на разных платформах уменьшает количество макетов и массив данных дизайн-системы в разы, поэтому дизайну предстояло решить ещё одну задачу, ранее не описанную в практиках продуктового дизайна и разработки — как, например кнопку для телефонов и планшетов переиспользовать на телевизорах? И как в принципе быть с размерами шрифтов и элементов на таких разных платформах?
Очевидно, требовалось спроектировать кроссплатформенную модульную сетку, которая будет задавать нужные нам размеры текста и элементов для каждой конкретной платформы. За точку отсчёта для сетки мы выбрали размер и количество постеров фильмов, которые хотим видеть на том или ином экране и, исходя из этого сформулировали правило построения колонок сетки, при условии — ширина одной колонки равна ширине постера.
Теперь нужно привести к одному размеру макета все большие экраны и вписать их в общую сетку. Apple TV и Roku разрабатываются в размер 1920x1080, Android TV — 960x540, Smart TV, в зависимости от вендора бывают такими же, а бывают 1280x720. Когда приложение рендерится и отображается на экранах Full HD, 960 умножается на 2, 1280 на 1,33, а 1920 выводится как есть.
Опуская скучные подробности, мы пришли к тому, что вообще все экраны, включая телеэкраны с точки зрения элементов и их размеров покрываются одним дизайн-макетом, а все телеэкраны являются частным случаем общей кроссплатформенной сетки, и состоят из пяти или шести колонок, как средний планшет или десктоп. Кому интересны подробности, го в комменты.
Единый UI для всех платформ
Теперь для отрисовки новой фичи нам не нужно рисовать макеты под каждую из платформ, плюс варианты адаптивности для каждой из них. Достаточно показать один макет и его адаптивность для всех платформ и устройств любой ширины: телефоны — 320–599, всё остальное — 600–1280.
Данные → разработка
Конечно, как бы нам ни хотелось прийти к абсолютно унифицированному дизайну, каждая платформа имеет свои уникальные особенности. Несмотря на то, что и веб, и Smart TV используют стек ReactJS + TypeScript, приложение для Smart TV запускается на устаревших WebKit- и Presto-клиентах, и потому не может использовать общие стили с вебом. А email-рассылки и вовсе вынуждены работать с табличной вёрсткой. При этом ни одна из не-html-платформ не использует и не планирует использовать React Native или какие-то её аналоги, опасаясь ухудшения производительности, так как у нас слишком много кастомных лэйаутов, коллекций со сложной логикой обновления, изображений и видео. Поэтому для нас не подходит распространённая схема — поставлять готовые CSS-стили или React-компоненты. Поэтому мы решили передавать данные в формате JSON, описывая значения в абстрактном декларативном виде.
Так свойствоrounding: 8
приложение Windows 10 преобразует вCornerRadius="8"
, веб —border-radius: 8px
, Android —android:radius="8dp"
, iOS —self.layer.cornerRadius = 8.0
.
CвойствоoffsetTop: 12
один и тот же веб-клиент в разных случаях может интерпретировать какtop
,margin-top
,padding-top
илиtransform
Декларативность описания также предполагает, что если платформа технически не может использовать какое-либо свойство или его значение, она может его проигнорировать. С точки зрения терминологии мы сделали некое подобие языка эсперанто: что-то взяли из Android, что-то из SVG, что-то из CSS.
В случае если на той или иной платформе потребуется отображать элементы как-то иначе, мы реализовали возможность передачи соответствующей генерации данных в виде отдельного JSON-файла. Например, состояние «в фокусе» для Smart TV, диктует изменение позиции текста под постером, значит для этой платформы данный компонент в значении свойства «отступ» будет содержать необходимые ей 8 поинтов отступа. Хоть это и усложняет инфраструктуру дизайн-системы, зато даёт дополнительную степень свободы, оставляя нам возможность самим управлять визуальной «непохожестью» платформ, а не быть заложниками нами же созданной архитектуры.
Пиктограммы
Иконографика в цифровом продукте — это всегда объёмный и не самый простой подпроект, часто имеющий отдельного дизайнера. Глифов всегда много, каждый из них имеет несколько размеров и цветов, к тому же платформам они нужны, как правило в разных форматах. В общем, не было повода не завести всё это в дизайн-систему.
Глифы загружаются в векторном SVG-формате, а значения цветов автоматически заменяются переменными. Приложения-клиенты могут получать их уже готовыми к использованию — в любом формате и цвете.
Предпросмотр
Поверх JSON’а с данными мы написали инструмент для предпросмотра компонентов — JS-приложение, на лету пропускающее JSON-данные через свои генераторы разметки и стилей, и отображающее в браузере различные вариации каждого из компонентов. По сути, предпросмотр является точно таким же клиентом, как и платформенные приложения, и работает с теми же данными.
Понять, как работает тот или иной компонент, проще всего путём взаимодействия с ним. Поэтому мы не стали использовать инструменты, подобные Storybook, а сделали интерактивный предпросмотр — можно пощупать, понаводить, покликать… При добавлении в дизайн-систему нового компонента он появляется в предпросмотре, чтобы платформам было на что ориентироваться при его внедрении.
Документация
На основе тех данных, которые в виде JSON поставляются платформам, автоматически формируется документация по компонентам. Описывается перечень свойств и возможные типы значений в каждом из них. После автогенерации информацию можно уточнить в ручном режиме, добавить текстовое описание. Предпросмотр и документация снабжены перекрёстными ссылками друг на друга на уровне каждого компонента, а вся информация, попадающая в документацию, доступна разработчикам в виде дополнительных JSON-файлов.
Депрекатор
Ещё одной необходимостью стала возможность со временем заменять и обновлять уже существующие компоненты. Дизайн-система научилась сообщать разработчикам, какие свойства или даже целые компоненты использовать нельзя и удалять их, как только они перестают использоваться на всех платформах. Пока в этом процессе ещё много «ручного» труда, но мы не стоим на месте.
Клиентская разработка
Несомненно, самым масштабным по сложности этапом стала интерпретация данных дизайн-системы в коде всех поддерживаемых нами платформ. Если, например, модульные сетки на вебе не являются чем-то новым, то разработчики нативных мобильных приложений под iOS и Android изрядно попотели, прежде чем придумали, как с этим жить.
Для верстки экранов iOS-приложения мы используем два базовых механизма, которые предоставляет iviUIKit: cвободная компоновка элементов и компоновка коллекций элементов. Мы используем VIPER, и всё взаимодействие с iviUIKit сосредоточено во View, а большая часть взаимодействия с Apple UIKit сосредоточена в iviUIKit. Размеры и расположение элементов задаётся в терминах колонок и синтаксических конструкций, работающих поверх нативных констрейнтов iOS SDK, делающих их более прикладными. Особенно это упростило нам жизнь при работе с UICollectionView. Мы написали несколько настраиваемых обёрток для лэйаутов, в том числе довольно сложных. Клиентского кода получилось минимум и он стал декларативным.
Для генерации стилей в проекте Android мы используем Gradle, превращая данные дизайн-системы в стили формата XML. При этом у нас есть несколько генераторов различного уровня:
- Базовые. Парсят данные примитивов для генераторов более высокого уровня.
- Ресурсные. Скачивают картинки, иконки, и прочую графику.
- Компонентные. Пишутся для каждого компонента, где описано какие свойства и как перевести в стили.
Релизы приложений
После того, как дизайнеры нарисовали новый компонент или переработали существующий, эти изменения попадают в дизайн-систему. Разработчики каждой из платформ дорабатывают свою кодогенерацию, обеспечивая поддержку изменений. После этого его можно использовать в реализации нового функционала, где этот компонент необходим. Таким образом, взаимодействие с дизайн-системой происходит не в реальном времени, а только в момент сборки новых релизов. Такой подход также позволяет лучше контролировать процесс передачи данных и гарантирует работоспособность кода в проектах клиентской разработки.
Итоги
Скоро год как дизайн-система стала частью инфраструктуры, обслуживающей развитие онлайн-кинотеатра Иви, и уже можно делать кое-какие выводы:
- Это большой и сложный в реализации проект, требующий постоянных выделенных ресурсов.
- Это позволило нам создать свой уникальный кроссплатформенный визуальный язык, отвечающий задачам сервиса онлайн видео.
- У нас больше нет визуально и функционально отстающих платформ.
Предпросмотр компонентов дизайн-системы Иви — design.ivi.ru