آموزش کاتلین مولتی پلتفرم در اندروید: راهنمای عملی KMP

برنامه نویسی اندروید
آموزش کاتلین مولتی پلتفرم در اندروید: راهنمای عملی KMP

در سال های اخیر توسعه موازی اپلیکیشن های موبایل برای دو سیستم عامل اندروید و iOS همواره یکی از پرهزینه ترین چالش های تیم های مهندسی محصول بوده است. نوشتن مجدد منطق تجاری، قوانین اعتبارسنجی فرم ها، مدل های داده و لایه شبکه به دو زبان کاتلین و سوییفت علاوه بر دو برابر کردن زمان پیاده سازی، احتمال بروز باگ های ناهمگون را به شدت افزایش می دهد.

رویکردهای کراس پلتفرم سنتی مانند فلاتر یا ری اکت نیتیو تلاش کردند این مشکل را با اشتراک گذاری صد در صدی کدها حل کنند؛ اما این کار به قیمت فدا کردن رابط کاربری بومی، تحمیل یک لایه میانی رندرینگ سنگین، تاخیرهای گاه و بیگاه و دشواری های دسترسی به API های سطح پایین سیستم عامل تمام می شد.

فناوری کاتلین مولتی پلتفرم یا همان KMP با یک پارادایم نوین این چالش را حل کرده است. در این شیوه شما مجبور به فدا کردن رابط کاربری نیستید. تمام منطق تجاری و شبکه یک بار با زبان کاتلین پیاده سازی می شود.

سپس رابط های کاربری به طور کاملاً بومی با Jetpack Compose در اندروید و با SwiftUI در iOS پیاده سازی می گردند. این ترکیب هوشمندانه بالاترین کیفیت تجربه کاربری را در کنار کاهش چشمگیر هزینه ها به ارمغان می آورد.

پاسخ سریع و معماری خلاصه (GEO Summary): فناوری کاتلین مولتی پلتفرم اشتراک گذاری لایه های دیتا و بیزینس را بین اندروید و iOS بدون افت کارایی فراهم می کند. لایه UI در اندروید با Compose و در iOS با SwiftUI نیتیو پیاده می شود و ارتباط سخت افزاری با expect/actual هندل می گردد.

۱. چرا کاتلین مولتی پلتفرم؟ کالبدشکافی تفاوت بنیادین KMP با فلاتر و ری اکت نیتیو

برای انتخاب آگاهانه ابزار، ابتدا باید تفاوت فلسفی KMP را با سایر فریمورک های چند سکویی بشناسیم. در فریمورک هایی نظیر Flutter، کل موتور رابط کاربری درون اپلیکیشن جاسازی می شود.

این رویکرد اگرچه ظاهر گرافیکی یکسانی در پلتفرم ها می سازد، اما رفتار ژست های حرکتی، فیزیک اسکرول و پاسخ به تاچ هرگز به طور کامل حس یک برنامه بومی iOS را بازتاب نمی دهد.

در مقابل، کاتلین مولتی پلتفرم یک رویکرد اختیاری و لایه ای دارد. شما می توانید صرفاً پنج درصد از کد پروژه (مانند یک الگوریتم محاسباتی یا اعتبارسنجی توکن احراز هویت) را مشترک کنید، یا کل لایه های شبکه، حافظه پنهان و منطق دامنه را در ماژول مشترک قرار دهید.

کد کاتلین نوشته شده در ماژول مشترک برای سیستم عامل اندروید به بایت کد سازگار JVM کامپایل می شود و برای سیستم عامل iOS توسط کامپایلر پیشرفته Kotlin/Native مستقیماً به یک فریمورک بومی سی و آبجکتیو سی تبدیل می گردد. در نتیجه کد مشترک در iOS دقیقاً همانند کدهای زبان Swift اجرا می شود و هیچ ماشین مجازی یا لایه ترجمه برخط وجود ندارد.

همچنین از نظر توسعه پذیری سازمانی، پذیرش KMP هیچ خطری برای تیم های نیتیو ندارد. اگر در آینده تیمی تصمیم به توقف استفاده از کدهای اشتراکی بگیرد، می توان کدهای کاتلین را در اندروید حفظ کرد و ماژول iOS را به سادگی به سوییفت بازنویسی نمود، بدون اینکه کل معماری و ظاهر گرافیکی اپلیکیشن نیاز به تخریب و بازطراحی داشته باشد.

اگر در آغاز مسیر توسعه نرم افزار موبایل هستید و می خواهید ساختار کلی کامپوننت های مدرن را از پایه بیاموزید، پیشنهاد می کنیم راهنمای جامع آموزش برنامه نویسی اندروید را به عنوان مرجع اصلی مطالعه فرمایید.

۲. معماری لایه ای در کاتلین مولتی پلتفرم و انطباق با معماری تمیز

بهترین الگوی ساختاری برای پروژه های سازمانی KMP، پیاده سازی اصول Clean Architecture است. در این الگو، پروژه به سه لایه کلی تفکیک می شود:

  • لایه داده (Data Layer): شامل کلاینت شبکه با Ktor، پایگاه داده محلی با SQLDelight یا Room KMP، و ریپازیتوری ها که صد در صد درون ماژول مشترک shared قرار دارند.
  • لایه دامنه (Domain Layer): شامل Use Case ها، موجودیت های تجاری و بیزینس لاجیک که کاملاً خالص (Pure Kotlin) بوده و بدون وابستگی به فریمورک های پلتفرمی در ماژول مشترک قرار می گیرند.
  • لایه نمایش (UI Layer): لایه ای که می تواند به صورت بومی با Compose در اندروید و SwiftUI در iOS نوشته شود، یا با استفاده از Compose Multiplatform بخش های زیادی از UI نیز به اشتراک گذاشته شود.
نمودار معماری لایه ای کاتلین مولتی پلتفرم و اشتراک گذاری منطق تمیز بین اندروید و آی او اس
جریان تبادل داده میان ماژول مشترک کاتلین و لایه های رابط کاربری بومی اندروید و iOS

در این ساختار، لایه دامنه هیچ گونه شناختی از سیستم عامل اندروید یا iOS ندارد. حتی کلاس های مربوط به Context یا کلاس های Foundation اپل نباید به این لایه نفوذ کنند. این استقلال مطلق باعث می شود تمام تست های اعتبارسنجی قوانین کسب و کار روی JVM ماشین توسعه دهنده با کسری از ثانیه اجرا شوند.

برای درک چگونگی تفکیک دقیق وظایف و ساختار ریپازیتوری ها بدون نشت لایه های پلتفرم، توصیه می شود مقاله تحلیلی معماری تمیز در مهندسی نرم افزار را بررسی نمایید.

پیشنهاد مطالعه
آموزش معماری تمیز در اندروید: راهنمای لایه بندی با کاتلین
آموزش جامع معماری تمیز (Clean Architecture) در برنامه نویسی اندروید با کاتلین. بررسی تفصیلی لایه های Presentation، Domain و Data، پیاده سازی الگوی Us…
مشاهده مقاله ←

۳. جدول مقایسه فنی: کاتلین مولتی پلتفرم در برابر فلاتر، ری اکت نیتیو و نیتیو خالص

برای معماران نرم افزار ارشد، انتخاب فریمورک نیازمند تراز دقیق هزینه های توسعه در برابر عملکرد و تجربه کاربری نهایی است:

معیار سنجش مهندسی کاتلین مولتی پلتفرم (KMP) فلاتر (Flutter) ری اکت نیتیو (React Native) توسعه نیتیو سنتی (جداگانه)
زبان برنامه نویسی کاتلین مدرن (Kotlin) دارت (Dart) تایپ اسکریپت / جاوا اسکریپت کاتلین برای اندروید، سوییفت برای iOS
رابط کاربری (UI) بومی ۱۰۰٪ (Compose + SwiftUI) موتور رندرینگ سفارشی (Impeller/Skia) ویجت های نیتیو از طریق پل ارتباطی (Bridge/JSI) بومی صد در صد مجزا
عملکرد و سرعت اجرا نیتیو خالص بدون سربار مجازی ساز بسیار خوب با کامپایل AOT دارت متوسط تا خوب وابسته به پل JSI حداکثر عملکرد ممکن سخت افزار
درصد اشتراک کد تجاری ۶۰ تا ۸۵ درصد (لایه های بیزینس و دیتا) ۹۰ تا ۹۵ درصد (کد و ظاهر گرافیکی) ۸۵ تا ۹۰ درصد صفر درصد (دوباره نویسی کامل)
ریسک انحصار پلتفرم حداقل (در صورت لزوم کد مشترک به نیتیو تبدیل می شود) بسیار بالا (وابستگی کامل به حیات اکوسیستم فلاتر) بالا (وابستگی به هسته فیس بوک) صفر درصد
دسترسی به API سخت افزار مستقیم و فوری با الگوی expect/actual نیازمند ایجاد MethodChannel دستی نیازمند نوشتن ماژول نیتیو NativeModule مستقیم و بدون واسطه

۴. ساختار پروژه و پیکربندی گریدل در ماژول های مشترک KMP

یک پروژه مدرن کاتلین مولتی پلتفرم شامل دایرکتوری های منبع تفکیک شده است. ساختار استاندارد شامل commonMain برای کدهای اشتراکی، androidMain برای کدهای اختصاصی اندروید، و iosMain برای تعاملات اکوسیستم اپل می باشد.

نمونه پیکربندی فایل build.gradle.kts در ماژول مشترک:

// shared/build.gradle.kts
plugins {
    alias(libs.plugins.kotlinMultiplatform)
    alias(libs.plugins.androidLibrary)
    alias(libs.plugins.kotlinxSerialization)
}

kotlin {
    androidTarget {
        compilations.all {
            kotlinOptions { jvmTarget = "17" }
        }
    }
    listOf(
        iosX64(),
        iosArm64(),
        iosSimulatorArm64()
    ).forEach { iosTarget ->
        iosTarget.binaries.framework {
            baseName = "SharedKit"
            isStatic = true
        }
    }
}

در ادامه، وابستگی های مورد نیاز ماژول مشترک درون بلوک sourceSets تعریف می گردند:

kotlin {
    sourceSets {
        commonMain.dependencies {
            implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.8.1")
            implementation("io.ktor:ktor-client-core:2.3.11")
            implementation("io.ktor:ktor-client-content-negotiation:2.3.11")
            implementation("io.ktor:ktor-serialization-kotlinx-json:2.3.11")
        }
        androidMain.dependencies {
            implementation("io.ktor:ktor-client-okhttp:2.3.11")
        }
        iosMain.dependencies {
            implementation("io.ktor:ktor-client-darwin:2.3.11")
        }
    }
}

با این ساختار هوشمندانه، کلاینت شبکه در لایه اشتراکی از موتور استاندارد بهره می برد؛ اما در اندروید از موتور باسابقه OkHttp و در iOS از موتور بومی URLSession شرکت اپل برای تبادل درخواست های HTTP استفاده می شود.

همچنین پشتیبانی از فرمت های خروجی کاتلین به توسعه دهنده اجازه می دهد فایل های فریمورک را از طریق CocoaPods، Swift Package Manager (SPM) یا باینری های محلی به سادگی به پروژه Xcode متصل کند. بدین ترتیب اعضای تیم توسعه iOS نیازی به باز کردن اندروید استودیو نخواهند داشت.

۵. مکانیزم طلایی Expect و Actual: پل ارتباطی کاتلین با قابلیت های اختصاصی پلتفرم

یکی از قدرتمندترین ابزار های کاتلین مولتی پلتفرم، کلمات کلیدی expect و actual هستند. این مکانیزم به شما اجازه می دهد در کدهای اشتراکی یک امضای تابع، کلاس یا رابط را اعلام کنید، و سپس پیاده سازی دقیق آن را به پلتفرم های مقصد واگذار نمایید.

گام اول: تعریف امضای مشترک با expect در commonMain

// commonMain/PlatformInfo.kt
expect class PlatformInfo() {
    val platformName: String
    val osVersion: String
    fun getBatteryLevelPercentage(): Int
}

گام دوم: پیاده سازی واقعی با actual در androidMain

// androidMain/PlatformInfo.kt
import android.os.Build

actual class PlatformInfo {
    actual val platformName: String = "Android"
    actual val osVersion: String = "SDK " + Build.VERSION.SDK_INT
    actual fun getBatteryLevelPercentage(): Int {
        return 85
    }
}

گام سوم: پیاده سازی واقعی با actual در iosMain

// iosMain/PlatformInfo.kt
import platform.UIKit.UIDevice

actual class PlatformInfo {
    actual val platformName: String = "Apple iOS"
    actual val osVersion: String = UIDevice.currentDevice.systemVersion
    actual fun getBatteryLevelPercentage(): Int {
        UIDevice.currentDevice.batteryMonitoringEnabled = true
        return (UIDevice.currentDevice.batteryLevel * 100).toInt()
    }
}

کامپایلر کاتلین در زمان کامپایل بررسی می کند که آیا تمام امضاهای تعریف شده با expect دارای پیاده سازی متناظر actual در تمام تارگت های فعال هستند یا خیر. در صورت عدم پیاده سازی، خطا بلافاصله ظاهر می شود که مانع از وقوع هرگونه خطای ناشناخته زمان اجرا در محیط پروداکشن می گردد.

نکته مهم در استفاده از این الگو، پرهیز از افراط است. منطق کسب و کار و الگوریتم ها باید تا جای ممکن با ابزار های استاندارد کاتلین نوشته شوند و استفاده از expect/actual صرفاً به تعامل با سخت افزار (دوربین، سنسورها، بلوتوث و فایل های سیستمی) محدود گردد.

۶. ارتباط با سرور و تبادل داده با کلاینت شبکه Ktor

در اپلیکیشن های نیتیو سنتی اندروید معمولاً از Retrofit استفاده می شود، اما Retrofit وابسته به بایت کد جاوای JVM است و در پلتفرم iOS اجرا نمی شود. کتابخانه رسمی Ktor Client استانداردی بی نظیر و تماماً کاتلینی برای درخواست های چند سکویی فراهم آورده است.

// commonMain/network/ApiClient.kt
import io.ktor.client.HttpClient
import io.ktor.client.call.body
import io.ktor.client.plugins.contentnegotiation.ContentNegotiation
import io.ktor.client.request.get
import io.ktor.serialization.kotlinx.json.json
import kotlinx.serialization.json.Json

class ApiClient(private val httpClient: HttpClient) {
    suspend inline fun <reified T> getRequest(url: String): T {
        return httpClient.get(url).body()
    }
}

fun createHttpClient(): HttpClient = HttpClient {
    install(ContentNegotiation) {
        json(Json {
            ignoreUnknownKeys = true
            isLenient = true
        })
    }
}

کلاینت Ktor از قابلیت های پیشرفته ای نظیر رهگیری درخواست ها (Interceptors)، مدیریت خودکار توکن احراز هویت (Auth Plugin) و مکانیزم های تلاش مجدد در صورت قطعی اینترنت پشتیبانی می کند. با پیاده سازی این موارد در ماژول مشترک، رفتارهای شبکه در هر دو نسخه اندروید و iOS صد در صد هماهنگ خواهد بود.

یکی از کاربردی ترین پلاگین های Ktor در پروژه های تجاری، پلاگین HttpTimeout است. این ابزار به شما امکان می دهد مهلت زمانی اتصال (Connect Timeout)، مهلت ارسال درخواست (Request Timeout) و زمان انتظار برای پاسخ سوکت (Socket Timeout) را به صورت دقیق کنترل کنید تا از معلق ماندن بیهوده منابع دستگاه در شرایط شبکه های ضعیف تلفن همراه جلوگیری شود.

همچنین در سناریوهای امنیتی سازمانی، پیاده سازی گواهی های امنیتی اختصاصی (SSL Pinning) در Ktor به کمک موتورهای پلتفرمی OkHttp و Darwin انجام می شود که حفاظت کامل داده های کاربران در برابر حملات جعل میانی را در هر دو سیستم عامل به صورت یکپارچه به ارمغان می آورد.

برای مقایسه عملکرد Ktor با سیستم های قدیمی رتروفیت در پروژه های صرفاً اندرویدی، مطالعه مقاله آموزش رتروفیت در اندروید به شما دید عمیقی از انتقال معماری شبکه خواهد داد.

۷. پایگاه داده آفلاین در KMP با SQLDelight و Room Multiplatform

ذخیره سازی داده های آفلاین یکی از نیازهای اصلی در برنامه های مدرن است. در اکوسیستم KMP، کتابخانه SQLDelight از ابتدا برای این منظور طراحی شده است. از نسخه اخیر اندروید، شرکت گوگل کتابخانه محبوب Room را نیز به عنوان Room Multiplatform به صورت رسمی برای پروژه های KMP معرفی کرده است.

// commonMain/data/DatabaseDriverFactory.kt
import app.cash.sqldelight.db.SqlDriver

expect class DatabaseDriverFactory {
    fun createDriver(): SqlDriver
}

// androidMain: ایجاد با AndroidSqliteDriver
// iosMain: ایجاد با NativeSqliteDriver

مزیت بزرگ SQLDelight این است که شما کوئری های SQL خام را در فایل های .sq می نویسید و کامپایلر به طور خودکار کدهای کاتلین Type-Safe برای اجرای آن کوئری ها ایجاد می کند. این رویکرد خطاهای گرامری SQL را در زمان کامپایل شناسایی می نماید.

مدیریت تغییرات شماتیک دیتابیس و مهاجرت ها (Migrations) نیز در این کتابخانه با فایل های نسخه بندی شده .sqm انجام می پذیرد. در نتیجه هنگامی که فیلد جدیدی به جداول پروژه اضافه می شود، اسکریپت های ارتقای دیتابیس به صورت خودکار و بدون خطر از دست رفتن داده های کاربران در هر دو نسخه اندروید و iOS اعمال می گردند.

همچنین برای اپلیکیشن هایی با الزامات امنیتی بالا، کتابخانه SQLDelight قابلیت رمزنگاری پایگاه داده در سطح دیسک با درایورهای SQLCipher را پشتیبانی می کند تا داده های حساس ذخیره شده روی حافظه فیزیکی گوشی از دسترسی های غیرمجاز کاملاً مصون بمانند.

جهت بررسی تکنیک های پیشرفته طراحی پایگاه داده های رابطه ای، مقاله مرجع آموزش دیتابیس Room در اندروید را در نقشه راه یادگیری خود قرار دهید.

۸. مدیریت همزمانی و جریان های واکنشی با Coroutines و StateFlow

کتابخانه kotlinx.coroutines هسته تپنده مدیریت ناهمگام در کاتلین مولتی پلتفرم است. در ماژول مشترک، شما می توانید عملیات های سنگین شبکه و محاسباتی را با ساختارهای تمیز suspend بنویسید و نتایج را در قالب StateFlow یا SharedFlow مخابره کنید.

// commonMain/viewmodel/CommonUserViewModel.kt
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.launch

sealed interface UiState {
    data object Loading : UiState
    data class Success(val username: String) : UiState
    data class Error(val message: String) : UiState
}

class CommonUserViewModel(private val scope: CoroutineScope) {
    private val _uiState = MutableStateFlow<UiState>(UiState.Loading)
    val uiState: StateFlow<UiState> = _uiState.asStateFlow()

    fun loadUserData() {
        scope.launch(Dispatchers.Default) {
            _uiState.value = UiState.Success("کاربر ارشد کاتلین")
        }
    }
}

در سمت سیستم عامل اندروید، کدهای Jetpack Compose مستقیماً با تابع collectAsStateWithLifecycle مقدار StateFlow را مصرف می کنند. در سمت سیستم عامل iOS، ابزار های محبوبی نظیر KMP-NativeCoroutines یا SKIE کدهای StateFlow را به صورت کامپایل شده به جریان های بومی AsyncSequence یا Combine زبان سوییفت تبدیل می نمایند تا توسعه دهندگان اپل حس کار با کدهای نیتیو سوییفت را داشته باشند.

مدل حافظه جدید کاتلین نیتیو که در نسخه های اخیر معرفی شد، محدودیت های قدیمی قفل شدن اشیاء بین تردها (Thread Freezing) را به طور کامل حذف کرده است. امروزه اشیای کاتلین می توانند آزادانه میان تردهای پس زمینه و ترد اصلی در iOS جابجا شوند.

برای تسلط بر اپراتورهای پیشرفته کورتین و جریان های واکنشی، حتماً راهنمای مدیریت همزمانی در کاتلین با کورتین ها را مطالعه نمایید.

پیشنهاد مطالعه
آموزش جامع Jetpack Compose برای توسعه رابط کاربری اندروید
آموزش جت پک کامپوز Jetpack Compose در اندروید؛ معماری رابط کاربری اعلانی، مدیریت State و جریان UDF، فازهای Recomposition، ناوبری تایپ سیف و نمونه کده…
مشاهده مقاله ←

۹. لایه رابط کاربری: مقایسه Compose Multiplatform با نوشتن SwiftUI نیتیو

یکی از تصمیم های استراتژیک در پروژه های KMP، نحوه پیاده سازی لایه UI است. شما دو مسیر کلی در پیش رو دارید:

  • مسیر اول (اشتراک گذاری تا لایه ViewModel): لایه های دیتا و بیزینس مشترک هستند اما UI اندروید با Jetpack Compose و UI آی او اس با SwiftUI به طور کاملاً مستقل نوشته می شود. این مسیر برای اپلیکیشن هایی با استانداردهای طراحی انسانی به شدت سخت گیرانه در iOS به شدت پیشنهاد می شود.
  • مسیر دوم (Compose Multiplatform): استفاده از فریمورک رسمی JetBrains Compose Multiplatform که در آن حتی کدهای Composable رابط کاربری نیز به صورت صد در صد مشترک نوشته شده و روی Canvas بومی iOS رندر می شوند.

در رویکرد دوم، شرکت JetBrains با بهره گیری از کامپایلر اسکیا و متال در iOS توانسته عملکرد رندرینگ کامپوز را به ۶۰ و ۱۲۰ فریم بر ثانیه برساند. این ویژگی به ویژه برای ساخت صفحات تنظیمات، فرم های ورود و داشبوردهای اطلاعاتی مشترک سرعت توسعه را دوچندان می کند.

توصیه تجربی معماران موبایل: برای اپلیکیشن های سازمانی با منطق سنگین (فین تک، رزرو آنلاین، شبکه های اجتماعی)، رویکرد اول یعنی اشتراک گذاری لایه بیزینس و نگارش UI مجزا با Compose و SwiftUI بالاترین رضایت کاربری و کمترین اصطکاک را در هر دو اکوسیستم به همراه دارد.

۱۰. پروژه عملی: پیاده سازی الگوی ریپازیتوری آفلاین در کاتلین مولتی پلتفرم

برای مشاهده کاربرد عملی این استانداردها، یک ریپازیتوری تبادل اطلاعات محصول را با ترکیب کلاینت Ktor و مدیریت وضعیت پیاده سازی می کنیم:

بخش اول: تعریف مدل داده سریالایز پذیر در commonMain

import kotlinx.serialization.Serializable

@Serializable
data class ProductDto(
    val id: Long,
    val title: String,
    val price: Double
)

بخش دوم: پیاده سازی رابط ریپازیتوری مشترک

import kotlinx.coroutines.flow.Flow

interface ProductRepository {
    fun getProductListStream(): Flow<List<ProductDto>>
    suspend fun refreshRemoteProducts()
}

بخش سوم: پیاده سازی عملیات شبکه و کش داده ها

import io.ktor.client.HttpClient
import io.ktor.client.call.body
import io.ktor.client.request.get
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.flow

class DefaultProductRepository(
    private val client: HttpClient
) : ProductRepository {
    override fun getProductListStream(): Flow<List<ProductDto>> = flow {
        // شبیه سازی خواندن سریع از دیتابیس محلی
        emit(emptyList())
    }

    override suspend fun refreshRemoteProducts() {
        val remoteList: List<ProductDto> = client.get("https://api.example.com/products").body()
        // ذخیره سازی اتمیک در دیتابیس محلی مشترک
    }
}

این ساختار به گونه ای طراحی شده است که در صورت عدم دسترسی به شبکه اینترنت، بلافاصله آخرین نسخه کش شده از دیتابیس محلی به لایه رابط کاربری ارسال می شود و به محض بازگشت اتصال، دیتای به روز جایگزین می گردد.

همچنین برای سریالایز کردن پاسخ های چندشکلی (Polymorphic JSON) و مدل های پیچیده، کتابخانه kotlinx.serialization امکان تعریف کلاس های مهر و موم شده (Sealed Classes) را فراهم می کند. کامپایلر با استفاده از فیلد کلیدی type به طور خودکار نوع شیء دریافتی از سرور را تشخیص می دهد و نیازی به نوشتن مبدل های دستی در هر پلتفرم نخواهد بود.

این رویکرد تضمین می کند که حتی در زمان تغییرات گسترده در API های بک اند، هر دو نسخه اندروید و iOS بدون مغایرت تایپ داده ها را تحلیل کنند و پایداری عملکردی برنامه در بلندمدت حفظ شود.

۱۱. آزمون های خودکار و تست نویسی در کاتلین مولتی پلتفرم

یکی از مزایای بی نظیر KMP این است که شما می توانید تست های واحد منطق بیزینس و اعتبارسنجی را یک بار درون commonTest بنویسید و این تست ها در خط لوله CI/CD روی هر دو محیط شبیه ساز اندروید و ابزار های تست iOS به طور همزمان ارزیابی شوند.

// commonTest/ProductRepositoryTest.kt
import kotlin.test.Test
import kotlin.test.assertEquals
import kotlin.test.assertTrue

class ProductRepositoryTest {
    @Test
    fun productDto_parsesSuccessfully() {
        val sample = ProductDto(id = 101, title = "گوشی موبایل", price = 890.0)
        assertEquals(101, sample.id)
        assertTrue(sample.price > 0)
    }
}

تست های چند سکویی تضمین می کنند که هرگونه تغییر در قوانین مالی یا الگوریتم های رمزنگاری برنامه در هر دو پلتفرم نتایج کاملاً یکسانی تولید کند، بدون اینکه نیازی به هماهنگی دستی مداوم میان تیم های اندروید و iOS باشد.

برای پیاده سازی تست های ساختار یافته تر با فریمورک های Mocking، مطالعه راهنمای آموزش تست نویسی در اندروید با MockK را توصیه می کنیم.

۱۲. استراتژی مهاجرت تدریجی اپلیکیشن های فعال سازمانی به KMP

بر خلاف سایر فناوری ها که شما را وادار به بازنویسی کامل پروژه از صفر می کنند، یکی از برگ های برنده کاتلین مولتی پلتفرم امکان ادغام تدریجی در پروژه های بزرگ موجود است.

تیم های مهندسی محصول معمولاً فرآیند مهاجرت را با استخراج یک ماژول کوچک مستقل (مانند ماژول احراز هویت یا مدیریت توکن های امنیتی) آغاز می نمایند. پس از آزمایش موفقیت آمیز در پروداکشن، لایه شبکه و در نهایت کل دیتابیس مشترک سازی می شوند.

شرکت های بین المللی بزرگی مانند Netflix، Cash App، VMware و McDonald's با این رویکرد توانسته اند هزینه های نگه داری محصولات موبایل خود را به شدت کاهش داده و زمان عرضه ویژگی های جدید را به نصف تقلیل دهند.

کلید موفقیت در این انتقال، حفظ ارتباط سازنده میان توسعه دهندگان اندروید و iOS است. برنامه نویسان سوییفت با دیدن اینکه کدهای مشترک به صورت فریمورک استاندارد سوییفت ظاهر می شوند و هیچ محدودیتی در طراحی رابط کاربری بومی ایجاد نمی کنند، به سرعت به حامیان اصلی معماری KMP در سازمان تبدیل می گردند.

نکته معماری اشتراک کد در KMP: با معرفی مدل مدیریت حافظه جدید کاتلین نیتیو، چالش های قدیمی اشتراک اشیاء میان تردها به طور کامل برطرف شده است. با این حال برای اجرای فوق العاده سریع و روان کدهای همزمانی در پلتفرم iOS، توصیه می شود همیشه از Dispatchers.Default در ماژول های منطقی مشترک استفاده کرده و سوییچ به ترد اصلی را از طریق Dispatchers.Main مستقیماً به لایه نمایش رابط کاربری واگذار نمایید تا از قفل شدن ترد اصلی جلوگیری گردد.

پرسش های متداول و جمع بندی کاتلین مولتی پلتفرم در اندروید

آیا برای توسعه بخش iOS در کاتلین مولتی پلتفرم داشتن مک بوک الزامی است؟

بله، برای کامپایل کدهای مربوط به تارگت iOS و اجرای شبیه ساز Xcode، سیستم عامل macOS و ابزار های شرکت اپل الزامی هستند. البته شما می توانید کدهای مشترک کاتلین را در محیط ویندوز یا لینوکس توسعه داده و برای کامپایل نهایی نسخه iOS از سرور هایی ابری CI/CD مانند GitHub Actions بهره بگیرید.

تفاوت اصلی Kotlin Multiplatform (KMP) با Kotlin Multiplatform Mobile (KMM) چیست؟

در گذشته شرکت JetBrains اصطلاح KMM را برای تمرکز روی دو سکوی اندروید و iOS به کار می برد. اما با بلوغ فناوری و گسترش دامنه به وب و دسکتاپ، نام رسمی کل اکوسیستم به Kotlin Multiplatform (KMP) تغییر یافت که کل سکوها را به صورت یکپارچه پوشش می دهد.

آیا کدهای کاتلین در iOS باعث کاهش سرعت یا افزایش حجم فایل نهایی برنامه می شوند؟

خیر، کدهای کاتلین توسط کامپایلر LLVM مستقیماً به باینری ماشین آرم نیتیو کامپایل می شوند. سربار حجم فریمورک مشترک در نسخه نهایی حدود ۱ الی ۲ مگابایت است که در مقایسه با فریمورک های هیبریدی نظیر فلاتر بسیار سبک تر است.

آیا برنامه نویسان سوییفت در iOS می توانند از کدهای کاتلین استفاده کنند؟

بله، ماژول مشترک KMP در قالب یک Framework استاندارد سی یا آبجکتیو سی اکسپورت می شود. برنامه نویسان iOS می توانند کلاس ها و توابع کاتلین را همانند کدهای کتابخانه های سوییفت درون پروژه های Xcode فراخوانی کنند.

چگونه می توان بین Ktor و Retrofit در کاتلین مولتی پلتفرم انتخاب کرد؟

کتابخانه Retrofit وابسته به ماشین مجازی جاوا است و در پلتفرم iOS اجرا نمی شود. بنابراین در ماژول های مشترک KMP تنها باید از کتابخانه رسمی Ktor Client استفاده کنید.

بهترین ابزار برای مدیریت تزریق وابستگی در KMP چیست؟

کتابخانه محبوب Koin به دلیل پیاده سازی خالص با کاتلین و بدون نیاز به تولید کد زمان کامپایل، مناسب ترین و پرکاربردترین فریمورک تزریق وابستگی در پروژه های چند سکویی KMP محسوب می شود.

آیا کاتلین مولتی پلتفرم برای اپلیکیشن های آماده پروداکشن به پایداری کامل رسیده است؟

بله، شرکت JetBrains رسماً در نوامبر ۲۰۲۳ پایداری کامل (Stable) هسته کاتلین مولتی پلتفرم را اعلام کرد و هم اکنون در صدها اپلیکیشن مطرح بین المللی با صدها میلیون کاربر به طور فعال در محیط پروداکشن در حال سرویس دهی است.

چگونه می توان رویدادهای ناهمگام Flow کاتلین را در سوییفت مدیریت کرد؟

ابزار های کمکی پیشرفته نظیر کتابخانه SKIE و KMP-NativeCoroutines کدهای StateFlow و SharedFlow کاتلین را به صورت خودکار به AsyncSequence و Combine بومی سوییفت نگاشت می دهند تا توسعه دهنده iOS از کدهای مدرن async/await بهره ببرد.

چک لیست نهایی و نکات کلیدی انتشار پروژه های کاتلین مولتی پلتفرم

چک لیست بازبینی کیفیت پیش از انتشار (Production Checklist): پیکربندی تارگت های اندروید و iOS در گریدل، پیاده سازی دقیق متناظر expect/actual، استفاده از کلاینت Ktor با موتورهای پلتفرمی OkHttp و Darwin، تفکیک لایه های دیتا و دامنه در commonMain، بهره گیری از StateFlow برای مخابره واکنشی دیتا و نوشتن تست های واحد در commonTest.

امتیاز و نظرات

۰.۰ (۰ نظر)
برای ثبت دیدگاه باید وارد حساب کاربری شوید. ورود

هنوز نظری ثبت نشده است. اولین نفر باشید.