---
title: 'Beta Dağıtımı'
source: 'https://academia.sh/tr/kurslar/ios-uretim/beta-dagitimi'
course: 'Mimari, Test ve Yayınlama'
language: tr
updated: '2026-10-21T05:03:07+00:00'
license: 'CC BY-SA 4.0'
objectives:
    - 'Beta dağıtımında sürümün kimlere ulaştığı ile özelliğin kimlere açık olduğunu ayırır'
    - 'Beta kullanıcısında açık diyen denetimin kitle dışına açılan bayrağı göremediğini ölçer'
    - 'Beta dışı kullanıcıda kapalı diyen denetimin kusuru ayırdığını doğrular'
    - 'Aynı denetimin kullanıcı listesine göre kör, ters, gürültülü ya da ayıran olabildiğini gösterir'
---

# Beta Dağıtımı

Bir özellik bayrağının beta kitlesi dışındaki kullanıcılara da açık olduğunu beta kullanıcısında açık diyen denetimin göremediğinin, beta dışı kullanıcıda kapalı diyen denetimin ise gördüğünün ölçümü.

Bir sürüm herkese açılmadan önce küçük bir kitleye verilebilir. Bu kitle ekibin kendisi, davet edilen dış test kullanıcıları ya da ikisi birden olur. Sürüm, bir **beta dağıtım servisi** üzerinden davet edilen kullanıcıların aygıtlarına ulaşır ve onlar sürümü gerçek kullanım içinde dener. Amaç, sorunu herkese ulaşmadan bulmaktır.

Sürümün bir kitleye ulaşması ile özelliğin o kitleye açık olması aynı şey değildir. Sürüm herkese aynıdır; yeni özellik ise bir **özellik bayrağıyla** (feature flag) kapalı gelebilir ve yalnız belirli kullanıcılar için açılır. Beta kitlesinin dışına açılan bir bayrak, beta dağıtımının var olma nedenini ortadan kaldırır.

Kursun ölçü adı **ayrım**dır: aynı denetimi doğru sürüme ve kusurlu sürüme uygulayınca iki yanıt farklı mı. Dört kategori vardır: doğru sürümün geçip kusurlu sürümün kaldığı **ayıran**, ikisinin de geçtiği **kör**, ikisinin de kaldığı **gürültülü** ve doğru sürümün kalıp kusurlu sürümün geçtiği **ters**. Çıktıda bunlar `ayiran`, `kor`, `gurultulu` ve `ters` olarak görünür. Bu ders çekirdek dosyayla ölçer.

```swift
// Separation.swift — bir denetimin dogru surumu kusurlu surumden ayirip ayirmadigini siniflandirir
struct Contrast<Output: CustomStringConvertible> {
    let label: String
    let correct: Output
    let faulty: Output
    let passesCorrect: Bool
    let passesFaulty: Bool

    var separation: String {
        switch (passesCorrect, passesFaulty) {
        case (true, false): return "ayiran"
        case (true, true): return "kor"
        case (false, false): return "gurultulu"
        case (false, true): return "ters"
        }
    }

    func describe() -> String {
        let onCorrect = passesCorrect ? "gecti" : "kaldi"
        let onFaulty = passesFaulty ? "gecti" : "kaldi"
        print("\(label) | dogru=\(correct)/\(onCorrect) kusurlu=\(faulty)/\(onFaulty) -> \(separation)")
        return separation
    }
}

func contrast<Output>(_ label: String, correct: Output, faulty: Output, check: (Output) -> Bool) -> Contrast<Output> {
    Contrast(label: label, correct: correct, faulty: faulty, passesCorrect: check(correct), passesFaulty: check(faulty))
}

func countSeparations(_ results: [String]) {
    for name in ["ayiran", "kor", "gurultulu", "ters"] {
        print("\(name): \(results.filter { $0 == name }.count)")
    }
}
```

Bu dersin kusuru bayrağın yapılandırmasındadır. Doğru sürümde yeni özellik yalnız bir izin listesindeki kullanıcılar için açıktır. Kusurlu sürümde yapılandırma "herkese açık" olarak kalmıştır ve izin listesi hiç okunmaz. Beta kullanıcıları için hiçbir şey değişmez: özellik onlar için açıktır ve çalışır. Fark yalnız beta dışındaki kullanıcılarda görünür.

## Bayrağın Modeli

Bayrak iki değerden oluşur: herkese açık olup olmadığı ve izin listesi. `isOn` bir kullanıcı için bayrağın açık olup olmadığını söyler: bayrak herkese açıksa açık, değilse kullanıcı izin listesindeyse açık. `exposure` bir kullanıcı listesinin her biri için durumu tek bir dizgiye yazar, böylece iki sürümün yanıtı yan yana okunur.

Yapılandırma genellikle şuna benzer bir dosyada durur. Anahtar adları gerçek bir hizmetinki değildir; ders yalnız biçimi gösterir.

```yaml
flags:
  new-checkout:
    enabled_for: beta
    allowlist: [u01, u02, u03]
```

Kusurlu sürümde `enabled_for` değeri `everyone` olarak kalmıştır; izin listesi yerindedir ama kimse ona bakmaz. Yapılandırmayı okuyan göz bunu fark eder, çünkü tek bir değerdir. Okumayan, yalnız davranışa bakan denetim için ise bu fark görünmez olabilir.

```swift
// Beta.swift — ozellik bayraginin izin listesi ve kullanici durumlari
struct Rollout {
    let everyone: Bool
    let allowlist: Set<String>
}

func isOn(_ user: String, rollout: Rollout) -> Bool {
    rollout.everyone || rollout.allowlist.contains(user)
}

func exposure(of users: [String], rollout: Rollout) -> String {
    users.map { "\($0):\(isOn($0, rollout: rollout) ? "acik" : "kapali")" }.joined(separator: " ")
}

let allowlist: Set<String> = ["u01", "u02", "u03"]
let betaTesters = ["u01", "u02", "u03"]
let newTester = ["u04"]
let outsiders = ["u10", "u11"]
let enabledForBeta = Rollout(everyone: false, allowlist: allowlist)
let enabledForAll = Rollout(everyone: true, allowlist: allowlist)
```

Dersin kullanıcıları kısa kimliklerle yazılır: üç beta kullanıcısı, bir yeni davet edilen beta kullanıcısı ve iki beta dışı kullanıcı. Yeni davet edilen kullanıcı beta servisinde vardır ama izin listesine henüz eklenmemiştir; neden önemli olduğu sınırlayıcı ölçümde görünecek.

**DG10.** Bu ölçüm kullanıcıları küçük bir kimlik listesiyle temsil eder. Listenin boyutu kitlenin büyüklüğü hakkında hiçbir şey söylemez ve gerçek bir beta kitlesinin nasıl seçildiği ölçülmedi.

## Üç Denetim

Bayrağa üç denetim uygulanır. İlki en doğal olanıdır: beta kullanıcılarında özellik açık mı. İkincisi beta dışı kullanıcılarda özelliğin kapalı olduğuna bakar. Üçüncüsü davranışa değil yapılandırmaya bakar: bayrak herkese açık değil mi.

```swift
// main.swift — uc denetim, iki kategori
let onBeta = contrast("beta-kullanicisinda-acik",
    correct: exposure(of: betaTesters, rollout: enabledForBeta),
    faulty: exposure(of: betaTesters, rollout: enabledForAll)) { !$0.contains("kapali") }.describe()
let onOutsiders = contrast("beta-disi-kullanicida-kapali",
    correct: exposure(of: outsiders, rollout: enabledForBeta),
    faulty: exposure(of: outsiders, rollout: enabledForAll)) { !$0.contains("acik") }.describe()
let configured = contrast("yapilandirma-herkese-acik-degil",
    correct: enabledForBeta.everyone,
    faulty: enabledForAll.everyone) { !$0 }.describe()

countSeparations([onBeta, onOutsiders, configured])
```

```text
beta-kullanicisinda-acik | dogru=u01:acik u02:acik u03:acik/gecti kusurlu=u01:acik u02:acik u03:acik/gecti -> kor
beta-disi-kullanicida-kapali | dogru=u10:kapali u11:kapali/gecti kusurlu=u10:acik u11:acik/kaldi -> ayiran
yapilandirma-herkese-acik-degil | dogru=false/gecti kusurlu=true/kaldi -> ayiran
ayiran: 2
kor: 1
gurultulu: 0
ters: 0
```

Üç denetimin üçü de doğru sürümde geçer. Kusurlu sürümde ise ilki de geçer: beta kullanıcılarında özellik **gerçekten** açıktır, kusurlu sürümde de. Bu denetim özelliğin çalışıp çalışmadığını doğru ölçer ve bayrağın kimlere açık olduğu hakkında hiçbir şey söylemez. İki sürümde de aynı yanıtı verir, **kör**.

İkinci denetim kusurun değiştirdiği kitleye bakar. Beta dışı kullanıcıda doğru sürüm kapalı, kusurlu sürüm açık gösterir ve denetim yalnızca kusurlu sürümde kalır: **ayıran**. Üçüncü denetim de ayırandır ama başka bir nedenle: kusur doğrudan yapılandırma değerinde durur ve denetim o değere bakar. İki ayıran denetimin farkı, ilkinin davranışı, ikincisinin dosyayı okumasıdır. Davranışı ölçen denetim yapılandırmanın başka bir yoldan değiştiği kusura da dayanıklıdır; yapılandırmayı okuyan denetim ise yapılandırmanın uygulamada gerçekten okunup okunmadığını göstermez.

## Davet, Sürüm ve Bayrak

Beta dağıtımında kimin neyi gördüğünü üç ayrı katman belirler ve her katmanın kendi listesi vardır. Birincisi davet listesidir: hangi kullanıcıların sürümü indirebildiğini söyler. İkincisi sürümün kendisidir: indirilen paketin içinde hangi kodun bulunduğunu belirler. Üçüncüsü bayrağın izin listesidir: paketin içindeki özelliğin kime açıldığını söyler. Üç liste ayrı yerde durur ve ayrı kişiler tarafından güncellenir.

Bu ayrım, dersin kusurunun neden sessiz kaldığını açıklar. Davet listesi doğru olabilir, sürüm doğru paketlenmiş olabilir ve yine de bayrak herkese açık kalmış olabilir. Her katman kendi içinde tutarlıdır; tutarsızlık katmanlar arasındadır. Bir katmanı denetleyen sınama diğerlerinin kusurunu göremez. Yeni davetli kullanıcı örneği bunun küçük bir hâlidir: davet listesinde vardır, izin listesinde yoktur ve iki liste birbirine bakmaz.

## Neden "Açık" Denetimi Yazılır

Beta kullanıcısında açık denetimi yaygındır, çünkü beta dağıtımının amacı özelliği denemektir ve ekip doğal olarak "özellik çalışıyor mu" diye sorar. Bu soru geçerlidir ve hattın bir yerinde durması gerekir. Ama bu soru **özellik çalışıyor mu** sorusudur, **özellik yalnız doğru kitlede mi çalışıyor** sorusu değildir. Bu iki soru farklı kusurları yakalar. Birinci soru kapalı gelen bayrağı bulur; ikinci soru fazla açılan bayrağı.

Fazla açılan bayrak daha az bilinen bir risktir, çünkü kimse şikâyet etmez. Beta kullanıcıları özelliği açık görür ve memnun kalır, beta dışı kullanıcılar da özelliği açık görür ve şikâyet etmez, çünkü özellik çalışıyordur. Hata ancak özellik beklenmedik bir şey yapınca, ya da yayın sorumlusu özelliğin kimlere göründüğüne baktığında ortaya çıkar. Kör denetim sessiz bir tehlikedir, çünkü bu sessizliği yeşil bir çıktı olarak raporlar.

## Kör Denetimi Tamamlamak

Kör denetim silinmez, tamamlanır. Burada tamamlayıcı denetim, beta dışı kullanıcıda kapalı olandır. İkisi birlikte bayrağın iki yüzünü örter: açık olması gerekenlerde açık, kapalı olması gerekenlerde kapalı. Yalnız birini yazmak, hangi yüzün sınandığını bilmek koşuluyla kabul edilebilir; bilmeden yazılan birinci denetim, ikinciyi yazmanın gerekli olmadığı izlenimini verir.

Bozma denemesi burada da geçerlidir. Yapılandırmada `enabled_for` değerini bilerek `everyone` yapıp denetimleri koşmak, hangi denetimin kırmızıya döndüğünü gösterir. Dersin ilk ölçümü bu denemenin sonucudur: üç denetimden biri hiç kızarmadı.

## Beta Geri Bildirimi Neyi Söylemez

Beta döneminin sonunda ekip genellikle geri bildirime bakar: kaç hata bildirimi gelmiş, kullanıcılar ne yazmış. Bildirimlerin azlığı sürümün sağlam olduğu izlenimini verir. Ama geri bildirim yalnız **görülen** davranışı yansıtır ve görülmeyen davranış için sessizdir. Bayrağın beta dışı kullanıcılara açık kalması bu sessizliğin tipik bir örneğidir: özellik çalışıyorsa kimse yazmaz.

Bu nedenle beta geri bildirimi bir denetim yerine geçmez. Geri bildirim "kullanıcılar bir şey fark etti mi" sorusunu yanıtlar; denetim "bayrak doğru kitleye mi açık" sorusunu yanıtlar. İkisi aynı beta döneminde birlikte yürür ve biri diğerinin eksiğini kapatmaz. Ekibin beta sonunda yazdığı özet iki ayrı satır taşırsa, geri bildirim ve bayrak durumu, okuyan kişi hangisinin neyi kanıtladığını bilir.

Kör bir denetimin bedeli de buradan görülür. Beta kullanıcısında açık diyen denetim her beta döneminde yeşildir ve bu yeşil ekibe beta döneminin sorunsuz geçtiği güvenini verir. Yeşilin altında bayrağın herkese açık olduğu bir hata yatıyorsa, güven yanlış yerdendir. Çözüm yeşili silmek değil, yanına kitle dışı denetimini koymaktır.

## Kitle Genişleyince Denetim

Beta kitlesi büyür: başka bir ekip eklenir, dış test kullanıcıları davet edilir. Her genişlemede izin listesi değişir ve "beta dışı" tanımı da onunla birlikte değişir. Beta dışı kullanıcılar için elle yazılmış bir liste, genişlemeden sonra bir beta kullanıcısını içerebilir. Böyle bir denetim doğru sürümde kalır, çünkü artık beta kullanıcısı olan kullanıcı için özellik açıktır. Denetim yanlış alarm verir ve ekip onu kapatır; kitle genişledi diye bir denetimin kapanması ise bayrağın kitle dışına açılma riskini örtüsüz bırakır.

Çözüm, beta dışı kullanıcıları listeden elle seçmek yerine davet listesinden **türetmektir**: davet listesinde olmayan her kullanıcı beta dışıdır. Tanım bir yerde durduğu için genişleme denetimi bozmaz. Denetimin okuduğu veri kaynağını bu şekilde birleştirmek, ayrımı kullanıcı seçimine bağlı olmaktan çıkarır.

## Bayrak Geri Alınırken

Beta sırasında bir sorun çıkarsa bayrak kapatılır; yeni bir sürüm yüklemek gerekmez. Bu, bayrakların asıl değerlerinden biridir ve geri alma da bir denetim konusudur. Bayrak kapatıldıktan sonra beta kullanıcılarında özelliğin **kapalı** olduğu denetlenirse, o denetim kapatma işleminin gerçekten uygulandığını gösterir. Burada da aynı soru geçerlidir: denetim, kapatılmamış bir bayrağı yakalayacak şekilde mi yazılmış? Beta kullanıcısında açık diyen denetimin tersini yazmak yetmez; hangi sürümde ne yanıt verdiğine bakmak gerekir.

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

Aynı iki denetim, farklı kullanıcı listeleriyle, farklı kategorilere düşer. Birinci liste üç beta kullanıcısıdır. İkinci liste, yeni davet edilen ve izin listesine henüz eklenmemiş tek bir beta kullanıcısıdır. Üçüncü ve dördüncü satırlar beta dışı kapalı denetimini beta kullanıcılarının listesine ve bir beta dışı kullanıcıya uygular.

```swift
// main.swift — ayni denetimler, farkli kullanici listeleri
let open = contrast("acik-uc-beta-kullanicisi",
    correct: exposure(of: betaTesters, rollout: enabledForBeta),
    faulty: exposure(of: betaTesters, rollout: enabledForAll)) { !$0.contains("kapali") }.describe()
let invited = contrast("acik-yeni-davetli",
    correct: exposure(of: newTester, rollout: enabledForBeta),
    faulty: exposure(of: newTester, rollout: enabledForAll)) { !$0.contains("kapali") }.describe()
let closedOnBeta = contrast("kapali-beta-kullanicilari-uzerinde",
    correct: exposure(of: betaTesters, rollout: enabledForBeta),
    faulty: exposure(of: betaTesters, rollout: enabledForAll)) { !$0.contains("acik") }.describe()
let closedOnOutsider = contrast("kapali-bir-beta-disi",
    correct: exposure(of: ["u10"], rollout: enabledForBeta),
    faulty: exposure(of: ["u10"], rollout: enabledForAll)) { !$0.contains("acik") }.describe()

countSeparations([open, invited, closedOnBeta, closedOnOutsider])
```

```text
acik-uc-beta-kullanicisi | dogru=u01:acik u02:acik u03:acik/gecti kusurlu=u01:acik u02:acik u03:acik/gecti -> kor
acik-yeni-davetli | dogru=u04:kapali/kaldi kusurlu=u04:acik/gecti -> ters
kapali-beta-kullanicilari-uzerinde | dogru=u01:acik u02:acik u03:acik/kaldi kusurlu=u01:acik u02:acik u03:acik/kaldi -> gurultulu
kapali-bir-beta-disi | dogru=u10:kapali/gecti kusurlu=u10:acik/kaldi -> ayiran
ayiran: 1
kor: 1
gurultulu: 1
ters: 1
```

Dört satırda dört kategori. `acik-uc-beta-kullanicisi` ilk ölçümle aynıdır: **kör**. `acik-yeni-davetli` **ters**tir: yeni davetli kullanıcı izin listesinde olmadığı için doğru sürümde özellik ona kapalıdır ve denetim kalır; kusurlu sürümde bayrak herkese açık olduğundan özellik ona da açıktır ve denetim geçer. Yani izin listesini güncellemeyi unutan ekip, doğru sürümde bir hata alır ve kusurlu sürümde hiç hata görmez. Kırmızı olan doğru sürümdür.

Üçüncü satırda denetim beta kullanıcıları üzerinde "kapalı" arar ve iki sürümde de kalır, **gürültülü**: beta kullanıcılarında özellik her iki sürümde de açıktır. Bu satır kötü bir denetimin tasarımını gösterir: denetimin beklentisi ile baktığı kullanıcılar uyuşmaz. Dördüncü satır, tek bir beta dışı kullanıcıyla, yine **ayıran**dır. Yani ayıranı bulmak için büyük bir kullanıcı listesi gerekmez; doğru kullanıcının listede bulunması yeter.

Bu ölçüm kullanıcı seçiminin önemini gösterir, ama bir sınırı da vardır. Listenin her biri küçüktür ve gerçek bir kitlede izin listesinin eksikleri, hatalı yazılmış kimlikleri ve eski hesapları da olur. Kitle büyüklüğü ve oranlar ölçülmedi.

**DG11.** Bu ölçüm izin listesinin beta davetlerinden ayrı bir yerde tutulduğunu varsayar. Davet ile listenin gerçek bir hatta nasıl eşitlendiği ölçülmedi.

**DG12.** Bu ölçüm beta servisinin sürümü kullanıcıya ulaştırma zamanını modellemez. Davetin ne zaman iletildiği ya da sürümün aygıta ne zaman indiği ölçülmedi.

## Özet

- Beta dağıtımı sürümü sınırlı bir kitleye ulaştırır; özelliğin kimlere açık olduğunu ise özellik bayrağı belirler.
- Beta kullanıcısında özelliğin açık olduğunu denetleyen sınama, bayrak kitle dışına da açıkken iki sürümde de geçer: kör.
- Beta dışı kullanıcıda kapalı olduğunu denetleyen sınama kusuru ayırır: ayıran.
- Aynı "açık" denetimi, izin listesine henüz eklenmemiş yeni davetli kullanıcıda ters olur.
- Denetimin ayrımı baktığı kullanıcı listesine bağlıdır; kör denetim silinmez, kapalı olması gerekenleri denetleyen bir eşle tamamlanır.
- Bu dersin ayrımı: **kör**.

## Sonraki Adım

Beta kitlesinde sınanan sürüm sonunda mağazanın incelemesine gider. Sıradaki derste, Mağaza İnceleme Süreci, bir hazırlık listesinin hangi maddelerinin kusuru ayırdığı ve hangilerinin her iki sürümde de kaldığı ölçülecek.
