---
title: 'Uzaktan Yapılandırma'
source: 'https://academia.sh/tr/kurslar/android-servisler/uzaktan-yapilandirma'
course: 'Platform Servisleri ve Tümleştirmeler'
language: tr
updated: '2026-10-21T05:02:41+00:00'
license: 'CC BY-SA 4.0'
objectives:
    - 'Getirme ile etkinleştirme adımlarını ayırır'
    - 'Etkinleştirmeden önce iki kez getirilen aynı anahtarın son değerinin kazandığını ölçer'
    - 'Getirilip etkinleştirilmeyen değerin kayıp olduğunu gösterir'
    - 'Uygulama içi varsayılanın teslim sayılmadığını açıklar'
---

# Uzaktan Yapılandırma

Uzaktan yapılandırmada uygulama sunucudan değerleri getirir ve ayrı bir adımda etkinleştirir. Ders etkinleştirmeden önce iki kez getirilen aynı anahtarın son değerinin kazanmasını, ilk değerin ezilmesini ve getirilip etkinleştirilmeyen değerin kayıp olduğunu ölçer.

Önceki derste olaylar sunucuya gitti. Bu derste yön tersine döner: sunucu uygulamaya bir değer gönderir, örneğin bir özelliğin açık mı kapalı mı olduğunu ya da bir üst sınırı. Böylece davranış, yeni sürüm yayımlanmadan değişir. Değer iki adımda uygulamaya girer: önce getirilir, sonra etkinleştirilir. Soru kursun sorusudur: **gönderilen bu olay alıcıya kaç kopya olarak ulaştı?** Burada olay bir yapılandırma değeridir, alıcı çalışan uygulamadır.

```kotlin
// Arrival.kt — gonderilen bir olayin aliciya kac kopya olarak ulastigini siniflandirir
class Signal(val key: String, val seq: Int)

class Arrival(val label: String, val sent: Signal, received: List<Signal>) {
    val copies: Int = received.count { it.seq == sent.seq }
    val verdict: String = when {
        copies > 1 -> "yinelenen"
        copies == 1 -> "birebir"
        received.any { it.key == sent.key && it.seq > sent.seq } -> "ezilen"
        else -> "kayip"
    }

    fun line() {
        println("$label: anahtar=${sent.key} | kopya=$copies -> $verdict")
    }
}

fun countArrivals(arrivals: List<Arrival>) {
    for (name in listOf("birebir", "yinelenen", "ezilen", "kayip")) {
        println("$name: ${arrivals.count { it.verdict == name }}")
    }
}
```

## Getirme ve Etkinleştirme

**Getirme**, değerin sunucudan alınıp aygıtta bekletilmesidir; uygulama onu henüz okumaz. **Etkinleştirme**, bekleyen değerin uygulamanın okuduğu değer olmasıdır. İki adımın ayrı olmasının nedeni, ekranda çalışan bir özelliğin değerinin ortasında değişmemesidir. Etkinleştirme uygun bir anda, örneğin bir sonraki açılışta yapılır.

Platformda bu ayrımın en yalın karşılığı, değeri bir yerde bekletip sonra uygulamanın okuduğu depoya yazmaktır.

```kotlin
// Platform kodu: SharedPreferences
val pending = context.getSharedPreferences("bekleyen", Context.MODE_PRIVATE)
val active = context.getSharedPreferences("etkin", Context.MODE_PRIVATE)
pending.edit().putString("ayar.tema", "koyu").apply()
active.edit().putString("ayar.tema", pending.getString("ayar.tema", null)).apply()
```

Bu parça platform kodudur ve burada çıktı, süre ya da sayı iddia etmiyoruz. Model, platformun bu kuralını kurar; model platformun kendisi değildir. Getirme sıklığını ve etkinleştirme anını platform ya da kullanılan çerçeve belirler; modelde ikisi de bir listedir.

Modelde getirilen değerler sıralı bir listedir. Etkinleştirme, her anahtar için listedeki son değeri seçer. Aynı anahtarın daha eski bir değeri, ayrı bir anahtarı etkilemez.

```kotlin
// Config.kt — etkinlestirme her anahtar icin getirilen son degeri secer
fun activateLatest(fetched: List<Signal>): List<Signal> =
    fetched.groupBy { it.key }.map { (_, values) -> values.maxBy { it.seq } }

fun activateUpTo(fetched: List<Signal>, count: Int): List<Signal> =
    activateLatest(fetched.take(count))
```

```kotlin
// Probe.kt — gonderilen degerler icin uygulamanin okudugu listeyi alici sayar
fun probe(sent: List<Signal>, received: List<Signal>): List<Arrival> =
    sent.mapIndexed { i, s -> Arrival("olay-${i + 1}", s, received) }
```

## Her Anahtar Bir Kez Getirilirse

Üç ayrı anahtar bir kez getirilir ve etkinleştirilir: tema, bir üst sınır ve bir özellik bayrağı.

```kotlin
// Main.kt — her anahtar bir kez getirilirse hepsi etkinlesir
fun main() {
    val theme = Signal("ayar.tema", 1)
    val limit = Signal("ayar.limit", 2)
    val flag = Signal("ayar.bayrak", 3)
    val sent = listOf(theme, limit, flag)
    val arrivals = probe(sent, activateLatest(sent))
    arrivals.forEach { it.line() }
    countArrivals(arrivals)
}
```

```text
olay-1: anahtar=ayar.tema | kopya=1 -> birebir
olay-2: anahtar=ayar.limit | kopya=1 -> birebir
olay-3: anahtar=ayar.bayrak | kopya=1 -> birebir
birebir: 3
yinelenen: 0
ezilen: 0
kayip: 0
```

Üç değerin üçü birer kopya olarak uygulamaya ulaştı. Hiçbir anahtar yarışmadı.

## Etkinleştirmeden Önce İki Kez Getirilirse

Şimdi tema değeri, etkinleştirme gelmeden önce iki kez getirilir: ilkinde açık tema, ikincisinde koyu tema. Sunucu arada değeri değiştirmiştir.

```kotlin
// Main.kt — ayni anahtar iki kez getirilirse son deger kazanir
fun main() {
    val first = Signal("ayar.tema", 1)
    val second = Signal("ayar.tema", 2)
    val limit = Signal("ayar.limit", 3)
    val sent = listOf(first, second, limit)
    val arrivals = probe(sent, activateLatest(sent))
    arrivals.forEach { it.line() }
    countArrivals(arrivals)
}
```

```text
olay-1: anahtar=ayar.tema | kopya=0 -> ezilen
olay-2: anahtar=ayar.tema | kopya=1 -> birebir
olay-3: anahtar=ayar.limit | kopya=1 -> birebir
birebir: 2
yinelenen: 0
ezilen: 1
kayip: 0
```

Bu dersin teslimi: ezilen. İlk tema değeri uygulamaya hiç ulaşmadı; aynı anahtarın daha büyük sıralı ikinci değeri onun yerini aldı. Kural nedeni görmez: ilk değerin yanlış olduğunu ya da ikincisinin düzeltme olduğunu bilmez, yalnızca aynı anahtarla daha yeni bir değerin ulaştığını görür. Önceki derslerdeki yinelenenle bir fark vardır: orada aynı olayın birden çok kopyası ulaşıyordu, burada ilk değerin hiçbir kopyası ulaşmadı.

Bu davranış yapılandırma için çoğunlukla istenendir. Uygulamanın ihtiyacı en güncel değerdir; eski değeri görmek bir kazanç sayılmaz. Bedeli, ilk değerin sıfır kopyayla geçmesidir; ilk değeri bir sayaca ya da bir deneye bağlayan taraf onun hiç uygulanmadığını bilmelidir.

**GD1.** Model, sıralı numaraları getirme anına göre doğru verilmiş varsayar. Platformda iki getirmenin sırası ağ gecikmesiyle karışabilir ve sunucudan gelen sürüm bilgisi bunun için kullanılır; modelde bu bilgi doğrudan sıralı numaradır.

**GD2.** Model, etkinleştirmeyi tek bir anda yapar ve bekleyen tüm değerleri birlikte etkinleştirir. Platformda etkinleştirme yarıda kalabilir ya da bazı anahtarlar sonraya bırakılabilir.

## Getirme Döngüsü

Uzaktan yapılandırma, tek bir istekle bitmez; bir döngüdür. Uygulama belli aralıklarla sunucuya sorar, sunucu o anki değerleri döner, uygulama değerleri bekleyen depoya yazar. Döngünün her turu bir getirmedir ve her tur öncekinden bağımsızdır: sunucu bu turda hangi değeri dönerse onu alır, uygulama önceki turda ne aldığını sunucuya söylemek zorunda değildir.

Bu bağımsızlığın bir sonucu vardır. İki tur arasında sunucudaki değer değiştiyse, bekleyen depoda aynı anahtar için iki değer birikebilir. Etkinleştirme henüz yapılmadığı için hiçbiri uygulamanın okuduğu değer değildir. Döngü getirdiği sürece bekleyen liste büyür ve uygulamanın gördüğü tek şey, etkinleştirmenin o an bıraktığı değerdir.

Getirme sıklığının neden sınırlandığı da buradan çıkar. Her tur bir ağ isteğidir; çok sık sormak pili ve ağı yorar, çok seyrek sormak da değişikliğin geç ulaşmasına yol açar. Modelde bu denge yoktur, çünkü model zamanı hiç taşımaz: getirilen değerler sıralı bir listedir ve iki tur arasındaki bekleme görünmez.

## Ezilen ve Kayıp Arasındaki Çizgi

İki sonucun arasındaki çizgi ince ama kesindir. Ezilen, değerin kopyası ulaşmadan aynı anahtarı taşıyan daha sonraki bir değerin ulaşıp onun yerini aldığını söyler; uygulamanın en güncel değerde olduğunu söylemez. Kayıp ise uygulamanın sunucunun son kararına ulaşamadığını söyler; uygulama daha eski bir değerle ya da varsayılanla çalışıyordur. Bir yayımlayan için ilki çoğu zaman beklenen bir sonuçtur, ikincisi izlenmesi gereken bir durumdur.

Bu yüzden iki sayıyı ayrı raporlamak gerekir. Ezilen sayısının yüksekliği sunucunun hızlı değiştiğini, kayıp sayısının yüksekliği ise etkinleştirmenin geride kaldığını gösterir. Tek bir "ulaşmayan değer" sayısına indirilirse iki farklı sorun aynı rakamda saklanır.

## Ölçümde Neyi Saymıyoruz

Kuralın görmediği şeyler, yapılandırma için en az kuraldaki kadar önemlidir. Kural bir değerin uygulamaya ulaşıp ulaşmadığını söyler; uygulamanın o değeri doğru kullandığını söylemez. Etkinleşmiş bir bayrak, bayrağı okuyan kod hatalıysa yine bir şey açmaz. Kural bir değerin ezilmesini ya da kaybolmasını işaretler, ama değerin sunucuda neden değiştirildiğini bilmez.

Bu sınırlar ölçümü zayıflatmaz, kapsamını gösterir. Ders tek bir soruyu yanıtlar: sunucunun gönderdiği değer uygulamanın okuduğu değer oldu mu. Değerin doğru olup olmadığı, doğru zamanda etkinleşip etkinleşmediği ve kullanıcıya ne gösterdiği başka sorulardır.

## Değer Ne Zaman Etkinleşir

Etkinleştirmenin zamanı, hangi değerin uygulamaya ulaşacağını belirler. Etkinleştirme bir önceki turdan hemen sonra yapılırsa her getirilen değer etkinleşir ve ezilen hiç oluşmaz; her tur sonunda tek bir değer vardır. Etkinleştirme birkaç tur sonra yapılırsa aynı anahtar için birikmiş değerlerden yalnız sonuncusu etkinleşir, öncekiler ezilir. Etkinleştirme hiç yapılmazsa hepsi kayıp kalır.

Yani ezilen, yapılandırmada bir hata değil, etkinleştirmenin geciktirilmesinin doğal sonucudur. Etkinleştirme uygulamanın bir sonraki açılışına bırakıldığında, açılışa kadar getirilen değerlerin sonuncusu kazanır. Aynı etkinleştirme noktası değişir, sonuç değişir: model bunu `activateUpTo` işlevinin `count` parametresiyle taklit eder. Etkinleştirmenin kaç değeri kapsadığı, bekleyen listede nerede durduğuna göre ezileni ya da kaybı üretir.

Bir anahtar üç kez getirilir, ardından başka bir anahtar gelir ve etkinleştirme yalnız ilk ikisini kapsar.

```kotlin
// Main.kt — etkinlestirme noktasi ezileni ve kaybi belirler
fun main() {
    val a = Signal("ayar.tema", 1)
    val b = Signal("ayar.tema", 2)
    val c = Signal("ayar.tema", 3)
    val limit = Signal("ayar.limit", 4)
    val sent = listOf(a, b, c, limit)
    val arrivals = probe(sent, activateUpTo(sent, 2))
    arrivals.forEach { it.line() }
    countArrivals(arrivals)
}
```

```text
olay-1: anahtar=ayar.tema | kopya=0 -> ezilen
olay-2: anahtar=ayar.tema | kopya=1 -> birebir
olay-3: anahtar=ayar.tema | kopya=0 -> kayip
olay-4: anahtar=ayar.limit | kopya=0 -> kayip
birebir: 1
yinelenen: 0
ezilen: 1
kayip: 2
```

Aynı anahtarın üç değerinden ikincisi etkinleşti. Birincisi ikincisi tarafından ezildi; üçüncüsü etkinleştirmenin kapsamı dışında kaldığı için ulaşmadı ve ondan daha büyük bir sıra ulaşmadığı için ezilen değil, kayıp yazıldı. Kural yalnız ulaşanlara bakar: üçüncü değerin kendisinden büyük bir kardeşi uygulamaya inmedi.

Burada bir tuzak vardır. Son getirilen değer, sunucunun en güncel kararıdır; ama etkinleştirme onu kapsamadıysa uygulama bir önceki değerle çalışır. Uygulamanın çalıştığı değer, sunucunun şu an istediği değer olmayabilir. Ölçümde "tema" için etkin değer ikincidir, ama sunucunun gönderdiği son değer üçüncüdür.

## Sınırlayıcı Ölçüm

Getirme tek başına teslim değildir. Değer getirilmiş ama etkinleştirilmemişse uygulama onu okuyamaz. Üç değer getirilir, etkinleştirme yalnız ilkini kapsayana kadar sürer ve uygulama kapanır.

```kotlin
// Main.kt — getirilip etkinlestirilmeyen deger uygulamaya ulasmaz
fun main() {
    val theme = Signal("ayar.tema", 1)
    val limit = Signal("ayar.limit", 2)
    val flag = Signal("ayar.bayrak", 3)
    val sent = listOf(theme, limit, flag)
    val arrivals = probe(sent, activateUpTo(sent, 1))
    arrivals.forEach { it.line() }
    countArrivals(arrivals)
}
```

```text
olay-1: anahtar=ayar.tema | kopya=1 -> birebir
olay-2: anahtar=ayar.limit | kopya=0 -> kayip
olay-3: anahtar=ayar.bayrak | kopya=0 -> kayip
birebir: 1
yinelenen: 0
ezilen: 0
kayip: 2
```

Limit ve bayrak getirildi ama etkinleşmedi; kural onları kayıp sayar. Ezilenden farkı şudur: onları ezen, aynı anahtarla daha yeni bir değer yoktur. Değer yalnızca bekleyen depoda kalmıştır.

Bu durumda uygulama ne okur? Sabit bir yedek, yani uygulama içi varsayılan. Varsayılan sunucudan gelen bir değer değildir; uygulamanın kendi içinde taşıdığı bir değerdir. Bu yüzden teslim sayılmaz. Hiç getirme olmadığında da aynı şey olur.

```kotlin
// Main.kt — hic getirilmeyen deger kayiptir, varsayilan teslim sayilmaz
fun main() {
    val theme = Signal("ayar.tema", 1)
    val limit = Signal("ayar.limit", 2)
    val sent = listOf(theme, limit)
    val arrivals = probe(sent, activateUpTo(sent, 0))
    arrivals.forEach { it.line() }
    countArrivals(arrivals)
}
```

```text
olay-1: anahtar=ayar.tema | kopya=0 -> kayip
olay-2: anahtar=ayar.limit | kopya=0 -> kayip
birebir: 0
yinelenen: 0
ezilen: 0
kayip: 2
```

İki değer de kayıp. Uygulama yine de çalışır, çünkü varsayılan değerleri vardır; ama bu değerler sunucunun gönderdiği şey değildir. Ölçüm, çalışan uygulamanın sunucuyla uyumlu olup olmadığını söylemez, yalnızca sunucunun gönderdiği değerin ulaşıp ulaşmadığını söyler.

**GD3.** Model, getirme ile etkinleştirme arasında değerin kaybolmadığını varsayar. Platformda bekleyen değer, depo temizlenirse ya da uygulama verisi silinirse gider.

## Sunucunun Rolü

Alıcı uygulamadır, ama değerin kaynağı sunucudur ve sunucunun yaptığı seçimler alıcıdaki sayıyı etkiler. Sunucu bir anahtarı sık değiştirirse, getirme aralığı kadar kısa sürede birden çok değer birikir ve ezilen sayısı artar. Sunucu anahtarı seyrek değiştirirse bekleyen listede aynı anahtar için tek değer kalır ve ezilen oluşmaz.

Bu yüzden ezilenin yüksek çıkması çoğu kez sunucunun değerleri çok hızlı değiştirdiğinin işaretidir, uygulamanın bir sorununun değil. Hangi değerin hangi uygulamada etkin olduğunu merak eden taraf, sunucudaki sürüm geçmişi ile uygulamanın kaydettiği etkin değeri yan yana koymalıdır. Biri olmadan öteki yanıltır: sunucu değeri gönderdiğini söyler, uygulama onu hiç görmemiş olabilir.

## Uygulamanın Yapacakları

Bu dersin alıcısı çalışan uygulamadır; yapılandırmanın uygulamaya doğru ulaşması için uygulama tarafında dört iş yapılır.

- **Her anahtar için bir varsayılan tanımlamak.** Varsayılan teslim sayılmaz, ama getirme başarısız olduğunda uygulamayı ayakta tutar. Varsayılanı, sunucunun göndermesi beklenen güvenli değere eşitlemek, yapılandırmanın ulaşmadığı durumlarda davranışı öngörülebilir kılar.
- **Etkinleştirme anını bilinçli seçmek.** Etkinleştirme hemen yapılırsa ekrandaki bir özellik ortada değişebilir; bir sonraki açılışa bırakılırsa son değer bir açılış geç gelir. İkisinin de bedeli vardır; hangisinin kabul edilebilir olduğu özelliğe bağlıdır.
- **Hangi değerin etkin olduğunu kaydetmek.** Bir deneyde ya da bir sayaçta kullanılan değerin sunucudaki değerle aynı olduğunu varsaymak yanlıştır. Etkin değeri ayrıca kaydeden uygulama, ezilen ve kayıp değerleri sonradan ayırt edebilir.
- **Getirme başarısızlığını sessiz bırakmamak.** Getirme hiç yapılamadıysa uygulama varsayılanla çalışır ve bunu kimse fark etmez. Başarısız getirmenin sayılması, kaybın sayısını dolaylı biçimde görünür kılar.

## Yaygın Yanılgılar

**Getirilen değer uygulamada geçerlidir.** Değildir. Ölçümde iki değer getirildi ama etkinleşmedi ve kayıp yazıldı. Getirme, değeri yalnız aygıta bırakır.

**Ezilen bir hatadır.** Değildir. Aynı anahtarın son değeri kazandı ve ilk değerin kopyası sıfır kaldı; yapılandırma için istenen davranış budur. Hata, ezilenin farkına varılmadan bir sayaca ya da deneye bağlanmasıdır.

**Varsayılan değer teslim edilmiş sayılır.** Sayılmaz. Hiç getirme olmayan ölçümde iki değer kayıptı, uygulama yine de çalıştı. Çalışması, sunucunun değerinin ulaştığı anlamına gelmez.

**Etkinleştirme her zaman en güncel değeri uygular.** Uygulamaz. Etkinleştirmenin kapsamı, getirmenin ilerisinde kalabilir; ölçümde üçüncü tema değeri getirildi ama etkinleşmedi, uygulama ikinciyle çalıştı.

## Özet

- Bu dersin teslimi: ezilen. Etkinleştirmeden önce iki kez getirilen aynı anahtarda son değer kazanır ve ilk değerin hiçbir kopyası ulaşmaz.
- Getirme değeri aygıtta bekletir, etkinleştirme onu uygulamanın okuduğu değer yapar; ikisi ayrı adımdır.
- Üç ayrı anahtar bir kez getirilince üçü birebir ulaşır. İki kez getirilen tema için ilk değer ezilen 1, ikincisi birebir olur.
- Getirilip etkinleştirilmeyen değer kayıptır: birebir 1, kayıp 2. Hiç getirilmeyen değer de kayıptır.
- Etkinleştirme noktası ezileni ve kaybı ayırır: üç tema değerinden ikincisi etkinleşince birinci ezilen, üçüncü kayıp olur.
- Uygulama içi varsayılan sunucudan gelmediği için teslim sayılmaz.

## Sonraki Adım

Bu derste son değer kazandı ve eski değer ezildi; çünkü yapılandırmada yalnız güncel olan işe yarar. Her dış hizmet böyle değildir. Sonraki derste uygulama içi satın alma ve reklam gelir: onaylanana kadar yeniden teslim edilen bir satın alma, bu dersteki sonuca benzemez. Orada neyin ulaştığını ve neyin ulaşmadığını yine ölçeceğiz.
