İçeriğe geç
academia.sh

Ders 07 / 10

Şema Sözleşmeleri

Üretici ile tüketici arasındaki şema sözleşmesinin kimi kırdığının ve kendi bedelinin sayılması: bir alanın adı değiştiğinde üretici tarafında hatalı satır 0 kalırken tüketici tarafında 200 satır ayıklamada, 200 satır daha tüketimde düşüyor ve özet 55 hücreden 45'e iniyor; sözleşme yazıldığında aynı bozulma aşama 0'da yakalanıyor ama çıktı düzelmiyor; alan kümesini birebir sabitleyen katı sözleşme hiçbir bozulma yokken 1200 iyi satırı engelleyip özeti 25 hücreye düşürüyor; yük düzeyi uygulama 2200 iyi satırı engelleyip hiç çıktı vermiyor, bağdaştırma aşaması ise sunumu tabana döndürürken hattı altı aşamaya çıkarıyor.

İçindekiler

Önceki dersin en hızlı yakalanan bozulması sema_degisti oldu: alan adı değiştiğinde sema denetimi aşama 0’da ateşledi. O denetimin baktığı alan listesi kodun içine gömülüydü ve listeyi kimin yazdığı sorulmadı. Liste tüketicinin varsayımıdır; üretici ondan habersizdir.

Bu ders o listeyi bir veri sözleşmesine (data contract) çevirir. Üç şey ölçülür: alan adı değiştiğinde kimin tarafında kaç satır düşüyor, sözleşme yazıldığında bozulma hangi aşamada yakalanıyor, ve sözleşmenin kendisi ne kadara mal oluyor. Üçüncü sayı en önemlisidir, çünkü kursun ikinci iddiasının örneğidir: denetim eklemek de bozar.

  • VK8. Kaynak, hat ve sözleşme kurgudur; gerçek bir veritabanı, dosya biçimi ya da orkestratör çağrılmaz. Tohum 20260218, ölçü koşumdan bağımsızdır.
  • VK9. İlişkisel şema, normalleştirme, kısıt ve tip yordamı Veritabanları müfredatında, Veri Modelleme ve İlişkisel Kuram kursunda ölçüldü ve tekrarlanmaz. Buradaki soru şemanın nasıl tasarlandığı değil, değiştiğinde kimin kırıldığıdır.
  • VK10. Şema değişimi bir saldırı değildir. Üretici alanın adını daha açık olsun diye değiştirir ya da yeni bir alan ekler; ikisi de sıradan bakım işidir.
  • VK11. Sözleşme aşama 0’da, kaynak hatta girmeden koşar ve satır düzeyinde uygulanır: uymayan satır engellenir, uyan satır geçer.
  • VK12. Taban çizgisi sözleşmesiz hattır: engellenen satır 0, yakalanan bozulma 0.
  • VK13. Çözünürlük: satır oranının adımı 0,0004, özet hücresinin 0,0182. Sunum üzerinde oran basılmaz, değerin kendisi yazılır.

Sözleşme Bir Alan Listesi Değildir

Bir alan listesi yalnızca “şu adlar bulunsun” der. Sözleşme üç şeyi birden bildirmek zorundadır: hangi alanlar var, her birinin türü ne, ve bildirilmeyen bir alan geldiğinde ne olacak. Üçüncüsü çoğunlukla yazılmaz ve bu dersin en pahalı sayısı oradan çıkar.

İki uygulama arasındaki fark tek satırlıktır. Kapsayan sözleşme, bildirilen alanların var olmasını ve türlerinin tutmasını ister; fazladan gelen alanı serbest bırakır. Katı sözleşme alan kümesinin bildirilenle birebir eşit olmasını ister; fazladan gelen alan da ihlaldir. İkisi de aynı sözleşme metnini okur ve bozulmuş kaynakta aynı davranır; ayrıştıkları yer zararsız değişimdir.

# KURGUDUR. Sayac okumalari, bes asamali hat ve sozlesme ders icinde tanimlanir;
# gercek bir depo, dosya bicimi 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


# ---- HAT: bes asama, her biri kendi dusurdugu satiri sayar
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):
    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)
        iz.append({"asama": ad, "kalan": len(veri), "dusen": dusen})
    return veri, iz


# ---- Ortak tanimin alti bozulma sinifindan bu ders yalnizca birini kosuyor.
def boz_sema(kayit, donem="2026-07"):
    """Uretici alanin adini degistirdi ; degerin kendisi ayni kaldi."""
    yeni, sayac = [], 0
    for k in kayit:
        if k["donem"] != donem:
            yeni.append(k)
            continue
        y = dict(k)
        y["endeks_degeri"] = y.pop("endeks")
        sayac += 1
        yeni.append(y)
    return yeni, sayac


def alan_ekle(kayit, ilk="2026-07"):
    """Uretici zararsiz bir alan ekledi ; var olan alanlar degismedi."""
    return [dict(k, sayac_seri="S" + k["abone"][1:]) if k["donem"] >= ilk else k
            for k in kayit]


# ---- SOZLESME: ureticinin yazdigini bildirdigi satirin tam semasi
SOZLESME = {"abone": str, "donem": str, "bolge": str, "tip": str,
            "endeks": int, "birim": str}


def kapsayan(k):
    """Bildirilen alanlar var ve turleri dogru ; fazla alan serbest."""
    return all(a in k and isinstance(k[a], t) for a, t in SOZLESME.items())


def kati(k):
    """Alan kumesi bildirilenle birebir esit olmali ; eklenen alan da ihlaldir."""
    return set(k) == set(SOZLESME) and kapsayan(k)


def sozlesmeli_al(kayit, kontrol=None):
    """Sozlesme asama 0'da kosar: uyan satir gecer , uymayan engellenir."""
    if kontrol is None:
        return kayit, 0
    gecen = [k for k in kayit if kontrol(k)]
    return gecen, len(kayit) - len(gecen)

Şema Değişimi Kimi Kırıyor

İkinci blok altı kurulumu aynı kaynağa uygular. giren sütunu hatta giren satırı, engel sözleşme tarafından aşama 0’da engellenen satırı, ayikla ile tuketim o iki aşamanın düşürdüğü satırı, ozet dördüncü aşamanın hücre sayısını verir. Son sütun sunulan beş değerin tabanla aynı kalıp kalmadığını yazar.

KAYNAK_KAYIT = kaynak_uret()
TABAN, _ = hat(KAYNAK_KAYIT)


def olc(ad, kayit, kontrol):
    giren, eng = sozlesmeli_al(kayit, kontrol)
    sunum, iz = hat(giren)
    print(f"{ad:<28}{len(giren):>7}{eng:>7}{iz[0]['dusen']:>8}{iz[2]['dusen']:>8}"
          f"{iz[3]['kalan']:>6}{'ayni' if sunum == TABAN else 'degisti':>9}")


bozuk, n = boz_sema(KAYNAK_KAYIT)
eklenmis = alan_ekle(KAYNAK_KAYIT)
print("taban sunum:", TABAN)
print("adi degisen satir:", n, " eklenen alani tasiyan satir:",
      sum(1 for k in eklenmis if "sayac_seri" in k))
print()
print(f"{'kurulum':<28}{'giren':>7}{'engel':>7}{'ayikla':>8}{'tuketim':>8}"
      f"{'ozet':>6}{'sunum':>9}")
olc("saglam , sozlesme yok", KAYNAK_KAYIT, None)
olc("ad degisti , sozlesme yok", bozuk, None)
olc("ad degisti , kapsayan", bozuk, kapsayan)
olc("alan eklendi , sozlesme yok", eklenmis, None)
olc("alan eklendi , kapsayan", eklenmis, kapsayan)
olc("alan eklendi , kati", eklenmis, kati)
print()
URETICI = ("abone", "donem", "bolge", "tip", "endeks_degeri", "birim")
print("ureticinin kendi semasina uymayan satir:",
      sum(1 for k in bozuk if k["donem"] == "2026-07"
          and not all(a in k for a in URETICI)))
print("sozlesmenin bildirdigi alan:", len(SOZLESME), " hattin okudugu alan:", 5)
taban sunum: {'merkez': 1321.45, 'kuzey': 1212.55, 'dogu': 881.36, 'bati': 833.09, 'guney': 1065.55}
adi degisen satir: 200  eklenen alani tasiyan satir: 1200

kurulum                       giren  engel  ayikla tuketim  ozet    sunum
saglam , sozlesme yok          2400      0       0       0    55     ayni
ad degisti , sozlesme yok      2400      0     200     200    45  degisti
ad degisti , kapsayan          2200    200       0     200    45  degisti
alan eklendi , sozlesme yok    2400      0       0       0    55     ayni
alan eklendi , kapsayan        2400      0       0       0    55     ayni
alan eklendi , kati            1200   1200       0       0    25  degisti

ureticinin kendi semasina uymayan satir: 0
sozlesmenin bildirdigi alan: 6  hattin okudugu alan: 5

Sondan bir önceki satır sorunun yanıtıdır: üreticinin kendi şemasına uymayan satır 0’dır. Üretici alanın adını değiştirmiş, bütün alanları eksiksiz yazmış, yazma işlemi hatasız tamamlanmıştır. Onun tarafında ölçülebilen hiçbir kusur yoktur. Kırılan taraf tüketicidir ve bunu ancak kendi hattında sayabilir.

İkinci satır sözleşmesiz durumu verir. Bozulmuş yük hatta olduğu gibi giriyor: ayıklama aşaması zorunlu alanı bulamadığı için 200 satır düşürüyor, tüketim aşaması bir dönem sonrasının önceki değerini bulamadığı için 200 satır daha düşürüyor. Toplam 400 satır, kaynağın altıda biri. Özet 55 hücreden 45’e iniyor ve sunulan beş değerin hepsi değişiyor. Hiçbir yerde bir hata kaydı yok; hat başarıyla tamamlandı.

Üçüncü satır sözleşmeli durumu verir ve dikkatle okunmalıdır. Sözleşme aşama 0’da 200 satırı engelliyor, yakalama gecikmesi 0. Ama özet yine 45 hücre, sunum yine değişmiş. Sözleşme çıktıyı düzeltmedi; yalnızca haber verdi. Düşen satırlar aşamalar arasında dağılmaktan çıkıp tek bir yerde toplandı: 400 satırın 200’ü artık ayıklama aşamasında değil kapıda duruyor, kalan 200’ü hâlâ tüketimde düşüyor çünkü bir sonraki dönemin önceki değeri gerçekten yok. Sözleşmenin ürettiği şey doğru sayı değil, doğru zamanda gelen sinyaldir.

Sözleşmenin Bedeli

Son üç satır kursun ikinci iddiasını taşır. Üretici 2026-07 döneminden başlayarak satırlara zararsız bir alan ekliyor: sayaç seri numarası. Var olan alanların hiçbiri değişmiyor, hiçbir tür kaymıyor, hattın okuduğu beş alan yerinde duruyor.

Sözleşmesiz hat bu değişimden hiç etkilenmiyor: 2400 satır giriyor, 55 hücre, sunum aynı. Kapsayan sözleşme de etkilenmiyor, çünkü fazladan gelen alanı ihlal saymıyor: engellenen satır 0, sunum aynı. Katı sözleşme ise 1200 satırı engelliyor. Eklenen alanı taşıyan satır sayısı da tam 1200’dür, yani katı sözleşme yeni alanı gören her satırı reddediyor. Özet 55 hücreden 25’e düşüyor, sunulan beş değerin hepsi değişiyor.

Bu satır bir kaza değil, sözleşmenin tanımından çıkan sonuçtur. Bozulma yok. Yakalanan bozulma 0. Yanlış engellenen iyi satır 1200. Kaynağın yarısı, hiçbir kalite kusuru taşımadığı hâlde hatta girmedi. Bir denetimin bedeli yalnızca yazma ve bakım emeği değildir; yanlış tanımlanmış bir sözleşme hattı, hiçbir bozulma olmadan durdurabilir.

Son satır bedelin ikinci yüzünü gösterir. Sözleşme altı alan bildiriyor, hat bunların beşini okuyor; tip alanı hiçbir aşamada kullanılmıyor. Sözleşme genişledikçe üretici bağlanır ve tüketicinin hiç okumadığı bir alanın türü değiştiğinde de hat durur. Kapsayan sözleşmenin katıdan üstünlüğü bu yüzden mutlak değildir: kapsayan sözleşme fazla alanı serbest bırakırken, bildirilen alanların değişimini de aynı sertlikte engeller. Sözleşme yazmanın kararı hangi alanın bildirileceğidir ve her bildirilen alan hem bir güvence hem bir kilit üretir.

Durdurmak ve Uyarlamak

Sözleşme ihlal edildiğinde ne yapılacağı ayrı bir karardır ve bedeli ayrı ölçülür. Buraya kadarki bütün satırlar satır düzeyi uygulamadır: uymayan satır engellenir, uyan satır geçer. İkinci seçenek yük düzeyi uygulamadır: yükte tek bir uymayan satır varsa tamamı reddedilir. Üçüncü seçenek engellemek yerine uyarlamaktır: tüketici bilinen eski adı sözleşmedeki ada çeviren bir aşama ekler.

def yuk_duzeyi(kayit, kontrol):
    """Tek satir bile uymuyorsa yukun tamami reddedilir."""
    return ([], len(kayit)) if any(not kontrol(k) for k in kayit) else (kayit, 0)


ESLEME = {"endeks_degeri": "endeks"}


def uyarla(kayit):
    """Ek asama: bilinen eski adi sozlesmedeki ada cevirir."""
    yeni = []
    for k in kayit:
        y = dict(k)
        for eski, ad in ESLEME.items():
            if eski in y:
                y[ad] = y.pop(eski)
        yeni.append(y)
    return yeni


def yaz(ad, giren, eng):
    sunum, iz = hat(giren)
    durum = "ayni" if sunum == TABAN else ("yok" if not sunum else "degisti")
    print(f"{ad:<26}{len(giren):>7}{eng:>7}{iz[3]['kalan']:>6}{durum:>9}")


print(f"{'uygulama':<26}{'giren':>7}{'engel':>7}{'ozet':>6}{'sunum':>9}")
yaz("satir duzeyi , kapsayan", *sozlesmeli_al(bozuk, kapsayan))
yaz("yuk duzeyi , kapsayan", *yuk_duzeyi(bozuk, kapsayan))
yaz("uyarlama + kapsayan", *sozlesmeli_al(uyarla(bozuk), kapsayan))
print()
print("yuk duzeyinde yanlis engellenen iyi satir:", sum(1 for k in bozuk if kapsayan(k)))
print("uyarlamanin ekledigi asama:", 1, " esleme tablosundaki ad:", len(ESLEME))
uygulama                    giren  engel  ozet    sunum
satir duzeyi , kapsayan      2200    200    45  degisti
yuk duzeyi , kapsayan           0   2400     0      yok
uyarlama + kapsayan          2400      0    55     ayni

yuk duzeyinde yanlis engellenen iyi satir: 2200
uyarlamanin ekledigi asama: 1  esleme tablosundaki ad: 1

Üç satır üç ayrı bedel gösterir. Satır düzeyi uygulama yanlış satırı ayıklar ve hattı yürütür; karşılığında eksik bir çıktı üretir ve o çıktı eksik olduğunu kendi üstünde taşımaz. Yük düzeyi uygulama hiç çıktı üretmez; sunum yoktur. Bu kimi zaman doğru karardır, çünkü yanlış sayı yayımlamak sayı yayımlamamaktan pahalıdır — ama bedeli açıktır: 2200 iyi satır yanlış engellenmiştir ve on bir sağlam dönemin tamamı, tek bir dönemin kusuru yüzünden beklemeye alınmıştır.

Üçüncü satır tek onarım yoludur: bağdaştırma aşaması eski adı yeni ada çevirdiğinde 2400 satırın hepsi geçiyor, özet 55 hücreye dönüyor ve sunum tabanla birebir aynı oluyor. Bedeli iki kalemde yazılır. Hat artık altı aşamalıdır, beş değil; ve eşleme tablosu tüketicinin sonsuza dek taşıyacağı bir yüktür. Bu tablo büyüdükçe sözleşme metni ile hattın gerçekte kabul ettiği şema birbirinden uzaklaşır: sözleşme endeks der, hat iki adı da kabul eder. Üretici bir gün eski adı başka bir anlamda geri getirirse eşleme sessizce yanlış alanı okur ve bu, bu kursun tanımıyla tam olarak bir sessiz bozulmadır.

Özet

  • Bir veri sözleşmesi üç şeyi birden bildirir: hangi alanlar var, türleri ne, ve bildirilmeyen bir alan geldiğinde ne olacak. Üçüncüsü yazılmadığında bedel katı yorumdan çıkar.
  • Alan adı değiştiğinde üreticinin kendi şemasına uymayan satır 0’dır; kırılan taraf tüketicidir ve 400 satır kaybını yalnızca kendi hattında sayabilir.
  • Sözleşmesiz hatta bozulma sessizdir: 200 satır ayıklamada, 200 satır tüketimde düşer, özet 55 hücreden 45’e iner, sunulan beş değer değişir ve hiçbir hata kaydı üretilmez.
  • Sözleşme yazıldığında aynı bozulma aşama 0’da yakalanır, ama özet yine 45 hücredir; sözleşme çıktıyı düzeltmez, doğru zamanda sinyal üretir.
  • Katı sözleşme zararsız bir alan eklemesinde 1200 iyi satırı engeller, özeti 25 hücreye düşürür ve bunu yakalanan bozulma 0 iken yapar; denetim eklemek de bozar.
  • İhlal edildiğinde ne yapılacağı ayrı bir bedeldir: satır düzeyi uygulama eksik çıktı verir, yük düzeyi uygulama 2200 iyi satırı engelleyip hiç çıktı vermez, uyarlama sunumu tabana döndürür ama hattı altı aşamaya çıkarır ve tüketiciye kalıcı bir eşleme tablosu bırakır.

Sonraki Adım

Sözleşme bozulmayı aşama 0’da yakaladı, ama yakalamak düzeltmek değildir: engellenen 200 satır bir yerde durmalı, üretici düzeltmeli ve o dönem hatta yeniden verilmelidir. Bu dersin hiçbir satırında hat iki kez koşmadı. İkinci koşum hattın en sık yapılan işidir ve kendi sayısını taşır: aynı dönem yeniden işlendiğinde satır sayısına ne oluyor, hangi aşama fazlalığı yutuyor ve sunulan değer bunu gösteriyor mu. Sonraki ders hattı yinelemeye dayanıklı olan ve olmayan iki biçimde koşturur, çoğalan satırı sayar ve sunumdaki farkı ölçer.

İ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