Про то, что такое дизайн-система, как она должна работать, уже написано немало статей. Но зачастую авторы охватывают лишь какой-то отдельный аспект этой обширной темы. Я же, в свою очередь, хочу рассмотреть именно сам процесс создания дизайн-системы, основанный на опыте нашей команды, рассказать об основных трудностях, с которыми мы столкнулись и, возможно, предостеречь от распространённых ошибок, которые мы совершили на этом тернистом пути. А следовать ему или нет, решение остается за вами.
Ну что же, погнали…
Немного теории
Что же такое дизайн-система? Согласно определению из «Википедии»: «дизайн-система — набор компонентов, правил, предписаний и инструментов для повышения качества и скорости разработки продуктов». Тут особо и поспорить-то не с чем.
Я бы, условно, разделил дизайн-систему на две составляющие:
визуальное представление (для дизайнеров);
техническая реализация (для разработчиков).
Визуальное представление — это набор компонентов, шрифтов, иконок, цветовых схем и так далее в условной Figma или Sketch. Эта часть разрабатывается и используется дизайнерами для быстрого проектирования и построения интерфейса.
Техническая реализация — это зеркальное отражение визуального представления, но только в коде для разработчиков. В отличие от визуального представления, которое должно существовать в единственном экземпляре, технических реализаций может быть много — начиная от разделения по платформам (iOS, Android, Web), заканчивая разделением по конкретным фреймворкам (iOS: UIKit и SwiftUI; Android: XML/Layout и Compose, Web: Angular и React).
Дополнительно я бы разделил дизайн-системы ещё на две категории:
локальные;
глобальные.
Локальные дизайн-системы — это системы, которые разработаны и работают только на одном продукте компании. В большинстве проектов реализован данный подход.
Глобальные дизайн-системы — концептуально почти ничем не отличают от локальных, за исключением того, что они создаются для группы продуктов, а это, в свою очередь, накладывает на них ряд дополнительных требований и ограничений.
Локальную дизайн-систему можно разрабатывать просто, как часть продукта без дополнительных расходов (вы просто складываете все ваши компоненты в одно место, объединяете общие компоненты между собой и подбиваете их под общую стилистику и гайдлайны вашей компании). Локальная дизайн система так или иначе появляется в любом проекте сама-собой, потому что дизайнерам и разработчикам нужно удобнее переиспользовать компоненты, чем каждый раз создавать новые. Но если вы все же хотите замахнуться на глобальную дизайн-систему, то она сама должна являться полноценным продуктом, которому вы будете посвящать большую часть времени команды. А потребителем продукта будет являться весьма искушённая публика — разработчики и дизайнеры.
Если преследуем цель повысить узнаваемость продукта, можно обойтись и локальными дизайн-системами, которые просто будут объединены общими гайдлайнами. Например, посмотрим на продукты той же самой компании «Яндекс»: когда открываешь приложение «Яндекс.Go» и «Яндекс.Еда», визуально кажется, что продукты похожи, хотя это две независимые команды, с разными локальными дизайн системами, объединенными единой стилистикой. (возможно на данный момент уже что-то поменялось)
Отлично, теперь можно переходить дальше.
Знакомимся с задачей
Перед моей командой была поставлена задача создания визуального представления и технической реализации дизайн-системы для крупного заказчика. Конечными потребителями должны были стать 15 миллионов пользователей. А использовать дизайн-систему должна была не одна команда, не две, а вся организация в целом.
Проводим анализ аудитории
Как мы помним, наша дизайн система - это самостоятельный продукт. И что же нам делать, когда мы приступаем к разработке продукта? Сразу бежать проектировать компоненты и писать код — конечно, нет! Нужно провести анализ аудитории, чтобы понять потребности других команд. Мы провели ряд опросов.
Опрос №1. Для дизайнеров
какими инструментами проектирования пользуются;
какие подходы к построению дизайна используют;
количество дизайнеров в команде.
Тут не было никаких откровений. Все дизайнеры пользовались Figma, подходы к проектированию у всех были плюс-минус одинаковыми. Но выяснился интересный факт, что в компании уже существует несколько локальных дизайн-систем, которые функционируют в рамках группы продуктов, но между собой они никак не связаны.
Задача перед дизайнерами была ясна и понятна: выбрать наиболее распространённую дизайн-систему и доработать её до того уровня, чтобы учитывать потребности всех остальных команд. Конечно, когда вы приходите на проект, хочется всё сжечь и сделать с нуля. Кажется, что так намного быстрее и правильнее, но как показывает практика - доработать и возможно немного переработать старое намного быстрее, чем разрабатывать с нуля.
Опрос №2. Для разработчиков
минимальная поддерживаемая версия операционной системы;
какой стек технологий используется;
количество разработчиков в команде.
После проведения опроса мы получили достаточно распространённую картину. Минимальные версии операционных систем у большинства команд были — iOS 11 и Android 5.0, стек стандартный: для iOS — UIKit, Android — Layout + XML.
Мы рассматриваем случай технического аспекта дизайн-системы для мобильной разработки, для веба всё плюс-минус аналогично.
Казалось бы, всё готово, статистика собрана, с командами пообщались, можно приниматься за разработку, но тут мы не учли один очень важный аспект, о котором поговорим далее.
Не пытайтесь быть умнее пользователей
Наша команда собрала статистку, учла все требования и пожелания и разработала первую версию библиотеки. Но мы не учли, что встретим серьёзное сопротивление со стороны большого числа других команд, работающими над продуктами с достаточно продолжительным жизненным циклом.
Виноваты ли были команды, что не хотели переходить на новую дизайн-систему? Конечно, нет! Только представьте, приходят к вам в команду незнакомые люди и говорят, что дизайнерам нужно полностью перевести дизайн на новые компоненты, а разработчикам полностью переписать весь код, связанный c UI, так потом ещё и провести полный регресс. Не знаю, кто бы на их месте ответил бы по-другому.
А что это значит? Что мы неправильно выбрали первоначальную аудиторию, на которую должны были ориентироваться. Ведь, как мы помним, дизайн-система должна ускорять процесс разработки продуктов, а не тормозить его. А для команд, которые уже давно работают над продуктом, предложенная новинка не принесёт никакой пользы, кроме огромного бэклога. Поэтому легче всего было пойти другим путём и найти молодые команды, которые только формировались и не имели полноценного дизайна, а разработка либо ещё не началась, либо была на начальном этапе.
Нам пришлось дополнить опрос и заново собрать статистику. Результат отличался. Если в случае с ОС от Google нам повезло и Android-сообщество использует в большинстве своём консервативные подходы к вёрстке — Layout + XML, то для iOS у новых команд был существенный перевес в сторону SwiftUI и для них это было важным критерием перехода на новую библиотеку.
Хорошо, что у нас было достаточно компетенции и команда быстро зарелизила новую версию под SwiftUI. Но из минусов остался тот факт, что нам до сих пор приходится поддерживать две версии библиотеки — SwiftUI и UIKit. А это в два раза больше работы.
Но нам нужно сохранять лояльность комьюнити, поэтому мы не бросаем поддержку UIKit, но все новые фичи в основном разрабатываем под SwiftUI.
Внедряйте дизайн-систему небольшими шагами
После того как мы провели опрос и реализовали базовую функциональность библиотеки, пришло время для её интеграции в другие продукты. К сожалению или радости, у нашей команды не было своего продукта, на котором можно в полной мере обкатать библиотеку.
Мы решили искать молодые команды, у которых только начиналась разработка нового продукта и у них не было времени на разработку собственной дизайн-системы. А главное, чтобы они были лояльны к багам и недоработкам в библиотеке.
Казалось бы, найти такие команды сложно. Но важно понять, что вы можете предложить взамен. Мы нашли компромисс: ребята использовали библиотеку, репортили о багах и недоработках в библиотеке, а мы брали их задачи в бэклог с максимальным приоритетом и оперативно выпускали хотфиксы в случае критических неисправностей.
Небольшой совет: я советую вам начинать обкатывать библиотеку, как можно быстрее, чтобы раньше собирать фидбэк пользователей. Лучше двигаться маленькими шагами и постоянно получать фидбэк, чем уйти на пол года, сделать что-то и понять, что конечный результат никому не нужен
Запустите систему сбора обратной связи
После того, как мы начали работать над дизайн-системой как над продуктом, которым будут пользоваться другие люди, мы поняли, что нужно как-то собирать обратную связь и демонстрировать статус работы.
Изначально мы начинали все с простого чата в Telegram, куда писали новости о релизах, обсуждали проблемы и так далее (не судите нас строго, нам нужно было быстро закрыть потребность сбора фидбэка). Но позже мы поняли, что очень много запросов пользователей теряется, а недовольство повышается.
Мы решили эту проблему просто открытием нашей доски Jira на просмотр всем командам. А также добавили шорткаты на заведение задач на баги и доработки.
Помимо этого, мы ввели дежурства. Дежурный — это разработчик, который отвечает за сбор обратной по багам. Если баги критические, то он либо правит их сам, либо назначает ответственного и позже выпускает hotfix с исправлениями. Также дежурный отвечает на вопросы по работе с библиотекой.
Если вы используете продукцию Atlassian, имеет смысл воспользоваться Jira Service Desk — это сервис для организации службы поддержки. В нём удобно разрабатывать формы заявки с автоматическим созданием задач в Jira.
К моменту публикации нашей статьи, мы уже согласовали со службой безопасности все нюансы и выложили библиотеку в открытый доступ. Поэтому стек технологий несколько поменялся, мы используем Github Projects + Issues, а общение и флуд по бибилотеке так же оставили в Telegram-канале
Синхронизация дизайна и кода
После того, как первые команды начали пользоваться нашей библиотекой на нас полетел шквал вопросов о статусе готовности компонентов, о том на каких фреймворках они работают, как называется класс в коде, соответсвующий компоненту.
И тут мы подходим к одному из самых острых вопросов, с которым вы точно сталкивались — синхронизация дизайна и кода.
Процесс проектирования дизайна всегда стартует чуть раньше разработки. И как решить проблему, чтобы предоставить дизайнерам доступ к новым компонентам как можно раньше, но, тем не менее, показать пользователям, что компонент ещё не готов в коде?
Мы ввели ряд правил:
изменения дизайна в существующих компонентах не публикуются, пока не будут произведены соответствующие доработки в коде;
в дизайн-системе проставляется статус готовности компонента — «не реализован» / «в разработке» / «готов»;
дизайн и разработка синхронизируются два раза в спринт.
На ранних этапах у нас возникали проблемы с тем, что дизайнер добавлял в дизайн систему новые компоненты или немного менял старые, не говоря об этом разработчику. Соответственно, страдали пользователи, потому что они не могли найти нужный компонент в дизайн-системе: в дизайне есть, а в коде — нет.
Изначально у нас было очень простое правило — готовые в коде компоненты дизайнер не меняет, а если меняет, то не публикует, пока разработчик не внесёт изменения в библиотеку. Если во время работы над дизайном возникает потребность в доработке компонента, то обязательно заводится задача на доработку в коде, и, пока её не реализовали, используется прошлая стабильная версия компонента.
Важно не забывать отмечать статус готовности компонента, название класса в коде и фреймворк, на котором он доступен.
P.S. Очень жалко, что в Figma нет нормальной поддержки версионирования или системы аналогичной Git для разработчиков. Не надо бежать и писать комментарии, что такая система есть, она как бы есть, но пока еще ни одна команда дизайнеров не показала, как ей удобно можно было бы пользоваться
Не откладывайте автоматизацию процессов
На первых этапах, когда мы только начали разрабатывать дизайн-систему, у нас был настроен только автоматический прогон тестов и деплой библиотеки.
Но на определённом моменте, разработка как будто стала сильно тормозить. Это было весьма странно, ведь никакой дополнительной нагрузки на нас не ложилось. Мы начали ресерчить эту ситуацию и поняли, что у нас просто катастрофически много времени уходит на рутинные процессы, типа обновления пака иконок и синхронизации цветовых палитр. А, на секундочку, в библиотеке сейчас около 200 иконок, 20 шрифтов и 3-х тем, состоящих из 30 цветов.
Давайте немного посчитаем, в среднем на обновление иконки, разработчик тратит от 1-5 мин, если с прогоном тестов, так и до полу часа, добавьте к этому тот факт, что обычно обновляется не одна и не 2 иконки и получите очень интересную картину. У нас разработчики могли спокойно потрать 2-3 часа в неделю на синхронизацию дизайна и кода.
Представьте, что в процессе разработки дизайн-системы, дизайнер постоянно обновляет все эти ресурсы, а затем разработчикам приходится вручную их выкачивать и сверять, правильно ли он всё загрузил. Несложно прикинуть в голове, что на добавление иконки человек тратит в среднем минуту — скачать, добавить и проверить. Это никуда не годится для команды, которая целиком занимается дизайн-системой.
Мы с ребятами, посидели, подумали, проанализировали решения команд из других IT-компаний и написали плагин, который умеет выгружать иконки — конвертировать их в Vector в Android и генерация xcassets в Xcode. Сейчас у нас каждый раз просто выкачивается весь пак иконок и автоматически конвертируется в нужный формат.
С темами и цветами схема поинтереснее — мы воспользовались API Figma для выгрузки компонентов. У Figma не самое удобное API, поэтому приходилось делать много запросов и склеивать. В результате у нас получился json-объект со всеми данными о теме. На его основе, используя язык шаблонной генерации liquid, генерируются .swift/.kt файлы с темами приложения.
За счёт автоматизации процессов мы существенно снизили время на синхронизацию, добавление/обновление новых тем и ресурсов.
Тут не обязательно самим писать тулзы для выкачивания ресурсов и кодогенерации. Мы сами написали эти скрипты, потому что у нас были специфичные нюансы и готовые решения нам не подходили. На первых этапах, я бы советовал воспользоваться готовыми тулзами c открытым исходным кодом: точно знаю, что у ребят из RedMadRobot и HeadHunter они лежат на GitHub.
Открыта для расширения, закрыта для изменения
Как только мы начали работать над инструментом, которым пользуются другие люди, на нас повалилось просто колоссальное количество предложений и пожеланий по улучшению. И самая частая просьба — «добавьте вот этот компонент в дизайн-систему, и вот этот, вот этот, а еще вот этот…».
Понятное дело, разработчики преследуют меркантильный интерес и просто хотят спихнуть поддержку и разработку компонента на вашу сторону. Тут важно найти баланс и видеть картину в целом: вы делаете систему, которой будут пользоваться не одна команда. Поэтому не стоит добавлять в дизайн-систему специфичные для конкретного продукта компоненты — это усложнит поддержку и вызовет негатив у других команд, которым компонент не нужен. Но с другой стороны, если он действительно будет использоваться большей частью команд, то включить его, конечно, стоит.
Если бы добавляли все компоненты, которые нас просили бы добавить другие команды, то наша дизайн система превратилась бы в простую свалку, которую потом бы никто не захотел тянуть к себе в проект
Как мы помним, дизайн-система призвана помогать и направлять, но ни в коем случае не ограничивать свободу и творчество людей, разрабатывающих на ее основе продукт. Поэтому мы использовали один из принципов SOLID: «открыт для расширения, закрыт для измерения». Разработчики и дизайнеры, могут изменять и комбинировать наши компоненты, тем самым создавая свой уникальный дизайн, но не ломая при этом основные принципы глобальной дизайн системы и не превращая ее в свалку.
Тут вам поможет понимания следующих правил. Дизайн-система состоит из атомов и молекул. Атомы — это минимальные неизменяемые компоненты, из которых строятся более сложные элементы — молекулы. Будет намного проще, если разрабатываемая система будет состоять в большей степени из атомов. Поэтому лучше сделать много маленьких компонентов и из них уже комбинировать дизайн, нежели сделать один большой и неповоротливый, а потом править его, чтобы удовлетворить потребности всех команд.
Найти баланс между функциональностью и универсальностью всегда очень сложно. Тут придётся рассматривать каждый случай индивидуально.
Разбивайте библиотеку на модули
После того, как продукты, использующие нашу библиотеку пошли несколько релизов в production, к нам постепенно начали обращаться команды с просьбами уменьшить вес библиотеки или ускорить процесс сборки.
Ни для кого не секрет, что одним из важных показателей, повышающим конверсию скачивания приложений, является размер.
Первым делом мы поджали размер ресурсов. Этого оказалось недостаточно, и мы пошли дальше. В iOS проекте у нас были и SwiftUI- и UIKit-компоненты, но зачем они разработчикам сразу в одном проекте. Куда лучше, если команда сама выбирает, что подключать. Вывод — нужно делить на модули.
Мы пришли к следующей схеме разделения:
модуль ресурсов — хранит все ресурсы, картинки, шрифты;
модуль темизации — хранит цветовые темы и механизм обновления;
модуль компонентов SwiftUI;
модуль компонентов UIKit.
Если команде нужны только шрифты и иконки, она подключает модуль ресурсов. Если только темизация — то модуль темизации. А если им нужны компоненты — то выбирают фреймворк, на основе которого им нужны компоненты, и подключают SwiftUI или UIKit соответственно.
Можно было пойти дальше и выделять каждый компоненты в отдельный модуль, но, на мой взгляд, это уже overhead.
Так же модульность повысит скорость сборки проекта. Какие-то части можно даже заранее упаковать в XCFramework и кэшировать на CI.
У нас был интересный кейс в iOS, с которым, мы, к сожалению, ничего не смогли сделать. Xcode 12/13 очень долго процессит SF Symbols, потому-то в у нас бибилиотеке их больше 200. Никакие настройки и флаги тут не помогли. Мы решили эту проблему выгрузкой бинарной версии библиотеки — SPM поддерживает такую возможность. (за счет нее не нужно пересобирать бибилиотеку каждый раз, она уже лежит скомпилированная)
Проработайте механизм темизации
Простите за тавтологию, но на тему темизации я могу дискутировать очень много, чем собственно я и занимался со своей командой.
Темизация — это одна из самых больших головных болей, с которой сталкивается каждая команда, работающая с дизайн-системой. В предыдущем шаге мы её вынесли в отдельный модуль.
Тема может состоять не только из цветов. В неё могут быть включены ещё и ресурсы.
Наша модель темы состоит из следующего набора:
цветовая палитра — набор цветов, используемых в теме;
шрифтовая палитра — набор шрифтов, используемых в теме;
ресурсы — набор специфичных ресурсов, которые могут меняться в зависисмости от темы.
На самом деле спектр настроек у темы может быть существенно шире, например, можно включить туда скругление и даже звуковые сигналы.
Самое сложное, с чем мы столкнулись — это синхронизировать нейминг токенов цветовой и шрифтовой схемы. На проектах с продолжительным жизненным циклом — это было огромной болью. При этом, цветовая тема так же должна быть открыта для расширения. Дизайнеры должны иметь возможность добавлять новые цветовые токены, тем самым расширяя количество персонализированных цветов.
Если вы жёстко зашьёте одну цветовую/шрифтовую схему, то просто поставите крест на дизайн-системе. Очень часто дизайнерам и разработчикам понадобятся новые цвета и шрифты, специфичные для их продукта.
Выходом будет добавить возможность расширять вашу тему новыми цветами и шрифтами, а еще лучше позволить вручную задавать цвета и шрифты компонентов без необходимости использовать темизацию. Это немного увеличит время разработки, но существенно повысит гибкость дизайн-системы.
У нас был пример команды, которая полностью отказалась от предложенной нами системы темизации и написала собственные схемы.
Полноценно работайте с example-проектом
Если у вас на проекте есть дизайн-система, выделенная в отдельный модуль, то с большей вероятности у вас есть и Sandbox (Example-проект), где вы проверяете ваши компоненты, чтобы не тащить их сразу в основной проект. Часто бывает, что это просто свалка, на которой линтер даже не настроен. Да и зачем же следить за этим проектом, он же не идет в Prod?
У нас есть свой Example-проект, но мы пошли немного дальше и решили его сделать полезным не только разработчикам, но и дизайнерам, тестировщикам, а так же пользователям нашей библиотеки.
Ранее я говорил, что у нашей дизайн-системы нет своего продукта, на котором мы обкатывали поведение компонентов, так вот Example-проект и является этим продуктом.
Для нас это приложение стало не просто витриной с компонентами, а полноценным инструментом взаимодействия разработчиков, дизайнеров и тестировщиков.
При разработке мы стремились сделать example-проекта максимально простым в реализации. Не стоит его слишком сильно усложнять и делать выбор в сторону функциональность и скорости разработки.
Мы выделили ряд функций, которым example-проект должно соответствовать:
отображать работу компонентов дизайн-системы во всех состояниях — это нужно для написания тестов и проведения дизайн-ревью;
код демонстрирует разработчикам, как правильно использовать те или иные компоненты. Помимо документации, иногда удобно открыть экран в приложении и посмотреть, как компонент работает или реализована определённая функция в коде;
возможность редактировать цвета и создавать новые темы. Эта функция появилась ни сразу, но у наших дизайнеров возникла потребность проверять, как будет выглядеть тот или иной цвет непосредственно на устройстве и тестировать это восприятие на пользователях. В Figma есть функция Mirror, который позволяет продемонстрировать макет на реальном устройстве — это удобно чисто для дизайнеров, но, например, если вы будете проводить тестирование на фокус-группе, то такой метод не очень подойдёт.
В результате у нас получился инструмент, с помощью которого мы не только демонстрируем дизайн-систему, но и всячески её тестируем и дорабатываем.
К сожалению, у нас тоже не хватает времени на всё, но следующим шагом по доработке приложения, мы хотели бы добавить возможность динамического заполнения экрана данными из JSON (своего рода Backend Driven UI для тестирования). Чтобы условно тестировщик писал тест-кейс в формате JSON на компонент со всеми краевыми случаями, в которых компонент может сломаться. Эти данные бы подставлялись и прогонялись автоматические тесты или ручное тестирование.
Организуйте внутреннее комьюнити вокруг библиотеки
Важно обрести союзников, которые понесут дизайн-систему дальше в проекты, будут отвечать на простые вопросы коллег и помогут с обратной связью. Проводите внутренние образовательные мероприятия, собирайтесь на неформальных встречах и просто любите создаваемый продукт.
Вместо заключения
На самом деле, я начал писать эту статью уже давно. Сейчас я больше склонен думать, что создание единой глобальной дизайн-системы скорее похоже на поиск Эльдорадо или священного грааля. Все его ищут, но мало кому удаётся найти. И главный вопрос нужен ли он вам на столько, чтобы тратить такое количество ресурсов или это просто тренд и прихоть?
На мой взгляд, в большинстве случаев стоит ограничиться единой системой гайдлайнов и фирменных цветов компании. Прибегать к глобальной дизайн-системе стоит только в том случае, если у вас есть действительно много внешне похожих продуктов с большим числом переиспользуемых компонентов. И желательно, чтобы они только планировались или находились на ранних этапах разработки. Или если вам нужно действительно быстро и с минимальными затратами выпускать MVP-проекты или White Label приложения.
Во всех остальных случаях я бы советовал придерживаться локальной системы с набором гайдлайнов.
Создание и внедрение дизайн-системы — сложный и кропотливый процесс. Надеюсь, я рассмотрел все его основные аспекты и узкие места. Дойдя до логичного конца, можно существенно ускорить работу коллег и повысить узнаваемость продуктов среди целевой аудитории. Но всегда думайте — а стоит ли оно того или можно обойтись малой кровью.