Kotlin Academy · Ders

Repository ve Use Case Katmanlarını Paylaşma

Maksimum yeniden kullanım için iş mantığını ve veri erişimini commonMain'e taşıyın.

3. ders / 413 adım

Repository ve Use Case Katmanlarını Paylaşma, CoddyKit'te ücretsiz bir Kotlin Academy dersidir. Bu, 4 dersinin 3. dersidir. Aşağıdan dersin tamamını ücretsiz okuyabilir, sonra tarayıcıda yerleşik kod editörü ve 7/24 yapay zeka koçu ile uygulamalı olarak pratik yapabilirsin. Bu, Kotlin Academy öğrenme yolunun bir parçasıdır ve ilerlemeniz web ve CoddyKit uygulaması arasında senkronize olur. Kotlin Academy kursu toplamda 4 dersten oluşur.

Mimari Hedef

KMP'de amaç, mümkün olduğunca fazla mantığı commonMain'e taşımaktır: alan modelleri, depo arayüzleri, kullanım senaryoları ve ViewModels. Yalnızca platform G/Ç işlemleri platform kaynak kümelerinde kalır.

// Target architecture:
// commonMain:
//   domain/    - data classes, interfaces
//   data/      - repository implementations using shared clients
//   usecase/   - business logic, composing repositories
// androidMain / iosMain:
//   DI wiring, platform drivers (DB, network)

commonMain'de Alan Katmanı

Alan varlıklarını ve depo arayüzlerini commonMain'de tanımlayın. Platform içe aktarmaları kullanmayın.

// commonMain/domain/User.kt
data class User(val id: String, val name: String, val email: String)

// commonMain/domain/UserRepository.kt
interface UserRepository {
    suspend fun getUser(id: String): User?
    suspend fun getAllUsers(): List<User>
    suspend fun saveUser(user: User)
}

Ktor ile Paylaşılan Depo Uygulaması

Depoyu çoklu platform desteğine sahip Ktor istemcisini kullanarak commonMain'de uygulayın. Gerçek HTTP altyapısı platforma göre sağlanır.

// commonMain/data/RemoteUserRepository.kt
import io.ktor.client.*
import io.ktor.client.call.*
import io.ktor.client.request.*
class RemoteUserRepository(private val client: HttpClient) : UserRepository {
    override suspend fun getUser(id: String): User? =
        client.get("https://api.example.com/users/$id").body()
    override suspend fun getAllUsers(): List<User> =
        client.get("https://api.example.com/users").body()
    override suspend fun saveUser(user: User) {
        client.post("https://api.example.com/users") { setBody(user) }
    }
}

Kullanım Senaryosu Katmanı

Kullanım senaryoları (etkileşimciler), depoları düzenler ve iş mantığını içerir. Platform bağımlılığı olmayan saf Kotlin kodudur.

// commonMain/usecase/GetUserUseCase.kt
class GetUserUseCase(private val repo: UserRepository) {
    suspend operator fun invoke(id: String): Result<User> =
        runCatching { repo.getUser(id) ?: error("User not found: $id") }
}

// commonMain/usecase/SaveUserUseCase.kt
class SaveUserUseCase(private val repo: UserRepository) {
    suspend operator fun invoke(user: User): Result<Unit> =
        runCatching { repo.saveUser(user) }
}

Paylaşılan ViewModel

ViewModels, kotlinx-coroutines ve StateFlow kullanılarak commonMain'de bulunabilir. Android bunu doğrudan kullanır; iOS ise SwiftUI içinde sarmalar.

// commonMain/viewmodel/UserViewModel.kt
import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*
class UserViewModel(private val getUser: GetUserUseCase) {
    private val scope = CoroutineScope(Dispatchers.Main + SupervisorJob())
    private val _user = MutableStateFlow<User?>(null)
    val user = _user.asStateFlow()
    fun load(id: String) {
        scope.launch { _user.value = getUser(id).getOrNull() }
    }
    fun clear() = scope.cancel()
}

Ktor HttpClient Yapılandırması

Ktor HttpClient'i paylaşılan yapılandırmayla commonMain'de oluşturun. Altyapı (OkHttp / Darwin), platforma göre sağlanır veya oluşturulur.

// commonMain/network/HttpClientFactory.kt
import io.ktor.client.*
import io.ktor.client.plugins.contentnegotiation.*
import io.ktor.serialization.kotlinx.json.*
fun createHttpClient(engine: io.ktor.client.engine.HttpClientEngine? = null) =
    HttpClient(engine ?: io.ktor.client.engine.cio.CIO) {
        install(ContentNegotiation) { json() }
    }

Paylaşılan Kalıcılık için SQLDelight

SQLDelight, commonMain'deki .sq dosyalarından tüm platformlar için tür güvenli Kotlin sorguları oluşturur. Gerçek veritabanı sürücüsü platforma özgüdür.

// commonMain/db/UserQueries.sq:
// CREATE TABLE User (id TEXT NOT NULL PRIMARY KEY, name TEXT NOT NULL);
// selectAll:
// SELECT * FROM User;

// Usage in commonMain:
// val db = UserDatabase(driver)
// val users = db.userQueries.selectAll().executeAsList()

Platform DI Bağlantısı

Her şeyi platforma özgü bir DI modülünde birbirine bağlayın. Arayüz ortaktır; yalnızca kurucu bağımsız değişkenleri farklıdır.

// androidMain:
val androidModule = module {
    single { AndroidSqliteDriver(UserDatabase.Schema, androidContext(), "users.db") }
    single { UserDatabase(get()) }
    single<UserRepository> { RemoteUserRepository(get()) }
    single { GetUserUseCase(get()) }
    viewModel { UserViewModel(get()) }
}

// iosMain:
// Same pattern with NativeSqliteDriver

commonTest'te Kullanım Senaryolarını Test Etme

Kullanım senaryolarının platform bağımlılığı yoktur; bu nedenle commonTest içinde sahte bir depoyla birim testine uygundur.

// commonTest/usecase/GetUserUseCaseTest.kt
import kotlin.test.Test
import kotlin.test.assertEquals
class FakeUserRepo : UserRepository {
    override suspend fun getUser(id: String) = if (id == "1") User("1", "Alice", "a@b.com") else null
    override suspend fun getAllUsers() = emptyList<User>()
    override suspend fun saveUser(user: User) {}
}
class GetUserUseCaseTest {
    private val useCase = GetUserUseCase(FakeUserRepo())
    @Test
    fun testGetExistingUser() = kotlinx.coroutines.runBlocking {
        val result = useCase("1")
        assertEquals("Alice", result.getOrNull()?.name)
    }
}

Kullanım Senaryolarında Hata Yönetimi

Paylaşılan kod ile platform sınırını aşan istisnalar olmadan hataları iletmek için kullanım senaryolarından Result veya mühürlü sınıf döndürün.

// commonMain:
sealed class UserResult {
    data class Success(val user: User) : UserResult()
    data class NotFound(val id: String) : UserResult()
    data class Error(val cause: Throwable) : UserResult()
}
class SafeGetUser(private val repo: UserRepository) {
    suspend operator fun invoke(id: String): UserResult = try {
        val user = repo.getUser(id)
        if (user != null) UserResult.Success(user) else UserResult.NotFound(id)
    } catch (e: Exception) { UserResult.Error(e) }
}

Platform Özgü Yaklaşımlardan Ödün Vermeden Paylaşım

Kullanıcı arayüzünü değil, mantığı paylaşın. Android Compose'u, iOS ise SwiftUI'yi kullanır. Her ikisi de platforma özgü bağlamalar aracılığıyla aynı paylaşılan ViewModel durumunu gözlemler.

// Android (Compose):
// val user by viewModel.user.collectAsState()

// iOS (SwiftUI):
// @State var user = viewModel.user.value
// viewModel.load(id: "1")

// Shared ViewModel:
// _user.value = ... (commonMain)
fun main() { println("Share logic; use platform UI frameworks") }

Hızlı Kontrol

İyi yapılandırılmış bir KMP projesinde hangi katmanda platforma özgü içe aktarmalar bulunmamalıdır?

Özet

Alan modellerini, depo arayüzlerini, kullanım senaryolarını ve paylaşılan ViewModels'ı commonMain'e yerleştirin. Ktor'u (ağ) ve SQLDelight'ı (veritabanı), DI katmanında platform altyapıları sağlanacak şekilde kullanın. İş mantığını commonTest'te sahte depolarla test edin.

Başlamak ücretsiz

Yapay zeka eğitmeniyle Kotlin öğren — ücretsiz

Tarayıcında gerçek kod yaz ve çalıştır, 7/24 yapay zeka eğitmeninden anında yardım al; web'de ya da uygulamada kaldığın yerden devam et.

Kurslar
51
Dersler
203

Sıkça Sorulan Sorular

“Repository ve Use Case Katmanlarını Paylaşma” dersi ücretsiz mi?

Evet — “Repository ve Use Case Katmanlarını Paylaşma” dersin tüm metni burada web'de ücretsiz olarak okunabilir. Etkileşimli olarak pratik yapmak (yerleşik kod editörü ve 7/24 yapay zeka koçu) ve Kotlin Academy kursunun geri kalanını açmak için CoddyKit PRO'ya yükselt. Kotlin Academy kursu toplamda 4 dersten oluşur.

“Repository ve Use Case Katmanlarını Paylaşma” dersinde ne öğreneceğim?

Maksimum yeniden kullanım için iş mantığını ve veri erişimini commonMain'e taşıyın. Kotlin Academy ile uygulamalı kodu tarayıcıda doğrudan çalıştırarak pratik yaparsın ve 7/24 yapay zeka koçu dersi çalışırken sorularını yanıtlar.

Kotlin Academy öğrenmeye başlamak için deneyim gerekli mi?

Önceden deneyim gerekmez. CoddyKit'te Kotlin Academy, başlangıçtan ileri seviyeye kadar yapılandırıldığı için buradan başlayabilir veya başından başlayıp kendi hızında ilerleme yapabilirsin. Bu, 4 dersinin 3. dersidir.

“Repository ve Use Case Katmanlarını Paylaşma” dersi ne kadar sürer?

Çoğu CoddyKit dersi yaklaşık 5–10 dakika sürer. Her biri kısa ve etkileşimli olduğu için sabit ilerleme yaparsın ve web ile uygulama arasında tam olarak bıraktığın yerden devam edebilirsin.

Bu Kotlin Academy dersinde kod yazıp çalıştırabilir miyim?

Evet. Her Kotlin Academy dersi yerleşik bir kod editörü içerir, bu sayede tarayıcıda gerçek kod yazıp çalıştırabilir ve anlık yapay zeka geri bildirimi alırsın — yerel kurulum gerekli değildir.

Bu kursun tüm dersleri

  1. KMP Proje Yapısı: commonMain, androidMain, iosMain
  2. Platform API'leri için expect/actual Mekanizması
  3. Repository ve Use Case Katmanlarını Paylaşma
  4. KMP'de Koin ile Bağımlılık Enjeksiyonu
← Kotlin Academy Sayfasına Dön