Ders 15 / 26
Kod Yardımcıları
Kurgu bir kod tabanı üzerinde tamamlama, açıklama ve dönüştürme kullanımlarının kabul oranıyla ölçülmesi: bağlamsız çağrı yirmi dört görevin yalnız yedisini kabule götürüyor ve çöküş tamamlama (1/8) ile dönüştürmede (2/8); ayakta kalan tek sınıf açıklama (4/8). Açık dosya bağlamı 10/24 veriyor ama aynı kurulumun iki koşum farkı 2/24 olduğu için kazanç dar. Bütün kod tabanı 18/24'e çıkarıyor, bedeli 1104 belirteçten 4224 belirtece; bin belirteç başına kabul 6,34'ten 4,26'ya düşüyor. Koşumdan bağımsız beklenen kabul sütununda dönüştürme, bütün kod tabanıyla bile (0,4675) hiç bağlamsız açıklamanın (0,6450) altında kalıyor.
İçindekiler
Bu kursun buraya kadarki dersleri çağrıyı hep bir ürünün içinde ele aldı: bir abone kısa bir destek talebi yazıyor, bir istemci onu bir model uç noktasına gönderiyor, ve ölçülen şey o hattın belirteci, yeniden denemesi, önbellek isabeti ve kesinti payı oluyordu. Aynı çağrının bir yerde daha yapıldığı hiç sayılmadı: geliştiricinin kendi masasında, henüz hiçbir aboneye ulaşmamış bir kodun üzerinde.
Oradaki ölçü farklıdır. Yanıtı okuyan bir abone değil, kodu yazan kişidir; ve o kişi yanıtı ya olduğu gibi kullanıma alır ya da atıp kendi yazar. Bu dersin ölçütü budur: kabul. Ders kurgu bir kod tabanı kurar, üç kullanım sınıfını aynı görev kümesinde ölçer ve düzeneksiz çağrının hangi sınıfta çöktüğünü sayar.
- YG1. Kod tabanı kurgudur: ölçüm ağının kendi yardımcı betikleri. Hiçbir gerçek depo, paket, çerçeve ya da ürün değildir. Beş modül, 53 satır.
- YG2. Kod yardımcısı bir benzeticidir; gerçek bir yardımcı, düzenleyici ya da eklenti
çağrılmaz. Tohum 20260218,
randomkullanılmaz. - YG3. Ölçüt kabuldür: geliştirici öneriyi kullanıma alıyorsa kabul, yeniden yazıyorsa ret. Önerinin gerçekten doğru olup olmadığı ayrı bir sorudur ve bu derste sorulmaz.
- YG4. Üç kullanım sınıfı: tamamlama (eksik bir gövdeyi yazmak), açıklama (var olan bir parçanın ne yaptığını söylemek), dönüştürme (var olan bir parçayı başka bir biçime çevirmek). Sınıf başına sekiz kurgu görev, toplam yirmi dört.
- YG5. Taban kabul olasılığı sınıfa göre farklıdır: açıklama 0,72, tamamlama 0,34, dönüştürme 0,18. Gerekçe yapısaldır: açıklamanın girdisi istemin içindedir; tamamlama ile dönüştürme kod tabanının geri kalanına uymak zorundadır.
- YG6. Bağlam örtüşmesi kabulü yükseltir, ilgisiz dosya düşürür, görev zorluğu düşürür. Üçü tek bir puanda toplanır ve puan sıfır ile bir arasına kırpılır.
- YG7. Bedel belirteçtir: taban 40, bağlamdaki dosya başına 26, dönüştürmeye 18 ek. Gecikme sınıfı üç kurulumda da aynıdır: tek çağrı, görev başına bir tane.
- YG8. Koşumdan bağımsız ölçü beklenen kabuldür (puanların ortalaması); sayılan kabul iki koşumda ayrı basılır (tohum 20260218 ve 20260219).
Kurgu Kod Tabanı
Ölçüm ağının saha ekibi, sayaç okumalarını rapora çeviren bir avuç yardımcı betik taşıyor. Bu betikler bir ürün değil, bir ekibin kendi işini gördüğü kısa dosyalardır ve kurgudur. Beş modül bir sözlükte tutulur; böylece hem tek blokta gösterilebilir hem de bağlam seçimi dosya adıyla yapılabilir.
# KURGU KOD TABANI -- gercek bir depo, paket ya da urun degildir. Olcum aginin # kendi yardimci betikleri: bes modul. Tohum 20260218. KOD = { "okuma.py": """ def ayristir(satir): p = satir.split(";") if len(p) != 4: return None if not p[3].lstrip("-").isdigit(): return None return {"abone": p[0], "bolge": p[1], "donem": p[2], "endeks": int(p[3])} def tuketim(onceki, simdiki): fark = simdiki - onceki if fark < 0: fark = fark + 100000 return fark """, "tarife.py": """ BASAMAK = ((10, 4), (25, 7), (40, 11)) USTU = 16 def bedel(m3): kalan, alt, top = m3, 0, 0 for ust, birim in BASAMAK: dilim = min(kalan, ust - alt) if dilim <= 0: break top += dilim * birim kalan -= dilim alt = ust return top + kalan * USTU """, "denetim.py": """ GECERLI_BOLGE = ("dogu", "bati", "kuzey", "guney", "merkez") def gecerli(kayit): if kayit is None: return False if kayit["endeks"] < 0: return False return kayit["bolge"] in GECERLI_BOLGE def ayikla(kayitlar): return [k for k in kayitlar if gecerli(k)] """, "ozet.py": """ def bolge_toplam(kayitlar, tuketimler): top = {} for k, t in zip(kayitlar, tuketimler): top[k["bolge"]] = top.get(k["bolge"], 0) + t return top def bolge_sayi(kayitlar): say = {} for k in kayitlar: say[k["bolge"]] = say.get(k["bolge"], 0) + 1 return say """, "bicim.py": """ def satir(bolge, m3, tutar): return bolge.ljust(8) + str(m3).rjust(7) + str(tutar).rjust(9) def rapor(baslik, satirlar): return "\\n".join([baslik] + satirlar) """, } def yukle(kod): ad = {} for dosya, kaynak in kod.items(): alan = {} exec(kaynak, alan) ad[dosya] = alan return ad AD = yukle(KOD) BOY = {d: len(k.strip().split("\n")) for d, k in KOD.items()} print("modul satir") for d in KOD: print(f" {d:<10}{BOY[d]:>4}") print(f" {'toplam':<10}{sum(BOY.values()):>4}") OKUMA = [ # KURGU sayac okumalari "A017;dogu;2026-01;41250", "A017;dogu;2026-02;41312", "B204;bati;2026-02;99800", "B204;bati;2026-03;300", "C088;kuzey;2026-02;7130", "C088;kuzey;2026-03;7166", "D311;disari;2026-03;5000", "E402;guney;2026-03;bozuk", ] kayitlar = [AD["okuma.py"]["ayristir"](s) for s in OKUMA] temiz = AD["denetim.py"]["ayikla"](kayitlar) print("\nokunan", len(kayitlar), "gecerli", len(temiz)) esler = [(temiz[i], temiz[i + 1]) for i in range(0, len(temiz) - 1, 2)] tuk = [AD["okuma.py"]["tuketim"](a["endeks"], b["endeks"]) for a, b in esler] sonraki = [b for _, b in esler] toplam = AD["ozet.py"]["bolge_toplam"](sonraki, tuk) satirlar = [AD["bicim.py"]["satir"](b, m, AD["tarife.py"]["bedel"](m)) for b, m in sorted(toplam.items())] print(AD["bicim.py"]["rapor"]("bolge m3 tutar", satirlar))
modul satir okuma.py 13 tarife.py 13 denetim.py 11 ozet.py 11 bicim.py 5 toplam 53 okunan 8 gecerli 6 bolge m3 tutar bati 500 7670 dogu 62 662 kuzey 36 266
Beş modül birbirine bağlıdır ve tek bir hat kurar: okuma.py satırı kayda çevirir, denetim.py
geçersizleri atar, ozet.py bölgeye toplar, tarife.py basamaklı bedeli hesaplar, bicim.py
hizalı satırı yazar. Sekiz okumanın ikisi elenmiştir: biri tanınmayan bir bölge taşıyor, birinin
endeksi sayı değil. Batı bölgesinin 500 metreküpü de bir kural sonucudur; sayaç 99800’den 300’e
dönmüştür ve tuketim bu dönüşü telafi eder.
53 satırın tamamı bir istemin içine sığar. Kod tabanının küçük tutulması kasıtlıdır: burada “bağlamı büyütmek” gerçekten bir seçenektir ve bedeli sayılabilir. Büyük bir depoda bu seçenek zaten yoktur, ama ölçünün yönü aynıdır.
Üç Kullanım Sınıfı ve Kabul
Yirmi dört kurgu görev üç sınıfa bölünür. Tamamlama bir gövdeyi yazmayı ister: bölge sayımı
alan yeni bir işlev, eksik bir dal, bir kenar durumu. Açıklama var olan bir parçanın ne
yaptığını sorar: tuketim niçin 100000 ekliyor, BASAMAK demeti neyi kodluyor. Dönüştürme
var olan bir parçayı başka bir biçime çevirir: sözlük yerine demet döndürmek, döngüyü kavramaya
çevirmek, iki modülü ortak bir imzada birleştirmek.
Bu üç sınıfın kabul oranı aynı olmaz ve nedeni benzeticiye taban olasılık olarak yazılmıştır. Açıklamanın girdisi istemin içindedir: açıklanacak parça zaten gönderilmiştir, dışarıdan bir şey bilmek gerekmez. Tamamlama ile dönüştürme ise kod tabanının görülmeyen kısmına uymak zorundadır — hangi anahtar adları kullanılıyor, hangi işlev neyi döndürüyor, hangi geçersizlik kuralı nerede uygulanıyor.
# YARDIMCI BENZETICISI -- KURGUDUR. Gercek bir kod yardimcisi cagrilmaz. # Kabul, gorev sinifi ile baglam ortusmesinden hesaplanir; random kullanilmaz. 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") DOSYA = ("okuma.py", "tarife.py", "denetim.py", "ozet.py", "bicim.py") GEREKEN = { # gorev numarasi -> gereken dosyalar 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): 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} KURULUM = (("yok", ()), ("acik dosya", ("okuma.py",)), ("butun kod tabani", DOSYA)) def olc(baglam, sinif, tohum=TOHUM): g = [x for x in GOREV if x["sinif"] == sinif] s = [yardimci(x, baglam, tohum) for x in g] return (sum(x["kabul"] for x in s), sum(x["puan"] for x in s) / len(s), sum(x["belirtec"] for x in s)) print("gorev sayisi", len(GOREV), " ornek:", ", ".join(g["ad"] + " -> " + "+".join(g["gereken"]) for g in GOREV[:2])) print("\nbaglam sinif beklenen kabul A kabul B") for ad, b in KURULUM: for s in SINIF: ka, p, _ = olc(b, s) kb, _, _ = olc(b, s, TOHUM + 1) print(f"{ad:<18}{s:<12}{p:>8.4f}{ka:>7}/8{kb:>7}/8") print("\nbaglam toplam A toplam B belirtec kabul/1000 belirtec") for ad, b in KURULUM: ta = sum(olc(b, s)[0] for s in SINIF) tb = sum(olc(b, s, TOHUM + 1)[0] for s in SINIF) bel = sum(olc(b, s)[2] for s in SINIF) print(f"{ad:<18}{ta:>7}/24{tb:>8}/24{bel:>10}{1000 * ta / bel:>17.2f}")
gorev sayisi 24 ornek: tamamlama-1 -> okuma.py, tamamlama-2 -> tarife.py baglam sinif beklenen kabul A kabul B yok tamamlama 0.2650 1/8 1/8 yok aciklama 0.6450 4/8 6/8 yok donusturme 0.1050 2/8 0/8 acik dosya tamamlama 0.3954 3/8 1/8 acik dosya aciklama 0.7417 5/8 6/8 acik dosya donusturme 0.2429 2/8 1/8 butun kod tabani tamamlama 0.6275 6/8 7/8 butun kod tabani aciklama 0.9813 8/8 8/8 butun kod tabani donusturme 0.4675 4/8 5/8 baglam toplam A toplam B belirtec kabul/1000 belirtec yok 7/24 7/24 1104 6.34 acik dosya 10/24 8/24 1728 5.79 butun kod tabani 18/24 20/24 4224 4.26
Düzeneksiz Çağrının Çöktüğü Yer
İlk üç satır çıplak çağrının tablosudur: bağlam yok, yalnız görev tarifi gönderiliyor. Yirmi dört görevin yedisi kabul ediliyor ve ikinci koşumda da yedisi. Toplam sabit görünse de dağılım sabit değildir, ve asıl bilgi dağılımdadır.
Çöküş iki sınıftadır. Tamamlama 1/8, iki koşumda da aynı; beklenen kabul 0,2650. Dönüştürme 2/8 ve ikinci koşumda 0/8; beklenen kabul 0,1050, tablonun en düşük sayısı. Ayakta kalan tek sınıf açıklamadır: 4/8 ve 6/8, beklenen kabul 0,6450. Bir geliştirici bağlamsız bir yardımcıya “bu işlev ne yapıyor” diye sorabilir ve yanıtın yarısından fazlasını kullanabilir; aynı yardımcıdan “bu işlevi tamamla” istediğinde sekiz denemenin yedisini atacaktır.
Neden yapısaldır ve sayı onu doğrular. Açıklama görevinde bilinmesi gereken her şey isteme konulmuştur. Tamamlama görevinde ise yazılacak gövdenin döndüreceği sözlüğün anahtarları, çağıracağı işlevin adı ve uyacağı geçersizlik kuralı başka dosyalardadır. Yardımcı onları göremediği için makul ama uymayan bir kod üretir; makul kod da reddedilen koddur.
Sınıf içinde de dağılım vardır ve tek sayı onu gizler. Her sınıfın sekiz görevi dört ayrı zorluk kademesine dağılır ve zorluk kabul puanından doğrudan düşülür; sınıfın ortalaması, en kolay görevle en zor görevin arasında bir yerdedir. İki koşum farkı ise ayrı bir şeyi ölçer: aynı görev, aynı bağlam ve aynı puan, iki tohumda iki ayrı karara varabilir. Bu yüzden tabloda sayılan kabulün yanına beklenen kabul sütunu konulmuştur; sayılan kabul koşuma bağlıdır, beklenen kabul kurulumun kendisine.
Bağlamın Kattığı ve Ödettiği
İkinci kurulum bir geliştiricinin en kolay yaptığı şeydir: o an açık olan dosyayı da göndermek.
Burada bu dosya okuma.py, ve her görev için aynı. Toplam 7/24’ten 10/24’e çıkıyor, kazanç
3/24. Aynı kurulumun iki koşum farkı ise 2/24 (10’a karşı 8). Kazanç, farkın ancak bir
buçuk katıdır; üstelik tamamlama sütununda yön tersine dönüyor (3/8 ve 1/8). Sabit tek bir
dosya bir düzenek değildir; görevle ilgisi olduğunda yardım eder, olmadığında ilgisiz bağlam
olarak sayılır.
Üçüncü kurulum belirsiz değildir. Bütün kod tabanı gönderildiğinde toplam 18/24 ve ikinci koşumda 20/24; tabana göre kazanç 11/24, iki koşum farkının beş katından fazla. Üç sınıf da yükseliyor: tamamlama 1/8’den 6/8’e, açıklama 4/8’den 8/8’e, dönüştürme 2/8’den 4/8’e.
Bedel sütunu bu kazancın fiyatını yazıyor. Çağrı sayısı üç kurulumda da 24‘tür ve gecikme sınıfı tek çağrı olarak aynı kalır; değişen yalnız belirteçtir: **1104’ten 4224’e**, yaklaşık 3,8 kat. Bin belirteç başına kabul ise 6,34’ten 5,79’a, oradan 4,26’ya düşüyor. Düzenek işi iyileştirdi ve birim başına verimi düşürdü; ikisi aynı anda doğrudur ve ikisi de yazılmak zorundadır.
Son olarak koşumdan bağımsız sütun bir sıralamayı sabitliyor. Dönüştürme, bütün kod tabanı verildiğinde bile 0,4675’te kalıyor; açıklama hiç bağlam olmadan 0,6450. Bağlam eklemek sınıfların yerini değiştirmiyor, hepsini birlikte yukarı taşıyor. Bir kod yardımcısını “iyi” ya da “kötü” diye tek sayıyla anmak bu yüzden yanıltıcıdır: sayı görev sınıfına göre değişir ve en çok bağlam alan zor sınıf, en az bağlam alan kolay sınıfın gerisinde kalabilir.
Özet
- Kurgu kod tabanı beş modül ve 53 satırdır; okuma, denetim, özet, tarife ve biçim tek bir rapor hattı kurar ve tamamı bir istemin içine sığar.
- Ölçüt kabuldür ve üç kullanım sınıfına göre ayrı sayılır; sınıflar arası fark yapısaldır, çünkü açıklamanın girdisi istemin içinde, tamamlama ile dönüştürmenin girdisi dışarıdadır.
- Bağlamsız çağrı 7/24 kabul veriyor; çöküş tamamlama (1/8) ile dönüştürmede (2/8), ayakta kalan tek sınıf açıklama (4/8, beklenen 0,6450).
- Tek bir sabit dosya eklemek 10/24 veriyor ama aynı kurulumun iki koşum farkı 2/24’tür ve tamamlama sütununda yön tersine döner: sabit bağlam bir düzenek değildir.
- Bütün kod tabanı 18/24’e çıkarıyor; bedel 1104 belirteçten 4224 belirtece, bin belirteç başına kabul 6,34’ten 4,26’ya iniyor. Çağrı sayısı ve gecikme sınıfı değişmiyor.
- Bağlam sınıfların sırasını değiştirmiyor: tam bağlamlı dönüştürme (0,4675) bağlamsız açıklamanın (0,6450) altında kalır.
Sonraki Adım
Bu derste bağlam üç kez sabit verildi: hiç, hep aynı dosya, ya da hepsi. Üçü de bir seçim değildir. Gerçek bir masada bağlam her görev için yeniden kurulur ve iki soru sorulur: hangi dosyalar ve kaç tane. Yukarıdaki tablo bu soruların ikisini de yanıtsız bırakıyor; yalnız uçları gösteriyor. Sonraki ders arayı doldurur: dosya sayısı bir bir artarken belirteç nasıl büyüyor, kabul nerede tepe yapıyor, ve görevle ilgisi olmayan bir dosya kabule ne yapıyor. Orada ölçülecek olan bağlamın boyu değil, seçimidir.
İlerlemeni kaydetmek ve not almak için Giriş yap
Notlarım
Not almak için giriş yapmalısın.