---
title: 'Bağlam Sağlama'
source: 'https://academia.sh/tr/kurslar/model-apileri/baglam-saglama'
course: "Model API'leri ile Uygulama Geliştirme"
language: tr
updated: '2026-08-17T18:06:37+00:00'
license: 'CC BY-SA 4.0'
---

# Bağlam Sağlama

Aynı kurgu kod tabanında bağlamı büyütmekle bağlamı seçmenin yan yana ölçülmesi: bütün dosyaları göndermek beklenen kabulü 0,6921'e çıkarıyor ve 4224 belirteç ile 120 dosya harcıyor, yalnız gereken dosyaları göndermek 0,8233'e çıkarıyor ve 2274 belirteç ile 45 dosya harcıyor. İlgisiz her dosya beklenen kabulden 0,0400 götürüyor ve 624 belirteç ekliyor; eşiği yoktur, ilk dosyadan başlar. Bağlam sağlayıcının belirteç bedeli isabetinden bağımsızdır ve 2274'te sabittir, ama beklenen kabul 0,4960 ile 0,8233 arasında değişir; sağlayıcının bütün kod tabanını göndermeyi geçmesi için gereken dosyaları dört görevin yaklaşık üçünde bulması gerekir.

Önceki ders bağlamı üç kez **sabit** verdi: hiç, hep aynı dosya, ya da hepsi. Uçlar arasındaki
mesafe büyüktü — yirmi dört görevin yedisinden on sekizine — ama üçü de bir seçim değildi. Bir
geliştirici masasında bağlam her görev için yeniden kurulur ve iki ayrı soru sorulur: **hangi
dosyalar** ve **kaç tane**.

Bu ders o iki soruyu ayırır. Önce bağlam **büyütülür**: aynı dosya kümesi herkese verilir ve boyu
bir bir artar. Sonra bağlam **seçilir**: her göreve yalnız o görevin gerektirdiği dosyalar gider.
İki eğri belirteç ekseninde yan yana konur, ve üzerine üçüncü bir sayı eklenir: **görevle ilgisi
olmayan bir dosyanın kabule ne yaptığı**.

- **YG9.** Kod tabanı önceki derste gövdeleriyle kurulan aynı **kurgu** kod tabanıdır: beş modül,
  **53 satır**. Burada yalnız yapısı gerekir, çünkü bağlam **dosya adıyla** seçilir.
- **YG10.** Görev kümesi ve yardımcı benzeticisi de aynıdır: yirmi dört kurgu görev, üç sınıf,
  tohum **20260218**, `random` yok.
- **YG11.** Bağlamın kabule etkisi iki terimlidir: **örtüşme** (gereken dosyaların kaçı bağlamda)
  kabulü yükseltir, **ilgisizlik** (bağlamdaki dosyaların kaçı gereksiz) düşürür.
- **YG12.** Bedel dosya başına düz **26 belirteçtir**; dosya boyu bedele girmez. Gerçek bir
  bağlamda büyük dosya pahalıdır, yani buradaki bedel eğrisi **iyimserdir**.
- **YG13.** Gönderilen dosya sayısı ayrıca sayılır; yirmi dört görev için toplamdır ve belirteçten
  bağımsız bir hacim ölçüsüdür.
- **YG14. Bağlam sağlayıcı kurgudur** ve tek bir ayarı vardır: **isabet**, yani gereken kümeyi
  doğru bulduğu görev payı. Kaçırdığında bir gereken dosyayı düşürür, yerine ilgisiz bir dosya
  koyar; **dosya sayısı değişmez**, yalnız hangi dosya olduğu değişir.
- **YG15.** Sağlayıcının kendi çekilişi **tohumla sabittir**; ikinci koşumda yalnız yardımcının
  belirsizliği değişir. Böylece iki koşum farkı seçime değil, yalnız modele yazılır.
- **YG16.** Koşumdan bağımsız ölçü yine **beklenen kabuldür**; sayılan kabul iki tohumda ayrı
  basılır. Gecikme sınıfı bütün kurulumlarda **tek çağrıdır**, görev başına bir tane.

## Kod Tabanının Yapısı ve Sağlayıcı

Bağlam seçimi için kod tabanının gövdeleri değil **yapısı** gerekir: hangi modül var, ne kadar
uzun ve dışarıya hangi adları veriyor. Bir bağlam sağlayıcının çalıştığı düzlem de budur.

```python
# AYNI KURGU KOD TABANI -- bes modul, 53 satir; govdeleri onceki derste kuruldu.
# Burada yalniz yapisi gerekiyor: boy ve disa verilen adlar.
BOY = {"okuma.py": 13, "tarife.py": 13, "denetim.py": 11, "ozet.py": 11, "bicim.py": 5}
DISA = {
    "okuma.py": ("ayristir", "tuketim"),
    "tarife.py": ("BASAMAK", "USTU", "bedel"),
    "denetim.py": ("GECERLI_BOLGE", "gecerli", "ayikla"),
    "ozet.py": ("bolge_toplam", "bolge_sayi"),
    "bicim.py": ("satir", "rapor"),
}
DOSYA = tuple(BOY)

TOHUM, M32 = 20260218, 0xFFFFFFFF


def uretec(t):
    x = ((t ^ (t >> 16)) * 2246822507) & M32
    x = ((x ^ (x >> 13)) * 3266489909) & M32
    s = [(x ^ (x >> 16)) & M32]

    def sonraki():
        s[0] = (s[0] * 1664525 + 1013904223) & M32
        return s[0] / 4294967296
    return sonraki


def izno(m):
    h = 2166136261
    for c in m:
        h = ((h ^ ord(c)) * 16777619) & M32
    return h


SINIF = ("tamamlama", "aciklama", "donusturme")
GEREKEN = {
    0: ("okuma.py",),
    1: ("tarife.py",),
    2: ("denetim.py", "okuma.py"),
    3: ("ozet.py", "denetim.py"),
    4: ("bicim.py", "ozet.py"),
    5: ("tarife.py", "okuma.py"),
    6: ("ozet.py", "okuma.py", "tarife.py"),
    7: ("denetim.py", "bicim.py"),
}
GOREV = [                                   # 24 KURGU gorev: 3 sinif x 8
    {"ad": s + "-" + str(i + 1), "sinif": s, "gereken": GEREKEN[i], "zorluk": 0.05 * (i % 4)}
    for s in SINIF
    for i in range(8)
]
TABAN = {"tamamlama": 0.34, "aciklama": 0.72, "donusturme": 0.18}


def yardimci(gorev, baglam, tohum=TOHUM):   # BENZETICI -- KURGUDUR
    r = uretec(tohum ^ izno(gorev["ad"] + "|" + ",".join(sorted(baglam))))
    ortu = sum(1 for d in gorev["gereken"] if d in baglam) / len(gorev["gereken"])
    ilgisiz = sum(1 for d in baglam if d not in gorev["gereken"]) / len(DOSYA)
    puan = TABAN[gorev["sinif"]] + 0.55 * ortu - 0.30 * ilgisiz - gorev["zorluk"]
    puan = min(max(puan, 0.0), 1.0)
    kabul = r() < puan
    belirtec = 40 + 26 * len(baglam) + (18 if gorev["sinif"] == "donusturme" else 0)
    return {"kabul": kabul, "puan": puan, "belirtec": belirtec}


def saglayici(gorev, isabet, tohum=TOHUM):
    """KURGU baglam saglayici. Isabet ettiginde gereken kumeyi bulur; kacirdiginda
    bir gereken dosyayi dusurur ve yerine ilgisiz bir dosya koyar. Dosya sayisi ayni."""
    r = uretec(tohum ^ izno("saglayici|" + gorev["ad"]))
    if r() < isabet:
        return tuple(gorev["gereken"])
    ek = tuple(d for d in DOSYA if d not in gorev["gereken"])[:1]
    return tuple(gorev["gereken"][1:]) + ek


print("modul       satir  disa verilen")
for d in DOSYA:
    print(f"  {d:<10}{BOY[d]:>4}   {', '.join(DISA[d])}")
dagilim = {}
for g in GOREV:
    dagilim[len(g["gereken"])] = dagilim.get(len(g["gereken"]), 0) + 1
print(f"\ngorev {len(GOREV)}, gereken dosya sayisi dagilimi {dict(sorted(dagilim.items()))}"
      f", toplam gereken dosya {sum(len(g['gereken']) for g in GOREV)}")
print("ornek gorev:", GOREV[6]["ad"], "->", "+".join(GOREV[6]["gereken"]),
      " belirtec", yardimci(GOREV[6], GOREV[6]["gereken"])["belirtec"],
      "/ butun kod tabaniyla", yardimci(GOREV[6], DOSYA)["belirtec"])
```

```
modul       satir  disa verilen
  okuma.py    13   ayristir, tuketim
  tarife.py   13   BASAMAK, USTU, bedel
  denetim.py  11   GECERLI_BOLGE, gecerli, ayikla
  ozet.py     11   bolge_toplam, bolge_sayi
  bicim.py     5   satir, rapor

gorev 24, gereken dosya sayisi dagilimi {1: 6, 2: 15, 3: 3}, toplam gereken dosya 45
ornek gorev: tamamlama-7 -> ozet.py+okuma.py+tarife.py  belirtec 118 / butun kod tabaniyla 170
```

Görevlerin yarısından çoğu **iki** dosya istiyor, altısı bir, üçü üç. Yirmi dört görevin toplam
ihtiyacı **45 dosyadır**. Bütün kod tabanını her göreve göndermek ise 120 dosya demektir, yani
gereğinin **iki katından fazlası**. Örnek görevde fark tek başına küçük görünüyor: 118 belirteçe
karşı 170. Yirmi dört görev boyunca aynı fark birikir.

## Büyütmek ile Seçmek

İki eğri aynı tabloda basılır. **Toplu** satırlar herkese aynı ilk `k` dosyayı verir; **seçili**
satırlar her göreve yalnız kendi gereken dosyalarını verir ve üzerine sırayla ilgisiz dosya
eklenir.

```python
def olc(sec, tohum=TOHUM):
    kabul = bel = dosya = 0
    puan = 0.0
    for g in GOREV:
        b = sec(g)
        s = yardimci(g, b, tohum)
        kabul += s["kabul"]
        puan += s["puan"]
        bel += s["belirtec"]
        dosya += len(b)
    return kabul, puan / len(GOREV), bel, dosya


def yaz(ad, sec):
    a = olc(sec)
    kb = olc(sec, TOHUM + 1)[0]
    print(f"{ad:<26}{a[3]:>7}{a[1]:>11.4f}{a[0]:>8}/24{kb:>8}/24{a[2]:>10}")


print("kurulum                    dosya   beklenen  kabul A  kabul B  belirtec")
for k in range(6):
    yaz(f"toplu {k}", lambda g, b=DOSYA[:k]: b)
yaz("secili (yalniz gereken)", lambda g: g["gereken"])
for n in (1, 2, 3):
    def sec(g, n=n):
        ek = tuple(d for d in DOSYA if d not in g["gereken"])[:n]
        return tuple(g["gereken"]) + ek
    yaz(f"secili + {n} ilgisiz", sec)

print("\nsaglayici isabeti  bulunan gereken payi  beklenen  kabul A  kabul B  belirtec")
for isb in (0.00, 0.25, 0.50, 0.75, 1.00):
    def sec(g, i=isb):
        return saglayici(g, i)
    a = olc(sec)
    kb = olc(sec, TOHUM + 1)[0]
    bulunan = sum(sum(1 for d in g["gereken"] if d in sec(g)) for g in GOREV)
    print(f"{isb:>13.2f}{bulunan / 45:>22.4f}{a[1]:>10.4f}{a[0]:>8}/24{kb:>8}/24{a[2]:>10}")
```

```
kurulum                    dosya   beklenen  kabul A  kabul B  belirtec
toplu 0                         0     0.3383       7/24       7/24      1104
toplu 1                        24     0.4600      10/24       8/24      1728
toplu 2                        48     0.5402      12/24      13/24      2352
toplu 3                        72     0.6013      15/24      13/24      2976
toplu 4                        96     0.6608      15/24      15/24      3600
toplu 5                       120     0.6921      18/24      20/24      4224
secili (yalniz gereken)        45     0.8233      19/24      19/24      2274
secili + 1 ilgisiz             69     0.7833      19/24      18/24      2898
secili + 2 ilgisiz             93     0.7433      20/24      18/24      3522
secili + 3 ilgisiz            114     0.7029      17/24      20/24      4068

saglayici isabeti  bulunan gereken payi  beklenen  kabul A  kabul B  belirtec
         0.00                0.4667    0.4960      13/24      10/24      2274
         0.25                0.6222    0.5796      15/24      12/24      2274
         0.50                0.7333    0.6404      15/24      14/24      2274
         0.75                0.8222    0.7050      17/24      15/24      2274
         1.00                1.0000    0.8233      19/24      19/24      2274
```

## Eğrinin Okunması

Toplu satırlar sezgiyi doğruluyor: dosya eklemek beklenen kabulü **0,3383'ten 0,6921'e** çıkarıyor
ve hiçbir adımda düşürmüyor. Bedel de düzgündür — her adım tam **624 belirteç**, çünkü yirmi dört
görevin her birine bir dosya daha giriyor. Eğri, bağlamı büyütmenin işe yaradığı iddiasının
sayısıdır ve doğrudur.

Eğrinin bir zayıflığı var ve tabloda görünmüyor: **sıra**. Toplu satırlar dosyaları modül
demetindeki sırayla ekliyor, yani ikinci satırın hangi dosyayı taşıdığı bir karar değil bir
tesadüftür. Başka bir sırayla aynı iki uç nokta arasında başka bir eğri çıkardı. Seçili kurulumun
böyle bir bağımlılığı yoktur, çünkü sıra sorusunu hiç sormaz. Bir kurulumun sayısı, listelenmemiş
bir keyfî karara duyarlıysa o sayı tek başına okunmamalıdır.

İkinci zayıflık bedel tarafındadır ve **seçimin lehinedir**. Bu ölçümde her dosya boyundan bağımsız
olarak 26 belirteç ediyor; oysa kod tabanının en uzun modülü en kısasının iki buçuk katından
uzundur.
Gerçek bir bağlamda toplu gönderim uzun dosyaların bedelini de öder, seçili gönderim çoğu zaman
ödemez. Yani aşağıdaki fark bir **alt sınırdır**.

Seçili satır aynı iddiayı yerinden ediyor. Yalnız gereken dosyalar gönderildiğinde beklenen kabul
**0,8233**; bütün kod tabanının **0,6921**'inden **0,1312** yüksek. Bunu **45 dosya** ve **2274
belirteç** ile yapıyor: dosya hacminin **üçte birinden biraz fazlası**, belirtecin **yüzde elli
dördü**.
İki eksende birden kazanan bir kurulum ender görülür ve buradaki nedeni açıktır: bütün kod
tabanını göndermek gereken dosyaları da gönderir, ama yanında **ortalama üç ilgisiz dosya**
taşır.

Aynı bedelde karşılaştırma bunu daha keskin yapıyor. **Toplu 2** kurulumu 2352 belirteç harcayıp
**0,5402** veriyor; seçili kurulum 2274 belirteçle, yani biraz daha azıyla, **0,8233**. Neredeyse
aynı bütçede **0,2831** fark. Belirteç bütçesi bir tasarım kısıtıysa, o bütçeyi nereye harcadığın
ne kadar harcadığından daha çok belirliyor.

Sayılan kabul sütunları bir uyarı taşıyor. Seçili satır **19/24** ve bütün kod tabanı **18/24**;
aradaki fark tek görev. Ama ikinci koşumda sıralama tersine dönüyor: 19/24'e karşı **20/24**.
Sayılan kabulle bakıldığında bu iki kurulum **ayırt edilemez**, çünkü fark iki koşum farkının
içinde kalıyor. Ayrımı yapan şey koşumdan bağımsız sütundur. Bu, kursun ölçü kuralının doğrudan
uygulanmasıdır: iki koşumda oynayan bir sayı, tek koşumda okunduğunda karar verdirmez.

## İlgisiz Dosyanın Eşiği Yoktur

Son üç seçili satır tek bir soruyu yanıtlıyor: doğru dosyalar zaten gönderildikten sonra
**fazladan bir dosya** ne yapar. Yanıt düzgün ve tek yönlüdür. Beklenen kabul **0,8233'ten
0,7833'e, 0,7433'e ve 0,7029'a** iniyor; her ilgisiz dosya tam **0,0400** götürüyor. Bedel aynı
anda **2274'ten 4068'e** çıkıyor, yine adım başına 624 belirteç.

Burada aranan "isabetin düştüğü nokta" bir eşik değildir: **ilk ilgisiz dosyadan başlar**. Bedava
bir ilgisiz dosya yoktur, çünkü ilgisizlik terimi doğrusaldır ve örtüşme terimi zaten
doyurulmuştur. Üç ilgisiz dosya eklemek belirteci **yüzde yetmiş dokuz** artırıp beklenen kabulden
**0,1204** götürüyor — eklenen düzeneğin işi kötüleştirdiği en yalın satır budur.

Sayılan kabul burada da yanıltıcıdır ve niçin olduğu görülüyor: 19, 19, 20, 17 diye gidiyor,
ikinci koşumda 19, 18, 18, 20. Tek koşuma bakan biri "iki ilgisiz dosya kabulü yükseltti"
diyebilir. Beklenen kabul sütunu bu yorumu kapatıyor. Yirmi dört görevlik bir kümede tek bir
kabulün ağırlığı 0,0417'dir, yani ilgisiz bir dosyanın gerçek etkisinden büyüktür; sayılan kabul
bu ayrıntıyı gösterecek çözünürlükte değildir ve daha büyük bir görev kümesi gerektirir.

## Sağlayıcının İsabeti Bedelden Bağımsızdır

İkinci tablo bağlam seçimini bir yeteneğe çeviriyor. Sağlayıcı her isabet düzeyinde **aynı sayıda
dosya** gönderir, dolayısıyla belirteç sütunu beş satırda da **2274**'tür. Değişen tek şey
**hangi** dosyaların gönderildiğidir, ve beklenen kabul **0,4960 ile 0,8233 arasında** oynuyor.
Bağlam kalitesi burada belirteçle satın alınmıyor; ölçülen fark tamamen seçimin kendisinden
geliyor.

Bu tablonun son satırı, bir önceki tablonun seçili satırıyla aynıdır ve aynı olması gerekir:
**1,00 isabet**, gereken kümeyi her görevde bilen bir sağlayıcıdır. Böyle bir sağlayıcı bir ölçüm
kurgusudur, bir kurulum değil. Hangi dosyaların gerektiğini bilmek, görevin çözülmüş olmasına çok
yakın bir bilgidir; gerçek bir sağlayıcı bunu ad benzerliği, çağrı ilişkisi ya da geçmiş
değişikliklerden **tahmin eder**. Bu yüzden 0,8233 bir hedef değil bir **üst sınırdır**, ve tablo
o sınıra ne kadar yaklaşıldığının bedelini değil, yaklaşamamanın bedelini gösterir.

Sıfır isabette bile bulunan gereken dosya payı **0,4667**'dir, çünkü iki dosyalık bir görevden
biri düşürüldüğünde öbürü yerinde kalır. Yani kötü bir sağlayıcı sıfır değildir, sadece
zayıftır — ve 0,4960 beklenen kabul, hiç bağlam göndermemenin (0,3383) üzerindedir.

Asıl karar noktası ortadadır. Bütün kod tabanını göndermek **0,6921** veriyor. Sağlayıcı bunu
0,50 isabette geçemiyor (**0,6404**), 0,75 isabette geçiyor (**0,7050**). Yani bir bağlam
sağlayıcısı, gereken dosyaları **dört görevin yaklaşık üçünde** bulabiliyorsa her şeyi göndermekten
iyidir; bulamıyorsa daha kötüdür ve üstelik bunu ucuz olduğu için fark etmek zordur. Bedel sütunu
sabit olduğu için sağlayıcının kötülüğü faturada görünmez, yalnız kabulde görünür.

## Özet

- Bağlamı büyütmek beklenen kabulü 0,3383'ten 0,6921'e çıkarır ve her adım tam 624 belirteç eder;
  eğri düzgündür ve hiçbir adımda düşmez.
- Bağlamı seçmek aynı görev kümesinde 0,8233 verir; bunu 45 dosya ve 2274 belirteçle yapar, yani
  bütün kod tabanından hem 0,1312 yüksek hem yaklaşık yarı bedelde.
- Neredeyse eşit bütçede fark daha da büyüktür: toplu iki dosya 2352 belirteçle 0,5402, seçili
  bağlam 2274 belirteçle 0,8233.
- İlgisiz her dosya beklenen kabulden tam 0,0400 götürür ve 624 belirteç ekler; eşiği yoktur,
  ilk dosyadan başlar ve üç dosyada 0,1204 kayıp eder.
- Sayılan kabul bu kararların ikisinde de ayrım yapmaz (19/24'e karşı 18/24, ikinci koşumda
  tersine döner); ayrımı koşumdan bağımsız beklenen kabul sütunu yapar.
- Bağlam sağlayıcının belirteç bedeli isabetinden bağımsızdır ve 2274'te sabittir; bütün kod
  tabanını göndermeyi geçmesi için gereken dosyaları dört görevin yaklaşık üçünde bulması gerekir.

## Sonraki Adım

Bu iki derste her görev **tek bir çağrıydı**: bağlam gitti, öneri geldi, geliştirici kabul etti ya
da etmedi. Karar noktası tekti ve hemen oradaydı. Bir geliştirme işi çoğu zaman böyle durmaz —
bir dosyayı okumak, bir işlevi değiştirmek, çağıranları güncellemek ve raporu yeniden biçimlemek
tek bir istekle devredildiğinde ortaya **çok adımlı** bir iş çıkar ve geliştirici artık her adımda
değil, durduğu yerde bakar. Sonraki ders bu durma yerini ölçer: kaç adımda bir durulduğunda bir
hata **yayılmadan** yakalanıyor, kaç adım boşa gidiyor ve durmanın kendisi kaç çağrıya mal oluyor.
