Кто я и почему пишу

Привет, Хабр! Меня по-прежнему зовут Сергей Орлов, я разработчик в Dodo Engineering и лидер дизайн-системы Android в приложении Пиццы. Это моя прощальная статья в Додо – про то, как мы заводили дизайн-систему, где наступили себе на ногу и что из этого вышло.

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

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

Поэтому на собеседовании в Додо я спросил, есть ли у них дизайн-система. Мне ответили, что нет.

Как выяснилось позже, ответ был не совсем точный. Но об этом чуть ниже.

Как мы дошли до жизни такой

Я пришел в Додо, когда готовился редизайн всего приложения. Честно говоря, он был нужен – просто посмотрите.

Меню приложения: слева до редизайна, справа сейчас

Если вам есть что сказать про дизайн приложения – велком в комментарии или в телеграм-канал наших дизайнеров designdodo. Троллей там тоже любят, так что не стесняйтесь.

Немного цифр для масштаба. В приложении Пиццы около 60 полноэкранных экранов, плюс порядка 40 диалогов и шторок. Считать элементы на всех этих layout’ах я не стал: боюсь, надоест, либо закончатся токены.

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

С чем мы столкнулись и что будет в этой статье

  1. Почему общий модуль компонентов – это еще не дизайн-система. Разбор на примере соседней платформы, где модуль живет с 2020 года и спокойно содержит пять реализаций одного контрола.

  2. Как отличить компонент дизайн-системы от компонента фичи. Мы не отличили – и получили две кнопки, которые подменяли друг друга по всему приложению.

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

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

  5. Как объяснить бизнесу, что ускорение сначала тормозит. Работает не объяснение, а цена: компонент надо сделать дешевле в спринте.

  6. Скриншот-тесты на компоненты. Что покрыли и почему для ДС они дешевле, чем кажется.

  7. Генерация компонентов нейронкой и пять слоев защиты вокруг нее. Что скармливаем на вход, что она стабильно делает плохо, и почему без предыдущих шести пунктов это не работает.

Дальше будет код, схемы и признания в собственных косяках. Если такое заходит – я про это регулярно пишу в своем телеграм-канале https://t.me/orlovsdev

Почему просто вынести компоненты в общий модуль недостаточно

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

Точнее так: собирать было из чего, и в этом заключалась проблема. Чтобы понять масштаб, достаточно посчитать, сколько в проекте было кнопок. Один класс-наследник MaterialButton, две кастомные View с «Button» в имени, пять самостоятельных Compose-кнопок в разных модулях, 28 XML-стилей кнопок и 14 layout-файлов, где кнопка собрана руками из кликабельного контейнера и TextView.

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

Так получилось, например, с экраном фидбека – кнопка, которая лежала в двух модулях побайтово одинаковая, а один блок разметки кнопки повторялся в семи файлах пяти модулей, отличаясь только id и text.

<Button
    android:id="@+id/buy_more_add_to_cart"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:text="@string/buy_more_add_to_cart"
    style="@style/PrimaryButton"
    />

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

Второй путь – не копировать, а брать чужой компонент напрямую – выглядел правильнее, но выходил дороже. Пятнадцать кастомных View стояли на экранах чужих модулей. Рекордсмен – ExpandableFoodValueInfoIconView (раскрывающаяся плашка с составом продукта) из модуля order, он попал в восемь чужих экранов.

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

Ни один из двух путей не ведет к системе. Копипаста позволяет команде не зависеть от чужого кода, но плодит копии одного и того же. Переиспользование чужого компонента убирает дублирование, но связывает команды общей реализацией. Иначе говоря: копипаста дает изоляцию без переиспользования, чужой компонент – переиспользование без изоляции. Дизайн-система нужна ровно затем, чтобы появился третий вариант: компонент, у которого есть владелец и контракт.

Онбординг стоит дороже, чем кажется

Compose меняется быстро и порой радикально – это все мы знаем. Из-за этого практики написания UI на проекте живут в головах, а не в коде.

Представьте нового человека на проекте, где есть Compose без ДС-обертки, а местами еще и View. Чтобы написать первый экран, ему нужно выяснить, как у вас принято собирать компоненты, найти похожие в коде, прочитать их реализацию и понять, какая из трех найденных версий правильная. Это не день и не два.

Задайте себе этот вопрос, когда будете думать про дизайн-систему. Именно про систему, а не просто про набор компонентов – почему второе тоже плохо, расскажу ниже.

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

Модуль есть, системы нет

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

И тут возникает соблазн: сделать свой техпак с компонентами и заставить всех их использовать. Задайте себе вопрос – это решит проблему или замаскирует ее?

У коллег с iOS такой модуль был: живой, с 2020 года, много тысяч строк кода. При этом внутри него уживались пять реализаций одного сегмент-контрола, а карточка продукта существовала в трех вариантах. То же самое, что у нас на Android, только сложенное в один модуль вместо разбросанного по проекту.

Проблема не в компоненте. Он может быть идеальным, написанным по всем лекалам.

Дизайн-система – это не только код. Это еще и договоренность между людьми.

Если вы договорились внутри своей команды, но не сказали дизайнерам и не построили с ними общий процесс – вы обрекаете себя копировать с мелкими изменениями собственные же эталонные компоненты.

Как отличить компонент ДС от компонента фичи

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

А через 24 дня мы сами же положили рядом с ним второй, который дизайн-системой не был.

Первый компонент

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

@Composable
fun DComposeButton(
    onClick: () -> Unit,
    text: String,
    buttonSize: ButtonSizesData,
    colors: ButtonColorsData,
    modifier: Modifier = Modifier,
    enabled: Boolean = true,
    isProgress: Boolean = false,
    imageData: ImageData? = null,
)

Сразу оговорюсь: восемь параметров подряд – это нарушение нашего же правила. Компонент должен принимать data class с параметрами, чтобы расширяться через него, а не через правку сигнатуры. На старте мы этого не сделали – и за два года кнопка обросла параметрами до неприличия, пока мы не завезли DButtonState. Правило, кстати, родилось именно отсюда.

Три состояния, четыре размера, пять цветовых стилей. Архитектура сразу двухслойная: композабл плюс AbstractComposeView поверх – чтобы кнопку можно было ставить в существующие XML-лейауты и не переписывать экран целиком ради одной кнопки. Позже от этого подхода мы отказались, и сейчас так устроена только эта кнопка. В тот же день появился сторибук для нее, про него расскажу ниже.

Через 24 дня

Мы совершили ошибку, которая стоила нам дорого и до сих пор живет в проекте. Мы добавили ProductButton.

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

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

val buttonSize = DButtonSizes.large.copy(
    contentPadding = PaddingValues(horizontal = 20.dp, vertical = 8.dp)
)

Button( // material3, не DButton
    onClick = onClick,
    shape = RoundedCornerShape(percent = 50),
    colors = colors.getButtonColors(),
) {
    when (price) {
        is ProductPrice.SimplePrice -> { /* иконка + цена */ }
        is ProductPrice.PersonalPrice -> { /* старая цена дугой + новая */ }
        is ProductPrice.CoinsPrice -> { /* валюта + курсив + додокоины */ }
        is ProductPrice.EditedSimplePrice -> { /* заголовок + цена мельче */ }
        is ProductPrice.EditedCoinsPrice -> { /* заголовок + валюта и коины */ }
    }
}

От ДС он взял ровно два объекта-токена – размер и цвета, причем размер тут же пропатчил через .copy().

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

Так у нас образовались две кнопки: одна из дизайн-системы, вторая из фичи, и вторая умела больше.

Чем это кончилось

Дальше произошло ровно то, что должно было. В макет просится DButton, но нужного состояния у него нет – а у ProductButton есть. Берем ProductButton. В компонент цены начинают доливать «просто текст»: состояние с произвольным заголовком, состояние с подписью под ценой.

Кончилось это вот таким кодом в конструкторе комбо:

if (screenState.selectedProduct != null) {
    ProductButton(
        modifier = Modifier.width(250.dp),
        productPrice = ProductPrice.PriceWithComment(/* ... */),
    )
} else {
    DButton(
        modifier = Modifier.size(width = 250.dp, height = 52.dp),
    )
}

Один слот на экране. Две разные кнопки. Выбор через if.

Правило, которое из этого выросло

Фича зависит от ДС, а не наоборот.

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

Проблема в том, что различить это надо до того, как написан код. Через восемь месяцев, когда компонент уже в проде и оброс состояниями, «просто переписать» стоит дороже, чем оставить как есть, – что мы и продемонстрировали.

И еще одна проблема, которая для меня оказалась важнее. Правило само по себе не работает, пока оно живет в голове одного человека. Нужен был механизм, который делает его общим и предъявляемым – не «мне кажется», а «смотрите, вот здесь не сходится».

Так у нас появились паспорта.

Паспорта компонентов и сторибук

Паспорт – это спецификация компонента, о которой дизайн и разработка договариваются до того, как написана первая строка кода. Название прижилось само.

Живет он в Figma, отдельной страницей на компонент, имея секции для дизайнеров и разработчиков. Внутри секции разработчиков живут подсекции для Android и iOS.

Зачем паспорт разработчику

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

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

Заполняет паспорт дизайнер, но принимаем мы вместе: на пятничном синке лиды ДС смотрят его и предлагают правки. Мы, как разработчики, приносим гайдлайны платформы, дизайнеры приносят замысел.

Помните спор про ProductButton, где у меня был правильный аргумент и не было инструмента? Мы просто положили рядом два паспорта – обычной кнопки и продуктовой – и увидели, что по составу это один и тот же компонент. Спорить стало не о чем: паспорт превращает мнение в аргумент.

Правила написания компонентов

Паспорт отвечает на вопрос «что делаем», правила разработки – на вопрос «как».

Правила лежат у нас во внутренней вики. Там зафиксировано, как должен быть устроен компонент:

  • только токены, никаких захардкоженных цветов и размеров;

  • состояние типизировано через sealed interface, а не через набор булевых флагов;

  • дефолты вынесены в отдельный объект;

  • компонент stateless и ничего не знает про заказ, корзину и тоглы;

  • опциональный контент передается слотом, а не тремя параметрами.

Антипример здесь – реальный код нашего DButton. Правило написано по следам собственной ошибки.

Сторибук: место, где компонент становится видимым

Паспорт живет в Figma, компонент – в коде, и между ними нужно место, где можно потрогать результат. У нас это сторибук: экран в дебажной сборке, где каждый компонент лежит отдельным пунктом и все его параметры переключаются прямо в UI.

Дизайнеру он нужен, чтобы не искать компонент по экранам приложения – приемка проходит именно там. Разработчику – чтобы увидеть, что уже сделано и в каком объеме.

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

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

Нас двое на две платформы

Механизм появился, а рук не прибавилось. И я знал это с самого начала, так как опыт имелся. Дизайн-системой занимались два человека – я на Android и коллега на iOS. На двоих приходилось около 20 фичевых разработчиков на двух платформах, редизайн всего приложения и библиотека компонентов, которую надо было довести до кода целиком.

Вариант «мы вдвоем все напишем, а команды будут пользоваться» отпал сразу. Даже если бы мы успели – это ровно тот bus factor, из-за которого дизайн-системы и умирают: два человека уходят, и система остается без хозяина.

Поэтому мы сели вдвоем и накидали процесс, в котором компонент делает тот, кому он понадобился.

Логика простая. Когда в фиче появляется компонент дизайн-системы, разработчик проверяет паспорт: существует ли он вообще и описаны ли в нем нужные состояния. Если чего-то не хватает, додумывать поведение на месте нельзя – вопрос уходит в общий канал к владельцам ДС и ответственному дизайнеру.

Когда паспорт на месте, решение зависит от того, что уже есть в коде и сколько времени в спринте:

Ситуация

Кто делает

Что происходит

Компонент реализован, состояний хватает

Разработчик фичи

Просто берет и использует

Компонента нет или не хватает состояний, времени нет

Владельцы ДС

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

Компонента нет, но время есть

Разработчик фичи

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

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

Хвост процесса общий для всех веток: разработка по паспорту и требованиям из вики, обязательное добавление в сторибук, потом два ревью – владельца ДС со стороны разработки и дизайнера. Замечаний нет – раскатываешь фичу.

В итоге мы получили не только дополнительные руки. Компоненты перестали быть чьей-то личной территорией, а разработчики получили задачи вне фичевой рутины. Плюс каждый, кто прошел процесс хоть раз, дальше сам замечает в макете компонент ДС.

Фича важнее компонента

Первое время разработчики делали компонент не целиком. Прилетел макет, в нем нужны два состояния из семи – два и написали. Формально компонент в дизайн-системе есть, фактически он дырявый, и следующий человек снова упирается в «нужного состояния нет».

Это логичное поведение, а не саботаж: у разработчика в спринте фича, а не дизайн-система.

И тут мы уперлись в то, во что упирается любая ДС. Продуктовые задачи всегда важнее, потому что они приносят деньги сейчас. Компонент целиком стоил 3–5 сторипоинтов – это заметный кусок спринта, и его старались срезать до тех состояний, без которых фича не поедет.

Объяснить бизнесу, почему штука, которая должна ускорять разработку, сначала ее тормозит, – задача со звездочкой. Но суть любых переговоров – это найти компромисс. С моей стороны родилась идея сделать компонент дешевле. Как? Пишу ниже.

Как мы сделали компонент дешевле

Компонент стоил 3–5 сторипоинтов, и это была честная оценка. Написать восемь состояний, покрыть превью, добавить в сторибук, пройти два ревью – работы там действительно на несколько дней.

Значит, снижать нужно было не оценку, а объем ручной работы.

Прежде чем генерировать – научились проверять

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

Механизм – Compose Preview Screenshot Testing: тест не описывает верстку сам, а переиспользует @Preview-функции из файла компонента.

class DButtonComposeScreenshotTests {

    @PreviewTest
    @Preview("Light")
    @Preview(
        "Dark",
        uiMode = Configuration.UI_MODE_NIGHT_YES or Configuration.UI_MODE_TYPE_NORMAL
    )
    @Composable
    @VisibleForTesting
    private fun Preview1() {
        DButtonPreview()
    }
}

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

Честно про цену: плагин до сих пор в статусе экспериментальной альфы, и мы это понимали, когда заводили.

Зачем эта сетка понадобилась на самом деле, стало понятно через полтора месяца.

А что, если бойлерплейт просто сгенерировать?

Я взял шторки – DBottomSheet и DContentBottomSheet – и попробовал сгенерировать их нейронкой.

Смысл был не в том, чтобы «ИИ написал за меня компонент». Смысл в том, что в компоненте дизайн-системы огромная доля работы – это бойлерплейт: разложить состояния, развесить токены, собрать Defaults, написать превью на каждый вариант. Все это выводится из паспорта механически.

Эксперимент получился. Дальше я рассказал о нем на общем синке команд – и подход разошелся по командам сам.

Нейронке нельзя оставлять выбор

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

  • Макет из Figma через MCP, фреймами.

  • Паспорт компонента – состояния, размеры, стили, правила поведения.

  • Правила и ограничения из нашей вики – как писать компоненты на нашем проекте.

  • Эталонный компонент как образец стиля.

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

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

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

Что нейронка делает плохо

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

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

Превью не пишет вообще, пока не ткнешь носом. Для Compose это база, любой разработчик их пишет по умолчанию – а модель их пропускает, и ее приходится отдельно вести по всем состояниям из паспорта. И это не косметика: без полного набора превью не работают скриншот-тесты, то есть молча ломается покрытие.

Выедает токены на больших компонентах. ДС – не единственная тема на проекте, контекст приходится делить.

Требует перепроверки. Модель регулярно продолжает следовать своим представлениям о прекрасном, даже когда в контексте лежат ваши правила.

Ошибаться можно. Дорого ошибаться – нельзя

Именно поэтому генерация работает не сама по себе, а внутри всего, что мы построили до нее:

  1. Паспорт – что именно должно получиться.

  2. Правила и эталонный компонент – как это писать у нас.

  3. Скриншот-тесты – регрессия ловится автоматически, а не глазами на ревью.

  4. Сторибук – дизайнер принимает компонент руками.

  5. Ревью – нейронкой и людьми. Состязательное ревью моделью работает неплохо: ошибается, но базу собирает хорошо. Поверх этого код смотрит разработчик, и я как лид отдельно прохожусь по компонентам. Здесь важно, что цена ошибки уже не та: если фича в проде, значит критических багов по ней нет, а поправить код компонента – не проблема. Все обложено тестами, и если новый компонент что-то сломает в фиче, мы это отловим.

Собственно, в этом и смысл всех пяти слоев. Не в том, чтобы нейронка не ошибалась, – она будет. А в том, чтобы ошибка стоила дешево и находилась до пользователя.

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

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

Выгода для бизнеса

Компонент стал стоить 2 сторипоинта стабильно вместо прежних 3–5.

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

Я не объяснял бизнесу, почему ускорение сначала тормозит. Я сделал компонент дешевле, и он объяснился сам.

Дальше стало возможным то, о чем раньше не заходила речь: мы поставили целью довести до кода все компоненты, уже готовые в Figma, и распределили их по командам – по тому, чьи модули и контуры они затрагивают и у кого какая загрузка.

Где мы сейчас

Цифры на август 2026 года:

  • 34 компонента в дизайн-системе, 31 из них готов на Android – 91%

  • 34 экрана компонентов в сторибуке плюс 5 экранов основ: типографика, цвета, градиенты, анимации, вибро

  • 23 файла скриншот-тестов и 115 эталонных картинок в ДС-модуле

  • ДС-модуль импортируют 479 kt-файлов. На старте их было 29

Дашборд появился не сразу и оказался нужнее, чем ожидалось. Там видно готовность по обеим платформам и тренд по времени – без него вопрос «а это уже сделано?» решался поиском по коду и опросом коллег.

На скрине видно разрыв: Android 91%, iOS 53%. Дело не в том, что коллеги медленнее – им прилетело жидкое стекло, и это переписывание половины UI под новую систему оформления, а не «доделать компонент». Мы в это время спокойно шли по своему бэклогу. По графику тренда, кстати, хорошо видно, что кривая iOS не встала, а продолжает расти – просто с другим стартом.

Что можно сделать лучше

Дизайн-система растет вместе с проектом, и работы в ней всегда хватает. Что напрашивается дальше:

Структурированное версионирование. Сейчас версия живет в паспорте, со стороны разработки процесс еще не до конца обточен. Это связано с тем, что у нас еще молодая ДС.

Дашборд пошире. Хочется видеть покрытие глубже.

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

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

Вместо заключения

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

Собственно, ради этого мы и раздавали разработку компонентов всем командам. Тогда bus factor был аргументом из презентации. Теперь он проверился на мне – и это, пожалуй, лучший результат из всех, что перечислены выше.

А я продолжаю писать про разработку в своем телеграм-канале – заходите, там про то, что происходит дальше: https://t.me/orlovsdev

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

Комментарии (1)


  1. yanpurvenes
    27.08.2026 10:15

    1. “Это моя прощальная статья в Додо”- как понял, что додо жалко было выделить ресурсы? И всем как бы плевать, с учетом сколько людей заложили и надежлы что ии вытащит? Причина ухода, что бизнесу с колокольни на дизайн систему и они жили без нее?

    2. Если отдали делать фичи командам компоненты, то сами команды в курсе были? Им срезали всякие kpi и метрики с учетом этого? Ну раз они стали еще тянуть это?

    3. С учетом истории ProductButton, стоит ожидать, что положат на дизайн систему конкретно после ухода.

      Ощущение попытки сэкономить на норм платформенной команде, которая бы тащила это все. Это при условии как компания кичится выручкой и блокирует в своем тех блоге в ТГ, за не удобные вопросы