Ders 07 / 26
Uyumlu Arayüz Katmanları
İki kurgu sağlayıcının ve aralarındaki ortak arayüzün alan alan sayılması: sağlayıcı A on iki alan sunuyor, sekizi taşınıyor ve dördü kayboluyor; sağlayıcı B on alan sunuyor, sekizi taşınıyor ve ikisi kayboluyor. Durdurma dizisi alanı yalnız A'da olduğu için kesişimde yer bulamıyor ve çıkış belirteci 773'ten 1638'e çıkıyor. Yüz yirmi çağrının 117'si uzunluk sınırında kesiliyor; iki sağlayıcı da bunu kendi arayüzünde bildiriyor, ortak arayüzden okunabilen kesilme sayısı 0. Aynı ortak çağrıda sıcaklık 0,6 A'da 0,5500, B'de 0,5000 isabet veriyor; sıcaklık 0,4 ile 0,6 B'de aynı ayara yuvarlandığı için ikisi de 0,5000 verirken A 0,7583 ile 0,5500 arasında ayrışıyor.
İçindekiler
Önceki dersteki gömme uç noktası ile daha önceki derslerdeki metin uç noktası aynı sağlayıcıdan gelmek zorunda değil. Bir uygulama büyüdükçe ikinci bir sağlayıcı eklenir, bir görev ucuz olana taşınır, bir başkası elde tutulur. O noktada her çağrı yerinde ayrı ayrı yazılmış alan adlarıyla uğraşmak istenmez ve ortak bir arayüz yazılır: tek bir işlev, tek bir ad kümesi, altında sağlayıcıya göre değişen bir eşleme.
Bu ders o katmanın ne yaptığını sayar. İki sağlayıcı benzetici düzeyinde kurulur, ikisi de kurgudur ve ikisi de altta aynı motoru çağırır. Ölçülen şey soyutlamanın taşıdığı ve kaybettiği alanlardır: kaç alan geçiyor, kaç alan düşüyor ve düşen alanların hangisi bir ölçüyü görünmez kılıyor. Veri Analitiği müfredatının Python ile Veri Analizi kursunda kurulan kural burada aynen geçerlidir: bir soyutlama altındaki kararı gizler.
- AK57. Kod bir benzeticidir. İki sağlayıcı da kurgudur ve benzetici düzeyinde kurulur; gerçek bir uç nokta çağrılmaz. Tohum 20260218, ikinci koşum 20260219.
- AK58. İki sağlayıcı tek bir motoru paylaşır. Böylece aralarındaki bütün farklar arayüz farkıdır, model farkı değil.
- AK59. Sağlayıcı A on iki alan, sağlayıcı B on alan sunar; adlar blokta listelidir.
B’de durdurma dizisi alanı yoktur ve B’nin
cesitayarı sıfır ile dört arasında tam sayıdır, yani kendi ölçeğine oturur. - AK60. Ortak arayüz iki sağlayıcının kesişimidir: yalnız her ikisinde de karşılığı olan alan taşınabilir. Bir alan tek sağlayıcıda varsa ortak arayüzde yeri yoktur.
- AK61. Durdurma dizisi üretimi belirli bir belirteçte kesen alandır; bu derste üç yanıt kalıbının da içindeki ortak bir sözcükte devreye girer.
- AK62. Benzetici her çağrının gerçek bitiş nedenini kendi kaydına yazar; ortak arayüzü kullanan bir uygulamanın böyle bir kaydı olmaz.
İki Sağlayıcı ve Aradaki Kesişim
Aşağıdaki blok motoru, iki sağlayıcıyı, alan envanterini ve ortak arayüzü kurar. Envanter bir düzyazı iddiası değil, kod içinde tutulan bir listedir; taşınan ve kaybedilen alanlar küme işlemiyle sayılır.
# BENZETICI -- KURGUDUR. Iki saglayici da kurgudur ve benzetici duzeyinde # kurulur. Gercek bir model uc noktasi cagrilmaz. import math TOHUM, M32 = 20260218, 0xFFFFFFFF PENCERE = 240 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"] 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"} KAVRAM = KONU + ["odeme", "sikayet", "bilgi", "genel"] SERBEST = [ # ucuncu kalip hicbir etiket tasimaz "talebiniz {} konusunda kaydedildi ayrica ekibimiz sizinle iletisime gececek" " ve sonuc size bildirilecektir", "{} kaydiniz acilmistir ayrica islem numaraniz kisa mesajla tarafiniza" " gonderilecek ve surec takip edilebilecektir", "kaydiniz alinmistir ayrica ilgili birim inceleyip size donus yapacak" " ve gerekirse ek belge istenecektir"] SAYAC, GERCEK = [0], [] # GERCEK: benzeticinin kendi kaydi def motor(istem, en_uzun, sicaklik, dur, tohum): """Iki saglayicinin da altinda calisan tek KURGU motor.""" SAYAC[0] += 1 bel = belirtecle(istem) bos = {"metin": "", "hal": "hata", "giris": len(bel), "cikis": 0} if len(bel) > PENCERE or SAYAC[0] % 37 == 0: n = "baglam_asimi" if len(bel) > PENCERE else "hiz_siniri" GERCEK.append(n) return dict(bos, bitis=n) r = uretec(tohum ^ izno(istem)) aday = [k for k in KAVRAM if k[:5] in bel] if len(aday) < 3: aday = list(KAVRAM) p = {k: 0.15 for k in aday} for t in bel: if IZ.get(t) in p: p[IZ[t]] += 1.0 if sicaklik <= 0.0: secim = max(sorted(p), key=lambda a: p[a]) else: ad = sorted(p) w = [math.exp(p[a] / sicaklik) for a in ad] secim = ad[ayrik(r(), [q / sum(w) for q in w])] kalip = SERBEST[ayrik(r(), [0.40, 0.36, 0.24])] cb, bitis = belirtecle(kalip.format(secim)), "dogal" for i, t in enumerate(cb): if t in dur: # durdurma dizisi: uretim burada kesilir cb, bitis = cb[:i], "durdurma" break if len(cb) > en_uzun: cb, bitis = cb[:en_uzun], "uzunluk" GERCEK.append(bitis) tam = kalip.format(secim) return {"metin": tam if bitis == "dogal" else " ".join(cb), "hal": "tamam", "giris": len(bel), "cikis": len(cb), "bitis": bitis} def saglayici_a(istem, en_cok=14, dagilim=0.6, dur=(), kip="serbest", tohum=TOHUM): """KURGU saglayici A. Alan adlari ve yanit bicimi kendisine ozgudur.""" s = motor(istem, en_cok, dagilim, dur, tohum) return {"metin": s["metin"], "hal": s["hal"], "giris_bel": s["giris"], "cikis_bel": s["cikis"], "bitis": s["bitis"], "kesildi": s["bitis"] == "uzunluk"} def saglayici_b(mesaj, sinir=14, cesit=2, sema=None, anahtar=TOHUM): """KURGU saglayici B. cesit 0-4 arasi tam sayidir ve kendi olcegine oturur.""" s = motor(mesaj, sinir, cesit / 4 * 1.6, (), anahtar) return {"cikti": s["metin"], "durum": s["hal"], "neden": s["bitis"], "kullanim": {"g": s["giris"], "c": s["cikis"]}} ALAN = {"A": ["istem", "en_cok", "dagilim", "dur", "kip", "tohum", "metin", "hal", "giris_bel", "cikis_bel", "bitis", "kesildi"], "B": ["mesaj", "sinir", "cesit", "sema", "anahtar", "cikti", "durum", "kullanim.g", "kullanim.c", "neden"]} ESLEME = {"istem": ("istem", "mesaj"), "en_uzun": ("en_cok", "sinir"), "sicaklik": ("dagilim", "cesit"), "tohum": ("tohum", "anahtar"), "yanit": ("metin", "cikti"), "durum": ("hal", "durum"), "giris": ("giris_bel", "kullanim.g"), "cikis": ("cikis_bel", "kullanim.c")} def ortak(saglayici, istem, en_uzun=14, sicaklik=0.6, tohum=TOHUM): """Ortak arayuz: yalnizca ESLEME'deki sekiz alan tasinir.""" if saglayici == "A": y = saglayici_a(istem, en_cok=en_uzun, dagilim=sicaklik, tohum=tohum) return {"yanit": y["metin"], "durum": y["hal"], "giris": y["giris_bel"], "cikis": y["cikis_bel"]} y = saglayici_b(istem, sinir=en_uzun, cesit=round(sicaklik * 4), anahtar=tohum) return {"yanit": y["cikti"], "durum": y["durum"], "giris": y["kullanim"]["g"], "cikis": y["kullanim"]["c"]} ONEK5 = {k[:5]: k for k in KONU} # kesilen yanitta etiket parcalanmis olabilir def oku(y): return next((ONEK5[s[:5]] for s in y.split() if s[:5] in ONEK5), None) YONERGE = ("Talebi su etiketlerden birine ata: fatura , ariza , sayac , tarife ," " kesinti . Talep: ") print("ortak arayuzun alanlari :", " , ".join(ESLEME)) for i, ad in enumerate(ALAN): tasinan = [e[i] for e in ESLEME.values()] kayip = [a for a in ALAN[ad] if a not in tasinan] print(f"saglayici {ad}: {len(ALAN[ad])} alan , tasinan {len(tasinan)} ," f" kaybedilen {len(kayip)} -> {' , '.join(kayip)}") istem = YONERGE + TALEP[2]["metin"] print("\nayni istem , dort yol -- metin disindaki alanlar:") for ad, y in (("A kendi + dur", saglayici_a(istem, dur=("ayric",))), ("B kendi", saglayici_b(istem)), ("ortak -> A", ortak("A", istem)), ("ortak -> B", ortak("B", istem))): alan = " , ".join(f"{k}={v}" for k, v in y.items() if k not in ("metin", "cikti", "yanit")) print(f" {ad:<14} {alan}")
ortak arayuzun alanlari : istem , en_uzun , sicaklik , tohum , yanit , durum , giris , cikis
saglayici A: 12 alan , tasinan 8 , kaybedilen 4 -> dur , kip , bitis , kesildi
saglayici B: 10 alan , tasinan 8 , kaybedilen 2 -> sema , neden
ayni istem , dort yol -- metin disindaki alanlar:
A kendi + dur hal=tamam , giris_bel=33 , cikis_bel=5 , bitis=durdurma , kesildi=False
B kendi durum=tamam , neden=uzunluk , kullanim={'g': 33, 'c': 14}
ortak -> A durum=tamam , giris=33 , cikis=14
ortak -> B durum=tamam , giris=33 , cikis=14
Envanter satırları soyutlamanın aritmetiğini veriyor. Sağlayıcı A on iki alan sunuyor, sekizi
taşınıyor, dördü kayboluyor. Sağlayıcı B on alan sunuyor, sekizi taşınıyor, ikisi kayboluyor.
Kaybın sebebi ortak arayüzün kötü tasarlanmış olması değil: dur ve kip yalnız A’da,
sema yalnız B’de var. Kesişim ancak iki tarafta da karşılığı olanı taşıyabilir, ve bir
sağlayıcı ne kadar çok alan sunarsa ortak arayüzde o kadar çok alanını kaybeder.
Dört yanıt biçimi aynı istemde yan yana duruyor. A kendi arayüzüyle çağrıldığında durdurma dizisi
işini yapıyor: çıkış beş belirteç ve bitis alanı durdurma diyor. B kendi arayüzüyle
çağrıldığında çıkış on dört belirteç ve neden alanı uzunluk diyor, yani yanıt kesildi. Ortak
arayüzden bakan iki satır ise ayırt edilemez: ikisi de durum: tamam ve cikis: 14. Yanıtın
tamamlanıp tamamlanmadığı bu iki satırda yazmıyor.
Kaybolan Alanların Bedeli
Yüz yirmi kurgu talep beş yoldan geçirilir. İlk ikisi A’nın kendi arayüzü (durdurma dizisiz ve dizili), üçüncüsü B’nin kendi arayüzü, son ikisi ortak arayüz. Her satırda giriş ve çıkış belirteci, etiket isabeti, ikinci koşum isabeti, benzeticinin kaydettiği gerçek kesilme sayısı ve o yoldan okunabilen kesilme sayısı basılır.
YOL = ("A kendi", "A kendi + dur", "B kendi", "ortak -> A", "ortak -> B") def kosum(yol, sicaklik=0.6, tohum=TOHUM): SAYAC[0], GERCEK[:] = 0, [] g = c = dg = gor = 0 for x in TALEP: istem = YONERGE + x["metin"] if yol.startswith("A kendi"): y = saglayici_a(istem, dagilim=sicaklik, tohum=tohum, dur=("ayric",) if "dur" in yol else ()) m, gi, ci = y["metin"], y["giris_bel"], y["cikis_bel"] gor += y["kesildi"] # bitis alani okunabiliyor elif yol == "B kendi": y = saglayici_b(istem, cesit=2, anahtar=tohum) m, gi, ci = y["cikti"], y["kullanim"]["g"], y["kullanim"]["c"] gor += y["neden"] == "uzunluk" # neden alani okunabiliyor else: y = ortak(yol[-1], istem, sicaklik=sicaklik, tohum=tohum) m, gi, ci = y["yanit"], y["giris"], y["cikis"] # bitis nedeni yok g, c = g + gi, c + ci dg += oku(m) == x["konu"] return g, c, dg / 120, GERCEK.count("uzunluk"), gor print("yol giris cikis isabet ikinci kosum gercek kesilme okunan") for yol in YOL: a, b = kosum(yol), kosum(yol, tohum=TOHUM + 1) print(f"{yol:<14} {a[0]:>6} {a[1]:>6} {a[2]:>7.4f} {b[2]:>13.4f}" f" {a[3]:>15} {a[4]:>7}") print("\nayni ortak cagri , iki saglayici:") print("sicaklik B'ye giden cesit ortak -> A ortak -> B fark") for s in (0.0, 0.2, 0.4, 0.6, 0.8, 1.0): a, b = kosum("ortak -> A", s)[2], kosum("ortak -> B", s)[2] print(f"{s:>8.1f} {round(s * 4):>17} {a:>11.4f} {b:>11.4f} {b - a:>+6.4f}")
yol giris cikis isabet ikinci kosum gercek kesilme okunan
A kendi 4054 1638 0.5500 0.5000 117 117
A kendi + dur 4054 773 0.5500 0.5000 0 0
B kendi 4054 1638 0.5000 0.3917 117 117
ortak -> A 4054 1638 0.5500 0.5000 117 0
ortak -> B 4054 1638 0.5000 0.3917 117 0
ayni ortak cagri , iki saglayici:
sicaklik B'ye giden cesit ortak -> A ortak -> B fark
0.0 0 0.8417 0.8417 +0.0000
0.2 1 0.7583 0.7583 +0.0000
0.4 2 0.7583 0.5000 -0.2583
0.6 2 0.5500 0.5000 -0.0500
0.8 3 0.5000 0.3167 -0.1833
1.0 4 0.4500 0.3167 -0.1333
İkinci satır kaybolan dur alanının bedelidir. Durdurma dizisi kullanıldığında çıkış belirteci
773, kullanılmadığında 1638: iki katından fazla. İsabet iki satırda da 0,5500, yani bu
belirteçlerin hiçbiri işe yaramıyor; kalıbın gövdesinden sonra gelen kibar kapanış cümlesi
ödeniyor ve atılıyor. Ortak arayüz bu alanı sunamaz, çünkü B’de karşılığı yoktur. Kesişimin
bedeli burada doğrudan belirteçle yazılıdır.
Son iki sütun kaybolan bitis ve neden alanlarının bedelidir ve bu dersin en sert satırıdır.
Yüz yirmi çağrının 117’si uzunluk sınırında kesiliyor. A kendi arayüzünde bunu kesildi
alanıyla, B kendi arayüzünde neden alanıyla bildiriyor: iki sağlayıcı da dürüst. Ortak arayüzden
okunabilen kesilme sayısı ise 0. Kesilme ortadan kalkmadı, sayılamaz hâle geldi. Kursun
kuralı tam buraya oturuyor: başarısızlığı yazılmayan çağrı ölçülmemiş sayılır. Ortak arayüzü
kullanan bir uygulama yüz on yedi yarım yanıtı kayıt sistemine yazar ve hiçbir sayacı kıpırdamaz.
Kaybolan alanın yerine konabilecek tek şey bir çıkarımdır: cikis sınıra eşitse yanıt kesilmiş
sayılır. Bu çıkarım sınıra tam denk gelerek doğal biten yanıtları da kesilmiş sayar, yani bir
ölçüm alanının yerine yeni bir hata sınıfı geçer.
Aynı Düğme, İki Ayrı Anlam
Alan sayısı soyutlamanın yalnız bir yüzüdür. Taşınan sekiz alanın aynı şeyi ifade ettiği
varsayımı ikinci ve daha sinsi yüzüdür. Ortak arayüzün sicaklik alanı A’ya olduğu gibi gider;
B’ye giderken sıfır ile dört arasında bir tam sayıya yuvarlanır, çünkü B’nin ölçeği odur.
Alt tablo bunun iki ayrı sonucunu gösteriyor. Birincisi: aynı ayar iki ayrı davranış demek.
Sıcaklık 0,4’te A 0,7583, B 0,5000 veriyor; fark 0,2583. Aynı satırdaki iki sayı aynı işlevin
aynı argümanıyla üretildi. İkincisi: iki ayrı ayar aynı davranış demek. Sıcaklık 0,4 ile 0,6 B’de
aynı cesit değerine yuvarlanıyor ve ikisi de 0,5000 veriyor, oysa A’da 0,7583 ile 0,5500
arasında 0,2083’lük bir ayrım var. Ortak arayüzün sürekli görünen düğmesi B üzerinde beş
konumludur ve aradaki konumlar sessizce yutulur.
Bu okumaların hangisinin ölçülmüş sayıldığı ikinci koşum sütunundan çıkar. A’nın iki koşum farkı 0,0500, B’nin 0,1083. Sıcaklık 0,6 satırındaki 0,0500’lük sağlayıcı farkı koşum farkının tam kendisidir ve ölçülmemiş sayılır; o değerde iki sağlayıcı arasında bir seçim yapılamaz. Sıcaklık 0,4 satırındaki 0,2583 ise koşum farkının beş katıdır ve gerçektir. Ortak arayüzü kullanan bir uygulama sağlayıcı değiştirdiğinde bu farkı hiçbir yerde görmez: alan adları aynı kalır, çağrı aynı kalır, yalnız sayı değişir.
Özet
- Ortak arayüz iki sağlayıcının kesişimidir: A’nın on iki alanından sekizi taşınır ve dördü düşer, B’nin on alanından sekizi taşınır ve ikisi düşer.
- Yalnız bir sağlayıcıda bulunan alan kesişime giremez;
durvekipA’da,semaB’de kalır. - Durdurma dizisinin kaybı belirteçle ödenir: çıkış 773’ten 1638’e çıkar, isabet 0,5500’de sabit kalır, yani eklenen belirteçler işe yaramaz.
- Yüz yirmi çağrının 117’si uzunluk sınırında kesilir; iki sağlayıcı da bunu kendi alanında bildirir, ortak arayüzden okunabilen kesilme sayısı 0’dır.
- Taşınan bir alan da aynı anlama gelmeyebilir: sıcaklık 0,4’te iki sağlayıcı 0,2583 ayrışır, 0,4 ile 0,6 ise B’de aynı ayara yuvarlandığı için tek bir değere çöker.
- Sağlayıcı farkının ölçülmüş sayılması koşum farkını aşmasına bağlıdır: 0,6 satırındaki 0,0500 koşum farkının kendisidir, 0,4 satırındaki 0,2583 onun beş katıdır.
Sonraki Adım
Bu derse kadar her ölçü istek başına bir çağrı varsayımıyla yazıldı: yüz yirmi talep, yüz yirmi çağrı. Oysa yönerge her çağrıda yeniden gönderiliyor ve tabloda giriş belirtecinin 4054’te sabit kalmasının sebebi budur. Talepler bir kerede biriktirilip tek çağrıda gönderilseydi bu tekrar ödenmezdi. Sonraki ders toplu çağrıyı ölçer ve tek bir soruya bağlar: toplu boyut büyüdükçe çağrı sayısı ve belirteç düşerken, tek bir başarısızlığın etkilediği istek sayısı ne oluyor.
İlerlemeni kaydetmek ve not almak için Giriş yap
Notlarım
Not almak için giriş yapmalısın.