---
title: 'Çıktı Doğrulama'
source: 'https://academia.sh/tr/kurslar/istem-muhendisligi/cikti-dogrulama'
course: 'İstem Mühendisliği'
language: tr
updated: '2026-08-17T18:06:38+00:00'
license: 'CC BY-SA 4.0'
---

# Çıktı Doğrulama

Şema doğrulaması ve iş kuralı denetiminin ayrı ayrı sayılması ve üzerine bir yeniden deneme döngüsü kurulması: 120 kurgu yanıtın 24'ü şemaya uymuyor, şemadan geçen 96 kaydın 24'ü iş kuralına takılıyor ve doğrulama yokken hatalı kayıt oranı 0,4000. İki denetim birlikte kabul oranını 0,6000'a indiriyor, bir yeniden deneme 26 kaydı kurtarıp 0,8167'ye çıkarıyor ve 48 ek çağrıya mal oluyor. İkinci deneme sekiz kayıt daha kurtarıyor ama kazancı 0,0666 ile iki koşum farkı 0,0667'nin altında kalıyor. Hatayı isteme yazan deneme 23 kayıt kurtarıyor ve 514 belirteç ekliyor.

Önceki ders çıktının biçimini üç düzeyde ölçtü ve doğrulayıcıyı yalnız bir sayaç olarak
kullandı: kaç yanıtın düştüğünü saydı, düşenleri attı. Kapanışında iki eksik yazılıydı. Birincisi,
bir üretim hattında düşen kaydı atmak bir seçenek değildir. İkincisi, şemadan geçen bir kayıt da
yanlış olabilir: önceki dersin biçim tarifi satırında şemadan geçen kayıtların on üçü, isteme
yazılan numaranın yerine kayıtlı olmayan bir talep numarası taşıyordu ve doğrulayıcı bunu hiç
görmedi.

Bu ders iki denetimi ayırır ve üzerine bir yeniden deneme döngüsü kurar. Girdi doğrulama, şema ve
iş kuralı yordamı M16'nın API sözleşmesi kursunda ve M24'te ölçüldü; burada tekrarlanmaz. Eklenen
tek şey **üreticinin belirsiz olmasıdır**: reddedilen bir kayıt yeniden istenebilir ve ikinci
istek başka bir yanıt verebilir. Ölçülecek olan da budur — doğrulamanın yakaladığı, yeniden
denemenin kurtardığı ve bunun kaç çağrıya mal olduğu.

- **CD25.** Kod bir **benzeticidir**; gerçek bir uç nokta çağrılmaz. Talepler, alanlar ve kurallar
  **kurgudur**, tohum **20260218**.
- **CD26.** Başlangıç istemi önceki dersin **biçim tarifi** istemidir; şema dayatması bilerek
  kullanılmaz, çünkü bu ders **hatalı çıktının** ne yapıldığını ölçer.
- **CD27. İki denetim ayrıdır.** Şema doğrulaması alanların varlığına ve değer kümelerine bakar.
  **İş kuralı denetimi** yalnız şemadan geçmiş kayıtlara uygulanır ve kurumun kurallarına bakar.
- **CD28. Üç iş kuralı kurgudur:** yüksek öncelikli bir kayıt bilgilendirmeyle kapatılamaz,
  kesinti konulu bir kayıt tek başına kayıtla kapatılamaz, ve talep numarası kayıtlı talepler
  kümesinde olmalıdır. Üçünü de şema **göremez**.
- **CD29. Yeniden deneme aynı isteği yeni bir tohumla tekrar eder.** Model belirsiz olduğu için
  ikinci yanıt başka çıkabilir; bu, düzeltmenin tek dayanağıdır.
- **CD30.** Bir değişke, hatayı isteme **yazar**: reddedilen yanıtın hata adı isteme eklenir.
  Bu, giriş belirtecini artırır.
- **CD31. Sisteme giren hatalı kayıt** ayrıca sayılır: doğrulama olmadığında kabul oranı 1,0000
  görünür ama kaydın bir bölümü bozuktur.
- **CD32.** Bedel ek çağrı sayısı ve toplam belirteç olarak yazılır; iki koşum farkı için ikinci
  koşum tohum 20260219 ile alınır.

## Şemanın Göremediği Hata

Şema bir kaydın **biçimini** tanımlar: hangi alanlar var, değerler hangi kümeden. Bir kurumun
kuralları ise kaydın **anlamına** bakar ve şemanın diliyle yazılamaz. Bu ders üç kurgu kural
tanımlar ve üçünün de kusursuz biçimli kayıtlarda tetiklendiğini gösterir.

```python
# BENZETICI -- KURGUDUR. Gercek bir model uc noktasi cagrilmaz. Sema dogrulamasi
# ve is kurali denetimi ders icinde yazilir; disaridan kitaplik 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 ayrik(u, w):
    t = 0.0
    for i, x in enumerate(w):
        t += x
        if u < t:
            return i
    return len(w) - 1


def belirtecle(m):                      # KURGU belirtecleyici, parca en cok bes damga
    b = []
    for s in m.lower().replace(",", " , ").split():
        while len(s) > 5:
            b.append(s[:5])
            s = s[5:]
        b.append(s)
    return b


def izno(m):
    h = 2166136261
    for c in m:
        h = ((h ^ ord(c)) * 16777619) & M32
    return h


KONU = ["fatura", "ariza", "sayac", "tarife", "kesinti"]
ONCELIK, AKSIYON = ["dusuk", "orta", "yuksek"], ["kayit", "yonlendirme", "bilgi"]
SEMA = {"talep_no": "sayi", "konu": KONU, "oncelik": ONCELIK, "aksiyon": AKSIYON}
KALIP = [("bu ayki fatura tutari gecen aya gore cok yuksek geldi", "fatura"),
         ("faturami odedim ama sistemde borc gorunuyor", "fatura"),
         ("fatura ayrintisini nereden gorebilirim", "fatura"),
         ("evde su akmiyor bir ariza var galiba", "ariza"),
         ("baglanti bozuk oldu ve hic calismiyor", "ariza"),
         ("ariza kaydi actim ama ekip gelmedi", "ariza"),
         ("sayac okumasi yanlis girilmis endeks tutmuyor", "sayac"),
         ("sayac degisimi icin randevu istiyorum", "sayac"),
         ("sayac uzerindeki endeks ile fatura ayni degil", "sayac"),
         ("hangi tarife basamagindayim ogrenmek istiyorum", "tarife"),
         ("tarife degisikligi icin ne yapmam gerekiyor", "tarife"),
         ("birim ucret abone tipine gore degisiyor mu", "tarife"),
         ("mahallede kesinti var ne zaman gelecek", "kesinti"),
         ("planli kesinti duyurusu nereden takip edilir", "kesinti"),
         ("aksamdan beri kesinti yasiyoruz", "kesinti")]
TALEP = []
for i in range(120):                    # 120 KURGU destek talebi
    r = uretec(TOHUM + i)
    k = KONU[ayrik(r(), [0.24, 0.22, 0.18, 0.20, 0.16])]
    TALEP.append({"no": 4001 + i, "konu": k,
                  "metin": [x for x in KALIP if x[1] == k][int(r() * 3)][0]})

IZ = {"fatur": "fatura", "tutar": "fatura", "ayrin": "fatura", "ariza": "ariza",
      "bozuk": "ariza", "calis": "ariza", "akmiy": "ariza", "sayac": "sayac",
      "endek": "sayac", "okuma": "sayac", "tarif": "tarife", "birim": "tarife",
      "abone": "tarife", "basam": "tarife", "kesin": "kesinti", "duyur": "kesinti",
      "mahal": "kesinti"}
TUZAK = {"degis": "tarife", "kayit": "ariza", "yukse": "tarife", "gorun": "fatura",
         "ekip": "kesinti", "takip": "tarife", "giril": "fatura"}   # yaniltici baglar
SAYAC = [0]


def ayristir(metin):
    """Anahtar=deger cifti ayristirici. Ayrilamayan yanit icin None doner."""
    if "=" not in metin:
        return None
    kayit = {}
    for parca in metin.split(";"):
        if "=" not in parca:
            return None
        a, _, d = parca.partition("=")
        kayit[a.strip()] = d.strip()
    return kayit


def dogrula(kayit):
    """Sema dogrulama: eksik anahtar, fazladan anahtar, gecersiz deger."""
    if kayit is None:
        return ["ayristirilamadi"]
    hata = [f"eksik:{a}" for a in SEMA if a not in kayit]
    hata += [f"fazla:{a}" for a in kayit if a not in SEMA]
    for a, kural in SEMA.items():
        if a not in kayit:
            continue
        d = kayit[a]
        if kural == "sayi" and not d.isdigit():
            hata.append(f"sayi_degil:{a}")
        elif kural != "sayi" and d not in kural:
            hata.append(f"gecersiz:{a}")
    return hata


def cekilis(istem, tohum, tuz):
    """Her karar icin ayri tuzlanmis tek cekilis; kararlar birbirine baglanmaz."""
    return uretec((tohum + tuz) ^ izno(istem))()


def cagir(istem, talep, tohum=TOHUM):
    """Onceki dersin bicim tarifi istemi; yanitin bir payi tarife uymaz."""
    SAYAC[0] += 1
    bel = belirtecle(istem)
    p = {k: 0.15 for k in KONU}
    for t in belirtecle(talep["metin"]):    # konu yalniz talep metninden okunur
        for tablo, w in ((IZ, 1.0), (TUZAK, 1.3)):
            if tablo.get(t) in p:
                p[tablo[t]] += w
    k = max(sorted(p), key=lambda a: p[a])
    o = ONCELIK[ayrik(cekilis(istem, tohum, 11), [0.31, 0.44, 0.25])]
    a = AKSIYON[ayrik(cekilis(istem, tohum, 29), [0.46, 0.32, 0.22])]
    duz = f"talep_no={talep['no']} ; konu={k} ; oncelik={o} ; aksiyon={a}"
    egilim = 0.62 if "bicim" in bel else 0.0            # istemdeki bicim tarifi
    if "hatal" in bel:                                  # hatayi isteme yazan deneme
        egilim += 0.14
    if cekilis(istem, tohum, 53) < egilim:
        return duz
    bozuk = ayrik(cekilis(istem, tohum, 71),            # tarife uymayan yanit
                  [0.22, 0.20, 0.18, 0.16, 0.24])
    if bozuk == 0:
        return f"talebiniz {k} konusunda kaydedildi ve {a} adimi baslatildi"
    if bozuk == 1:
        return f"talep_no={talep['no']} ; konu={k} ; aksiyon={a}"
    if bozuk == 2:
        return f"talep_no={talep['no']} ; konu={k} ; oncelik=acil ; aksiyon={a}"
    if bozuk == 3:
        return f"talep_no=TL{talep['no']} ; konu={k} ; oncelik={o} ; aksiyon={a}"
    return f"talep_no={talep['no'] + 500} ; konu={k} ; oncelik={o} ; aksiyon={a}"


TARIF = ("Yaniti su bicimde yaz: talep_no=<sayi> ; konu=<fatura|ariza|sayac|"
         "tarife|kesinti> ; oncelik=<dusuk|orta|yuksek> ; aksiyon=<kayit|"
         "yonlendirme|bilgi> . ")


def istemi(onek, x):
    return onek + f"Talep {x['no']} : {x['metin']}"


KAYITLI = {t["no"] for t in TALEP}


def is_kurali(kayit):
    """Semadan gecen kaydin kurum kurallari. Sema bunlarin hicbirini goremez."""
    hata = []
    if kayit.get("oncelik") == "yuksek" and kayit.get("aksiyon") == "bilgi":
        hata.append("yuksek_oncelik_bilgi_ile_kapanamaz")
    if kayit.get("konu") == "kesinti" and kayit.get("aksiyon") == "kayit":
        hata.append("kesinti_kayitla_kapanamaz")
    if kayit.get("talep_no", "").isdigit() and int(kayit["talep_no"]) not in KAYITLI:
        hata.append("kayitli_olmayan_talep_no")
    return hata


sem, isk, gorulen = 0, 0, {}
for x in TALEP:
    y = cagir(istemi(TARIF, x), x)
    kayit = ayristir(y)
    h = dogrula(kayit)
    if h:
        sem += 1
        continue
    k = is_kurali(kayit)
    isk += bool(k)
    if k:
        gorulen.setdefault(k[0], y)
print(f"KURGU talep {len(TALEP)}: semaya takilan {sem}, is kuraline takilan {isk}")
for e, y in sorted(gorulen.items()):
    print(f"  {e}\n    {y}")
```

```
KURGU talep 120: semaya takilan 24, is kuraline takilan 24
  kayitli_olmayan_talep_no
    talep_no=4505 ; konu=sayac ; oncelik=orta ; aksiyon=kayit
  kesinti_kayitla_kapanamaz
    talep_no=4015 ; konu=kesinti ; oncelik=dusuk ; aksiyon=kayit
  yuksek_oncelik_bilgi_ile_kapanamaz
    talep_no=4022 ; konu=tarife ; oncelik=yuksek ; aksiyon=bilgi
```

İki sayı birbirine eşit ve bu eşitlik dersin çıkış noktasıdır: **24 yanıt şemaya uymuyor, şemadan
geçen 96 yanıtın 24'ü iş kuralına takılıyor.** Yani biçim denetimi hatanın ancak yarısını
görüyor. Üç örneğin üçü de kusursuz biçimlidir; ayrıştırıcı ve doğrulayıcı hiçbirinde bir şey
bulmaz. Birincisinde talep numarası istemde yazılı olmayan bir sayıdır, ikincisinde kesinti
kaydı yanlış aksiyonla kapatılmıştır, üçüncüsünde yüksek öncelikli bir kayıt bilgilendirmeye
bağlanmıştır.

Bu üç kural şemanın diline çevrilemez, çünkü hiçbiri tek bir alanın değeriyle ilgili değildir.
İlk ikisi **alanlar arası** bir tutarlılıktır, üçüncüsü ise kaydın **dış dünyayla** tutarlılığıdır.
Belirsiz bir üreticinin çıktısında bu iki sınıf ayrı ayrı sayılmadan doğrulama ölçülmüş sayılmaz.

## Yeniden Denemenin Kurtardığı

Altı hat aynı 120 talepte koşturulur. İlk üçünde yeniden deneme yoktur ve yalnız denetimin
neyi elediği ölçülür; son üçü reddedilen kaydı yeniden ister.

```python
HAT = [("dogrulama yok", False, False, 0, False),
       ("yalniz sema", True, False, 0, False),
       ("sema + is kurali", True, True, 0, False),
       ("+ 1 yeniden deneme", True, True, 1, False),
       ("+ 2 yeniden deneme", True, True, 2, False),
       ("+ 1 deneme, hata istemde", True, True, 1, True)]


def denetle(kayit, semali, kurali):
    h = dogrula(kayit) if semali else []
    if not h and kurali and kayit is not None:
        h = is_kurali(kayit)
    return h


def hat(semali, kurali, deneme, hatayi_yaz, tohum=TOHUM):
    SAYAC[0] = 0
    ilk_sema = ilk_kural = kurtarilan = kabul = hatali = ek = bel = 0
    for x in TALEP:
        istem = istemi(TARIF, x)
        y = cagir(istem, x, tohum)
        bel += len(belirtecle(istem)) + len(belirtecle(y))
        kayit = ayristir(y)
        ilk_sema += bool(dogrula(kayit))
        ilk_kural += not dogrula(kayit) and bool(is_kurali(kayit))
        h = denetle(kayit, semali, kurali)
        for d in range(deneme):
            if not h:
                break
            ek += 1
            i2 = istem + f" Onceki yanit hatali: {h[0]} ." if hatayi_yaz else istem
            y = cagir(i2, x, tohum + 1 + d)
            bel += len(belirtecle(i2)) + len(belirtecle(y))
            kayit = ayristir(y)
            h = denetle(kayit, semali, kurali)
            kurtarilan += not h
        kabul += not h
        hatali += (not h) and bool(dogrula(kayit) or is_kurali(kayit))
    return (ilk_sema, ilk_kural, kurtarilan, kabul / 120, hatali / 120, ek, bel)


print("hat                       sema  kural  kurtarilan  kabul   hatali  ek cagri  belirtec")
for ad, s, k, d, w in HAT:
    a = hat(s, k, d, w)
    print(f"{ad:<25} {a[0]:>4}  {a[1]:>5}  {a[2]:>10}  {a[3]:>6.4f}  {a[4]:>6.4f}"
          f"  {a[5]:>8}  {a[6]:>8}")
b = hat(True, True, 1, False, TOHUM + 1)
print(f"ikinci kosum (+ 1 yeniden deneme): kabul {b[3]:.4f}, kurtarilan {b[2]}, "
      f"ek cagri {b[5]}")
```

```
hat                       sema  kural  kurtarilan  kabul   hatali  ek cagri  belirtec
dogrulama yok               24     24           0  1.0000  0.4000         0      7403
yalniz sema                 24     24           0  0.8000  0.2000         0      7403
sema + is kurali            24     24           0  0.6000  0.0000         0      7403
+ 1 yeniden deneme          24     24          26  0.8167  0.0000        48     10350
+ 2 yeniden deneme          24     24          34  0.8833  0.0000        70     11716
+ 1 deneme, hata istemde    24     24          23  0.7917  0.0000        48     10864
ikinci kosum (+ 1 yeniden deneme): kabul 0.7500, kurtarilan 26, ek cagri 56
```

İlk üç satır tek bir çağrıyla üretilmiştir ve belirteç sütunu üçünde de aynıdır: **7403**.
Değişen tek şey kabulden önce yapılan denetimdir. Doğrulama yokken kabul oranı **1,0000** görünür
ve kayıt sistemine giren yanlış kayıt oranı **0,4000**'dır. Yani hiçbir şey ölçülmediğinde
sistem kusursuz görünür ve her beş kayıttan ikisi bozuktur. Şema eklendiğinde hatalı kayıt
**0,2000**'a, iş kuralı da eklendiğinde **0,0000**'a iniyor.

Bunun bedeli kabul oranıdır: **1,0000'dan 0,6000'a**. Doğrulama hiçbir kaydı düzeltmez, yalnız
görünür kılar. Üçüncü satırdaki sistem birincisinden daha iyidir ama daha az iş yapar; 48 talep
elde kalır. Doğrulamanın ölçüsü kabul oranı değil, **kabul edilenlerin ne kadarının doğru
olduğudur**.

## Kurtarmanın Bedeli

Dördüncü satır yeniden denemeyi ekliyor. **26 kayıt kurtarılıyor** ve kabul oranı 0,6000'dan
**0,8167**'ye çıkıyor; hatalı kayıt oranı **0,0000**'da kalıyor, çünkü kurtarma denetimin
önüne değil arkasına konmuştur. Bedel **48 ek çağrı** ve **2947 belirteçtir**: kurtarılan kayıt
başına 1,85 çağrı ve 113,3 belirteç. Kazanç 0,2167 ve iki koşum farkı 0,0667 olduğu için bu
satır rahatça ölçülebilir.

Beşinci satır kursun kuralının en keskin uygulandığı yerdir. İkinci deneme sekiz kayıt daha
kurtarıyor ve kabul oranını **0,8833**'e çıkarıyor. Kazanç **0,0666**. Aynı hattın iki koşum
farkı ise **0,0667**: birinci koşumda 0,8167, ikinci koşumda 0,7500. Kazanç farktan **büyük
değil**, dolayısıyla **ölçülmemiş sayılır**. Bu satır için ödenen bedel ise kesindir: 22 ek çağrı
ve 1366 belirteç, kurtarılan kayıt başına 2,75 çağrı. Ölçülemeyen bir kazanç, ölçülebilir bir
bedelle satın alınmıştır.

Altıncı satır sezgiye en uygun düzeltmeyi sınıyor: reddedilen yanıtın hatasını isteme yazmak.
Sonuç 26 yerine **23 kurtarma** ve kabul oranında **0,7917**. Aradaki 0,0250, iki koşum farkı
0,0667'nin çok altında kaldığı için bu satırla dördüncü satır arasında **ölçülebilir bir fark
yoktur**. Bedel ise ölçülebilir: aynı 48 çağrıyla belirteç 10350'den **10864'e** çıkıyor, yani
**514 belirteç** eklenmiştir. Hataları isteme yazmak burada bir iyileştirme değil, ölçülmemiş
bir tahmindir.

Üç sayıyla toparlanır. Önceki istem biçim tarifi istemidir: kabul 0,6000, hatalı kayıt 0,0000,
7403 belirteç, 120 çağrı. Değiştirilmiş hat bir yeniden deneme ekler: kabul 0,8167, aynı hatalı
kayıt oranı, 10350 belirteç, 168 çağrı. Bedel **48 çağrı ve 2947 belirteçtir**; bu kursta ilk
kez bir düzenek **çağrı sayısını** oynatıyor ve bedelin belirteçten büyük olan kısmı orada
duruyor.

## Özet

- Şema doğrulaması 24 yanıtı eliyor, iş kuralı denetimi şemadan geçen 96 yanıtın 24'ünü daha
  eliyor: biçim denetimi hatanın yarısını görüyor.
- Üç iş kuralının üçü de kusursuz biçimli kayıtlarda tetikleniyor; ikisi alanlar arası
  tutarlılık, biri kaydın dış dünyayla tutarlılığıdır.
- Doğrulama yokken kabul oranı 1,0000 ve sisteme giren hatalı kayıt 0,4000'dır; iki denetim
  hatalıyı 0,0000'a indirirken kabulü 0,6000'a düşürür. Doğrulama düzeltmez, görünür kılar.
- Bir yeniden deneme 26 kaydı kurtarır ve kabulü 0,8167'ye çıkarır; bedeli 48 ek çağrı ve 2947
  belirteçtir, kurtarılan kayıt başına 1,85 çağrı.
- İkinci denemenin kazancı 0,0666, hattın iki koşum farkı 0,0667'dir: kazanç ölçülmemiş sayılır
  ve karşılığında 22 çağrı ile 1366 belirteç ödenir.
- Hatayı isteme yazmak 26 yerine 23 kayıt kurtarır ve 514 belirteç ekler; iki hat arasında
  ölçülebilir bir fark yoktur.

## Sonraki Adım

Bu derste kurtarma tek bir kaldıraçla yapıldı: aynı isteği yeniden sormak. Kurtarılamayan 14
kayıt ise hiç incelenmedi. Onların bir kısmı ne kadar denenirse denensin düzelmez, çünkü sorun
yanıtın çekilişinde değil, modelin **bilmediği bir şeyde**dir. Bir talebin hangi tarife
basamağına girdiği isteme yazılmamışsa, daha iyi bir yönerge bunu üretemez. Sonraki ders bu
ayrımı sayar: aynı yanlış yanıt bazen daha iyi bir yönergeyle, bazen yalnız eksik bilginin
sağlanmasıyla düzelir. Hangi hatanın hangisiyle düzeldiği ayrı ayrı sayılır ve ikisinin bedeli
karşılaştırılır.
