Birleştirme
- Kotlin kursu
- İleri seviye
- Ders 83/83
- 6 dk
Tüm katmanları birleştirerek çalışan bir mini servis yazarsın.
Birleştirme: API + DB + coroutines
Son ders tüm parçaları birleştirir. UserRepo suspend metotlarla veri yönetir, UsersTable veriyi saklar, Api suspend route ile yol yönlendirir, main runBlocking ile çağrılır.
Bu yapı, Ktor API + Exposed DB + coroutines desenini küçük çapta bir araya getirir. Artık repoya bir kullanıcı ekleyip API üzerinden suspend erişebilirsin. Bu kalıp, üretim Kotlin backend'lerinin temelidir.
Proje yapısı
Projenin son hali dört katman içerir. User veri sınıfı en altta; UsersTable onu saklar; UserRepo iş mantığını sarar; Api dışarıdan gelen yolları repoya yönlendirir.
Tüm suspend metotlar runBlocking içinde çağrılır. Bu ayrım, her katmanı bağımsız test etmeyi ve ileride gerçek DB'ye geçişi kolaylaştırır. Beşinci ders, bu akışın çalıştığını bir main çağrısıyla gösterir.
Uygulama Final: tüm parçaları birleştir
Mevcut tüm tanımları koru. main içinde repo.save(User(1, "Ayşe")) ile kullanıcı ekle, val api = Api(repo) oluştur ve println(api.route("/users/1")) yazdır. main runBlocking ile acilmalı.
Başlangıç kodu
import kotlinx.coroutines.runBlocking
data class User(val id: Int, val name: String)
object UsersTable {
val rows = mutableListOf<User>()
fun insert(u: User) { rows.add(u) }
fun select(id: Int): User? = rows.find { it.id == id }
}
class UserRepo {
suspend fun save(u: User) { UsersTable.insert(u) }
suspend fun find(id: Int): User? = UsersTable.select(id)
}
class Api(val repo: UserRepo) {
suspend fun route(path: String): String {
return when {
path.startsWith("/users/") -> {
val id = path.removePrefix("/users/").toInt()
repo.find(id)?.name ?: "not found"
}
else -> "404"
}
}
}
// main = runBlocking: User ekle, Api oluştur, /users/1 yazdırÖrnek çözüm
import kotlinx.coroutines.runBlocking
data class User(val id: Int, val name: String)
object UsersTable {
val rows = mutableListOf<User>()
fun insert(u: User) { rows.add(u) }
fun select(id: Int): User? = rows.find { it.id == id }
}
class UserRepo {
suspend fun save(u: User) { UsersTable.insert(u) }
suspend fun find(id: Int): User? = UsersTable.select(id)
}
class Api(val repo: UserRepo) {
suspend fun route(path: String): String {
return when {
path.startsWith("/users/") -> {
val id = path.removePrefix("/users/").toInt()
repo.find(id)?.name ?: "not found"
}
else -> "404"
}
}
}
fun main() = runBlocking {
val repo = UserRepo()
repo.save(User(1, "Ayşe"))
val api = Api(repo)
println(api.route("/users/1"))
}Beklenen çıktı
Ayşe
Soru ve cevaplar
Dersin sorularını cevaplarıyla birlikte inceleyebilirsin. Kendini denemek istersen dersi interaktif olarak çöz.
1 Bu projede main neden runBlocking ile açılır?
- Çünkü daha hızlıdır
- Çünkü suspend fonksiyonlar çağrılır Doğru cevap
- Çünkü test zorunludur
- Çünkü derleme hatası verir
Açıklama: runBlocking suspend fonksiyonlar için scope açar.
2 Proje parçalarını eşle
| Kavram | Anlamı |
|---|---|
UserRepo |
İş mantığı |
UsersTable |
Veri katmanı |
Apı |
Yönlendirme |
runBlocking |
Coroutine scope |
3 route çağrısını tamamla
val api = Api(repo)
println(api.____("/users/1"))
val api = Api(repo)
println(api.route("/users/1"))
Açıklama: api.route bir yolu yorumlar.