Подумываете о переходе на Kotlin Multiplatform? Мы предоставим вам всю необходимую информацию для принятия решения.

Новые компании и те, кто стремится расширить свои возможности, часто предпочитают технологии вроде Flutter и React Native. Единая кодовая база и команда разработчиков, снижение затрат и упрощение сопровождения — эти преимущества весьма привлекательны.
Однако, если у компании имеются хорошо зарекомендовавшие себя мобильные продукты, реализованные в родном формате, переход на одну из этих технологий — решение неочевидное. В этой ситуации приложение обычно полностью переписывается с помощью выбранной платформы.
Kotlin Multiplatform — совершенно новый подход к платформонезависимой разработке, основная цель которого — не замена нативных приложений, а их совершенствование. Он легко интегрируется с имеющимися проектами, при этом сохраняются преимущества нативной разработки, к которым прибавляются выгоды совместного использования кода Android и iOS.
Хотите сделать разработку эффективнее, не переписывая приложения? Воспользуйтесь Kotlin Multiplatform. Расскажем о выборе этой технологии, ее преимуществах и универсальной стратегии плавного перехода, при котором сохраняется надежность цифрового продукта.
Что такое Kotlin Multiplatform?
Не все знают, что язык Kotlin, на котором каждодневно создаются приложения Android, не предназначался конкретно для Android. Он был задуман как современный язык, компилируемый на другие с возможностью применения на различных платформах. Аналогично и Kotlin Multiplatform — это лишь набор официальных инструментов, которыми упрощается процесс одновременного использования Kotlin на разных платформах.

Применяемый в Kotlin Multiplatform платформонезависимый подход невероятно прост и отличается от других. От разработчиков не требуется создавать все приложение в отдельном фреймворке, вместо этого в различных нативных приложениях задействуется имеющийся код Kotlin.
В итоге многие разработчики и компании по всему миру перешли на эту технологию создания цифровых продуктов. Среди них Netflix, McDonald’s, Forbes и 9GAG.

Расскажем, как с Kotlin Multiplatform совершенствовать имеющиеся нативные приложения без их полного переписывания.
Почему стоит задуматься о переходе на Kotlin Multiplatform?
Раньше было очень сложно решиться перевести имеющийся мобильный продукт на платформонезависимый фреймворк. Новое приложение Flutter или React Native создавалось месяцами, а для проектов покрупнее — даже годами. Когда продукт переписывается в абсолютно новой технологии, не весь функционал приложения обрабатывается с тем же качеством и удобством для работы пользователя.
Однако с Kotlin Multiplatform в этом отношении все меняется. Им предлагается совершенно новый подход к платформонезависимой разработке, легко интегрируемый с имеющимися мобильными приложениями.
Вместо переписывания приложения — постепенная миграция
С Kotlin Multiplatform не понадобятся месяцы работы, чтобы увидеть первые преимущества платформонезависимой разработки. Новая команда, чтобы создать совершенно новый продукт с нуля, тоже не нужна. Процесс миграции — это не переписывание всего приложения, а постепенный перенос кода Kotlin из приложения Android в модуль Multiplatform. Затем этот общий код интегрируется в приложение iOS с заменой исходной реализации Swift. Довольно просто.

Начинайте использовать Kotlin Multiplatform на любом этапе проекта
Kotlin Multiplatform интегрируется в нативный проект на любом этапе разработки: только планируете проект, уже начали работать над продуктом с минимальным функционалом или ваш готовый продукт уже в продакшене. Это принципиальное отличие от других платформонезависимых решений. Например, выбирая между нативным приложением и Flutter или React Native, всегда оказываешься в ситуации «или-или»: или 100 % нативное приложение, или 100 % платформонезависимое. С Kotlin Multiplatform получаешь полную гибкость в распределении кода между приложениями, поэтому никогда не поздно начать применять его.

Не жертвуйте нативной функциональностью
Нативными мобильными приложениями для такого функционала, как уведомления, службы определения местоположения, камера, Bluetooth, NFC, обычно используются системные API. А еще часто применяются внешние, сторонние SDK-пакеты для задач аналитики, распознавания изображений, сканирования документов, других сложных операций.
При переходе на Kotlin Multiplatform заменять эти нативные зависимости не нужно. Совместимость Kotlin с другими языками и платформами расширяется двунаправленно. Хотя Kotlin включается в нативные приложения, для прямого доступа из Kotlin в нативные платформы никаких мостов не требуется.

Так у вас и вашей команды появляется значительная гибкость при реализации нативного функционала в приложениях. Нет необходимости искать альтернативы с открытым исходным кодом или обертки для использования системных API или нативных SDK, а это типичное требование в экосистемах Flutter и React Native.
Сохраняйте оптимальное пользовательское взаимодействие
Несмотря на сходства Android и iOS, каждой операционной системой обеспечивается собственное пользовательское взаимодействие. Различия в стиле анимации, режиме прокрутки, схемах навигации, жестах и поведении компонентов пользовательского интерфейса очевидны. Пользователи на каждой платформе привыкли к особой эстетике своих приложений, с тем же приложением в другой системе они обычно дезориентируются.

Kotlin Multiplatform выгодно отличается уникальным нативным пользовательским интерфейсом, подходом с разделением логики. Логика приложения — обычно это 70–80 % общей кодовой базы — реализуется в Kotlin единожды. При этом пользовательский интерфейс по-прежнему реализуется нативно и остается отдельным для каждой платформы, чем обеспечивается на 100 % нативное пользовательское взаимодействие без компромиссов.
Сохраняйте оптимальную производительность
Нативные приложения эксплуатируются максимально близко к базовой операционной системе без дополнительных уровней, которые сказываются на производительности. Скомпилированный код этих приложений выполняется непосредственно операционной системой.
Функционирование фреймворков вроде Flutter или React Native осуществляется по-другому. Хотя их создатели обещают производительность, аналогичную нативной, они отличаются от чисто нативных приложений. У Flutter и React Native имеются собственные движки, написанные на C++. Когда запускается приложение, операционной системой инициируется только движок фреймворка. В дальнейшем код приложения выполняется этим движком, а не системой напрямую.
Многие компании с нативными приложениями не торопятся переходить на Flutter или React Native из-за возможных последствий для производительности конечного продукта. Здесь Kotlin Multiplatform серьезно расходится с этими фреймворками. Это не фреймворк, а только платформонезависимый язык: в отличие от движков Flutter и React, у него нет собственной среды выполнения.

Kotlin всегда компилируется в полностью машинный код, интегрируемый в приложение и доступный из его кодовой базы. Поэтому в конечном продукте, опубликованном в магазине, не содержится кода Kotlin или дополнительных уровней выполнения, таких как движки или виртуальные машины. Все выполняется непосредственно операционной системой, как любой код в обычном нативном приложении.
Выпускайте новый функционал быстрее, устраняйте баги проще
Благодаря разделению значительной части кодовой базы между приложениями, заметно снижаются затраты на разработку и сопровождение. Например, если обеими командами выпуск планируемого нового функционала для приложения оценивается в 10 сумасшедших дней, всего получится 20 человеко-дней. С применением же Kotlin Multiplatform эта оценка потенциально сокращается до 12-13 человеко-дней, то есть разработка и выпуск функционала ускоряются на 30–40 %.

С Kotlin Multiplatform логика реализуется в Kotlin единожды, в нативных приложениях нужно только добавить пользовательский интерфейс поверх этого общего уровня. Кроме того, когда большая часть кодовой базы общая для приложений, сопровождение значительно упрощается. Если появляется ошибка, ее требуется исправить только в одном месте. Изменение имеющейся логики тоже задача, решаемая однократно.
Совершенствуйте взаимодействие нативных команд
Перенос нативного проекта на Kotlin Multiplatform очень позитивно сказывается на командах. Когда приложения Android и iOS независимы, команды их разработчиков со временем становятся все изолированнее.
Они в разном темпе работают, по-разному интерпретируют бизнес-требования, разными способами их реализуют. Такие различия чреваты бизнес-проблемами, когда одно приложение опережает другое или отличается от него поведением. Внедрением в проект общей реализации Kotlin смягчаются последствия таких сценариев и совершенствуется взаимодействие разработчиков.
Со временем обмен знаниями между командами становится ощутимым. Сначала, чтобы понять общую кодовую базу, разработчики iOS знакомятся с Kotlin, а в итоге даже приступают к самостоятельной реализации логики Kotlin. В свою очередь, разработчики Android изучают платформу iOS, в частности SwiftUI, которая похожа на Compose.
Как перейти на Kotlin Multiplatform?
Разобрав преимущества перехода на Kotlin Multiplatform, рассмотрим этот процесс на практике. При корректном планировании и выполнении миграции осуществляется беспроблемная интеграция в обычный рабочий процесс. Команда продолжает разрабатывать и выпускать новый функционал, устранять имеющиеся баги и бесперебойно выдавать обновления для магазинов.
На высоком уровне процесс миграции разворачивается в трех простых этапах.
- Настройка модуля Multiplatform и подключение его к обоим нативным приложениям.
- Перемещение выбранного кода из имеющегося проекта Android в модуль Multiplatform.
- Интегрирование этого кода в проект iOS с заменой исходной реализации Swift.

Важно отметить, что такой миграцией не подразумевается перемещение всего кода сразу, это итеративный процесс. На каждой итерации выбирается часть кодовой базы, которая переносится в модуль Kotlin Multiplatform, интегрируется в проект iOS, и исходная реализация Swift удаляется. Затем в магазинах выпускаются обновленные версии приложения. При этом обычная разработка приложения продолжается без остановки.
Начните с модели
Обычно процесс миграции начинается с простейшей и автономной части приложения — модели. На этом уровне содержатся простые объекты, это основные бизнес-сущности, например User, Product или Article, а также связанные с ними бизнес-правила, которыми определяется их поведение. Благодаря миграции модели, нативными приложениями применяется унифицированное представление используемых ими данных.

Затем перенесите источники данных
После переноса модели следующий этап — внешние компоненты кодовой базы, а именно источники данных. Самые распространенные из них — это серверные службы и локальные базы данных. Благодаря разделению этих компонентов между приложениями, создается единое определение конечных точек, таблиц баз данных, запросов и объектов передачи данных.

Добавьте общие интерфейсы для нативных API и SDK
Мобильные приложения часто взаимодействуют не только с источниками данных, но и с системными API-интерфейсами и внешними SDK-пакетами. Хотя у них обычно имеются реализации для конкретных платформ, модулем Kotlin Multiplatform предоставляются общие интерфейсы, доступные для всех приложений. Важно отметить, что реализация этих интерфейсов остается полностью нативной: никакие обертки или мосты не нужны.

Перенесите бизнес-логику
После переноса модели, источников данных, системных API и внешних SDK следующий этап — бизнес-логика, которой интегрируются все предыдущие компоненты. Эта логика «знает», что делается при отправке заказа или какие данные загружаются после входа в приложение. Благодаря единой реализации этой логики смягчаются последствия критических багов, обеспечивается согласованное поведение на мобильных платформах.

Вишенка на торте: общий слой представления
Наконец, добрались до слоя представления, последнего перед пользовательским интерфейсом. Им контролируется состояние экранов или компонентов пользовательского интерфейса, форматируются данные, проверяется пользовательский ввод и обрабатываются пользовательские взаимодействия. Разделением этой реализации упрощается пользовательский интерфейс, а команды концентрируются на обеспечении оптимального пользовательского взаимодействия. Вся базовая логика реализуется и тестируется в модуле Multiplatform единожды.

Разделите миграцию по функциям
В крупных проектах применение функциональных модулей — обычная практика. Разработчики разбивают кодовую базу на отдельные функции, каждая из которых — единый поток внутри приложения. У этих функций, например регистрации, адаптации, заказов и настроек, обычно имеются собственные слои представления, бизнес-логика, модель, источники данных, а иногда даже специфические API-интерфейсы или SDK-пакеты.
В таких случаях процесс совершенствуется внедрением функционального подхода, которым дополняется миграция слоя за слоем. Так осуществляется распараллеливание миграции разными разработчиками или командами. Каждый из них занимается переносом конкретной функции в собственном темпе, не вмешиваясь в перенос других.

Каковы риски миграции Kotlin Multiplatform и как смягчить их последствия?
С Kotlin Multiplatform технические риски минимизируются. Здесь нет необходимости в новом языке программирования, обеспечивается постепенный процесс миграции, поддерживаются на 100 % нативная производительность и пользовательский интерфейс для оптимального пользовательского взаимодействия, сохраняется доступ ко всем нативным API и SDK.
В целом с Kotlin Multiplatform риски внедрения меньше, чем с Flutter или React Native, но не исключены полностью, как и в любой технологии. При учете особенностей и рекомендаций эти риски эффективно контролируются и предотвращаются.
Потенциальный дисбаланс распределения задач в командах
Около 80 % кодовой базы объединяется в Kotlin и совместно используется на разных платформах. Для команды Android этот переход сопровождается помещением имеющейся реализации в модуль Multiplatform, причем без больших изменений. Для команды iOS сценарий отличается. С Kotlin Multiplatform большая часть кода, обычно написанного на Swift, теперь реализуется в Kotlin разработчиками Android. Если размер обеих команд одинаков, у команды iOS оказывается меньше работы, ведь основная ее часть выполняется их коллегами из Android.
Одно из эффективных решений — постепенный обмен знаниями между командами. При таком подходе разработчики iOS не только используют общую реализацию Kotlin, но и участвуют в ее создании. Многие успешно внедрили эту стратегию, стимулируя интерес своих iOS-инженеров к изучению Kotlin.
Если обмен знаниями затруднителен, создавайте асимметричные команды с большим количеством разработчиков Android и меньшим iOS. Так обеспечивается из плавное взаимодействие без простоев, поддерживается эффективность на протяжении всего процесса миграции.
Риск игнорирования потребностей iOS
При использовании Kotlin Multiplatform общий код написан преимущественно на Kotlin, в проектах Android тоже активно применяется Kotlin. Следовательно, различие между специфичной для Android реализацией и Multiplatform размывается, ведь внешне и функционально они часто идентичны. Но очень важно, чтобы эта общая реализация Kotlin оставалась доступной и применимой на стороне iOS.
Избегайте ситуаций, где общий код разрабатывается без консультаций с разработчиками iOS. Для успешной интеграции Kotlin Multiplatform важна эффективная коммуникация. Ответственность за общую реализацию разделяется обеими нативными командами. Разработчикам Android следует ознакомиться с тем, как Kotlin преобразуется в Swift. Подробную информацию о процессе преобразования они найдут здесь.
В свою очередь, инженеры iOS должны понимать общедоступный API общего кода, активно участвовать в формировании его технических решений. В долгосрочной перспективе с созданием среды, где разработчики iOS вносят вклад в общую кодовую базу Kotlin и сопровождают ее, совершенствуется не только понимание, но и взаимодействие в совместном владении.
Потенциальные ограничения в функциях Kotlin на iOS
Kotlin начали разрабатывать в JetBrains задолго до того, как Swift стал активно применяться в сообществе разработчиков Apple. Поэтому для перевода Kotlin на Objective-C — оригинальный, основной язык для всех операционных систем Apple — разработали компилятор Kotlin/Native. Этим решением поддерживаются самые разные проекты, но и накладываются определенные ограничения. Базовый функционал вроде классов, свойств и функций преобразуется легко, но продвинутый вроде запечатанных классов, приостанавливающих функций или потоков сталкивается с проблемами.
Плагином SKIE компилятора эти ограничения устраняются: вместо Objective-C генерируется код Swift. Так поддерживаются продвинутые функции Kotlin, они преобразуются в свои аналоги Swift: перечисления со связанными значениями, функции async/await и AsyncSequence.
Прямая совместимость Kotlin и Swift запланирована на 2024 год. В JetBrains тесно сотрудничают с создателями SKIE, планируют интегрировать аналогичную функциональность прямо в компилятор Kotlin/Native.
Возможная необходимость в дополнительном рефакторинге
Сложность перехода на Kotlin Multiplatform варьируется в зависимости от качества и чистоты архитектуры приложения. Плавный переход обычно осуществляется, когда пользовательский интерфейс корректно отделен от логики приложения, а внешние зависимости упрощены. Если же некоторые части архитектуры неоптимальны, потребуются дополнительные изменения. Хотя сам рефакторинг — не проблема, чтобы завершить полную миграцию Kotlin Multiplatform и получить все преимущества, требуются дополнительные усилия.
Как эффективно справляться с этим? Избегать непредусмотренных перепроектирований. Начните с анализа проекта, выявляя области, где нужны изменения. Затем разбейте этот процесс на управляемые части и соответствующим образом спланируйте каждый этап. При проведении рефакторинга разделы кодовой базы, которым не требуются корректировки, переносятся в Kotlin Multiplatform параллельно. Благодаря стратегическому планированию и сегментации задач расширяются возможности контролировать весь процесс миграции.
В Kotlin Multiplatform обеспечиваются автономия и гибкость в определении того, какие части кодовой базы должны разделяться приложениями. Иногда усилия, необходимые для рефакторинга кода, весомее преимуществ его разделения. В таких случаях разделяйте все остальное, а эти конкретные компоненты сохраните как отдельные реализации для каждого приложения.
Переход на Kotlin Multiplatform, заключительные мысли
Раньше в Google рекомендовали Kotlin для нативной разработки Android, теперь рекомендуют писать логику приложения на Kotlin Multiplatform и разделять ее с приложением iOS. Сейчас Kotlin — стандарт индустрии. Ожидается, что очень скоро таким же стандартом станет и Kotlin Multiplatform.
В крупных компаниях с высококачественными мобильными продуктами уже решили интегрировать Kotlin Multiplatform в свои проекты. Примеры — McDonald’s, Netflix, Phillips, Bolt. Недавно даже в Google объявили о применении Kotlin Multiplatform в их приложении Google Docs и о планах перенести и другие свои продукты, такие как Gmail и Google Drive.
Несомненно, Kotlin Multiplatform — это будущее нативной мобильной разработки. Здесь впервые не нужно переписывать нативные приложения, нет необходимости и в новом фреймворке или языке, чтобы воспользоваться преимуществами платформонезависимой разработки.
Kotlin Multiplatform легко интегрируется в нативное приложение на любом этапе разработки. Не нужно тратить месяцы на создание нового приложения с нуля. Начните разрабатывать и выпускать новый функционал с Kotlin Multiplatform прямо сейчас и отправляйте его на продакшен в ближайшие спринты. При этом переносите имеющийся код на Multiplatform, упрощая его сопровождение и внесение будущих изменений. Все это делается с сохранением приложения на 100 % нативным, с оптимальными производительностью и пользовательским взаимодействием, полным доступом ко всем системным API и нативным SDK.
Читайте также:
- Дорожная карта iOS для разработчиков Android: основы
- Стековая и кучная память в Kotlin
- Шпаргалка Swift для разработчиков Android/Kotlin
Читайте нас в Telegram, VK и Дзен
Перевод статьи Marcin Piekielny: Convert Your Native Project to Kotlin Multiplatform: Why, When and How