Ders 14 / 14
Belgelendirme
Dört kaynak sürümünden üretilen belge 2 ayrı sonuç verir ve bayat imza sayısı dördünde de 0 kalırken elle yazılan belgede 2 ile 3 arasında durur; üretim imzayı tekleştirir, özet metnindeki iddiayı tekleştirmez ve o iddiayı ancak çalıştırılabilir örnek yakalar.
İçindekiler
Önceki ders yayımlanmış bir sürümün içeriğini adına bağladı: değiştirilemez bir kayıtta
(ad, sürüm) çifti tek bir dağıtımı adlandırır. Paket kurulan tarafa kodu taşır.
Kodun nasıl kullanılacağını taşımaz. O bilgi belgeden gelir ve belge iki yoldan üretilebilir: elle yazılarak ya da kaynaktan üretilerek. Bu kursun son dersi ikisini aynı soruyla ölçer: üretim hangi sonucu tekleştirir, hangisini tekleştirmez?
Üretimin Girdisi ve Çıktısı
Kaynaktan belge üretiminin yaklaşımları Teknik Yazarlık ve Dokümantasyon kursunda kuruldu; bayatlama ve denetim de orada ele alındı. Burada o tartışma tekrarlanmaz. Ölçülen tek şey, üretimin kaç ayrı sonucu bire indirdiğidir.
Bu kurs araç adı yazmaz. Belge üreticisi burada tek bir işlevle modellenir: kaynağı ayrıştırır, adı alt çizgiyle başlamayan işlevleri seçer, her biri için imzayı ve özet metninin ilk satırını okur, sonucu ada göre sıralar. Gerçek bir üretici çok daha fazlasını yapar — bağlantı kurar, tip bilgisini işler, sayfa düzeni üretir; modelin tuttuğu tek özellik, çıktısının tümüyle kaynaktan türetilmiş olmasıdır.
Ölçüm dört kaynak sürümü tanımlar: kanonik yazım, işlev tanımlarının sırası değişmiş yazım, özel bir yardımcı işlevin eklendiği yazım, ve iki imzanın değiştiği yazım. Bunların yanında bir de elle yazılmış belge durur; eski imzalarla yazılmıştır ve o günden beri elle güncellenmemiştir.
Ölçümün varsayımları:
- KY29 — Üç işlev ortak kurgudan alınır;
indirimişlevinin gövdesi değiştirilmez ve kusurlu tavan yerinde durur. - KY30 —
indirimişlevinin özet metni tavanın yüzde 25 olduğunu yazar; gövde ise 20 uygular. İddia ile davranış arasındaki bu ayrım kurgunun kendisidir. - KY31 — Belge üreticisi yalnız kaynaktan okur ve hiçbir iddiayı davranışla karşılaştırmaz; yaptığı denetim sayısı 0’dır.
- KY32 — Elle yazılan belge dört kaynak sürümünde de aynıdır; kaynağı hiç izlemez.
- KY33 — Çalıştırılabilir örneklerin koşumu standart kitaplığın belge testi düzeneğiyle yapılır. Belge testinin ne olduğu bu kursun belge testleri dersinde kuruldu; burada bir denetim aracı olarak kullanılır, yeniden kurulmaz.
- KY34 — Süre ölçülmez, dosya yazılmaz. Sayılan şey ayrı belge, bayat imza ve düşen örnek sayısıdır.
Ölçüm
"""Belgelendirme: uretim neyi tekleştirir, neyi tekleştirmez.""" import ast import doctest import hashlib import types GOVDE = { "indirim": ( "(tutar, uye, kupon)", '"""Uye ve kupon indirimini uygular; tavan oran yuzde 25\'tir.\n\n' " >>> indirim(100, True, True)\n 75\n \"\"\"\n" " oran = 0\n if uye:\n oran += 10\n" " if kupon:\n oran += 15\n" " if oran > 20:\n oran = 20\n" " return tutar - tutar * oran // 100\n"), "uygun": ( "(paket)", '"""Bildirimin araligina giren surumleri verir.\n\n' ' >>> uygun("rapor")\n [(1, 0), (1, 1)]\n """\n' " alt, ust = BILDIRIM[paket]\n" " return [s for s in DEPO[paket] if alt <= s < ust]\n"), "kilit": ( "(secim)", '"""Cozumlemenin sonucunu sabitler.\n\n' " >>> kilit({\"rapor\": (1, 1)})\n {'rapor': (1, 1)}\n \"\"\"\n" " return dict(secim)\n"), } BASLIK = ('DEPO = {"rapor": [(0, 9), (1, 0), (1, 1)]}\n' 'BILDIRIM = {"rapor": ((1, 0), (2, 0))}\n\n\n') YARDIMCI = 'def _normalle(s):\n """Ic kullanim."""\n return tuple(s)\n\n\n' YENI_IMZA = {"indirim": "(tutar, uye, kupon, tavan)", "kilit": "(secim, dogrula)"} def kur(adlar, yardimci=False, imza_degisti=False): p = BASLIK + (YARDIMCI if yardimci else "") for ad in adlar: im, govde = GOVDE[ad] if imza_degisti and ad in YENI_IMZA: im = YENI_IMZA[ad] p += f"def {ad}{im}:\n {govde}\n\n" return p SURUMLER = { "kanonik": kur(["indirim", "uygun", "kilit"]), "sırası değişik": kur(["kilit", "uygun", "indirim"]), "özel yardımcı eklenmiş": kur(["indirim", "uygun", "kilit"], yardimci=True), "imzası değişmiş": kur(["indirim", "uygun", "kilit"], imza_degisti=True), } ELLE = {"indirim": "indirim(tutar, uye)", "uygun": "uygun(paket, bildirim)", "kilit": "kilit(secim)"} def uret(kaynak): """Belge ureticisi modeli: genel adlarin imzasi ve ozeti kaynaktan okunur.""" kayit = {} for d in ast.parse(kaynak).body: if isinstance(d, ast.FunctionDef) and not d.name.startswith("_"): im = ", ".join(a.arg for a in d.args.args) ilk = (ast.get_docstring(d) or "").split("\n")[0] kayit[d.name] = f"{d.name}({im}) — {ilk}" return "\n".join(kayit[a] for a in sorted(kayit)) def imza(kaynak, ad): for d in ast.parse(kaynak).body: if isinstance(d, ast.FunctionDef) and d.name == ad: return f"{ad}({', '.join(a.arg for a in d.args.args)})" return "" def belgedeki_imza(belge, ad): for s in belge.splitlines(): if s.startswith(ad + "("): return s.split(" — ")[0] return "" def ozet(metin): return hashlib.sha256(metin.encode()).hexdigest()[:8] print(f"{'kaynak sürümü':<24s} {'genel ad':>8s} {'belge özeti':>12s} " f"{'üretilende bayat':>16s} {'elle yazılanda bayat':>21s}") belgeler = [] for ad, k in SURUMLER.items(): b = uret(k) belgeler.append(ozet(b)) bu = sum(1 for a in ELLE if belgedeki_imza(b, a) != imza(k, a)) be = sum(1 for a in ELLE if ELLE[a] != imza(k, a)) print(f"{ad:<24s} {len(b.splitlines()):8d} {ozet(b):>12s} " f"{bu:>13d}/{len(ELLE)} {be:>18d}/{len(ELLE)}") print(f"dört kaynak sürümü, {len(set(belgeler))} ayrı üretilmiş belge; " f"elle yazılan belge dördünde de aynı") print() modul = types.ModuleType("olcum") exec(compile(SURUMLER["kanonik"], "<olcum>", "exec"), modul.__dict__) denenen, dusen = 0, [] for t in doctest.DocTestFinder().find(modul): kosucu = doctest.DocTestRunner(verbose=False) kosucu.run(t, out=lambda s: None) denenen += kosucu.tries if kosucu.failures: dusen.append(t.name.split(".")[-1]) print(f"belge testi {denenen} örnek denedi, {len(dusen)} tanesi düştü: " f"{', '.join(dusen)}") print("belge üreticisinin iddia için yaptığı denetim: 0")
kaynak sürümü genel ad belge özeti üretilende bayat elle yazılanda bayat kanonik 3 0aab9512 0/3 2/3 sırası değişik 3 0aab9512 0/3 2/3 özel yardımcı eklenmiş 3 0aab9512 0/3 2/3 imzası değişmiş 3 65a37bdf 0/3 3/3 dört kaynak sürümü, 2 ayrı üretilmiş belge; elle yazılan belge dördünde de aynı belge testi 3 örnek denedi, 1 tanesi düştü: indirim belge üreticisinin iddia için yaptığı denetim: 0
Tekleşen: İmza
Tablonun ilk üç satırı aynı belge özetini veriyor: 0aab9512. Üç kaynak sürümü ayrı
metinlerdir — biri işlev tanımlarını başka sırada yazar, biri özel bir yardımcı işlev
taşır — ama ürettikleri belge tektir. Üretici çıktısını ada göre sıraladığı için tanım
sırası düşer; alt çizgiyle başlayan adı atladığı için özel yardımcı düşer.
Dördüncü satır ayrı bir özet veriyor: 65a37bdf. İki imza değişti, belge değişti. Bu bir
kusur değil, üretimin tanımıdır: belge kaynağın genel arayüzünü izler ve yalnız onu
izler.
Bayat imza sütunları ayrımı sayıyla veriyor. Üretilen belgede bayat imza dört sürümde de 0/3. Elle yazılan belgede ilk üç sürümde 2/3, dördüncüde 3/3 — üstelik elle yazılan belge hiç değişmedi. Kaynak ilerledikçe bayatlık kendiliğinden büyüyor ve bunu haber veren hiçbir şey yok.
Aradaki fark bir emek farkı değil, bir bağ farkıdır. Üretilen belgede imza ile kaynak arasında bir kopya yoktur; imza her üretimde yeniden okunur. Elle yazılan belgede kopya vardır ve kopyanın aslıyla eşit kalması bir insanın hatırlamasına bağlıdır. Üretimin tekleştirdiği sonuç tam olarak budur: aynı kaynaktan tek belge, ve o belgede sıfır bayat imza.
Tekleşmeyen: İddia
Alt satırlar ölçümün ikinci yarısını veriyor ve tekleşmenin nerede durduğunu gösteriyor.
indirim işlevinin özet metni tavanın yüzde 25 olduğunu yazıyor; gövde 20 uyguluyor.
Üretici bu satırı belgeye olduğu gibi taşıyor. Yaptığı denetim sayısı 0, çünkü
üretici bir kopyalayıcıdır: kaynakta ne yazıyorsa belgede o yazar. Kaynağın kendisi yanlış
bir şey söylüyorsa, üretim o yanlışı daha da yaygınlaştırır.
Belge testi ise 3 örnek deniyor ve 1 tanesi düşüyor: indirim. Düşmesinin nedeni
örneğin yanlış olması değil, örneğin çalıştırılabilir olmasıdır. Aynı iddia düzyazı
olarak yazılsaydı hiçbir şey düşmezdi.
Buradan dersin sonucu çıkar. Üretim iki sonucu tekleştirir: belgenin kaynakla aynı arayüzü göstermesini, ve aynı kaynaktan aynı belgenin çıkmasını. Bir sonucu tekleştirmez: belgedeki iddianın davranışla uyuşmasını. O uyuşma ancak iddia çalıştırılabilir bir biçimde yazıldığında sınanır, ve sınandığında da denetleyen şey belge üreticisi değil, testtir.
Bu, kursun kapsam ölçümüyle aynı biçimdedir. Kapsam kodun nerede yürüdüğünü sayar, testin neye baktığını değil. Üretim belgenin neyi gösterdiğini belirler, doğru olup olmadığını değil. Her araç kendi girdisine bakar; kâhini olan tek şey beklentidir.
Özet
- Belge üreticisi çıktısını tümüyle kaynaktan türetir; tanım sırası ve özel adlar sonuca girmez.
- Dört kaynak sürümü 2 ayrı üretilmiş belge verir; ilk üçü tek bir özette birleşir, dördüncüsü imza değiştiği için ayrılır.
- Üretilen belgede bayat imza dört sürümde de 0/3; elle yazılan belgede 2/3 ve 3/3, üstelik belge hiç değişmeden.
- Üretim iddiayı tekleştirmez:
indirimişlevinin özet metnindeki yüzde 25 iddiası belgeye olduğu gibi taşınır ve üreticinin yaptığı denetim 0’dır. - Aynı iddia çalıştırılabilir örnek olarak yazıldığında 3 örnekten 1’i düşer; iddiayı sınayan şey üretici değil, testtir.
Kurs Kapanışı
Bu kurs on dört ders boyunca tek bir soru sordu: aynı girdi kaç ayrı sonuç verdi? Soru hiçbir derste “çalışıyor mu” biçimine dönüşmedi, çünkü çalışan bir şeyin kaç ayrı biçimde çalıştığı ayrı bir sorudur ve yeniden üretilebilirlik o soruyla ölçülür.
| ders | ölçülen | ayrı sonuç sayısı |
|---|---|---|
| Sanal Ortamlar | altı kurulum sırası, paylaşılan ve yalıtılmış site | paylaşılanda 5, yalıtılmışta 1 |
| Bağımlılık Bildirimi | aynı bildirim, iki strateji ve iki depo görüntüsü | 2, kilitle 1; dört kurulumda 3, kilitle 1 |
| Paket Yöneticileri | dört çözümleme stratejisi, gevşek ve sıkı kısıt | 4 küme (3 tutarlı); sıkıda 2 küme (0 tutarlı); kilitle 1 |
| Sürüm Yönetimi | aynı bildirim üç kurgu yorumlayıcıda | 2; dokuz kurulumda 6 kabul, 3 ret |
| Test Çerçeveleri | iki yazım biçimi, üç keşif kuralı | yazımda 1; bulunan testte 3, raporda 1 |
| Düzenek ve Parametreleme | aynı beş testlik takım üç sırada | 2, düzenekle 1 |
| Sahte Nesneler | aynı test üç kipte, sahte ve gerçek kaynak | gerçekle 3, sahteyle 1; sapmış sahteyle 2 |
| Belge Testleri | on iki iddianın biçim değişikliğiyle bayatlaması | sese dönen bayat 4 ve 6: 2 |
| Kapsam Ölçümü | üç testlik kümenin kapsamı ve kâhinden sapan çağrı | satır ve dal 1,0000, geçen 3/3; sapan çağrı 1; dördüncü testle kapsam 1, geçen oranı 2 |
| Biçimlendirici ve Tüy Toplayıcılar | aynı işlevin altı ayrı yazımı | metin 6 → 1; bulgu kümesi 5 → 1 |
| Çoklu Ortam Testi | aynı takım üç eksenli matriste, 18 koşum | 4; kilitle 3, düzenekle 2 |
| Paketleme | aynı kaynaktan dokuz üretim, üç dahil etme kuralı | 5; açık listeyle 1; kurulumda 3 ve 1 |
| Yayımlama | aynı kilit dosyasıyla iki kurulum, iki kayıt ilkesi | 2, değiştirilemez kayıtta 1 |
| Belgelendirme | dört kaynak sürümünden üretilen belge | 2; bayat imza 0’a karşı 2 ve 3 |
Tablonun okunuşu tek cümlede toplanır: hemen her satırda ilk sayı birden büyük, ikinci sayı bir. Aradaki fark bir araç farkı değil, bir karar farkıdır. Kilit dosyası çözümlemeyi ortadan kaldırmadı; kararı bir kez verdirip yazıya geçirdi. Yalıtım kurulumu kolaylaştırmadı; kurulum sırasının sonucu değiştirmesini durdurdu. Düzenek testi hızlandırmadı; sıranın kararı belirlemesini durdurdu. Açık liste dosya seçmedi; seçimin dizinin durumuna bağlı olmasını durdurdu. Her durumda tekleşen şey işin kendisi değil, kararın kaynağıydı.
İkinci bir örüntü de tabloda duruyor: tekleşen sayı doğruluk vermez. Kapsam bire indirdiği yerde bile kusurlu beklentiyi görmedi; biçimlendirici altı yazımı bire indirdi ama kalan altı bulgunun hiçbiri kusuru bildirmedi; belge üretimi belgeyi tekleştirdi ama belgedeki yanlış iddiayı taşıdı. Tekleşme karşılaştırılabilirliğin koşuludur, doğruluğun değil. Doğruluğu veren tek şey kâhindir, ve kâhin her zaman ölçümün dışından gelir.
| kurs | ölçü ekseni |
|---|---|
| Python Temelleri | sözdizimin çağırdığı protokol |
| Veri Yapıları ve Fonksiyonel Araçlar | var edilen, tutulan ve paylaşılan nesne |
| Nesneye Dayalı Python ve Tipler | çağrıyı kim yanıtladı, sözü kim denetledi |
| Eşzamanlılık ve Başarım | örtüşen adım |
| Python Projeleri: Paketleme ve Test | aynı girdi kaç ayrı sonuç verdi |
Beş eksen bir dizi oluşturuyor. İlk kurs sözdizimin altına bakıp her biçimin hangi özel yöntemi çağırdığını saydı. İkincisi nesnenin nasıl var edildiğini, nerede tutulduğunu ve kimlerle paylaşıldığını ölçtü. Üçüncüsü çağrının hangi sınıfta yanıtlandığını ve verilen sözün ne zaman denetlendiğini ayırdı. Dördüncüsü işin kaç adımının örtüştüğünü saydı ve süre yerine adım saymanın gerekçesini kurdu. Beşincisi bunların hepsini bir projeye koydu ve aynı girdinin kaç ayrı sonuç verdiğini sordu.
Beşi birlikte bir dilin kendi düzeneğini kuruyor: dil neyi çağırıyor, ne tutuyor, neyi denetliyor, işi nasıl bölüyor ve bir proje olarak nasıl tekrarlanabilir hale geliyor. Bu düzenek dile özgüdür ve başka bir dile olduğu gibi taşınmaz.
Taşınan şey sorulardır. M08 ile başlayan dil müfredatları aynı beş soruyu başka bir dile sorar ve yanıtları başka çıkar: bir dilde özel yöntemle verilen yanıt öbüründe arayüzle, bir dilde çalışma zamanında denetlenen söz öbüründe derleme anında, bir dilde yorumlayıcı kilidiyle sınırlanan örtüşme öbüründe başka bir düzenekle karşılanır. Bir dilin kendi düzeneği kuruldu; sıra başka bir dilin aynı soruları nasıl yanıtladığında.
İlerlemeni kaydetmek ve not almak için Giriş yap
Notlarım
Not almak için giriş yapmalısın.