Ders 10 / 11
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.
İçindekiler
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ı.
# 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.
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.
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.
İlerlemeni kaydetmek ve not almak için Giriş yap
Notlarım
Not almak için giriş yapmalısın.