> Насколько интересно писать на Kotlin Multiplatform и участвовать в переписывании Android и iOS приложений (Kotlin, iOS, Swift, Android)
Уровень: senior · Роль: mobile · Категория: Технические вопросы
Компании: Travelata
Стек: Kotlin, iOS, Swift, Android
> Пример ответа
Короткий ответ
Kotlin Multiplatform интересен как инженерный вызов: вы получаете единую бизнес-логику на Kotlin, но сохраняете нативные UI и платформенные API. Это снижает дублирование кода, но добавляет сложности с expect/actual, синхронизацией версий и тулингом. Участие в переписывании - это возможность переосмыслить архитектуру, но нужно быть готовым к trade-off между скоростью разработки и нативной гибкостью. Интересно, если вам нравится решать задачи на стыке платформ.
Подробное объяснение
Kotlin Multiplatform (KMP) - это не про "один код на всё", а про шаринг логики: сетевой слой, репозитории, state management, валидация, декодирование JSON. UI остаётся нативным - SwiftUI/UIKit для iOS и Compose/Views для Android. Это принципиально отличает KMP от Flutter или React Native.
Интерес в KMP складывается из нескольких факторов:
- Архитектурная свобода: вы сами решаете, что выносить в shared-модуль. Можно начать с малого - только сеть и модели - и постепенно расширять.
- Работа с expect/actual: это механизм, который заставляет думать о платформенных различиях явно. Например, работа с файловой системой, датами, криптографией - всё это требует actual-реализаций.
- Kotlin/Native и memory model: нужно понимать, как работает заморозка объектов, потоки, взаимодействие с Objective-C/Swift через generated framework. Это добавляет глубины.
- Инструменты: Gradle, cocoapods, Xcode integration, klib, binary compatibility - всё это требует отдельного скилла.
Переписывание приложений на KMP - это отдельный сценарий. Обычно это означает:
- рефакторинг существующей логики из Swift и Java/Kotlin в общий модуль;
- необходимость сохранить поведение и API, но улучшить тестируемость;
- часто переписывание сопровождается внедрением новых подходов: MVI, Clean Architecture, DI (Koin, Kodein).
Сложность в том, что iOS-часть на Swift и Android-часть на Kotlin могут иметь разную историю, разные модели данных и разный уровень качества. Приведение их к общему знаменателю - это долгий итеративный процесс.
На практике
На практике KMP интересен, когда:
- у вас есть команда, которая готова учиться и поддерживать общий код;
- продукт имеет сложную бизнес-логику, которая действительно дублируется;
- вы готовы к тому, что часть времени уходит не на фичи, а на инфраструктуру: настройка сборки, интеграция с Xcode, отладка Kotlin/Native.
Типичный рабочий процесс:
- shared-модуль содержит: модели, сетевой слой (Ktor), навигацию (частично), state (например, ViewModel на Kotlin), DI, логику.
- Android-приложение использует shared-код напрямую, часто через Compose.
- iOS-приложение подключает shared-фреймворк через Swift Package Manager или CocoaPods, и вызывает Kotlin-классы из Swift.
Проблемы, с которыми сталкиваются на практике:
- Swift ↔ Kotlin mapping: не все типы маппятся удобно. Например, sealed class в Kotlin становится enum с associated values в Swift - это работает, но не всегда интуитивно.
- Coroutines и Swift Concurrency: нужно аккуратно мостить suspend-функции и async/await. Есть поддержка, но есть нюансы с cancellation.
- Производительность: Kotlin/Native не всегда так быстр, как нативный Swift, особенно в горячих путях.
- Отладка: дебажить Kotlin-код из Xcode сложнее, чем из Android Studio.
Пример кода
Простой пример expect/actual для получения текущего времени в миллисекундах:
// shared/src/commonMain/kotlin/Platform.kt expect fun currentTimeMillis(): Long // shared/src/androidMain/kotlin/Platform.android.kt actual fun currentTimeMillis(): Long = System.currentTimeMillis() // shared/src/iosMain/kotlin/Platform.ios.kt import platform.Foundation.NSDate import platform.Foundation.timeIntervalSince1970 actual fun currentTimeMillis(): Long = (NSDate().timeIntervalSince1970 * 1000).toLong()
Пример вызова из Swift:
SWIFTlet time = PlatformKt.currentTimeMillis()
Как отвечать на собеседовании
На собеседовании важно показать, что вы понимаете не только плюсы, но и ограничения KMP. Отвечайте структурно:
- начните с того, что KMP - это не замена нативному UI, а шаринг логики;
- приведите конкретный пример, что вы выносили в shared-модуль и почему;
- расскажите про expect/actual и как вы решали платформенные расхождения;
- упомяните инструменты: Gradle, CocoaPods, Xcode, Kotlin/Native;
- покажите, что понимаете trade-off: скорость разработки против сложности инфраструктуры.
Если вас спрашивают про переписывание - говорите о стратегии: как вы анализировали существующий код, что оставили на платформах, как обеспечивали совместимость с существующими фичами.
Что проверяет интервьюер
Интервьюер оценивает:
- понимание архитектуры KMP и места shared-кода;
- знание Kotlin/Native, memory model, взаимодействия с Swift;
- умение принимать решения: что выносить в общий код, а что оставить нативным;
- опыт работы с инструментами и CI для мультиплатформенных проектов;
- способность объяснить trade-off и риски.
Также проверяется, насколько вы реально работали с KMP, а не просто читали статьи. Вопросы про expect/actual, про сборку, про отладку - хороший фильтр.
Типичные ошибки
- Утверждение, что KMP - это "один код на все платформы". Это не так, и это сразу выдаёт непонимание.
- Игнорирование платформенных особенностей. Например, попытка вынести UI в shared - это антипаттерн, если только вы не используете Compose Multiplatform, но это отдельная история.
- Непонимание memory model. Заморозка объектов, потоки, контексты - без этого нельзя писать стабильный код.
- Отсутствие стратегии миграции. Если вы переписываете приложение, нельзя просто "взять и перенести всё". Нужен план: что переносим первым, как тестируем, как обеспечиваем обратную совместимость.
- Недооценка сложности интеграции с iOS. Xcode, CocoaPods, Swift Package Manager, генерация фреймворка - это отдельная боль, и её нельзя игнорировать.
- Отсутствие тестов. KMP даёт хорошие возможности для юнит-тестов на common-коде, но если вы их не пишете, то теряете главное преимущество.
> Похожие задачи по mobile
Как вызвать синхронную задачу на главном потоке, чтобы избежать дедлока
Что такое Storyboards и XIB
Как реализовать функцию вставки и удаления элементов в структуре данных
В чем разница между захватом переменной в closure и копированием
> ГОТОВЫ К СЛЕДУЮЩЕМУ СОБЕСЕДОВАНИЮ?
Запустите тренировочную сессию с ИИ и получите детальную обратную связь, чтобы увереннее проходить реальные интервью