---
title: 'Çalışma Zamanı Doğrulama'
source: 'https://academia.sh/tr/kurslar/python-nesne-ve-tipler/calisma-zamani-dogrulama'
course: 'Nesneye Dayalı Python ve Tipler'
language: tr
updated: '2026-08-17T18:10:30+00:00'
license: 'CC BY-SA 4.0'
---

# Çalışma Zamanı Doğrulama

Dört ihlali üç katman ayrı ayrı görür: çalışma zamanı 0, denetleyici 2, alan kuralı 2 yakalar ve dördü ancak iki katman birlikte kullanıldığında görünür; şema tabanlı doğrulama dördünü de yakalar ama yalnız uğradığı çağrıda.

Önceki ders alan kuralını tipe taşıdı ve kuralın bir yapıcının gövdesine, yani çalışma
zamanına düştüğünü gösterdi. Her alan için ayrı bir sınıf yazmak ölçeklenmez: kural sayısı
arttıkça yapıcılar birbirini tekrar eder ve kuralların nerede durduğu dağılır.

Kuralları tek bir yerde toplamanın adı **şema (schema)**dır: hangi alanın hangi tipte
olduğu ve hangi koşulu sağlaması gerektiği, veriden ayrı bir tanımda durur. **Çalışma
zamanı doğrulama (runtime validation)** bu tanımı çağrı anında değere uygular. Bu ders o
katmanı kurar ve kursun son sayısını sorar: dört ihlali görmek için kaç katman gerekir?

## Şema Ders İçinde Modellenmiştir

Bir uyarı, önceki derstekinin aynısı: buradaki şema ve doğrulayıcı **ders içinde
yazılmıştır**. Hazır bir doğrulama katmanı kullanılmaz ve hiçbir aracın adı geçmez. Ölçülen
şey bir programın davranışı değil, **yaklaşımın kapsamıdır**.

Şema doğrulamanın kendisi bu kursta ilk kez geçmiyor. **Veri Modelleme ve İlişkisel Kuram**
kursu şemayı veri tarafında bütünlük kısıtlarıyla kurdu; **Web API Tasarımı** kursu da alan
düzeyi hata bildirimini istek ve yanıt gövdelerinde kurdu. **O yordamlar burada
tekrarlanmaz.** Buradaki soru dar ve ölçülebilir: **hangi katman hangi ihlali yakalar?**

Ölçümün varsayımları:

- **TP28** — Kâhin kurgunun kendisidir: beş çağrının ikisi tip ihlali, ikisi alan ihlali
  taşır, biri temizdir. Dizi kursun ortak kurgusundan gelir ve değiştirilmez.
- **TP29** — Denetleyici ve alan kuralı önceki derslerdeki modellerin aynısıdır; denetleyici
  yalnız tipi, alan kuralı yalnız değerin anlamını görür.
- **TP30** — Şema üç şeyi tek yerde tutar: alan adı, beklenen tip ve alan koşulu. Sınama
  önce tipe, tip geçerse koşula bakar; bu sıra bir tasarım kararıdır ve iletilerde görünür.
- **TP31** — Doğrulama, işlevi saran bir katman olarak uygulanır: sınama geçmezse **çağrı
  hiç başlamaz**. Yakalama ölçüsü bu sarmalın istisna fırlatmasıdır.
- **TP32** — Çalışma zamanı sütunu sarmalsız çağrının istisna fırlatıp fırlatmadığıdır;
  gövde bir dizgi biçimlemesidir ve her tipi kabul eder.
- **TP33** — "Birlikte" sayısı iki katmanın yakaladığı çağrıların birleşimidir, toplamı
  değil.
- **TP34** — Kapsam ölçümünde beş çağrının üçünün çalıştırıldığı bir koşum varsayılır; hangi
  üçü olduğu kurguya yazılıdır ve ölçüm bunu bir olasılık olarak değil, tek bir koşum olarak
  sayar.
- **TP35** — Ortama bağlı hiçbir veri yazılmaz; bütün sayılar kurgudan ve koşumdan gelir.

## Ölçüm

```python
"""Calisma zamani dogrulama: dort ihlali kac katman gorur."""


def yas_yaz(ad: str, yas: int) -> str:
    return f"{ad}:{yas}"


CAGRILAR = (
    ("ad", 30),            # uygun
    ("ad", "otuz"),        # tip ihlali: yas dizgi
    (7, 30),               # tip ihlali: ad sayi
    ("ad", -5),            # tip uygun, alan ihlali: yas negatif
    ("", 30),              # tip uygun, alan ihlali: ad bos
)


def denetleyici(islev, cagrilar):
    """Aciklamalari okuyan modellenmis denetleyici: yalniz tipi gorur."""
    aciklama = [(a, t) for a, t in islev.__annotations__.items() if a != "return"]
    bulunan = []
    for i, arg in enumerate(cagrilar):
        for (ad, tip), deger in zip(aciklama, arg):
            if not isinstance(deger, tip):
                bulunan.append((i, ad))
    return bulunan


def alan_kurali(ad, yas):
    """Tipin goremedigi anlam kosullari."""
    hatalar = []
    if isinstance(ad, str) and not ad:
        hatalar.append("ad bos")
    if isinstance(yas, int) and yas < 0:
        hatalar.append("yas negatif")
    return hatalar


# Sema ders icinde modellenmistir: alan adi, tip ve alan kurali tek yerde.
SEMA = (("ad", str, lambda d: bool(d), "boş"),
        ("yas", int, lambda d: d >= 0, "negatif"))


def dogrula(sema, degerler):
    """Sema tabanli dogrulama: cagri aninda hem tipi hem alani sinar."""
    hatalar = []
    for (alan, tip, kural, ileti), deger in zip(sema, degerler):
        if not isinstance(deger, tip):
            hatalar.append(f"{alan}: tip")
        elif not kural(deger):
            hatalar.append(f"{alan}: {ileti}")
    return hatalar


def korumali(sema, islev):
    """Islevi semayla saran katman: dogrulama gecmezse cagri hic baslamaz."""
    def sarmal(*arg):
        hatalar = dogrula(sema, arg)
        if hatalar:
            raise ValueError("; ".join(hatalar))
        return islev(*arg)
    return sarmal


bulunan = {b[0] for b in denetleyici(yas_yaz, CAGRILAR)}
tip_ihlali = [i for i, a in enumerate(CAGRILAR)
              if not isinstance(a[0], str) or not isinstance(a[1], int)]
alan_ihlali = [i for i, a in enumerate(CAGRILAR) if alan_kurali(*a)]
korunan = korumali(SEMA, yas_yaz)

ham_hata = 0
sema_yakalanan = set()
for i, arg in enumerate(CAGRILAR):
    try:
        yas_yaz(*arg)
    except Exception:
        ham_hata += 1
    try:
        korunan(*arg)
    except ValueError:
        sema_yakalanan.add(i)

print(f"{'çağrı':>6s} {'tip ihlali':>11s} {'alan ihlali':>12s} "
      f"{'çalışma zamanı':>15s} {'denetleyici':>12s} {'alan kuralı':>12s} "
      f"{'şema':>6s}")
for i, arg in enumerate(CAGRILAR):
    print(f"{i:6d} {str(i in tip_ihlali):>11s} {str(i in alan_ihlali):>12s} "
          f"{'hata yok':>15s} {str(i in bulunan):>12s} "
          f"{str(i in alan_ihlali):>12s} {str(i in sema_yakalanan):>6s}")
print()
print(f"çağrı {len(CAGRILAR)}, ihlalli "
      f"{len(set(tip_ihlali) | set(alan_ihlali))} | yakalayan: çalışma zamanı "
      f"{ham_hata}, denetleyici {len(bulunan)}, alan kuralı {len(alan_ihlali)}, "
      f"şema {len(sema_yakalanan)}")
print(f"denetleyici ile alan kuralı birlikte: "
      f"{len(bulunan | set(alan_ihlali))}")
print(f"şema iletileri: {[dogrula(SEMA, a) for a in CAGRILAR]}")

CALISAN = [0, 2, 4]
print()
print(f"yazılan çağrı yeri {len(CAGRILAR)}, çalıştırılan {len(CALISAN)} | "
      f"denetleyicinin gördüğü {len(CAGRILAR)}, yakaladığı {len(bulunan)} | "
      f"şemanın uğradığı {len(CALISAN)}, yakaladığı "
      f"{len(sema_yakalanan & set(CALISAN))}")
```

```
 çağrı  tip ihlali  alan ihlali  çalışma zamanı  denetleyici  alan kuralı   şema
     0       False        False        hata yok        False        False  False
     1        True        False        hata yok         True        False   True
     2        True        False        hata yok         True        False   True
     3       False         True        hata yok        False         True   True
     4       False         True        hata yok        False         True   True

çağrı 5, ihlalli 4 | yakalayan: çalışma zamanı 0, denetleyici 2, alan kuralı 2, şema 4
denetleyici ile alan kuralı birlikte: 4
şema iletileri: [[], ['yas: tip'], ['ad: tip'], ['yas: negatif'], ['ad: boş']]

yazılan çağrı yeri 5, çalıştırılan 3 | denetleyicinin gördüğü 5, yakaladığı 2 | şemanın uğradığı 3, yakaladığı 2
```

## Üç Katman, Üç Ayrı Yakalama

Tablo dört ihlali üç sütunda dağıtıyor ve hiçbir sütun ötekinin kopyası değil.

**Çalışma zamanı 0 yakalıyor.** Beş satırda da "hata yok". Açıklama çağrıyı durdurmaz;
kursun ilk dersinde ölçülen sayı burada da aynı çıkıyor.

**Denetleyici 2 yakalıyor** ve yakaladıkları tip ihlalleridir. Alan ihlallerinde sütun
yanlış diyor, çünkü **-5** bir tam sayı, boş dizgi bir dizgidir.

**Alan kuralı 2 yakalıyor** ve yakaladıkları tam olarak denetleyicinin göremedikleridir.
İki sütun **kesişmiyor**: birinin bulduğunu öbürü bulamıyor.

Bunun doğrudan sonucu alt satırda: **denetleyici ile alan kuralı birlikte 4** yakalıyor —
ihlallerin tamamı. Toplam değil birleşim; iki katmanın kapsamı çakışmadığı için birleşim
toplama eşit çıkıyor. **Dört ihlalin tamamı ancak iki katman birlikte kullanıldığında
görünür.**

Şema sütunu ise beş çağrının **4**'ünde yakalıyor. Sebebi şemanın iki bilgiyi tek yerde
taşıması: tip ve koşul. İleti listesi bunu ayrıntısıyla veriyor — iki çağrıda `tip`, birinde
`negatif`, birinde `boş`. Yani şema yeni bir görme yeteneği getirmiyor; denetleyicinin
bildiğiyle alan kuralının bildiğini **aynı tanımda** birleştiriyor ve ikisini çağrı anında
uyguluyor.

İleti listesi şemanın bir tasarım kararını da açığa çıkarıyor. Yaşı dizgi olan çağrıda ileti
`yas: tip`, negatif olan çağrıda `yas: negatif`. Aynı alan için iki ileti birden çıkmıyor,
çünkü sınama önce tipe bakıyor ve tip geçmeden koşula geçmiyor. Bu sıra zorunlu: `d >= 0`
karşılaştırması bir dizgiyle yapılamaz. Alan koşulu **tipin doğru olduğunu varsayar**;
kural yazarken bu varsayımın nereden geldiğini bilmek, kuralın kendisini yazmak kadar
önemlidir.

Sarmal katmanın bir farkı daha var. Doğrulama geçmediğinde çağrı **hiç başlamıyor**; gövde
koşmuyor, yarım bir iş kalmıyor. Önceki derslerde ölçülen "çalışma zamanı ancak işlemi
yaparken düşer" durumu burada ortadan kalkıyor: düşme çağrının **önünde**.

Bunun bir bedeli var ve ölçümde görünüyor: sarmal, ihlalli olsun olmasın **her** çağrıda
şemayı baştan sona uyguluyor. Temiz çağrı da sınanıyor. Denetleyici ise çalışma zamanında
hiçbir şey yapmıyor; işini bir kez, koşumdan önce görüyor. İki katmanın bedeli de kapsamı
gibi ayrı cinsten: biri koşum başına bir kez, öbürü çağrı başına her seferinde.

## Kapsam: Yazılan Kod ve Uğranan Çağrı

Son satır şemanın bedelini gösteriyor ve bu bedel kursun ölçü ekseninin son sözü.

Yazılan çağrı yeri **5**, tek bir koşumda çalıştırılan **3**. Denetleyici beşinin beşini de
görüyor ve **2** ihlal bildiriyor — kodu hiç çalıştırmadan. Şema yalnız uğradığı **3**
çağrıyı sınıyor ve o üçte **2** ihlal yakalıyor; uğramadığı iki çağrıdaki ihlaller o koşumda
görünmüyor.

Örüntü şudur: **denetleyicinin kapsamı yazılan koddur, doğrulamanın kapsamı uğranan
çağrıdır.** Şemayı daha titiz yazmak bu farkı kapatmaz, çünkü fark titizlikte değil,
katmanın ne zaman çalıştığındadır. Aynı biçimde, denetleyiciyi daha titiz yazmak alan
ihlallerini bulmasını sağlamaz — o da bilgi sınırıdır.

İki katman birbirinin yerine geçmiyor ve birbirini de doğrulamıyor: biri **her yerde az
şey**, öbürü **bazı yerlerde çok şey** biliyor.

Kapsam farkı doğrulamanın nereye konacağını da belirliyor. Şemayı her işlevin önüne koymak
sınama sayısını çağrı sayısıyla büyütür ve aynı değer aynı koşumda defalarca sınanır. Buna
karşılık verinin programa **girdiği** noktaya konan tek bir doğrulama, o noktadan sonraki
bütün çağrılar için bir güvence üretir — sınama bir kez yapılır, sonuç içeride taşınır.
Ölçümdeki şema bu yüzden alan adını da taşıyor: bir ihlal bildirildiğinde hangi alanın
sorunlu olduğu, sınamanın yapıldığı yerden uzakta da okunabilir olmalı.

Bu, önceki dersteki `Yas` sınıfının yaptığı işin ölçeklenmiş biçimidir. Orada kural tek bir
yapıcının gövdesine yazılmıştı ve her alan için ayrı bir sınıf gerekiyordu; burada kurallar
tek bir tanımda toplandı ve doğrulayıcı o tanımı okuyor. Değişen şey kuralın **ne zaman**
çalıştığı değil — ikisi de çalışma zamanıdır — kuralın **nerede yazılı olduğudur**.

## Özet

- Şema, alan adını, beklenen tipi ve alan koşulunu tek bir tanımda toplar; çalışma zamanı
  doğrulama bu tanımı çağrı anında uygular ve doğrulama geçmezse çağrı hiç başlamaz.
- Üç katman üç ayrı şey yakalar: çalışma zamanı **0**, denetleyici **2**, alan kuralı
  **2**. İki katmanın kapsamı kesişmez, bu yüzden birleşimleri **4**'tür — dört ihlalin
  tamamı ancak birlikte görünür.
- Şema tabanlı doğrulama tek başına **4** yakalar, çünkü denetleyicinin ve alan kuralının
  bildiklerini aynı tanımda birleştirir; yeni bir görme yeteneği eklemez.
- Kapsamlar ayrıdır: denetleyici yazılan **5** çağrı yerinin beşini de görür, şema tek
  koşumda uğranan **3** çağrıyı sınar ve o üçte **2** ihlal yakalar.
- Katmanların sınırları ayrı cinstendir; denetleyicininki bilgi sınırı, doğrulamanınki
  kapsam sınırıdır ve hiçbiri ötekini titizlikle kapatamaz.

## Kurs Kapanışı

Kurs tek bir soruyla açıldı ve on bir derste aynı soruyu iki yarıda ölçtü: **çağrıyı kim
yanıtladı, sözü kim denetledi?** Birinci yarıda yanıt bir sınıftı; ikinci yarıda bir
katman. İkisinde de ölçülen şey tasarımın ne yaptığı değil, **sorumluluğun nerede
durduğuydu**.

| ders | ölçülen | yanıtlayan ya da yakalayan |
|---|---|---|
| Sınıf ve Örnek | özniteliğin sınıfta mı örnekte mi durduğu: **1**'e karşı **3** nesne | adı ilk bulan ad alanı — önce örnek sözlüğü, sonra sınıf |
| Kalıtım ve Yöntem Çözümleme Sırası | dört yeteneğin gövdesinin nerede yazılı olduğu: **0/4**'e karşı **4/4** | çözümleme sırasında ilk gelen sınıf; bileşimde `Sarmal` |
| Kapsülleme Sözleşmeleri | dört erişim biçiminden kaçının değeri verdiği: **3**, engellenen **0** | yöntem gövdesi — ad değil |
| Özel Yöntemler | hiçbir özel yöntem yazmayan sınıfın katıldığı sözdizim: **5**, yanıtladığı: **0** | sessiz varsayılan; yazan sınıfta yöntemin kendisi |
| Özellikler ve Betimleyiciler | aynı yedi erişimin çalıştırdığı gövde: doğrudan alanda **0**, araya giren tanımda **7** | araya giren gövde; betimleyici sınıfta bir kez var edilir |
| Veri Sınıfları | kısa tanımın yazdığı özel yöntem: **4**; seçeneklerle **8**, **6** ve **10** | kısa tanımın sınıf sözlüğüne yazdığı yöntemler |
| Soyut Temel Sınıflar ve Protokoller | üç adaydan soy bağı sınamasını geçen **1**, yöntem sınamasını geçen **3** | iki sınama da; ama geçmek çağrının karşılanacağını söylemez |
| Tip İpuçları | beş çağrının **4**'ü ihlalli, çalışma zamanında hata veren **0** | hiçbir katman |
| Genellikler ve Tip Değişkenleri | dört yazımın bildirdiği ihlal: **0**, **4**, **3**, **2** | açıklamayı okuyan taraf — bağ kurulmuşsa |
| Statik Tip Denetimi | denetleyicinin bulduğu **2**, göremediği **2** | denetleyici; kapsamı yazılan kod |
| Çalışma Zamanı Doğrulama | çalışma zamanı **0**, denetleyici **2**, alan kuralı **2** | şema tabanlı doğrulama — uğradığı çağrıda **4** |

Tablonun iki yarısı aynı örüntüyü veriyor. Kalıtımda gövdenin nerede yazılı olduğunu okumak
yanıtın nereden geleceğini söylemedi; açıklamanın koda yazılmış olması da sözün
denetleneceğini söylemedi. Her iki durumda da sorunun yanıtı **yazının kendisinde değil,
onu çözen düzenekte** duruyor: birinde çözümleme sırası, öbüründe denetim katmanı.

Bütün bu ölçümlerin ortak bir varsayımı vardı ve hiç yazılmadı: **tek bir akış**. Yanıtı
veren sınıf sorulduğunda tek bir çözümleme zinciri yürüdü; ihlali yakalayan katman
sorulduğunda çağrılar sırayla, biri bitince öbürü başlayarak koştu. Bu yüzden "kim
yanıtladı" sorusunun her seferinde tek bir yanıtı oldu.

Birden çok akış olduğunda bu soru yeniden açılır. Aynı nesneye iki yerden aynı anda
uğrandığında özniteliği hangi yazmanın bıraktığı, doğrulamayı geçen bir değerin gövde
koşarken hâlâ geçerli olup olmadığı ve iki akıştan hangisinin önce davrandığı, artık
kaynağa bakarak okunamaz. Sonraki kurs **Eşzamanlılık ve Başarım** tam buradan başlıyor:
tek akışta kimin yanıtladığı bellidir; birden çok akışta bu soru yeniden sorulur ve yanıtı
bu kez bir sıralamaya bağlıdır.
