---
title: 'Üretilen Kodun İncelenmesi'
source: 'https://academia.sh/tr/kurslar/model-apileri/uretilen-kodun-incelenmesi'
course: "Model API'leri ile Uygulama Geliştirme"
language: tr
updated: '2026-08-17T18:06:37+00:00'
license: 'CC BY-SA 4.0'
---

# Üretilen Kodun İncelenmesi

Kurgu bir kod tabanına gelen yirmi dört üretilmiş yamanın üç savunma denetiminden geçirilmesi: kabul sınaması altı davranış kusurunun beşini yakalıyor, örüntü taraması sekiz bulgunun sekizini, bağımlılık varlık denetimi dokuz uydurma adın dokuzunu. Yirmi sekiz kusurun yirmi altısı yakalanıyor, ikisi biçim hatası olarak kaçıyor ve kaçanlardan biri hiçbir uyarı almadan kod tabanına giriyor.

Önceki ders çok adımlı bir devirde **denetim noktasının** nereye konacağını ölçtü: kaç adımda
bir durulduğunda hata yayılmadan yakalanıyor ve durmanın bedeli ne. Denetim noktası bir yerdir.
Orada **ne yapılacağı** söylenmedi. Duran insanın önünde bir yama durur ve o yamaya bakmanın
kendi kapsamı, kendi maliyeti ve kendi kör noktası vardır.

Bu ders o bakışı üç ayrı denetime böler ve her birinin **eriştiği kusur sınıfını** sayar: kod
tabanının **sınama koşumu**, üretilen metnin **örüntü taraması** ve alınan bağımlılıkların
**varlık denetimi**. Kod incelemesinin genel yordamı Yazılım Kalitesi ve Test müfredatında,
güvenlik denetiminin yordamı Siber Güvenlik ve Uygulama Güvenliği müfredatlarında ölçüldü;
burada tekrarlanmaz. Eklenen tek şey **üreticinin kimliğidir**: incelenen yama bir insandan
değil belirsiz bir bileşenden geliyor, bu yüzden kusurların **dağılımı** başkadır ve denetimlerin
kapsadığı alanın sınırı sayılmalıdır.

- **YG31.** Kod tabanı **kurgudur**: ölçüm ağının kendi yardımcı betikleri. Hiçbir gerçek depo,
  paket ya da ürün değildir. **Beş modül, 53 satır.** Tohum **20260218**.
- **YG32.** Bu ders bir saldırı dersi değildir. **Koşan kod her zaman savunma tarafındadır**:
  sınama, tarama, sayım, doğrulama. Hiçbir sömürü kodu, yük ya da atlatma yordamı yazılmaz.
- **YG33.** Üretilen yama iki parçadır: değişen bir **modül** ve yeni bir **yardımcı dosya**.
  Yardımcı dosyayı hiçbir sınama çağırmaz; kod tabanına henüz bağlanmamıştır.
- **YG34.** Kod tabanına konan altı **davranış kusuru** kaynak metinde tek dizge değişimidir;
  altıncısı bir **biçim** kusurudur ve çıktının hizasını bozar.
- **YG35.** Kabul sınaması **on maddedir** ve ders içinde yazılır. Kod tabanının kendi
  sınamasıdır, üretilen bir sınama değildir.
- **YG36.** Örüntü taraması dört dizge arar. Bulgu bir kanıt değil bir **işarettir**; insanın
  bakması gereken satırı gösterir.
- **YG37.** Varlık denetimi: bir `import` satırındaki ad kod tabanının modülleri arasında ya da
  izinli standart kitaplık adları arasında değilse **uydurmadır**. Uydurma adlar kurgudur.
- **YG38.** Sayılan birim **kusurdur, aday değildir**. Bir aday birden çok kusur taşıyabilir;
  **işaretli aday** en az bir denetimden uyarı alandır.

## Kurgu Kod Tabanı ve İncelemenin Konusu

İnceleme, üzerinde durulacak bir gövde ister. Gövde şudur: ölçüm ağının okuma, tarife hesabı,
kayıt denetimi, bölge özeti ve çıktı biçimlendirmesi için yazılmış beş küçük modülü. Modüller
metin olarak tutulur ve çalıştırılmak istendiğinde ayrı bir ad alanına yüklenir; bu, aynı kod
tabanının **bozulmuş bir sürümünü** yan yana koşturmayı ucuzlatır.

```python
# KURGU kod tabani: olcum aginin kendi yardimci betikleri. Gercek bir depo,
# paket ya da urun degildir. Bes modul, 53 satir. Tohum 20260218.
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 izno(m):
    h = 2166136261
    for c in m:
        h = ((h ^ ord(c)) * 16777619) & M32
    return h


KOD = {
    "okuma.py": """
def ayristir(satir):
    p = satir.split(";")
    if len(p) != 4:
        return None
    if not p[3].lstrip("-").isdigit():
        return None
    return {"abone": p[0], "bolge": p[1], "donem": p[2], "endeks": int(p[3])}

def tuketim(onceki, simdiki):
    fark = simdiki - onceki
    if fark < 0:
        fark = fark + 100000
    return fark
""",
    "tarife.py": """
BASAMAK = ((10, 4), (25, 7), (40, 11))
USTU = 16

def bedel(m3):
    kalan, alt, top = m3, 0, 0
    for ust, birim in BASAMAK:
        dilim = min(kalan, ust - alt)
        if dilim <= 0:
            break
        top += dilim * birim
        kalan -= dilim
        alt = ust
    return top + kalan * USTU
""",
    "denetim.py": """
GECERLI_BOLGE = ("dogu", "bati", "kuzey", "guney", "merkez")

def gecerli(kayit):
    if kayit is None:
        return False
    if kayit["endeks"] < 0:
        return False
    return kayit["bolge"] in GECERLI_BOLGE

def ayikla(kayitlar):
    return [k for k in kayitlar if gecerli(k)]
""",
    "ozet.py": """
def bolge_toplam(kayitlar, tuketimler):
    top = {}
    for k, t in zip(kayitlar, tuketimler):
        top[k["bolge"]] = top.get(k["bolge"], 0) + t
    return top

def bolge_sayi(kayitlar):
    say = {}
    for k in kayitlar:
        say[k["bolge"]] = say.get(k["bolge"], 0) + 1
    return say
""",
    "bicim.py": """
def satir(bolge, m3, tutar):
    return bolge.ljust(8) + str(m3).rjust(7) + str(tutar).rjust(9)

def rapor(baslik, satirlar):
    return "\\n".join([baslik] + satirlar)
""",
}


def yukle(kod):
    ad = {}
    for dosya, kaynak in kod.items():
        alan = {}
        exec(kaynak, alan)
        ad[dosya] = alan
    return ad


SINIF = ("tamamlama", "aciklama", "donusturme")
DOSYA = ("okuma.py", "tarife.py", "denetim.py", "ozet.py", "bicim.py")
GEREKEN = {0: ("okuma.py",), 1: ("tarife.py",), 2: ("denetim.py", "okuma.py"),
           3: ("ozet.py", "denetim.py"), 4: ("bicim.py", "ozet.py"),
           5: ("tarife.py", "okuma.py"), 6: ("ozet.py", "okuma.py", "tarife.py"),
           7: ("denetim.py", "bicim.py")}
GOREV = [{"ad": s + "-" + str(i + 1), "sinif": s, "gereken": GEREKEN[i],
          "zorluk": 0.05 * (i % 4)} for s in SINIF for i in range(8)]

BOY = {d: len(k.strip().split("\n")) for d, k in KOD.items()}
AD = yukle(KOD)
print("kod tabani:", BOY, "toplam", sum(BOY.values()), "satir")
print("gorev sayisi:", len(GOREV), "-", " , ".join(SINIF))
print("bedel(0,10,25,40,60):", [AD["tarife.py"]["bedel"](m) for m in (0, 10, 25, 40, 60)])
print("tuketim(99800,300):", AD["okuma.py"]["tuketim"](99800, 300))
```

```
kod tabani: {'okuma.py': 13, 'tarife.py': 13, 'denetim.py': 11, 'ozet.py': 11, 'bicim.py': 5} toplam 53 satir
gorev sayisi: 24 - tamamlama , aciklama , donusturme
bedel(0,10,25,40,60): [0, 40, 145, 310, 630]
tuketim(99800,300): 500
```

Son iki satır kod tabanının **doğru davranışını** sabitliyor. Kademeli tarifede altmış metreküp
**630** ediyor; sayaç doksan dokuz binden üç yüze döndüğünde tüketim **500** çıkıyor. Bu iki sayı
bundan sonra ölçüt olacak: bir yama bunları değiştiriyorsa yama yanlıştır. İnceleme yordamının
ilk kuralı budur — doğruluk bir izlenim değil, **önceden yazılmış bir beklentidir**.

Yirmi dört kurgu görev üç sınıfa ayrılmıştır ve her görev belirli modülleri ilgilendirir. Bir
görevin yanıtı olarak gelen yama, o modüllerden birini değiştirir ve yanına bir yardımcı dosya
bırakır. Denetimlerin erişimi bu iki parça arasında bölünecektir.

## Üç Denetimin Erişimi

Üç denetim üç ayrı yere bakar. **Sınama koşumu** yalnız değişen modülü görür ve yalnız
sınamaların ölçtüğü davranışı görür. **Örüntü taraması** metne bakar, çalıştırmaz. **Varlık
denetimi** yalnız `import` satırlarına bakar. Üçünün birleşimi kod tabanının tamamı değildir ve
bu dersin ölçtüğü şey tam olarak aradaki boşluktur.

```python
HATA = [("H1", "tarife.py", "USTU = 16", "USTU = 11"),
        ("H2", "okuma.py", "if fark < 0:", "if fark < -100000:"),
        ("H3", "denetim.py", 'kayit["endeks"] < 0', 'kayit["endeks"] < -1'),
        ("H4", "ozet.py", 'top.get(k["bolge"], 0) + t', 'top.get(k["bolge"], 0) + 1'),
        ("H5", "okuma.py", "len(p) != 4", "len(p) < 4"),
        ("H6", "bicim.py", "rjust(9)", "rjust(7)")]
UYDURMA = ("olcum_araclari", "tarife_yardim", "bolge_ozet", "sayac_kit")
ORUNTU = ("eval(", "except:", "== None", "open(")
EK = {"eval(": "def cevir(ifade):\n    return eval(ifade)\n",
      "except:": "def tamsayi(s):\n    try:\n        return int(s)\n    except:\n        return 0\n",
      "== None": "def bos_mu(kayit):\n    return kayit == None\n",
      "open(": "def yedek(yol):\n    return open(yol).read()\n"}
STANDART = ("math", "json")


def bozuk(kod, hata):
    _, dosya, eski, yeni = hata
    yeni_kod = dict(kod)
    yeni_kod[dosya] = kod[dosya].replace(eski, yeni, 1)
    return yeni_kod


def uret(gorev, tohum=TOHUM):
    r = uretec(tohum ^ izno(gorev["ad"]))
    u = [r() for _ in range(6)]
    hata = HATA[int(u[1] * 6)] if u[0] < 0.46 else None
    ithal = UYDURMA[int(u[3] * 4)] if u[2] < 0.30 else "math"
    oru = ORUNTU[int(u[5] * 4)] if u[4] < 0.34 else None
    return {"kod": bozuk(KOD, hata) if hata else dict(KOD),
            "hata": hata[0] if hata else None, "ithal": ithal, "oru": oru,
            "yardim": "import " + ithal + "\n\n" + (EK[oru] if oru else "")}


KAYITLAR = [{"bolge": "dogu", "endeks": 120}, {"bolge": "yildiz", "endeks": 40},
            {"bolge": "bati", "endeks": 90}]


def sinama_kos(kod):
    a = yukle(kod)
    o, t, d, z, b = (a["okuma.py"], a["tarife.py"], a["denetim.py"],
                     a["ozet.py"], a["bicim.py"])
    dusen = []
    for ad, sonuc in (
            ("ayristir-alan", o["ayristir"]("A017;dogu;2026-01;41250") ==
             {"abone": "A017", "bolge": "dogu", "donem": "2026-01", "endeks": 41250}),
            ("ayristir-fazla", o["ayristir"]("A017;dogu;2026-01;41250;ek") is None),
            ("tuketim-donus", o["tuketim"](99800, 300) == 500),
            ("bedel-basamak", [t["bedel"](m) for m in (0, 10, 25, 40, 60)] ==
             [0, 40, 145, 310, 630]),
            ("gecerli-eksi", d["gecerli"]({"bolge": "dogu", "endeks": -1}) is False),
            ("ayikla-bolge", len(d["ayikla"](KAYITLAR)) == 2),
            ("toplam-bolge", z["bolge_toplam"](KAYITLAR, [12, 5, 8]) ==
             {"dogu": 12, "yildiz": 5, "bati": 8}),
            ("sayi-bolge", z["bolge_sayi"](KAYITLAR) ==
             {"dogu": 1, "yildiz": 1, "bati": 1}),
            ("bicim-satir", "dogu" in b["satir"]("dogu", 12, 48)),
            ("bicim-rapor", b["rapor"]("bas", ["a", "b"]).count("\n") == 2)):
        if not sonuc:
            dusen.append(ad)
    return dusen


def oruntu_tara(metin):
    return [o for o in ORUNTU if o in metin]


def bagimlilik_dene(metin, kod):
    yok = []
    for s in metin.split("\n"):
        if s.startswith("import "):
            a = s[7:].strip()
            if a + ".py" not in kod and a not in STANDART:
                yok.append(a)
    return yok


def olc(tohum=TOHUM):
    kusur = {"davranis": 0, "oruntu": 0, "uydurma": 0}
    yakalanan = {"sinama": 0, "oruntu": 0, "bagimlilik": 0}
    kacan, sessiz, isaretli = [], 0, 0
    for g in GOREV:
        a = uret(g, tohum)
        bayrak = 0
        if a["oru"]:
            kusur["oruntu"] += 1
            if oruntu_tara(a["yardim"]):
                yakalanan["oruntu"] += 1
                bayrak += 1
        if a["ithal"] in UYDURMA:
            kusur["uydurma"] += 1
            if bagimlilik_dene(a["yardim"], a["kod"]):
                yakalanan["bagimlilik"] += 1
                bayrak += 1
        if a["hata"]:
            kusur["davranis"] += 1
            if sinama_kos(a["kod"]):
                yakalanan["sinama"] += 1
                bayrak += 1
            else:
                kacan.append((g["ad"], a["hata"],
                              "isaretli" if bayrak else "temiz"))
                sessiz += bayrak == 0
        isaretli += bayrak > 0
    return kusur, yakalanan, kacan, sessiz, isaretli


print("taban ORUNTU bulgusu:", oruntu_tara("".join(KOD.values())) or "yok")
print("kusur  dosya        dusen sinama")
for h in HATA:
    print("%-6s %-12s %s" % (h[0], h[1], sinama_kos(bozuk(KOD, h)) or "yok"))
print()
print("tohum     | davranis oruntu uydurma | sinama oruntu bagimlilik"
      " | isaretli kacan sessiz")
sonuc = {}
for tohum in (TOHUM, TOHUM + 1):
    k, y, kc, ss, isr = olc(tohum)
    sonuc[tohum] = kc
    print("%d  | %8d %6d %7d | %6d %6d %10d | %8d %5d %6d"
          % (tohum, k["davranis"], k["oruntu"], k["uydurma"], y["sinama"],
             y["oruntu"], y["bagimlilik"], isr, len(kc), ss))
print("kacan kusur, tohum 20260218:", sonuc[TOHUM])
print("kacan kusur, tohum 20260219:", sonuc[TOHUM + 1] or "yok")
```

```
taban ORUNTU bulgusu: yok
kusur  dosya        dusen sinama
H1     tarife.py    ['bedel-basamak']
H2     okuma.py     ['tuketim-donus']
H3     denetim.py   ['gecerli-eksi']
H4     ozet.py      ['toplam-bolge']
H5     okuma.py     ['ayristir-fazla']
H6     bicim.py     yok

tohum     | davranis oruntu uydurma | sinama oruntu bagimlilik | isaretli kacan sessiz
20260218  |       11      8       9 |      9      8          9 |       16     2      1
20260219  |        6      9      12 |      6      9         12 |       17     0      0
kacan kusur, tohum 20260218: [('tamamlama-4', 'H6', 'isaretli'), ('aciklama-7', 'H6', 'temiz')]
kacan kusur, tohum 20260219: yok
```

İlk satır taramanın **temiz bir taban** üzerinde çalıştığını söylüyor: kod tabanının kendisinde
aranan dört dizgeden hiçbiri yok. Bulgu çıkarsa üretilen koddan çıkacak demektir; bu, tarama
sonuçlarını yorumlanabilir kılan önkoşuldur.

İkinci tablo bu dersin **koşumdan bağımsız** ölçüsüdür. Altı davranış kusuru tek tek kod tabanına
konur ve kabul sınaması koşturulur. Beşi tek bir sınamayı düşürüyor: kademeli bedel, sayaç
dönüşü, eksi endeks denetimi, bölge toplamı ve fazla alanlı satır. Altıncısı **hiçbir sınamayı
düşürmüyor**. Sebep sınamanın kendisindedir: biçim modülünü ölçen iki madde çıktının içinde bölge
adının geçmesine ve satır sayısına bakıyor, **sütun genişliğine** bakmıyor. Kusur oradadır ve
sınama oraya bakmaz. Bu sonuç tohumdan, görev dağılımından ve üretimden bağımsızdır.

## Kalıntı ve İşaretin Yanıltıcılığı

Üçüncü tablo iki koşumu yan yana koyuyor. İlk koşumda yirmi dört yamada **11 davranış kusuru,
8 örüntü bulgusu ve 9 uydurma bağımlılık** var; toplam **28 kusur**. Örüntü taraması sekizin
sekizini, varlık denetimi dokuzun dokuzunu yakalıyor. Sınama koşumu on birin **dokuzunu**
yakalıyor. Toplamda 28 kusurun 26'sı görülüyor, **2'si kaçıyor** ve ikisi de biçim kusuru.

İkinci koşumda kaçan yoktur ve bu, denetimin iyileştiği anlamına gelmez. O koşumda hiç biçim
kusuru üretilmemiştir; üretilen altı davranış kusurunun altısı da sınamanın baktığı yerdedir.
Kaçan sayısı **kusurun dağılımına** bağlıdır, denetimin kapsamına değil. Kapsamı okuyan sayı
ikinci tablodadır ve orada altıda bir kusur örtüsüz durur. Bir denetimin gücü, iyi bir koşumda
verdiği sıfırla değil, **erişemediği sınıfın adıyla** ölçülür.

Son satır işaretin kendisini sorguluyor. Kaçan iki yamadan biri (`tamamlama-4`) aslında
**işaretlidir**: uydurma bir bağımlılık almış ve yardımcı dosyasında bir örüntü bulgusu var. Bu
yamaya bakan insan iki uyarı görür, ikisini de giderir ve yamayı kabul eder. Giderilenler
kusurdur, ama **kusurun tamamı değildir**; biçim hatası kabulle birlikte kod tabanına girer.
İkincisi (`aciklama-7`) hiç uyarı almaz ve doğrudan girer. Bedel sütunu da buradadır: ilk koşumda
**16 aday işaretlenir**, yani insanın bakması gereken yama sayısı yirmi dörtte on altıdır;
işaretsiz geçen sekiz yamanın **biri kusurludur**. İkinci koşumda işaretli sayı **17'ye** çıkar
ve elde edilen kazanç sıfırdır, çünkü o koşumda zaten kaçan yoktu. İnceleme yükü kusur sayısıyla
değil, **işaret sayısıyla** büyür.

## Özet

- Kurgu kod tabanı beş modül ve 53 satırdır; doğru davranışı iki sayıyla sabitlenir, kademeli
  bedelde 630 ve sayaç dönüşünde 500.
- Üç denetim üç ayrı yere bakar: sınama koşumu değişen modülün davranışına, örüntü taraması
  metne, varlık denetimi yalnız içe aktarma satırlarına.
- Koşumdan bağımsız ölçü: altı davranış kusurunun beşi kabul sınamasını düşürür, biçim kusuru
  hiçbirini düşürmez, çünkü sınama sütun genişliğine bakmaz.
- İlk koşumda 28 kusurun 26'sı yakalanır, 2'si kaçar; ikinci koşumda kaçan sıfırdır ama bunun
  nedeni kapsamın değil kusur dağılımının değişmesidir.
- İşaretli aday sayısı yakalanan kusur sayısı değildir: kaçan iki yamadan biri başka bir kusur
  yüzünden işaretlidir ve uyarıları giderilerek kabul edilir.
- İnceleme bedeli işaret sayısıyla ölçülür; ilk koşumda 24 yamanın 16'sı insana gider ve
  işaretsiz geçen sekizden biri kusur taşır.

## Sonraki Adım

Bu derste kabul sınaması **elle yazılmıştı** ve kapsamı bilinen bir büyüklüktü: on madde, beş
modül, bilinen bir kör nokta. Sınamayı yazmak da bir iştir ve aynı yardımcıya devredilebilecek
görevlerin en çok önerileni budur. Sonraki ders sınamayı üretilen tarafa geçirir ve aynı soruyu
sınamanın kendisine sorar: üretilen sınamalar kod tabanına konan altı kusurun kaçını yakalıyor,
kaç sınama bütün sürümlerde aynı sonucu verip hiçbir şey ayırt etmiyor, ve üretilen belgede kaç
iddia makinece doğrulanabiliyor.
