---
title: Belgelendirme
source: 'https://academia.sh/tr/kurslar/python-projeleri/belgelendirme'
course: 'Python Projeleri: Paketleme ve Test'
language: tr
updated: '2026-08-17T18:10:32+00:00'
license: 'CC BY-SA 4.0'
---

# Belgelendirme

Dört kaynak sürümünden üretilen belge 2 ayrı sonuç verir ve bayat imza sayısı dördünde de 0 kalırken elle yazılan belgede 2 ile 3 arasında durur; üretim imzayı tekleştirir, özet metnindeki iddiayı tekleştirmez ve o iddiayı ancak çalıştırılabilir örnek yakalar.

Önceki ders yayımlanmış bir sürümün içeriğini adına bağladı: değiştirilemez bir kayıtta
`(ad, sürüm)` çifti tek bir dağıtımı adlandırır. Paket kurulan tarafa kodu taşır.

Kodun **nasıl kullanılacağını** taşımaz. O bilgi belgeden gelir ve belge iki yoldan
üretilebilir: elle yazılarak ya da kaynaktan üretilerek. Bu kursun son dersi ikisini aynı
soruyla ölçer: **üretim hangi sonucu tekleştirir, hangisini tekleştirmez?**

## Üretimin Girdisi ve Çıktısı

Kaynaktan belge üretiminin yaklaşımları **Teknik Yazarlık ve Dokümantasyon** kursunda
kuruldu; bayatlama ve denetim de orada ele alındı. Burada o tartışma tekrarlanmaz. Ölçülen
tek şey, üretimin **kaç ayrı sonucu bire indirdiğidir**.

Bu kurs araç adı yazmaz. **Belge üreticisi** burada tek bir işlevle **modellenir**: kaynağı
ayrıştırır, adı alt çizgiyle başlamayan işlevleri seçer, her biri için imzayı ve özet
metninin ilk satırını okur, sonucu ada göre sıralar. Gerçek bir üretici çok daha fazlasını
yapar — bağlantı kurar, tip bilgisini işler, sayfa düzeni üretir; modelin tuttuğu tek
özellik, **çıktısının tümüyle kaynaktan türetilmiş olmasıdır**.

Ölçüm dört kaynak sürümü tanımlar: kanonik yazım, işlev tanımlarının sırası değişmiş yazım,
özel bir yardımcı işlevin eklendiği yazım, ve iki imzanın değiştiği yazım. Bunların yanında
bir de **elle yazılmış belge** durur; eski imzalarla yazılmıştır ve o günden beri elle
güncellenmemiştir.

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

- **KY29** — Üç işlev ortak kurgudan alınır; `indirim` işlevinin gövdesi değiştirilmez ve
  kusurlu tavan yerinde durur.
- **KY30** — `indirim` işlevinin özet metni tavanın yüzde 25 olduğunu **yazar**; gövde ise
  20 uygular. İddia ile davranış arasındaki bu ayrım kurgunun kendisidir.
- **KY31** — Belge üreticisi yalnız kaynaktan okur ve hiçbir iddiayı davranışla
  karşılaştırmaz; yaptığı denetim sayısı **0**'dır.
- **KY32** — Elle yazılan belge dört kaynak sürümünde de aynıdır; kaynağı hiç izlemez.
- **KY33** — Çalıştırılabilir örneklerin koşumu standart kitaplığın belge testi
  düzeneğiyle yapılır. Belge testinin ne olduğu bu kursun belge testleri dersinde kuruldu;
  burada bir **denetim aracı** olarak kullanılır, yeniden kurulmaz.
- **KY34** — Süre ölçülmez, dosya yazılmaz. Sayılan şey **ayrı belge**, **bayat imza** ve
  **düşen örnek** sayısıdır.

## Ölçüm

```python
"""Belgelendirme: uretim neyi tekleştirir, neyi tekleştirmez."""

import ast
import doctest
import hashlib
import types

GOVDE = {
    "indirim": (
        "(tutar, uye, kupon)",
        '"""Uye ve kupon indirimini uygular; tavan oran yuzde 25\'tir.\n\n'
        "    >>> indirim(100, True, True)\n    75\n    \"\"\"\n"
        "    oran = 0\n    if uye:\n        oran += 10\n"
        "    if kupon:\n        oran += 15\n"
        "    if oran > 20:\n        oran = 20\n"
        "    return tutar - tutar * oran // 100\n"),
    "uygun": (
        "(paket)",
        '"""Bildirimin araligina giren surumleri verir.\n\n'
        '    >>> uygun("rapor")\n    [(1, 0), (1, 1)]\n    """\n'
        "    alt, ust = BILDIRIM[paket]\n"
        "    return [s for s in DEPO[paket] if alt <= s < ust]\n"),
    "kilit": (
        "(secim)",
        '"""Cozumlemenin sonucunu sabitler.\n\n'
        "    >>> kilit({\"rapor\": (1, 1)})\n    {'rapor': (1, 1)}\n    \"\"\"\n"
        "    return dict(secim)\n"),
}
BASLIK = ('DEPO = {"rapor": [(0, 9), (1, 0), (1, 1)]}\n'
          'BILDIRIM = {"rapor": ((1, 0), (2, 0))}\n\n\n')
YARDIMCI = 'def _normalle(s):\n    """Ic kullanim."""\n    return tuple(s)\n\n\n'
YENI_IMZA = {"indirim": "(tutar, uye, kupon, tavan)", "kilit": "(secim, dogrula)"}


def kur(adlar, yardimci=False, imza_degisti=False):
    p = BASLIK + (YARDIMCI if yardimci else "")
    for ad in adlar:
        im, govde = GOVDE[ad]
        if imza_degisti and ad in YENI_IMZA:
            im = YENI_IMZA[ad]
        p += f"def {ad}{im}:\n    {govde}\n\n"
    return p


SURUMLER = {
    "kanonik": kur(["indirim", "uygun", "kilit"]),
    "sırası değişik": kur(["kilit", "uygun", "indirim"]),
    "özel yardımcı eklenmiş": kur(["indirim", "uygun", "kilit"], yardimci=True),
    "imzası değişmiş": kur(["indirim", "uygun", "kilit"], imza_degisti=True),
}
ELLE = {"indirim": "indirim(tutar, uye)", "uygun": "uygun(paket, bildirim)",
        "kilit": "kilit(secim)"}


def uret(kaynak):
    """Belge ureticisi modeli: genel adlarin imzasi ve ozeti kaynaktan okunur."""
    kayit = {}
    for d in ast.parse(kaynak).body:
        if isinstance(d, ast.FunctionDef) and not d.name.startswith("_"):
            im = ", ".join(a.arg for a in d.args.args)
            ilk = (ast.get_docstring(d) or "").split("\n")[0]
            kayit[d.name] = f"{d.name}({im}) — {ilk}"
    return "\n".join(kayit[a] for a in sorted(kayit))


def imza(kaynak, ad):
    for d in ast.parse(kaynak).body:
        if isinstance(d, ast.FunctionDef) and d.name == ad:
            return f"{ad}({', '.join(a.arg for a in d.args.args)})"
    return ""


def belgedeki_imza(belge, ad):
    for s in belge.splitlines():
        if s.startswith(ad + "("):
            return s.split(" — ")[0]
    return ""


def ozet(metin):
    return hashlib.sha256(metin.encode()).hexdigest()[:8]


print(f"{'kaynak sürümü':<24s} {'genel ad':>8s} {'belge özeti':>12s} "
      f"{'üretilende bayat':>16s} {'elle yazılanda bayat':>21s}")
belgeler = []
for ad, k in SURUMLER.items():
    b = uret(k)
    belgeler.append(ozet(b))
    bu = sum(1 for a in ELLE if belgedeki_imza(b, a) != imza(k, a))
    be = sum(1 for a in ELLE if ELLE[a] != imza(k, a))
    print(f"{ad:<24s} {len(b.splitlines()):8d} {ozet(b):>12s} "
          f"{bu:>13d}/{len(ELLE)} {be:>18d}/{len(ELLE)}")
print(f"dört kaynak sürümü, {len(set(belgeler))} ayrı üretilmiş belge; "
      f"elle yazılan belge dördünde de aynı")

print()
modul = types.ModuleType("olcum")
exec(compile(SURUMLER["kanonik"], "<olcum>", "exec"), modul.__dict__)
denenen, dusen = 0, []
for t in doctest.DocTestFinder().find(modul):
    kosucu = doctest.DocTestRunner(verbose=False)
    kosucu.run(t, out=lambda s: None)
    denenen += kosucu.tries
    if kosucu.failures:
        dusen.append(t.name.split(".")[-1])
print(f"belge testi {denenen} örnek denedi, {len(dusen)} tanesi düştü: "
      f"{', '.join(dusen)}")
print("belge üreticisinin iddia için yaptığı denetim: 0")
```

```
kaynak sürümü            genel ad  belge özeti üretilende bayat  elle yazılanda bayat
kanonik                         3     0aab9512             0/3                  2/3
sırası değişik                  3     0aab9512             0/3                  2/3
özel yardımcı eklenmiş          3     0aab9512             0/3                  2/3
imzası değişmiş                 3     65a37bdf             0/3                  3/3
dört kaynak sürümü, 2 ayrı üretilmiş belge; elle yazılan belge dördünde de aynı

belge testi 3 örnek denedi, 1 tanesi düştü: indirim
belge üreticisinin iddia için yaptığı denetim: 0
```

## Tekleşen: İmza

Tablonun ilk üç satırı aynı belge özetini veriyor: `0aab9512`. Üç kaynak sürümü ayrı
metinlerdir — biri işlev tanımlarını başka sırada yazar, biri özel bir yardımcı işlev
taşır — ama ürettikleri belge tektir. Üretici çıktısını ada göre sıraladığı için tanım
sırası düşer; alt çizgiyle başlayan adı atladığı için özel yardımcı düşer.

Dördüncü satır ayrı bir özet veriyor: `65a37bdf`. İki imza değişti, belge değişti. Bu bir
kusur değil, üretimin tanımıdır: **belge kaynağın genel arayüzünü izler ve yalnız onu
izler.**

Bayat imza sütunları ayrımı sayıyla veriyor. Üretilen belgede bayat imza dört sürümde de
**0/3**. Elle yazılan belgede ilk üç sürümde **2/3**, dördüncüde **3/3** — üstelik elle
yazılan belge hiç değişmedi. Kaynak ilerledikçe bayatlık kendiliğinden büyüyor ve bunu
haber veren hiçbir şey yok.

Aradaki fark bir emek farkı değil, bir **bağ** farkıdır. Üretilen belgede imza ile kaynak
arasında bir kopya yoktur; imza her üretimde yeniden okunur. Elle yazılan belgede kopya
vardır ve kopyanın aslıyla eşit kalması bir insanın hatırlamasına bağlıdır. Üretimin
tekleştirdiği sonuç tam olarak budur: **aynı kaynaktan tek belge, ve o belgede sıfır bayat
imza.**

## Tekleşmeyen: İddia

Alt satırlar ölçümün ikinci yarısını veriyor ve tekleşmenin nerede durduğunu gösteriyor.

`indirim` işlevinin özet metni tavanın yüzde 25 olduğunu yazıyor; gövde 20 uyguluyor.
Üretici bu satırı belgeye **olduğu gibi** taşıyor. Yaptığı denetim sayısı **0**, çünkü
üretici bir kopyalayıcıdır: kaynakta ne yazıyorsa belgede o yazar. Kaynağın kendisi yanlış
bir şey söylüyorsa, üretim o yanlışı **daha da yaygınlaştırır**.

Belge testi ise **3** örnek deniyor ve **1** tanesi düşüyor: `indirim`. Düşmesinin nedeni
örneğin yanlış olması değil, örneğin **çalıştırılabilir** olmasıdır. Aynı iddia düzyazı
olarak yazılsaydı hiçbir şey düşmezdi.

Buradan dersin sonucu çıkar. Üretim **iki sonucu** tekleştirir: belgenin kaynakla aynı
arayüzü göstermesini, ve aynı kaynaktan aynı belgenin çıkmasını. **Bir sonucu
tekleştirmez:** belgedeki iddianın davranışla uyuşmasını. O uyuşma ancak iddia
çalıştırılabilir bir biçimde yazıldığında sınanır, ve sınandığında da denetleyen şey belge
üreticisi değil, testtir.

Bu, kursun kapsam ölçümüyle aynı biçimdedir. Kapsam kodun nerede yürüdüğünü sayar, testin
neye baktığını değil. Üretim belgenin neyi gösterdiğini belirler, doğru olup olmadığını
değil. **Her araç kendi girdisine bakar; kâhini olan tek şey beklentidir.**

## Özet

- Belge üreticisi çıktısını tümüyle kaynaktan türetir; tanım sırası ve özel adlar sonuca
  girmez.
- Dört kaynak sürümü **2 ayrı üretilmiş belge** verir; ilk üçü tek bir özette birleşir,
  dördüncüsü imza değiştiği için ayrılır.
- Üretilen belgede bayat imza dört sürümde de **0/3**; elle yazılan belgede **2/3** ve
  **3/3**, üstelik belge hiç değişmeden.
- Üretim iddiayı tekleştirmez: `indirim` işlevinin özet metnindeki yüzde 25 iddiası
  belgeye olduğu gibi taşınır ve üreticinin yaptığı denetim **0**'dır.
- Aynı iddia çalıştırılabilir örnek olarak yazıldığında **3** örnekten **1**'i düşer;
  iddiayı sınayan şey üretici değil, testtir.

## Kurs Kapanışı

Bu kurs on dört ders boyunca tek bir soru sordu: **aynı girdi kaç ayrı sonuç verdi?** Soru
hiçbir derste "çalışıyor mu" biçimine dönüşmedi, çünkü çalışan bir şeyin kaç ayrı biçimde
çalıştığı ayrı bir sorudur ve yeniden üretilebilirlik o soruyla ölçülür.

| ders | ölçülen | ayrı sonuç sayısı |
|---|---|---|
| Sanal Ortamlar | altı kurulum sırası, paylaşılan ve yalıtılmış site | paylaşılanda **5**, yalıtılmışta **1** |
| Bağımlılık Bildirimi | aynı bildirim, iki strateji ve iki depo görüntüsü | **2**, kilitle **1**; dört kurulumda **3**, kilitle **1** |
| Paket Yöneticileri | dört çözümleme stratejisi, gevşek ve sıkı kısıt | **4** küme (**3** tutarlı); sıkıda **2** küme (**0** tutarlı); kilitle **1** |
| Sürüm Yönetimi | aynı bildirim üç kurgu yorumlayıcıda | **2**; dokuz kurulumda **6** kabul, **3** ret |
| Test Çerçeveleri | iki yazım biçimi, üç keşif kuralı | yazımda **1**; bulunan testte **3**, raporda **1** |
| Düzenek ve Parametreleme | aynı beş testlik takım üç sırada | **2**, düzenekle **1** |
| Sahte Nesneler | aynı test üç kipte, sahte ve gerçek kaynak | gerçekle **3**, sahteyle **1**; sapmış sahteyle **2** |
| Belge Testleri | on iki iddianın biçim değişikliğiyle bayatlaması | sese dönen bayat **4** ve **6**: **2** |
| Kapsam Ölçümü | üç testlik kümenin kapsamı ve kâhinden sapan çağrı | satır ve dal **1,0000**, geçen **3/3**; sapan çağrı **1**; dördüncü testle kapsam **1**, geçen oranı **2** |
| Biçimlendirici ve Tüy Toplayıcılar | aynı işlevin altı ayrı yazımı | metin **6** → **1**; bulgu kümesi **5** → **1** |
| Çoklu Ortam Testi | aynı takım üç eksenli matriste, 18 koşum | **4**; kilitle **3**, düzenekle **2** |
| Paketleme | aynı kaynaktan dokuz üretim, üç dahil etme kuralı | **5**; açık listeyle **1**; kurulumda **3** ve **1** |
| Yayımlama | aynı kilit dosyasıyla iki kurulum, iki kayıt ilkesi | **2**, değiştirilemez kayıtta **1** |
| Belgelendirme | dört kaynak sürümünden üretilen belge | **2**; bayat imza **0**'a karşı **2** ve **3** |

Tablonun okunuşu tek cümlede toplanır: **hemen her satırda ilk sayı birden büyük, ikinci
sayı bir.** Aradaki fark bir araç farkı değil, bir **karar** farkıdır. Kilit dosyası
çözümlemeyi ortadan kaldırmadı; kararı bir kez verdirip yazıya geçirdi. Yalıtım kurulumu
kolaylaştırmadı; kurulum sırasının sonucu değiştirmesini durdurdu. Düzenek testi
hızlandırmadı; sıranın kararı belirlemesini durdurdu. Açık liste dosya seçmedi; seçimin
dizinin durumuna bağlı olmasını durdurdu. Her durumda tekleşen şey işin kendisi değil,
**kararın kaynağıydı**.

İkinci bir örüntü de tabloda duruyor: **tekleşen sayı doğruluk vermez.** Kapsam bire
indirdiği yerde bile kusurlu beklentiyi görmedi; biçimlendirici altı yazımı bire indirdi ama
kalan altı bulgunun hiçbiri kusuru bildirmedi; belge üretimi belgeyi tekleştirdi ama
belgedeki yanlış iddiayı taşıdı. Tekleşme **karşılaştırılabilirliğin** koşuludur, doğruluğun
değil. Doğruluğu veren tek şey kâhindir, ve kâhin her zaman ölçümün dışından gelir.

| kurs | ölçü ekseni |
|---|---|
| Python Temelleri | sözdizimin çağırdığı protokol |
| Veri Yapıları ve Fonksiyonel Araçlar | var edilen, tutulan ve paylaşılan nesne |
| Nesneye Dayalı Python ve Tipler | çağrıyı kim yanıtladı, sözü kim denetledi |
| Eşzamanlılık ve Başarım | örtüşen adım |
| Python Projeleri: Paketleme ve Test | aynı girdi kaç ayrı sonuç verdi |

Beş eksen bir dizi oluşturuyor. İlk kurs sözdizimin altına bakıp her biçimin hangi özel
yöntemi çağırdığını saydı. İkincisi nesnenin nasıl var edildiğini, nerede tutulduğunu ve
kimlerle paylaşıldığını ölçtü. Üçüncüsü çağrının hangi sınıfta yanıtlandığını ve verilen
sözün ne zaman denetlendiğini ayırdı. Dördüncüsü işin kaç adımının örtüştüğünü saydı ve
süre yerine adım saymanın gerekçesini kurdu. Beşincisi bunların hepsini bir projeye koydu ve
aynı girdinin kaç ayrı sonuç verdiğini sordu.

Beşi birlikte **bir dilin kendi düzeneğini** kuruyor: dil neyi çağırıyor, ne tutuyor, neyi
denetliyor, işi nasıl bölüyor ve bir proje olarak nasıl tekrarlanabilir hale geliyor. Bu
düzenek dile özgüdür ve başka bir dile olduğu gibi taşınmaz.

Taşınan şey **sorulardır**. M08 ile başlayan dil müfredatları aynı beş soruyu başka bir
dile sorar ve yanıtları başka çıkar: bir dilde özel yöntemle verilen yanıt öbüründe
arayüzle, bir dilde çalışma zamanında denetlenen söz öbüründe derleme anında, bir dilde
yorumlayıcı kilidiyle sınırlanan örtüşme öbüründe başka bir düzenekle karşılanır. **Bir
dilin kendi düzeneği kuruldu; sıra başka bir dilin aynı soruları nasıl yanıtladığında.**
