---
title: 'Geliştirme Araçlarıyla Tümleştirme'
source: 'https://academia.sh/tr/kurslar/mcp/gelistirme-araclariyla-tumlestirme'
course: 'Model Bağlam Protokolü ve Araç Ekosistemi'
language: tr
updated: '2026-08-17T18:06:40+00:00'
license: 'CC BY-SA 4.0'
---

# Geliştirme Araçlarıyla Tümleştirme

Aynı sunucunun ikinci bir istemciye takılmasının bedelinin sayılması: üç araçlık zincirin tanımı 24 satırdır ve protokolsüz kurulumda her istemci bu 24 satırı yeniden taşır, dört istemcide 96 satır eder; protokollü kurulumda tanım tek yerde 24 satır kalır ama her istemci 10 istek, 10 yanıt, 289 zarf belirteci ve 17 gidiş-dönüş öder, dört istemcide 40 istek ve 1156 belirteç. İkinci istemcinin marjinal bedeli 0 tanım satırı ve 20 mesajdır. Arayüz değiştiğinde protokolsüz kurulum dört istemcide 52 satırı dört ayrı noktada, protokollü kurulum 13 satırı tek noktada yeniden yazar. Tek istemcide protokol saf bedeldir.

Bir önceki dersin tablosu tek bir istemci içindi ve o istemci için protokol saf bedeldi: 10 istek,
10 yanıt, 289 belirteç ve 17 gidiş-dönüş ödenip ders içinde tanımlı bir aracın verdiği sonucun
aynısı alındı. Tanımın karşı tarafta durmasının **karşılığı** ise hiç sayılmadı. Karşılık ancak
ikinci bir istemci ortaya çıktığında görünür olur, çünkü tanım o zaman **ikinci kez yazılmaz**.
Bu ders aynı kurgu sunucuyu dört ayrı istemci türüne bağlar ve iki şeyi ayrı ayrı sayar: kaç satır
tanım yeniden yazılıyor ve kaç mesaj yeniden ödeniyor. **Taşınabilirliğin ölçüsü budur.**

Kod yardımcılarının kendi ölçümü Model API'leri ile Uygulama Geliştirme kursunda yapıldı ve burada
tekrarlanmaz. İstemciler burada **türleriyle** anılır: kod düzenleyicisinin içinde çalışan bir
istemci, kabuk üzerinden çalışan bir istemci, sürekli tümleştirme işinde koşan bir istemci ve
destek arayüzünün arkasındaki bir istemci. Hiçbir ürün, eklenti ya da düzenleyici adı geçmez;
ölçülen şey istemcinin **sayısı**dır, kimliği değil.

- **GE46.** Ortam, üç sunucu, zarf sayımı ve yetenek uzlaşması **kurgudur**; gerçek bir sunucu,
  istemci ya da düzenleyici çağrılmaz. Tohum **20260218**.
- **GE47.** **Tanım satırı** bir aracın gerçekleştirim satırları ile bir şema satırının
  toplamıdır. Sayı kaynaktan okunur, elle yazılmaz.
- **GE48.** Abone tablosunun kendisi tanım satırına **sayılmaz**. Sayılsaydı protokolsüz sütun daha
  da büyürdü; ölçü bu yüzden protokolün lehine değil, aleyhine kuruludur.
- **GE49.** Her istemci **kendi kurulumunu** yapar: kimlik adımı, yetki adımı, el sıkışması ve
  zincir. İstemciler arasında hiçbir kalem paylaşılmaz.
- **GE50.** Dört istemci dört ayrı abone üzerinde çalışır; işleri farklıdır, sözleşmeleri aynıdır.

## Sunucu Bir, İstemci Dört

Birinci blok ortak tanımı kurar: kurgu ölçüm ağı, üç kurgu sunucu, zarf sayacı, yetenek uzlaşması
ve araç çağrısı.

```python
# KURGUDUR. Olcum aginin abone kayitlari, uc sunucu, zarf sayaci ve yetenek
# uzlasmasi ders icinde tanimlanir; gercek bir sunucu ya da istemci 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


def belirtecle(m):
    b = []
    for s in str(m).lower().replace(",", " , ").split():
        while len(s) > 5:
            b.append(s[:5])
            s = s[5:]
        b.append(s)
    return b


BOLGE = ["dogu", "bati", "kuzey", "guney", "merkez"]
TIP = ["mesken", "isyeri"]
ABONE = {}
for i in range(60):
    r = uretec(TOHUM + 31 * i)
    onceki = 10000 + int(r() * 80000)
    ABONE[f"A{i + 1:03d}"] = {"bolge": BOLGE[int(r() * 5)], "tip": TIP[int(r() * 2)],
                              "onceki": onceki, "simdiki": onceki + int(r() * 70)}
BASAMAK, USTU, ISYERI_KAT = ((10, 4), (25, 7), (40, 11)), 16, 2


def _bedel(m3, tip):
    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) * (ISYERI_KAT if tip == "isyeri" else 1)


def t_sayac(abone=None, **_):
    a = ABONE.get(abone)
    return {"hata": "abone yok"} if a is None else {
        "onceki": a["onceki"], "simdiki": a["simdiki"], "tip": a["tip"]}


def t_tuketim(onceki=None, simdiki=None, **_):
    if onceki is None or simdiki is None:
        return {"hata": "eksik alan"}
    f = simdiki - onceki
    return {"m3": f + 100000 if f < 0 else f}


def t_tarife(m3=None, tip="mesken", **_):
    return {"hata": "eksik alan"} if m3 is None else {"tutar": _bedel(m3, tip)}


def t_bolge(bolge=None, **_):
    if bolge not in BOLGE:
        return {"hata": "bolge yok"}
    n = sum(1 for a in ABONE.values() if a["bolge"] == bolge)
    return {"bolge": bolge, "abone": n}


def t_kayit(abone=None, sutun=None, deger=None, **_):
    if not (abone and sutun and deger is not None):
        return {"hata": "eksik alan"}
    return {"yazildi": True}


SUNUCU = {
    "olcum": {"surum": 2, "aktarim": "yerel",
              "arac": {"sayac_oku": {"islev": t_sayac, "alan": ("abone",), "yan_etki": False},
                       "tuketim": {"islev": t_tuketim, "alan": ("onceki", "simdiki"),
                                   "yan_etki": False}},
              "kaynak": ("abone_listesi",), "istem": ()},
    "tarife": {"surum": 1, "aktarim": "uzak",
               "arac": {"tarife": {"islev": t_tarife, "alan": ("m3", "tip"), "yan_etki": False}},
               "kaynak": ("basamak_tablosu",), "istem": ("bedel_aciklamasi",)},
    "kayit": {"surum": 3, "aktarim": "uzak",
              "arac": {"bolge_ozet": {"islev": t_bolge, "alan": ("bolge",), "yan_etki": False},
                       "kayit_yaz": {"islev": t_kayit, "alan": ("abone", "sutun", "deger"),
                                     "yan_etki": True}},
              "kaynak": (), "istem": ()},
}
ISTEMCI_SURUM = {"olcum": 2, "tarife": 1, "kayit": 2}      # kayit sunucusu ileride
IZIN = ("sayac_oku", "tuketim", "tarife", "bolge_ozet")     # kayit_yaz izin listesinde yok

SAYIM = {"istek": 0, "yanit": 0, "bildirim": 0, "belirtec": 0, "gidis_donus": 0}


def mesaj(tur, govde, aktarim="yerel"):
    """KURGU zarf. Gercek bir protokol uygulanmaz; sayilan sey zarfin bedelidir."""
    SAYIM[tur] += 1
    b = len(belirtecle(govde)) + 8                       # zarf sabiti
    SAYIM["belirtec"] += b
    if tur == "istek":
        SAYIM["gidis_donus"] += 2 if aktarim == "uzak" else 1
    return b


def elsikismasi(istemci_surum=None, izin=None):
    """Yetenek uzlasmasi: surum uyusmazligi ve izin listesi arac kumesini daraltir."""
    istemci_surum = ISTEMCI_SURUM if istemci_surum is None else istemci_surum
    izin = IZIN if izin is None else izin
    anlasilan, dusen = {}, []
    for ad, s in SUNUCU.items():
        mesaj("istek", f"yetenek sor {ad}", s["aktarim"])
        mesaj("yanit", f"yetenek bildir {ad} surum {s['surum']} "
                       + " ".join(s["arac"]) + " " + " ".join(s["kaynak"]))
        if istemci_surum.get(ad, 0) < s["surum"]:
            dusen.append((ad, "surum", s["surum"], istemci_surum.get(ad, 0)))
            continue
        for t, tan in s["arac"].items():
            if t not in izin:
                dusen.append((ad, "izin", t, None))
                continue
            anlasilan[t] = dict(tan, sunucu=ad, aktarim=s["aktarim"])
    return anlasilan, dusen


def cagir(anlasilan, ad, durum):
    if ad not in anlasilan:
        return {"hata": "arac bildirilmedi"}
    t = anlasilan[ad]
    kw = {a: durum[a] for a in t["alan"] if a in durum}
    mesaj("istek", f"{ad} " + " ".join(f"{k} {v}" for k, v in kw.items()), t["aktarim"])
    s = t["islev"](**kw)
    mesaj("yanit", " ".join(f"{k} {v}" for k, v in s.items()))
    return s
```

## İki Sütun: Tanım Satırı ve Mesaj

Tanım satırı elle yazılmaz, kaynaktan okunur: bir aracın gerçekleştirim satırları artı bir şema
satırı. Protokolsüz sütun bu sayıyı istemci sayısıyla çarpar, protokollü sütun sabit tutar. Mesaj
sütunları ise tersine davranır.

```python
import inspect

ZINCIR = ("sayac_oku", "tuketim", "tarife")
GERCEKLESTIRIM = {"sayac_oku": (t_sayac,), "tuketim": (t_tuketim,), "tarife": (t_tarife, _bedel)}
ISTEMCI = (("kod duzenleyicisi", "A017"), ("kabuk istemcisi", "A042"),
           ("surekli tumlestirme", "A003"), ("destek arayuzu", "A055"))


def tanim_satiri(araclar):
    """Protokolsuz bir istemcinin tasimak zorunda oldugu satir: gerceklestirim
    satirlari + arac basina bir sema satiri."""
    n = 0
    for ad in araclar:
        for f in GERCEKLESTIRIM[ad]:
            n += len(inspect.getsource(f).rstrip().splitlines())
        n += 1
    return n


def on_adim(sunucular):
    for ad, s in sunucular.items():
        if s["aktarim"] == "uzak":
            mesaj("istek", f"kimlik sun {ad}", "uzak")
            mesaj("yanit", f"kimlik kabul {ad}")
            mesaj("istek", f"yetki iste {ad} arac kumesi", "uzak")
            mesaj("yanit", f"yetki verildi {ad} izin listesi")


def istemci_bagla(abone):
    """Bir istemcinin kendi kurulumu: kimlik ve yetki adimi, el sikismasi, zincir."""
    on_adim(SUNUCU)
    anlasilan, _ = elsikismasi()
    durum = {"abone": abone}
    for ad in ZINCIR:
        durum.update(cagir(anlasilan, ad, durum))
    return durum.get("tutar")


L = tanim_satiri(ZINCIR)
print("arac basina tanim satiri:", {a: tanim_satiri([a]) for a in ZINCIR}, "toplam:", L)
print("\nistemci  eklenen tur          protokolsuz protokollu istek yanit belirtec gidis-donus")
for k in range(1, len(ISTEMCI) + 1):
    for j in SAYIM:
        SAYIM[j] = 0
    sonuc = [istemci_bagla(a) for _, a in ISTEMCI[:k]]
    print(f"{k:>7}  {ISTEMCI[k - 1][0]:<19} {k * L:>11} {L:>10} {SAYIM['istek']:>5}"
          f" {SAYIM['yanit']:>5} {SAYIM['belirtec']:>8} {SAYIM['gidis_donus']:>11}")
print("dort istemcinin sonuclari:", sonuc)

DEGISEN = ("tarife",)
print("\narayuz degistiginde yeniden yazilan satir (degisen arac: " + DEGISEN[0] + ")")
for k in (1, 2, 4):
    print(f"  {k} istemci: protokolsuz {k * tanim_satiri(DEGISEN):>3} satir,"
          f" {k} degisiklik noktasi;  protokollu {tanim_satiri(DEGISEN):>3} satir, 1 nokta")
```

```
arac basina tanim satiri: {'sayac_oku': 5, 'tuketim': 6, 'tarife': 13} toplam: 24

istemci  eklenen tur          protokolsuz protokollu istek yanit belirtec gidis-donus
      1  kod duzenleyicisi            24         24    10    10      289          17
      2  kabuk istemcisi              48         24    20    20      578          34
      3  surekli tumlestirme          72         24    30    30      867          51
      4  destek arayuzu               96         24    40    40     1156          68
dort istemcinin sonuclari: [844, 68, 211, 684]

arayuz degistiginde yeniden yazilan satir (degisen arac: tarife)
  1 istemci: protokolsuz  13 satir, 1 degisiklik noktasi;  protokollu  13 satir, 1 nokta
  2 istemci: protokolsuz  26 satir, 2 degisiklik noktasi;  protokollu  13 satir, 1 nokta
  4 istemci: protokolsuz  52 satir, 4 degisiklik noktasi;  protokollu  13 satir, 1 nokta
```

## İkinci İstemcinin Marjinal Bedeli

Birinci satır kursun ikinci iddiasının en yalın hâlidir: **tek istemcide standartlaştırmak saf
zarardır.** Protokolsüz sütun da protokollü sütun da 24 satır gösteriyor, yani tanım her iki hâlde
de bir kez yazılıyor; ama protokollü kurulum bunun üstüne 10 istek, 10 yanıt, 289 belirteç ve 17
gidiş-dönüş ödüyor. Kazanç sıfır, bedel yirmi mesaj. Bir sunucuyu tek bir istemci için protokole
taşımak, ölçüldüğünde savunulacak bir karar değildir.

İkinci satır tabloyu çevirir. Tanım sütunu protokolsüzde 48'e çıkarken protokollüde **24'te
kalıyor**; ikinci istemcinin marjinal bedeli **0 tanım satırı ve 20 mesajdır** (10 istek, 10 yanıt,
289 belirteç, 17 gidiş-dönüş). Dördüncü istemcide protokolsüz sütun **96 satıra** ulaşıyor,
protokollü sütun hâlâ 24; buna karşılık mesaj tarafı 40 isteğe, 1156 belirtece ve 68 gidiş-dönüşe
çıkıyor. İki sütun **ortak birim taşımaz**: biri kaynak satırı, öbürü mesajdır. Bu yüzden burada
başabaş noktası hesaplanmaz; hangi ölçütün ağır bastığı yazılır. Satır sayısı bir kez ödenen ve
sonsuza kadar bakılan bir bedeldir, mesaj ise her koşumda yeniden ödenir.

Taşınabilirliğin ölçüsü tam olarak şu iki sayıdır: **her yeni istemci 24 tanım satırı kazandırır ve
20 mesaj ödetir.** Kazanç istemci sayısıyla doğrusal büyür, bedel de öyle; ama kazanç **yazılan
şeye**, bedel **koşan şeye** aittir. Dört istemcili bir kurulumda protokolsüz tarafın taşıdığı 96
satırın 72'si aynı üç işlevin kopyasıdır ve bu kopyaların birbirinden ayrışması hiçbir hata
üretmez; yalnızca dört istemcinin dört ayrı sonuç vermesiyle görünür.

## Değişiklik Noktası

Son çıktı sözleşmenin asıl sayısını verir. `tarife` aracının hesabı değişirse — basamak sınırı
kayar, iş yeri katsayısı başkalaşır — protokolsüz kurulumda 13 satır her istemcide yeniden yazılır:
iki istemcide 26 satır ve **iki değişiklik noktası**, dört istemcide 52 satır ve **dört değişiklik
noktası**. Protokollü kurulumda aynı değişiklik her sayıda istemci için **13 satır ve tek
noktadır**.

Değişiklik noktası sayısı, kursun kuralının doğrudan ölçüsüdür: **bir araç bağlantısının sayısı
aracın sayısı değil sözleşmenin sayısıdır ve değiştiğinde kimin kırılacağı yazılmayan arayüz
ölçülmemiş sayılır.** Protokolsüz kurulumda "kimin kırılacağı" sorusunun yanıtı hiçbir yerde
yazılı değildir; yalnızca dört kopyayı da bulup okuyan biri bilir. Protokollü kurulumda yanıt
tektir ve el sıkışmasının kendisi bunu her oturumda yeniden söyler.

Tablodaki sayıların hiçbiri tohuma bağlı değildir. Dört istemci dört ayrı abone üzerinde çalışıyor
ve dört ayrı sonuç veriyor (844, 68, 211, 684), ama istemci başına düşen mesaj sayımı dördünde de
aynı: 10 istek, 10 yanıt, 289 belirteç, 17 gidiş-dönüş. Ölçülen şey işin büyüklüğü değil,
sözleşmenin biçimidir.

## Kullanılmayan Aracın Bedeli

Yukarıdaki tablo dört istemcinin de üç aracın hepsini kullandığını varsayar. Gerçekte istemciler
farklı işler yapar: kabuk istemcisi tüketim sorar, sürekli tümleştirme işi yalnız tarife hesaplar.
Protokolsüz kurulumda bu, taşınan satırı düşürür — kullanılmayan araç yazılmaz. Protokolde ise el
sıkışması **sunucu düzeyindedir**, araç düzeyinde değil.

```python
KULLANIM = {"kod duzenleyicisi": ZINCIR, "kabuk istemcisi": ("sayac_oku", "tuketim"),
            "surekli tumlestirme": ("tarife",), "destek arayuzu": ZINCIR}
BASLANGIC = {"abone": "A017", "m3": 30, "tip": "mesken"}


def kismi(araclar):
    """Yalniz kendi ihtiyaci olan araclari cagiran bir istemcinin bedeli."""
    for j in SAYIM:
        SAYIM[j] = 0
    on_adim(SUNUCU)
    anlasilan, _ = elsikismasi()
    durum = dict(BASLANGIC)
    for ad in araclar:
        durum.update(cagir(anlasilan, ad, durum))
    return dict(SAYIM, kullanilmayan=len(anlasilan) - len(araclar))


print("istemci turu         kullandigi arac  protokolsuz satir  istek belirtec kullanilmayan")
tp, ti, tb = 0, 0, 0
for tur, araclar in KULLANIM.items():
    s = kismi(araclar)
    tp += tanim_satiri(araclar)
    ti += s["istek"]
    tb += s["belirtec"]
    print(f"{tur:<20} {len(araclar):>15}  {tanim_satiri(araclar):>17}  {s['istek']:>5}"
          f" {s['belirtec']:>8} {s['kullanilmayan']:>13}")
print(f"{'toplam':<20} {'':>15}  {tp:>17}  {ti:>5} {tb:>8}")
print("sunucudaki tanim satiri:", tanim_satiri(ZINCIR))
```

```
istemci turu         kullandigi arac  protokolsuz satir  istek belirtec kullanilmayan
kod duzenleyicisi                  3                 24     10      289             0
kabuk istemcisi                    2                 11      9      264             1
surekli tumlestirme                1                 13      8      234             2
destek arayuzu                     3                 24     10      289             0
toplam                                               72     37     1076
sunucudaki tanim satiri: 24
```

İhtiyaçlar ayrıştığında protokolsüz sütun 96'dan **72 satıra** iner: kullanılmayan araç yazılmadığı
için kopyalanmaz da. Protokollü sütun yine **24 satırdır**; kazanç 72'ye karşı 24, yani 48 satır.
Mesaj tarafında ise ayrışma pek bir şey kazandırmıyor: tek araç kullanan istemci **8 istek ve 234
belirteç** ödüyor, üç araç kullanan **10 istek ve 289 belirteç**. Aradaki fark iki istektir, çünkü
bedelin çoğu el sıkışmasının kendisidir ve el sıkışması **üç sunucunun tamamına** sorar.

Son sütun bunu adıyla sayar: sürekli tümleştirme istemcisinin anlaştığı araçların **ikisi
kullanılmıyor**, kabuk istemcisinin **biri**. Kullanılmayan araç bedelsiz değildir; yetenek
bildiriminde taşınmıştır, izin listesinden geçmiştir ve istemcinin araç kümesinde durmaktadır.
Kursun ikinci iddiası burada ikinci kez görünür: standartlaştırma, dar bir ihtiyacı olan istemciye
**geniş bir sözleşmenin tamamını** ödetir.

## Özet

- Üç araçlık zincirin tanımı 24 satırdır; protokolsüz kurulumda her istemci bu satırları yeniden
  taşır, protokollü kurulumda sayı istemci sayısından bağımsızdır.
- İkinci istemcinin marjinal bedeli 0 tanım satırı ve 20 mesajdır; taşınabilirliğin ölçüsü budur.
- Tek istemcide protokol saf bedeldir: aynı 24 satır, üstüne 289 belirteç ve 17 gidiş-dönüş.
- Arayüz değiştiğinde protokolsüz kurulum dört istemcide 52 satırı dört noktada, protokollü kurulum
  13 satırı tek noktada yeniden yazar.
- El sıkışması sunucu düzeyindedir: tek araç kullanan istemci 8 istek ve 234 belirteç öder ve
  kullanmadığı iki araçla anlaşır.
- Tanım satırı ile mesaj ortak birim taşımaz; hangi ölçütle okunduğu yazılmadan iki sütun
  karşılaştırılamaz.

## Sonraki Adım

Bu derste sunucu hep **bizimdi**: tanımı biz yazdık, izin listesini biz kurduk ve karşı tarafın
bildirdiği şeyin doğru olduğunu hiç sorgulamadık. Taşınabilirliğin kazandırdığı sayı, aynı kolaylığı
**bizim yazmadığımız** bir sunucuya da verir: ağın ötesindeki bir sunucu da yeteneklerini bildirir,
araç adlarını kendisi seçer ve her aracın ne yaptığını kendi açıklamasıyla anlatır. O açıklamayı
okuyan taraf istemcidir ve istemcinin elinde onu doğrulayacak hiçbir şey yoktur. Sonraki ders
güvenilmeyen bir sunucunun bildirdiği tanımları sayar: kaçı izin listesi dışında, kaçı yan etkili,
kaçı şüphe örüntüsü taşıyor, denetim kaçını yakalıyor ve aynı denetim **güvenilir** sunucularda kaç
bulgu veriyor.
