İçeriğe geç
academia.sh

Ders 02 / 10

Yaşam Döngüsü

Altı bozulma sınıfının aynı beş aşamalı hattan geçirilip her aşamanın kendi bozulmaya açıklığının sayılması: ayıklama yalnız alan adı değişimini, tekilleştirme yalnız çift kaydı görüyor, tüketim aşaması eksik satırın bedelini tam iki katına çıkarıyor (40 satır 80'e, 46 satır 92'ye, 200 satır 400'e), özet aşamasında hücre sayısı 55'ten 45 ve 53'e düşüyor, sunma aşaması ise altı sınıfın hiçbirinde beş değerden başka bir şey üretmiyor. Üç sınıf sunulan sayıyı birebir aynı bırakıyor: yinelenen tekilleştirmede yutuluyor, kayan_tip hattın kendi tür dönüşümüyle sessizce onarılıyor, birim_degisti ise özetin on hücresini yıktığı hâlde iki dönem birbirini götürdüğü için sunulan değeri değiştirmiyor. gec_gelen ve birim_degisti tam olarak aynı sayıda özet hücresini bozuyor, biri sunumu değiştiriyor öbürü değiştirmiyor.

İçindekiler

Önceki ders hattı sağlam bir kaynakla koşturdu ve iz tablosu her aşamada beklenen sayıyı verdi: 2400, 2400, 2200, 55, 5. Kaynağın sağlam gelmesi bir varsayımdı ve üretimde bu varsayım tutmaz. Bir dönemin kayıtları geç gelir, aynı kayıt iki kez yazılır, bir alanın adı değişir, bir okuma başka bir birimle gönderilir, bir bölgenin bölümü hiç yazılmaz, sayı alanı metne döner.

Bu dersin sorusu şudur: bu kazalar aynı hattan geçtiğinde hangi aşamada iz bırakır. Beş aşamanın her biri belirli bir hataya karşı yapısal olarak duyarlı, geri kalanına yapısal olarak kördür ve bu körlük hattın tasarımından gelir, bir eksiklikten değil. Ölçülecek şey her aşamanın kendi bozulmaya açıklığıdır.

  • YD9. Hat, kaynak ve tohum önceki dersle aynıdır. Değişen tek şey kaynağın kendisidir: bozulma hatta değil, hatta girmeden önce uygulanır.
  • YD10. Altı bozulma sınıfının hiçbiri saldırı değildir. Hepsi üretici tarafında olan günlük kazalardır: bir toplama işi geç bitmiştir, bir yeniden gönderim iki kez yazmıştır, bir alan adı yeniden adlandırılmıştır, bir sahadaki dönüştürücü değişmiştir, bir bölümün yazımı atlanmıştır, bir dışa aktarım her alanı metin olarak vermiştir.
  • YD11. Her sınıf tek bir dönemi bozar (2026-07); kalan on bir dönem sağlam kalır. Bu, bozulmanın etkisini yalıtmak içindir: iz tablosundaki her fark tek dönemin farkıdır.
  • YD12. Sınıfların bozduğu satır sayısı tanım gereğidir: gec_gelen bu dönemde ilk kırk abonenin kaydını hiç getirmez (40), yinelenen ilk altmış abonenin kaydını iki kez yazar (60 fazla satır), sema_degisti endeks alanının adını değiştirir (200), birim_degisti okumayı bine katlar ama birim etiketini m3 bırakır (200), eksik_bolum bir bölgenin bölümünü hiç yazmaz (46), kayan_tip sayı alanını metne çevirir (200).
  • YD13. Bu derste hiçbir denetim yoktur. Taban çizgisi denetimsiz hattır: yakalanan bozulma 0, yakalama gecikmesi tanımsız. Ölçülen tek şey hattın kendi izidir.
  • YD14. Ölçü birimi satır ve özet hücresidir. Süre yazılmaz. Hat belirlenimci olduğu için ikinci koşum aynı tabloyu verir; aşağıdaki her fark bozulmadan gelir, oynaklıktan değil.
  • YD15. Çözünürlük önceki dersteki gibidir: satır oranında 0,0004, özet hücresinde 0,0182, sunum değerinde 0,2000. Sunum üzerinde oran basılmaz.

Altı Sınıfın İzi

Aşağıdaki blok önceki dersin hattını aynen kurar, üzerine altı bozulma sınıfını ekler ve her sınıfı ayrı ayrı aynı hattan geçirir. İki tablo basılır: aşamalardan kaç satır çıktığı ve her aşamanın kaç satır düşürdüğü.

# KURGU hat ve KURGU bozulma siniflari -- gercek bir depo ya da orkestrator cagrilmaz.
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


BOLGE = ["dogu", "bati", "kuzey", "guney", "merkez"]
TIP = ["mesken", "isyeri"]
DONEM = [f"2026-{a:02d}" for a in range(1, 13)]
ABONE = {}
for i in range(200):
    r = uretec(TOHUM + 37 * i)
    ABONE[f"A{i + 1:03d}"] = {"bolge": BOLGE[int(r() * 5)], "tip": TIP[int(r() * 2)],
                              "baslangic": 10000 + int(r() * 60000)}


def kaynak_uret():
    kayit = []
    for i, (ab, a) in enumerate(ABONE.items()):
        e = a["baslangic"]
        for d in DONEM:
            r = uretec(TOHUM + 101 * i + 7 * DONEM.index(d))
            e += 4 + int(r() * 46)
            kayit.append({"abone": ab, "donem": d, "bolge": a["bolge"], "tip": a["tip"],
                          "endeks": e, "birim": "m3"})
    return kayit


# Hicbiri bir saldiri degildir; hepsi uretici tarafi kazalaridir.
BOZULMA = ["gec_gelen", "yinelenen", "sema_degisti", "birim_degisti", "eksik_bolum", "kayan_tip"]


def boz(kayit, sinif, donem="2026-07"):
    """Tek bir donemi bozar , kalan donemler saglam kalir."""
    yeni, sayac = [], 0
    for k in kayit:
        if k["donem"] != donem:
            yeni.append(k)
            continue
        if sinif == "gec_gelen":
            if k["abone"] <= "A040":                # bu donemde 40 abone hic gelmedi
                sayac += 1
                continue
            yeni.append(k)
        elif sinif == "yinelenen":
            yeni.append(k)
            if k["abone"] <= "A060":                # 60 kayit iki kez geldi
                yeni.append(dict(k))
                sayac += 1
        elif sinif == "sema_degisti":
            y = dict(k)
            y["endeks_degeri"] = y.pop("endeks")    # alan adi degisti
            sayac += 1
            yeni.append(y)
        elif sinif == "birim_degisti":
            y = dict(k)
            y["endeks"] = k["endeks"] * 1000        # m3 yerine litre
            y["birim"] = "m3"                       # ETIKET DEGISMEDI , sessiz bozulma
            sayac += 1
            yeni.append(y)
        elif sinif == "eksik_bolum":
            if k["bolge"] == "kuzey":               # bir bolgenin bolumu hic yazilmadi
                sayac += 1
                continue
            yeni.append(k)
        elif sinif == "kayan_tip":
            y = dict(k)
            y["endeks"] = str(k["endeks"])          # sayi metne dondu
            sayac += 1
            yeni.append(y)
    return yeni, sayac


def a1_ayikla(kayit):
    ZOR = ("abone", "donem", "bolge", "endeks", "birim")
    tut = [k for k in kayit if all(a in k for a in ZOR)]
    return tut, len(kayit) - len(tut)


def a2_tekille(kayit):
    gor, tut = set(), []
    for k in kayit:
        ad = (k["abone"], k["donem"])
        if ad in gor:
            continue
        gor.add(ad)
        tut.append(k)
    return tut, len(kayit) - len(tut)


def a3_tuketim(kayit):
    """Donem farkindan tuketim. Onceki donem yoksa satir hesaplanamaz."""
    tablo = {(k["abone"], k["donem"]): k for k in kayit}
    cikti, dusen = [], 0
    for k in kayit:
        i = DONEM.index(k["donem"])
        if i == 0:
            continue
        onceki = tablo.get((k["abone"], DONEM[i - 1]))
        if onceki is None:
            dusen += 1
            continue
        try:
            f = int(k["endeks"]) - int(onceki["endeks"])
        except (TypeError, ValueError):
            dusen += 1
            continue
        cikti.append(dict(k, m3=f))
    return cikti, dusen


def a4_ozet(kayit):
    top = {}
    for k in kayit:
        ad = (k["bolge"], k["donem"])
        top[ad] = top.get(ad, 0) + k["m3"]
    return top, 0


def a5_sun(ozet):
    bolge = {}
    for (b, d), v in ozet.items():
        bolge.setdefault(b, []).append(v)
    return {b: round(sum(v) / len(v), 2) for b, v in bolge.items()}, 0


ASAMA = [("ayikla", a1_ayikla), ("tekille", a2_tekille), ("tuketim", a3_tuketim),
         ("ozet", a4_ozet), ("sun", a5_sun)]


def hat(kayit):
    iz, veri = [], kayit
    for ad, f in ASAMA:
        veri, dusen = f(veri)
        n = len(veri) if hasattr(veri, "__len__") else 0
        iz.append({"asama": ad, "kalan": n, "dusen": dusen})
    return veri, iz


kaynak = kaynak_uret()
_, taban_iz = hat(kaynak)
BAS = ("ayikla", "tekille", "tuketim", "ozet", "sun")
print(f"{'sinif':<14}{'bozulan':>8}" + "".join(f"{a:>9}" for a in BAS))
print(f"{'saglam':<14}{0:>8}" + "".join(f"{a['kalan']:>9}" for a in taban_iz))
for s in BOZULMA:
    kb, n = boz(kaynak, s)
    print(f"{s:<14}{n:>8}" + "".join(f"{a['kalan']:>9}" for a in hat(kb)[1]))
print()
print(f"{'sinif':<14}" + "".join(f"{a:>9}" for a in BAS[:3]) + f"{'ikincil':>10}")
for s in BOZULMA:
    kb, n = boz(kaynak, s)
    iz = hat(kb)[1]
    print(f"{s:<14}" + "".join(f"{a['dusen']:>9}" for a in iz[:3])
          + f"{taban_iz[2]['kalan'] - iz[2]['kalan']:>10}")
sinif          bozulan   ayikla  tekille  tuketim     ozet      sun
saglam               0     2400     2400     2200       55        5
gec_gelen           40     2360     2360     2120       55        5
yinelenen           60     2460     2400     2200       55        5
sema_degisti       200     2200     2200     1800       45        5
birim_degisti      200     2400     2400     2200       55        5
eksik_bolum         46     2354     2354     2108       53        5
kayan_tip          200     2400     2400     2200       55        5

sinif            ayikla  tekille  tuketim   ikincil
gec_gelen             0        0       40        80
yinelenen             0       60        0         0
sema_degisti        200        0      200       400
birim_degisti         0        0        0         0
eksik_bolum           0        0       46        92
kayan_tip             0        0        0         0

İkinci tablo her aşamanın neye açık olduğunu birebir yazıyor. ayikla aşaması yalnız tek bir sınıfı görüyor: sema_degisti, çünkü alan adı değiştiğinde satır zorunlu alan listesini karşılamıyor. Kalan beş sınıfın hiçbiri bu aşamada bir satır düşürmüyor. tekille aşaması da yalnız bir sınıf görüyor: yinelenen, altmış çift kayıt. Bu iki aşamanın açıklığı dar ve kesindir; gördükleri şeyi kaçırmazlar, görmedikleri şeye tamamen kördürler.

tuketim aşaması farklı davranıyor. Kendi başına hiçbir bozulmayı tanımıyor, ama üç sınıfın etkisini taşıyor: gec_gelen için 40, sema_degisti için 200, eksik_bolum için 46 satır bu aşamada düşüyor. Bu satırlar bozuk değildir; önceki dönemleri kaybolduğu için farkları hesaplanamayan sağlam satırlardır. Bir aşamanın düşürdüğü satırın kendi hatası olmayabilir.

Son iki sütun ise okumanın sonucudur. ozet aşamasında hücre sayısı yalnız iki sınıfta düşüyor: sema_degisti on hücre kaybettiriyor (45), eksik_bolum iki hücre (53). Ve sun sütunu altı satırın hepsinde 5. Sunma aşamasının çıktı sayısı bölge sayısına bağlıdır, kaynağın durumuna değil; bu yüzden hattın en çok bakılan katmanı, bozulmayı satır sayısıyla hiçbir koşulda haber veremez.

Bir Satırın İki Satıra Mal Olması

Birinci tablonun ikincil sütunu ayrı bir nicelik ölçüyor: bozulma sonucu tüketim çıkışında eksilen satır. gec_gelen kaynaktan 40 satır eksiltiyor, tüketim çıkışında 80 satır eksiliyor. eksik_bolum 46 eksiltiyor, çıkışta 92. sema_degisti 200 eksiltiyor, çıkışta 400. Katsayı üçünde de tam olarak iki.

Bu katsayı bir ölçüm sonucu değil, tanımın sonucudur ve koşum yapılmadan türetilir. Tüketim iki komşu dönemin endeks farkıdır; 2026-07 kaydı kaybolduğunda o abonenin hem temmuz farkı hem de ağustos farkı hesaplanamaz hâle gelir, çünkü ağustosun önceki dönemi temmuzdur. Bir satırın kaybı iki çıkış satırını götürür. Aynı gerekçe katsayının neden ikiden büyük olmadığını da söyler: eylülün önceki dönemi ağustostur ve ağustos kaydı yerindedir, zincir orada kapanır.

Bu, veri hatlarında sık karşılaşılan bir yanılgıyı düzeltir. Bir kaynak eksikliği raporlandığında etkisi genellikle eksilen kaynak satırıyla yazılır. Aşama zinciri satırlar arasında bağ kuran bir dönüşüm içeriyorsa gerçek etki bu sayıdan büyüktür ve büyüme çarpanı hattın tanımından okunabilir. Burada çarpan iki; komşu üç dönemi birleştiren bir dönüşümde üç olurdu.

Özet Bozulurken Sunumun Bozulmaması

Şimdiye kadarki iki tablo yalnız satır ve hücre sayısına baktı. Sayı aynı kalırken değerin değişmiş olması hâlâ mümkündür. Aşağıdaki blok özet hücrelerini ve sunulan değerleri sağlam hatla karşılaştırır.

def son_iki(kayit):
    v1, _ = a1_ayikla(kayit)
    v2, _ = a2_tekille(v1)
    v3, _ = a3_tuketim(v2)
    oz, _ = a4_ozet(v3)
    return oz, a5_sun(oz)[0]


t_ozet, t_sunum = son_iki(kaynak)
print(f"{'sinif':<14}{'hucre':>7}{'degisen':>9}{'eksik':>7}{'sunum ayni':>12}")
for s in BOZULMA:
    oz, sn = son_iki(boz(kaynak, s)[0])
    dg = sum(1 for a in oz if a in t_ozet and oz[a] != t_ozet[a])
    ek = sum(1 for a in t_ozet if a not in oz)
    print(f"{s:<14}{len(oz):>7}{dg:>9}{ek:>7}"
          + f"{('evet' if sn == t_sunum else 'hayir'):>12}")
b_ozet, b_sunum = son_iki(boz(kaynak, "birim_degisti")[0])
print("\nbirim_degisti , kuzey ozet hucreleri")
for d in ("2026-06", "2026-07", "2026-08", "2026-09"):
    print(f"  {d}  taban {t_ozet[('kuzey', d)]:>5}   bozuk {b_ozet[('kuzey', d)]:>12}")
print("  11 hucrenin toplami  taban", sum(v for (b, d), v in t_ozet.items() if b == "kuzey"),
      " bozuk", sum(v for (b, d), v in b_ozet.items() if b == "kuzey"))
print("  sunulan kuzey degeri  taban", t_sunum["kuzey"], " bozuk", b_sunum["kuzey"])
sinif           hucre  degisen  eksik  sunum ayni
gec_gelen          55       10      0       hayir
yinelenen          55        0      0        evet
sema_degisti       45        0     10       hayir
birim_degisti      55       10      0        evet
eksik_bolum        53        0      2       hayir
kayan_tip          55        0      0        evet

birim_degisti , kuzey ozet hucreleri
  2026-06  taban  1041   bozuk         1041
  2026-07  taban  1251   bozuk   1812946491
  2026-08  taban  1119   bozuk  -1812944121
  2026-09  taban  1300   bozuk         1300
  11 hucrenin toplami  taban 13338  bozuk 13338
  sunulan kuzey degeri  taban 1212.55  bozuk 1212.55

Son sütun bu müfredatın en önemli iddiasını taşıyor: altı sınıfın üçü sunulan beş değeri birebir aynı bırakıyor. Üçünün mekanizması da farklıdır. yinelenen tekilleştirme aşamasında yutuluyor; altmış çift kayıt düşüyor ve geriye tam olarak sağlam küme kalıyor. kayan_tip hattın kendi tür dönüşümüyle sessizce onarılıyor; tuketim aşaması metni sayıya çeviriyor, dönüşüm başarılı oluyor ve ne satır ne değer değişiyor. Bu ikinci durum özellikle yanıltıcıdır, çünkü onarım yalnız rakamdan oluşan metinler için işler; alandan boş ya da biçimsiz bir değer geldiğinde aynı satır sessizce düşerdi ve yine hiçbir yerde yazılmazdı.

Üçüncüsü, birim_degisti, ayrı bir sınıftır. Tabloda on özet hücresi değişiyor, yani elli beş hücrenin 0,1818’i; buna karşılık sunulan beş değerin hiçbiri oynamıyor. Mekanizma alt tabloda açıkça görülüyor: kuzey bölgesinin temmuz toplamı 1251’den 1812946491‘e, ağustos toplamı 1119’dan eksi 1812944121’e gidiyor. Temmuz okuması bine katlandığı için temmuz farkı devasa pozitif, ağustos farkı ise aynı büyüklükte negatif oluyor. On bir hücrenin toplamı iki durumda da 13338; sunulan değer iki durumda da 1212,55. İki bozuk dönem birbirini tam olarak iptal ediyor, çünkü toplam ardışık farklardan oluşuyor ve zincirin uçları bozulmamış.

Tablonun en keskin karşılaştırması ilk ve dördüncü satırdır. gec_gelen ile birim_degisti tam olarak aynı sayıda özet hücresini bozuyor: onar hücre. Biri sunulan değeri değiştiriyor, öbürü değiştirmiyor. Bozulan ara hücre sayısı, bozulmanın sunuma ulaşıp ulaşmayacağını söylemiyor; belirleyen şey bozulmanın işareti ve dağılımıdır. Buradan müfredatın üçüncü iddiası doğrudan çıkar: çıktıya bakmak yetmez. Sunulan sayının doğru görünmesi, hattın doğru çalıştığının değil, yalnız o sayının o bozulmaya duyarsız olduğunun kanıtıdır.

Özet

  • Altı bozulma sınıfının hiçbiri saldırı değildir; hepsi üretici tarafında olan kazalardır ve her biri tek bir dönemi bozar.
  • ayikla yalnız sema_degisti’yi, tekille yalnız yinelenen’i görüyor; iki aşamanın açıklığı dar ve kesindir, geri kalan sınıflara tamamen kördürler.
  • tuketim aşaması kendi başına hiçbir bozulmayı tanımıyor ama üç sınıfın etkisini taşıyor ve eksik satırın bedelini tam iki katına çıkarıyor: 40 satır 80’e, 46 satır 92’ye, 200 satır 400’e. Katsayı tanımdan türetilir, koşumdan değil.
  • sun aşaması altı sınıfın hiçbirinde 5’ten başka bir sayı üretmiyor; hattın en çok bakılan katmanı bozulmayı satır sayısıyla hiçbir koşulda haber veremez.
  • Üç sınıf sunulan değeri birebir aynı bırakıyor: yinelenen tekilleştirmede yutuluyor, kayan_tip hattın kendi tür dönüşümüyle onarılıyor, birim_degisti ise iki dönem birbirini iptal ettiği için sunuma hiç ulaşmıyor.
  • gec_gelen ve birim_degisti aynı sayıda özet hücresini (onar hücre) bozuyor, biri sunumu değiştiriyor öbürü değiştirmiyor; bozulan ara hücre sayısı sunuma ulaşmanın ölçüsü değildir.

Sonraki Adım

Bu dersin tabloları hattı tek bir gözden okudu: kaç satır girdi, kaç satır çıktı, hangi hücre değişti. Üretimde bu hattın çevresinde tek bir göz yoktur. Hattın aşamalarını yazan ve iz tablosuna bakan bir rol vardır; hattın sonundaki tabloyu öznitelik olarak alıp üzerine model kuran ve başarım sayısına bakan başka bir rol vardır. İki rol aynı hattın farklı yerlerinde durur ve aynı bozulmayı farklı ölçülerle görür. Sonraki ders bu iki ölçüyü yan yana koyar: aynı altı sınıf için satır izi ile model başarımı ayrı ayrı basılır. Sonuç iki rolün de rahat edemeyeceği bir tablodur, çünkü bir sınıf ikisinde de hiçbir iz bırakmıyor.

İlerlemeni kaydetmek ve not almak için Giriş yap

Notlarım

Not almak için giriş yapmalısın.

Aramak için yazmaya başlayın.

↑↓ Esc gezin · aç · kapat