Привет! Меня зовут Денис Попов, и я iOS-разработчик в QIC digital hub. В этой статье я расскажу о кодогенерации в мобильной разработке: кто действительно нуждается в ней, как она применяется на практике и какую ценность можно извлечь из этого процесса.
Мой путь в мире мобильной разработки начался в 2018 году. За это время я работал в нескольких компаниях и сталкивался с различными задачами, связанными с кодогенерацией. В каждой из этих организаций мы искали индивидуальные решения и использовали разные инструменты. В QIC я также обнаружил несколько интересных примеров использования кодогенерации, которыми с удовольствием поделюсь в этой статье.
Преимущества кодогенерации
Для нас, как для разработчиков, кодогенерация предоставляет множество преимуществ: мы пишем меньше кода, уменьшаем вероятность ошибок, а сам код становится более консистентным.
Проблемы, которые решает кодогенерация
Кодогенерация помогает решать систематически возникающие проблемы в процессе разработки и вопросы, требующие времени и взаимодействия с коллегами. Важно отметить, что кодогенерация не является универсальным решением, и в вашем проекте вы можете столкнуться с подводными камнями, которые нужно будет решать, ища обходные пути.
![Кодогенерация: кому нужна и как настроить - 1 Кодогенерация: кому нужна и как настроить - 1](https://www.pvsm.ru/images/2025/01/18/kodogeneraciya-komu-nujna-i-kak-nastroit.png)
Я разбил жизненный цикл разработки функциональности на три основных блока: получение данных от сервера, их обработка и подготовка к отображению. Следующим шагом является рендеринг макетов, которые нам подготовили дизайнеры, а в конце пути мы должны проанализировать, какой профит мы получили от этой функциональности — то есть отправить аналитику.
Первый шаг: получение данных
Даже в самом простом случае, например, при обработке ответа от сервера, реализации на платформах iOS и Android могут отличаться. Кто-то декодирует поля по-разному, и из-за этого изменяется реализация функции. Для решения даже таких минимальных проблем мы используем Swagger Codegen. Он фактически генерирует модели, описанные в спецификации OpenAPI. Это публичный инструмент, который вы также можете использовать в своем проекте. Swagger Codegen генерирует как клиентские SDK, так и документацию, и дает возможность использовать свои шаблоны или дефолтные.
Я постарался описать в четырех шагах, как этот процесс работает у нас:
![Кодогенерация: кому нужна и как настроить - 2 Кодогенерация: кому нужна и как настроить - 2](https://www.pvsm.ru/images/2025/01/18/kodogeneraciya-komu-nujna-i-kak-nastroit-2.png)
При проработке функции мы описываем спецификацию конкретной модели, после чего выбираем нужный генератор — например, генератор под iOS. При необходимости на третьем шаге можно добавить кастомные параметры, которые будет использовать генератор. В конце концов, мы получаем сгенерированный код, который можем использовать в разработке. Таким образом мы, как мобильные разработчики, можем сосредоточиться на написании логики, избегая создания дополнительного boilerplate-кода.
Пример описания спецификации:
![Кодогенерация: кому нужна и как настроить - 3 Кодогенерация: кому нужна и как настроить - 3](https://www.pvsm.ru/images/2025/01/18/kodogeneraciya-komu-nujna-i-kak-nastroit-3.png)
Для примера я взял простую спецификацию, касающуюся AppConfigResponse. На слайде вы можете увидеть, что есть поле response, которое является обязательным и ссылается на созданную схему. Это позволяет нам переиспользовать уже существующие модели, что упрощает описание спецификаций.
Результат на картинке:
![Кодогенерация: кому нужна и как настроить - 4 Кодогенерация: кому нужна и как настроить - 4](https://www.pvsm.ru/images/2025/01/18/kodogeneraciya-komu-nujna-i-kak-nastroit-4.png)
Слева вы видите AppConfig Response для iOS, справа — для Android. Это одни и те же поля, и нам не нужно ничего дополнительно делать. Казалось бы, все отлично: мы написали спецификацию, не внося изменений в код. Аналитики, в свою очередь, описали схемы, которые мы можем использовать.
Однако вскоре мы столкнулись с проблемой. У нас была задача разработать новую функцию, для чего мы создали отдельный endpoint и надеялись получить ответ, содержащий массив объектов, где мы передаем type и в зависимости от него декодируем объект.
Ожидания:
![Кодогенерация: кому нужна и как настроить - 5 Кодогенерация: кому нужна и как настроить - 5](https://www.pvsm.ru/images/2025/01/18/kodogeneraciya-komu-nujna-i-kak-nastroit-5.png)
Проведя некоторое время на Stack Overflow и погуглив, мы написали спецификацию и были довольны результатом. Но генератор имел свое мнение и сгенерировал что-то, что не собиралось. Реальность:
![Кодогенерация: кому нужна и как настроить - 6 Кодогенерация: кому нужна и как настроить - 6](https://www.pvsm.ru/images/2025/01/18/kodogeneraciya-komu-nujna-i-kak-nastroit-6.png)
Как это исправить, было не совсем ясно, а у нас, как всегда, были сжатые дедлайны и недостаточно времени на исследование.
В итоге мы нашли альтернативное решение: начали передавать опциональные параметры. К счастью, поскольку функция была небольшой и параметров не так много, это дало возможность передавать type и необходимые для каждого объекта опциональные параметры.
![Кодогенерация: кому нужна и как настроить - 7 Кодогенерация: кому нужна и как настроить - 7](https://www.pvsm.ru/images/2025/01/18/kodogeneraciya-komu-nujna-i-kak-nastroit-7.png)
Второй шаг: рендеринг
На данный момент мы уже обработали модели и ответ сервера и готовы к отображению данных. В этом блоке, посвященном рендерингу, я хотел бы обсудить один важный аспект. Возможно, в небольших проектах его не так очевидно заметить, но с ростом проектов вы, скорее всего, услышите термин «дизайн-система». Каждая компания и проект имеют свои уникальные требования и пожелания относительно дизайн-системы. В нашем проекте она уже внедрена. Для примера я хочу рассмотреть работу с цветами.
Мы генерируем цвета из Figma, для чего написали пользовательский инструмент, который извлекает цвета, описанные нашими дизайнерами, и создает расширение с этими цветами.
![Кодогенерация: кому нужна и как настроить - 8 Кодогенерация: кому нужна и как настроить - 8](https://www.pvsm.ru/images/2025/01/18/kodogeneraciya-komu-nujna-i-kak-nastroit-8.png)
Что под капотом
У нас есть YAML-конфигурационный файл, из которого мы берем путь для обращения к API Figma. Через API мы получаем все стили; в моем примере — цвета. Это массив цветов, которые используют дизайнеры при создании макетов. Это удобно как для дизайнеров в Figma, так и для нас при обработке данных. Получив всю информацию, мы выбираем нужный шаблон для генерации кода в зависимости от платформы — iOS или Android. В итоге мы получаем строку кода, которую вставляем в нужный файл проекта.
Теперь давайте посмотрим на конкретные примеры, так это будет более наглядно.
![Кодогенерация: кому нужна и как настроить - 9 Кодогенерация: кому нужна и как настроить - 9](https://www.pvsm.ru/images/2025/01/18/kodogeneraciya-komu-nujna-i-kak-nastroit-9.png)
На картинке вы видите нашу таблицу в Figma, составленную дизайнерами, где указаны необходимые цвета и их применение. Важно понимать, что у каждого цвета есть токен с именем и его значением в формате HEX. Для удобства работы в Figma мы добавили визуальное отображение, показывающее, как цвет выглядит на самом деле. Обратите внимание, что в таблице справа есть колонки, которые еще не заполнены. Эти колонки предназначены для темной темы. У нас в приложении ее сейчас нет, но мы предусмотрели возможность ее добавления в будущем. Заполнив такую таблицу, мы сможем быстро реализовать темную тему с минимальными затратами. Однако стоит отметить, что здесь есть свои подводные камни, о которых я расскажу позже.
В результате мы извлекли цвета из Figma, и для iOS я покажу простой шаблон, который мы используем для генерации статических переменных (static vars) в расширении.
![Кодогенерация: кому нужна и как настроить - 10 Кодогенерация: кому нужна и как настроить - 10](https://www.pvsm.ru/images/2025/01/18/kodogeneraciya-komu-nujna-i-kak-nastroit-10.png)
Мы просто сохраняем RGB-значения.
![Кодогенерация: кому нужна и как настроить - 11 Кодогенерация: кому нужна и как настроить - 11](https://www.pvsm.ru/images/2025/01/18/kodogeneraciya-komu-nujna-i-kak-nastroit-11.png)
На двух скриншотах слева представлен пример для iOS, а справа — для Android. Как видно, сгенерированные цвета совпадают, что приятно.
Хочу также поделиться интересной историей, которая произошла со мной в середине лета. Мне была поставлена задача перекрасить все приложение. Все, что мне нужно было сделать, — это в командной строке ввести команду для повторной генерации цветов из дизайн-системы, и значения в файле автоматически обновились. Это безусловно удобно. Однако, к сожалению, не все токены из Figma были использованы в проекте или изменились названия. Поэтому мне, как разработчику, пришло время проверить код, исправить несколько ошибок в нейминге и уточнить у дизайнеров, использованы ли правильные цвета для токенов. Тем не менее инструмент значительно сократил мое время на обработку, и я смог быстро завершить задачу. Я считаю это достаточно успешным опытом.
В конце этого блока я хотел бы поделиться всеми зависимостями, которые использует наш инструмент для генерации кода. Это на самом деле не так сложно.
Аналитика и KMM
Двигаемся дальше. После того как мы внедрили функцию, необходимо покрыть ее аналитикой. Я думаю, многие сталкивались с ситуациями, когда данные в аналитике могут расходиться, например, когда на iOS что-то не отправляется, а на Android, наоборот, отправляется слишком много параметров. Чтобы избежать этих проблем, мы используем KMM.
Важно отметить, что это не генерация кода, как я описывал ранее, а компиляция Kotlin-кода из основного модуля в нативный для iOS. В результате мы получаем framework-файл, который используем как библиотеку в iOS. Я немного отклонился от темы, но хотел акцентировать внимание на том, что у нас есть четкий процесс версионирования с единым источником правды.
Процесс аналитики
Как это выглядит на практике? Мы описываем события аналитики для каждого экрана в проекте. Обычно они могут быть как кастомными, так и статичными. На каждом экране мы точно знаем, какие события могут быть отправлены.
![Кодогенерация: кому нужна и как настроить - 12 Кодогенерация: кому нужна и как настроить - 12](https://www.pvsm.ru/images/2025/01/18/kodogeneraciya-komu-nujna-i-kak-nastroit-12.png)
![Кодогенерация: кому нужна и как настроить - 13 Кодогенерация: кому нужна и как настроить - 13](https://www.pvsm.ru/images/2025/01/18/kodogeneraciya-komu-nujna-i-kak-nastroit-13.png)
Для iOS и Android предусмотрен единый интерфейс, что исключает возможность отправки лишних данных или пропуска необходимых.
![Кодогенерация: кому нужна и как настроить - 14 Кодогенерация: кому нужна и как настроить - 14](https://www.pvsm.ru/images/2025/01/18/kodogeneraciya-komu-nujna-i-kak-nastroit-14.png)
На этом примере показан процесс на iOS. Нам достаточно вызвать событие с нужным экраном, и это очень удобно.
Теперь расскажу о процессе покрытия аналитики. Обычно создаются три тикета: для iOS, для Android и один для обновления KMM. Прелесть в том, что весь процесс может быть выполнен одним разработчиком, который затем может передать эстафету команде.
На первом шаге мы создаем pull request с описанием новых событий. Возможно, потребуется пообщаться с аналитиками для оптимизации событий и их описания. При создании pull request срабатывает триггер, который собирает предпросмотр сборки. Пока pull request открыт, можно оставлять комментарии, и мы можем проверить, правильно ли собирается код и всё ли указано верно перед внесением изменений в основную ветку.
Отдельно выделю, что при каждом обновлении pull request пересобирается предпросмотр, что позволяет нам проверить и избежать попадания в основную ветку неподходящего кода. На последнем шаге мы получаем новую версию релиза, и разработчики могут обновить версии для новых функций.
Заключение
Кодогенерация — замечательный инструмент, но его нужно использовать обдуманно. Злоупотребление кодогенерацией может ограничить возможности кастомизации, однако это, в свою очередь, заставляет команды работать эффективнее. В QIC мы постоянно улучшаем процессы и стремимся не создавать костылей. Если что-то идет не так, мы стараемся находить элегантные решения. А как вы используете кодген?
Автор: vegopunk