Наш опыт внедрения Compose в большой проект
Меня зовут Максим Рыбалов, я Android-разработчик в Kolesa Group. Расскажу, как мы постепенно внедрили в приложение Kolesa.kz новый инструмент от Google для разработки интерфейсов — Jetpack Compose.
Во многих командах понимают, что это перспективная технология. Но начать использовать Compose мешает нехватка знаний и опыта.
В этой статье расскажу:
- Как мы внедрили Compose в большой проект и ничего не сломали;
- Что помогло команде разобраться с этой технологией.
Jetpack Compose — это рекомендуемый Google набор инструментов для создания пользовательского интерфейса. Есть вероятность, что через несколько лет эта технология заместит XML. Поэтому команде Android-разработки нужно прокачивать экспертизу уже сейчас.
Плюсы и минусы Jetpack Compose
Команде предстояло разработать новую интересную фичу. Ответственный за задачу сотрудник предложил руководству использовать Compose. Мы рассчитывали потренироваться и в случае успеха начать внедрение Compose в проект. Тимлид и техлид Android-разработки дали добро.
Дальше нужно было защитить идею перед менеджером. Как это нередко бывает с новыми технологиями, в начале пути их использование скорее затратно, чем выгодно. Растягиваются сроки, возможны поломки.
Мы не хотели играть в новые технологии. У Compose есть объективные плюсы:
- Декларативный UI. Даёт сконцентрироваться на том, что должно быть отражено, а не как. Это делает код более читаемым, компактным и понятным.
- Гибкость и модульность. Упрощает создание и настройку компонентов пользовательского интерфейса для более лёгкого масштабирования, переиспользования и обслуживания кода.
- Интерактивность. Предлагает удобный инструментарий для работы с анимацией.
- Поддержка со стороны разработчиков ОС. Они рекомендуют использовать Compose в Android-разработке и будут поддерживать эту технологию в будущем.
- Быстрое превью. Показывает изменения в реальном времени.
- Расширение стека. Позволяет заинтересовать команду и в будущем нанимать скилловых специалистов.
Минусы Compose:
- Декларативный UI. Отличная штука, но сначала надо привыкнуть к ней и научиться так работать.
- Нестабильность. Технология всё ещё новая.
- Зависимость от поддержки. Любая технология, которую вы не контролируете, влияет на ваш продукт.
- Отсутствие компонентов. Некоторых компонентов пока нет, или они в альфа/бета-версии.
Добавим к этим минусам и нехватку знаний у команды. Нужно было выучить новые классы, теги, аннотации и прочее.
Мы поняли, что время сыграет нам на руку: постепенно Compose усовершенствуется, а XML будет использоваться всё меньше. Команда Android-разработки должна развиваться в направлении, которое задаёт Google. Значит, в долгосрочной перспективе освоение Compose не только важно для нас, но и выгодно компании.
Возник вопрос: с чего начать? Сразу начинать писать новые фичи на Compose — рискованно, есть риск создать баги и неоптимизированный интерфейс. К тому же в нашей немаленькой команде никто не имел опыта работы с Compose.
Как построить процесс разработки?
У нас было три условия:
- Время — деньги. Нужно найти способ практиковаться без отрыва от работы, прямо на наших продуктах.
- Научиться работать с Compose должна вся команда.
- Нельзя нанести ущерб пользователям приложения.
В итоге мы продумали плавный процесс перехода с XML на Compose, который устроил и разработку, и бизнес.
Начали с изменений на non-critical экранах
Это экраны, которые пользователь либо не видит, или открывает крайне редко. Вносить изменения здесь безопасно — в случае ошибки лишь малая часть пользователей столкнётся с трудностями.
Переход с XML на Compose проходил плавно. Начали с тех экранов, которые пользователь не видит. Постепенно перешли на экраны, которые видит пользователь, например «О приложении». В таких случаях вводили новый вариант с помощью А/B-тестов. На случай поломки у нас был экспериментальный вариант.
Использовали Compose для новых компонентов в дизайн-системе
Крутой способ наработать навыки создания Compose-элементов — реализовать компонент с нуля.
Например, нам дали задачу создать вот такую кнопку:
Мы взяли стандартный элемент из библиотеки Compose — Button. Понадобилось несколько изменений кода под наши нужды, поэтому мы написали свою реализацию базовой кнопки — CustomButton. Далее прописали DefaultButton и объявили в этом компоненте логику всех кнопок в нашем приложении.
Внутрь пробросили ButtonContent — информацию о том, какой контент содержится в кнопке.
ButtonState — информация о состоянии кнопки. В нашем случае это три варианта — Normal, Disabled и Loading.
А здесь — набор цветов для конкретного состояния кнопки:
Теперь, если нам нужна конкретная реализация кнопки — например, красная или синяя с иконкой — вот как она будет выглядеть:
Создаём Composable функцию BlueButton, внутри используем DefaultButton и передаём состояние кнопки с соответствующим набором цветов.
Теперь, если мы хотим где-то использовать BlueButton, то мы просто делаем так:
Если в нашей кнопке нам понадобится любая иконка, то в качестве ButtonContent указываем TextAndIcon. Аналогично и для любого другого контента.
В итоге у нас получилась такая иерархия классов кнопок:
На первом уровне базовая реализация самой простой кнопки, затем реализация кнопки с логикой для всех наших кнопок, и снизу — разные конкретные варианты, используемые в приложении.
Переписывать все элементы, уже созданные с помощью XML, не нужно. Мы можем прямо в XML вызвать BlueButtonView, и это будет прекрасно работать.
Сделали мы это при помощи AbstractComposeView. Он служит мостиком между классической системой Android Views и Jetpack Compose. Это абстрактный класс, который позволяет интегрировать контент, написанный с использованием Compose, в традиционное дерево представлений Android (View).
Вот как это реализуется у нас:
Есть ButtonView, он наследуется у AbstractComposeView. В этом случае вы обязаны заоверрайдить метод Content. В нём мы передаём вызов ButtonComponent — абстрактную функцию нашего абстрактного класса.
Для реализации BlueButtonView создаём этот класс, наследуем его от ButtonView и оверрайдим метод ButtonComponent. Внутри делегируем вызов компоненту BlueButton, написанный нами на Compose.
Теперь в иерархии кнопок появился вариант для реализации их XML-вариантов:
Со временем взялись за продуктовые экраны
Компетенция разработчиков росла. Ребята поопытнее, поработав с non-critical экранами и компонентами, стали пилить несложные продуктовые экраны. Часть приложения, с которой множество пользователей взаимодействуют каждый день, требует более ответственного отношения.
Вот пример такого экрана:
Здесь нам понадобилось реализовать функцию refresh: пользователь тянет за шторку вниз, и содержание экрана обновляется. Эта фича появилась в более поздней версии Compose, и функционал успешно внедрили.
Такие задачи удалось закрывать без ошибок, и и с точки зрения пользователей переход происходил бесшовно.
Научился — передай опыт коллеге
Итак, разработчики практикуются с Compose, когда переписывают non-critical экраны и создают новые элементы дизайн-системы. После этого опытные разработчики смело берутся за важные фичи и популярные экраны.
Но количество задач ограничено, при этом обучить нужно всю команду.
У нас сложилась такая система распределения задач:
1. Non-critical задачи даём тем, кто не работал с Compose вообще или работал меньше всех. Даже если здесь будут ошибки, это не критично.
2. Простые задачи назначаем на человека, у которого опыта с Compose меньше, чем у других ребят, но он не допустит критических багов.
3. Сложные, комплексные задачи даём более опытному специалисту. Он декомпозирует задачу и передаёт сабтаски менее опытным сотрудникам. Так можно задействовать несколько человек.
В команде kolesa.kz восемь Android-разработчиков. Спустя несколько месяцев такого подхода каждый из них успел поработать с Compose на «боевых» задачах, при этом не выкраивал дополнительное время на обучение.
Итоги и выводы
- Элементы Сompose есть на 70% экранов приложения Kolesa.kz.
- Благодаря плавному подходу не возникло ни одной поломки.
- Вырос средний уровень технической подкованности команды.
- Стек технологий стал более актуальным. Если в будущем Compose заменит XML, мы сможем нанимать скилловых специалистов и предлагать им интересные задачи.
Да, мы внедрили новую технологию — помогли нашему продукту сделать шаг в будущее. Ещё важнее, что команда осваивала Compose в рабочее время, разработчики не тратили на это личное время.
Каждый из нас получил стимул изучить новую технологию. При этом соблюдаем баланс работы и отдыха, и остаётся «мыслетопливо» для сложных задач.
Когда задействована вся команда, радует, что ты не останешься один на один с проблемой. В любой момент можно посоветоваться с коллегами, а если сам научился делать что-то новое — делишься с командой и зарабатываешь очки репутации.
Дальше — больше. В планах:
- Повышать экспертизу в Compose;
- Пилить всё больше элементов на Compose разного уровня сложности;
- Сделать крутую дизайн-систему.