Ders 03 / 11
Mimarın Sorumlulukları
Karar, iletişim ve gözetim sorumluluklarının bir matris olarak kurulması: kararın makinece denetlenebilir kısıt biçimine çevrilmesi, kısayol ekleyen bir kod tabanında gözetimli ve gözetimsiz düzenin aynı kenar dizisiyle koşturulması, kodda karşılığı kalmayan karar oranı ve üç sorumluluğun saat dağılımı.
İçindekiler
Önceki iki ders kararı verilmiş bir şey gibi ele aldı: karar vardır, kapsamı ölçülür, düzeyi belirlenir. Üç düzeyli düzenin 47 danışmasını yapan biri var ve o kişinin işi yalnız karar vermek değil. Bu ders mimarın işini üç sorumluluğa ayırır.
Karar bir seçeneğin seçilmesidir. İletişim kararın kapsamındaki birimlere, uygulanabilir bir biçimde ulaşmasıdır. Gözetim kararın kodda karşılığının kalmaya devam etmesidir. Üçü arasında bir sıra yok; eksik olan biri ötekileri değersizleştirir. Ölçülecek şey de budur: karar verilmiş ve duyurulmuş olmasına rağmen kodda karşılığı olmayan kararların oranı.
Kararın Yazılı Biçimi
Bir kararın gözetlenebilmesi için makinenin denetleyebileceği bir biçime çevrilmesi gerekir. Bu modelde biçim şudur: hangi modüller hangi modülü doğrudan ithal edemez (MN7). “Veri erişimi tek katmandan geçer” kararı, uç modüllerin veri erişim modülüne doğrudan kenar çekememesi demektir; kenar varsa karar ihlal edilmiştir. Bu, Servis Mimarileri kursunda kurulan sınır ihlali ölçüsüyle aynı biçimdir.
Her karar bu biçime çevrilemez. E-posta gövdesinin düz metin olması, günlük raporun ayrı bir modülde üretilmesi ve kiosk ucunun ayrı bir dağıtım birimi olması ithal grafiğinde görünmez. Bunlar başka yollarla denetlenir; ölçümde denetlenebilir kararlardan ayrı tutulur.
Model, önceki dersin ithal grafiğini yeniden kullanır; blok kendi başına çalışsın diye grafik tekrarlanıyor.
// mimari/model.mjs — MODEL kutuphane agi kod tabani: ithal grafigi ve kararlarin govdesi. // Gercek bir kurum degildir; kenarlar ve karar govdeleri elle secilmistir. export const ITHAL = { yapilandirma: [], zaman: [], kayit: ["yapilandirma"], "veri-erisim": ["yapilandirma", "kayit"], "olay-yolu": ["yapilandirma", "kayit"], "kimlik-dogrulama": ["veri-erisim", "yapilandirma", "kayit"], yetki: ["kimlik-dogrulama"], "katalog-baglayici": ["yapilandirma", "kayit"], "katalog-onbellek": ["katalog-baglayici", "zaman"], "odunc-kural": ["yapilandirma", "zaman"], "odunc-cekirdek": ["odunc-kural", "veri-erisim", "olay-yolu", "zaman", "katalog-baglayici"], ayirtma: ["odunc-cekirdek", "bildirim-kuyruk", "veri-erisim"], "uye-kayit": ["veri-erisim", "kayit"], "uye-ceza": ["uye-kayit", "odunc-kural", "zaman", "veri-erisim"], "sube-envanter": ["veri-erisim", "olay-yolu"], "sube-esitleme": ["sube-envanter", "olay-yolu", "katalog-baglayici", "kayit"], "bildirim-kuyruk": ["veri-erisim", "olay-yolu"], "bildirim-eposta": ["bildirim-kuyruk", "yapilandirma"], "rapor-gunluk": ["veri-erisim", "zaman"], "rapor-toplu": ["veri-erisim", "sube-envanter", "zaman", "kayit"], "web-ucu": ["odunc-cekirdek", "katalog-onbellek", "uye-kayit", "ayirtma", "kimlik-dogrulama"], "personel-ucu": ["odunc-cekirdek", "uye-kayit", "uye-ceza", "sube-envanter", "rapor-gunluk", "kimlik-dogrulama", "yetki"], "kiosk-ucu": ["odunc-cekirdek", "katalog-onbellek", "kimlik-dogrulama"], "toplu-is": ["rapor-toplu", "sube-esitleme", "bildirim-kuyruk", "bildirim-eposta"], }; export const KARAR = [ { ad: "veri erisimi tek katmandan gecer", govde: ["veri-erisim"] }, { ad: "ayar degerleri tek kaynaktan okunur", govde: ["yapilandirma"] }, { ad: "envanter olay yolu uzerinden esitlenir", govde: ["olay-yolu", "sube-esitleme"] }, { ad: "dis kataloga tek baglayici uzerinden erisilir", govde: ["katalog-baglayici"] }, { ad: "kimlik dogrulama tek modulde toplanir", govde: ["kimlik-dogrulama"] }, { ad: "odunc suresi kurali yapilandirmadan okunur", govde: ["odunc-kural"] }, { ad: "saat kaynagi tek modulden alinir", govde: ["zaman"] }, { ad: "ceza hesabi uye kaydindan ayri durur", govde: ["uye-ceza"] }, { ad: "gunluk rapor ayri bir modulde uretilir", govde: ["rapor-gunluk"] }, { ad: "eposta bildirimi duz metin govdeyle gider", govde: ["bildirim-eposta"] }, { ad: "kiosk ucu ayri bir dagitim birimidir", govde: ["kiosk-ucu"] }, ]; export const MODULLER = Object.keys(ITHAL);
Ölçüm
İkinci dosya sorumluluk matrisini kurar, kod tabanını on tur boyunca değiştirir ve aynı kenar dizisini iki düzende koşturur. Değişimin biçimi şudur: bir geliştirici, dolaylı olarak zaten eriştiği bir modüle doğrudan kenar çeker — kısayol (MN8). Kısayol yeni bir erişim yaratmaz, var olan dolaylı erişimi kısaltır; bu yüzden havuzu sonludur ve her ekleme havuzdan bir kenar eksiltir. Dizi bir kez üretilir ve iki düzene aynen verilir.
// mimari/sorumluluk.mjs — sorumluluk matrisi, gozetimli ve gozetimsiz duzenin karsilastirmasi import { ITHAL, KARAR, MODULLER } from "./model.mjs"; const UC = ["web-ucu", "personel-ucu", "kiosk-ucu", "toplu-is"]; // KISIT — kararin ithal grafiginde denetlenebilir karsiligi: kaynaklardan hedefe dogrudan kenar yasak const KISIT = [ { karar: 0, kaynak: UC, hedef: "veri-erisim" }, { karar: 1, kaynak: UC, hedef: "yapilandirma" }, { karar: 2, kaynak: ["web-ucu", "kiosk-ucu", "personel-ucu"], hedef: "sube-envanter" }, { karar: 3, kaynak: UC, hedef: "katalog-baglayici" }, { karar: 4, kaynak: ["ayirtma", "uye-kayit", "uye-ceza", "sube-envanter", "rapor-gunluk", "rapor-toplu"], hedef: "kimlik-dogrulama" }, { karar: 5, kaynak: ["web-ucu", "personel-ucu", "kiosk-ucu"], hedef: "odunc-kural" }, { karar: 6, kaynak: UC, hedef: "zaman" }, { karar: 7, kaynak: ["uye-kayit"], hedef: "uye-ceza" }, ]; const DENETLENEMEZ = [8, 9, 10]; // gunluk raporun uretim yeri, eposta govde bicimi, kiosk dagitimi // sorumluluk matrisi: her karar icin uc sorumlulugun durumu // verildi = karar alinmis; yazili = makinece denetlenebilir bir kisit bicimi var; gozetilir = duzene bagli const matris = KARAR.map((k, i) => ({ ad: k.ad, verildi: true, yazili: !DENETLENEMEZ.includes(i), })); const sut = (s, n) => String(s).padEnd(n); const im = (b) => (b ? "evet" : "hayir"); console.log(sut("karar", 46) + sut("verildi", 9) + "yazili kisit"); console.log("-".repeat(67)); for (const m of matris) console.log(sut(m.ad, 46) + sut(im(m.verildi), 9) + im(m.yazili)); console.log(`\nverilen karar = ${matris.length}/${matris.length}; yazili kisit bicimi olan = ${matris.filter((m) => m.yazili).length}/${matris.length}`); console.log(`yazili bicimi olmayan karar gozetlenemez: ${DENETLENEMEZ.map((i) => KARAR[i].ad).join("; ")}`); // ---- kod tabani zamanla degisir: gelistirici dolayli erisimi dogrudan kenara cevirir ---- function uretec(tohum) { let s = tohum >>> 0; return () => (s = (s * 1664525 + 1013904223) >>> 0) / 2 ** 32; } const erisir = (g, a, b) => { const gor = new Set([a]), yig = [a]; while (yig.length) for (const h of g[yig.pop()]) if (!gor.has(h)) { gor.add(h); yig.push(h); } return gor.has(b); }; const kisayollar = (g) => { const c = []; for (const a of MODULLER) for (const b of MODULLER) if (a !== b && !g[a].includes(b) && erisir(g, a, b)) c.push([a, b]); return c; }; const ihlalEder = (a, b) => KISIT.filter((c) => c.hedef === b && c.kaynak.includes(a)); const TUR = 10, TURDA = 5, TOHUM = 90210; const temel = Object.fromEntries(MODULLER.map((m) => [m, [...ITHAL[m]]])); const havuz = kisayollar(temel); const rast = uretec(TOHUM); // tohum gorunur; dizi bir kez uretilir const kalan = [...havuz], DIZI = []; for (let i = 0; i < TUR * TURDA; i++) DIZI.push(kalan.splice(Math.floor(rast() * kalan.length), 1)[0]); console.log(`\nkisayol havuzu = ${havuz.length} kenar; ${DIZI.length} kenar cekildi (tohum ${TOHUM})`); console.log(`cekilen kenarlarin ${DIZI.filter(([a, b]) => ihlalEder(a, b).length).length}'i bir kisiti ihlal ediyor`); const baslangic = []; for (const a of MODULLER) for (const b of ITHAL[a]) for (const c of ihlalEder(a, b)) baslangic.push(`${a} -> ${b}`); console.log(`kararin verildigi anda zaten ihlal edilmis kisit = ${baslangic.length} (${baslangic.join(", ") || "yok"})`); function kosu(gozetim) { const g = Object.fromEntries(MODULLER.map((m) => [m, [...ITHAL[m]]])); let eklenen = 0, geriAlinan = 0, saat = 0; for (let t = 0; t < TUR; t++) { for (const [a, b] of DIZI.slice(t * TURDA, (t + 1) * TURDA)) { g[a].push(b); eklenen++; } if (!gozetim) continue; saat += 0.5; // tur basina bir denetim kosumu for (const a of MODULLER) for (const b of [...g[a]]) if (!ITHAL[a].includes(b) && ihlalEder(a, b).length) { g[a].splice(g[a].indexOf(b), 1); geriAlinan++; saat += 1; // geri alma bedeli } } const bozuk = new Set(); for (const a of MODULLER) for (const b of g[a]) for (const c of ihlalEder(a, b)) bozuk.add(c.karar); return { eklenen, geriAlinan, saat, bozuk: bozuk.size }; } const D = KISIT.length; const A = kosu(false), Bk = kosu(true); console.log(`\n${TUR} tur, turda ${TURDA} kisayol; denetlenebilir karar = ${D}`); console.log(sut("duzen", 12) + sut("eklenen", 10) + sut("geri alinan", 13) + sut("bozulan karar", 15) + sut("uygulanma", 11) + "gozetim saati"); console.log("-".repeat(74)); for (const [ad, r] of [["gozetimsiz", A], ["gozetimli", Bk]]) console.log(sut(ad, 12) + sut(r.eklenen, 10) + sut(r.geriAlinan, 13) + sut(`${r.bozuk}/${D}`, 15) + sut(`${(((D - r.bozuk) / D) * 100).toFixed(0)}%`, 11) + r.saat); console.log(`\ngozetimsiz duzende kodda karsiligi kalmayan karar = ${A.bozuk}/${D}; gozetimli duzende ${Bk.bozuk}/${D}`); console.log(`gozetimin kurtardigi karar = ${A.bozuk - Bk.bozuk}; bedeli ${Bk.saat} saat, karar basina ${(Bk.saat / (A.bozuk - Bk.bozuk)).toFixed(1)} saat`); // ---- ucun zaman dagilimi ---- const SAAT = { "karar verme": KARAR.length * 3, iletisim: 47 * 0.5, gozetim: Bk.saat }; const toplam = Object.values(SAAT).reduce((a, b) => a + b, 0); console.log(`\n${sut("sorumluluk", 14)}saat pay`); console.log("-".repeat(28)); for (const [k, v] of Object.entries(SAAT)) console.log(sut(k, 14) + sut(v.toFixed(1), 7) + `${((v / toplam) * 100).toFixed(0)}%`); console.log(sut("toplam", 14) + toplam.toFixed(1));
karar verildi yazili kisit ------------------------------------------------------------------- veri erisimi tek katmandan gecer evet evet ayar degerleri tek kaynaktan okunur evet evet envanter olay yolu uzerinden esitlenir evet evet dis kataloga tek baglayici uzerinden erisilir evet evet kimlik dogrulama tek modulde toplanir evet evet odunc suresi kurali yapilandirmadan okunur evet evet saat kaynagi tek modulden alinir evet evet ceza hesabi uye kaydindan ayri durur evet evet gunluk rapor ayri bir modulde uretilir evet hayir eposta bildirimi duz metin govdeyle gider evet hayir kiosk ucu ayri bir dagitim birimidir evet hayir verilen karar = 11/11; yazili kisit bicimi olan = 8/11 yazili bicimi olmayan karar gozetlenemez: gunluk rapor ayri bir modulde uretilir; eposta bildirimi duz metin govdeyle gider; kiosk ucu ayri bir dagitim birimidir kisayol havuzu = 58 kenar; 50 kenar cekildi (tohum 90210) cekilen kenarlarin 19'i bir kisiti ihlal ediyor kararin verildigi anda zaten ihlal edilmis kisit = 1 (personel-ucu -> sube-envanter) 10 tur, turda 5 kisayol; denetlenebilir karar = 8 duzen eklenen geri alinan bozulan karar uygulanma gozetim saati -------------------------------------------------------------------------- gozetimsiz 50 0 6/8 25% 0 gozetimli 50 19 1/8 88% 24 gozetimsiz duzende kodda karsiligi kalmayan karar = 6/8; gozetimli duzende 1/8 gozetimin kurtardigi karar = 5; bedeli 24 saat, karar basina 4.8 saat sorumluluk saat pay ---------------------------- karar verme 33.0 41% iletisim 23.5 29% gozetim 24.0 30% toplam 80.5
Gözetimsiz Kararın Uygulanma Oranı
On bir kararın hepsi verilmiş, sekizinin yazılı ve denetlenebilir bir kısıt biçimi var. On tur boyunca 50 kısayol eklendi; bunların 19’u bir kısıtı ihlal ediyor. Gözetimsiz düzende bu 19 kenar kalıcı oldu ve sekiz karardan altısı kodda karşılığını yitirdi — uygulanma oranı %25. Gözetimli düzende her turun sonunda ihlal eden kenarlar geri alındı ve sonda yalnız bir karar bozuk kaldı; uygulanma oranı %88.
Kalan o bir karar ölçümün en öğretici parçası. Personel uygulaması şube envanterine daha kararın verildiği gün doğrudan bakıyordu; gözetim yalnız karardan sonra eklenen kenarları geri alıyor. Verildiği anda ihlal edilmiş bir karar gözetimle düzelmez, ayrı bir taşıma işi ister. Bu ayrım yazılmadığında gözetim raporu “bir karar hâlâ bozuk” der ve nedeni görünmez.
Farkın bedeli de sayılı: gözetim beş kararı kurtardı ve 24 saate mal oldu — karar başına 4,8 saat. Bu sayı bir savunmadır. “Mimar kararları izlemelidir” cümlesi bir karar değildir; “gözetimsiz düzende sekiz karardan altısı on turda kodda karşılığını yitiriyor, gözetim bunun beşini karar başına 4,8 saate kurtarıyor” cümlesi denetlenebilir.
Üç denetlenemeyen kararın durumu ayrıca not edilmeli. Ölçüm onları hiç saymadı, çünkü ithal grafiğinde iz bırakmıyorlar. Yazılı biçimi olmayan bir karar gözetlenemez; gözetlenemeyen bir kararın uygulanma oranı ölçülemez. Sorumluluk matrisinin “yazılı kısıt” sütunu bu yüzden karar sütunundan daha bilgilendiricidir: 11 kararın 11’i verilmiş, 8’i denetlenebilir.
Zaman Dağılımı
Son tablo üç sorumluluğun saatlerini toplar. Karar verme, karar başına üç saatle 33 saat; iletişim, önceki dersin üç düzeyli düzeninde sayılan 47 danışmanın yarım saatiyle 23,5 saat; gözetim, ölçülen 24 saat (MN9). Toplam 80,5 saatin %41’i karar verme, %29’u iletişim, %30’u gözetim.
Dağılımın söylediği şudur: karar verme, mimarın işinin yarısından azıdır. İletişim ve gözetim birlikte %59 tutuyor ve ikisi de kesildiğinde görünen bir şey olmuyor — kesilen iletişim önceki dersin 31 çelişen gerçekleştirimini, kesilen gözetim bu dersin altı bozuk kararını üretiyor. İkisinin de bedeli kararın verildiği anda değil, aylar sonra ödeniyor.
Özet
- Mimarın işi üç sorumluluktur: karar, iletişim ve gözetim; ölçülebilir olması için kararın makinece denetlenebilir bir kısıt biçimine çevrilmesi gerekir.
- Model kod tabanında 11 kararın 11’i verilmiş, ama yalnız 8’inin ithal grafiğinde denetlenebilir bir karşılığı var; kalan üçü gözetlenemez ve uygulanma oranları ölçülemez.
- On tur boyunca 50 kısayol eklendi, 19’u bir kısıtı ihlal etti; gözetimsiz düzende sekiz kararın altısı kodda karşılığını yitirdi (uygulanma %25), gözetimli düzende bir karar bozuk kaldı (%88).
- Kalan bozuk karar, karardan önce var olan bir kenardan geliyor; gözetim yalnız karardan sonrasını korur, önceden var olan ihlal ayrı bir taşıma işidir.
- Gözetim beş kararı karar başına 4,8 saate kurtardı; üç sorumluluğun 80,5 saatlik toplamında karar verme %41, iletişim %29, gözetim %30 pay tuttu.
Sonraki Adım
Bu dersin gözetim düzeni bir şeyi sessizce varsaydı: kararı veren kişinin ithal grafiğini gerçekten görebildiğini. Kısıtları yazan, ihlalleri sayan ve geri alan aynı kişi, kodun o an ne durumda olduğunu biliyor. Bu varsayım her düzende doğru değil. Karar veren kişi koda hiç dokunmuyorsa, kararını verdiği andaki grafik ile aylar sonraki grafik arasında bir fark birikir ve karar bu farkın üstüne kurulur. Sonraki ders o farkı modeller: karar verenle uygulayanın bildiği modül kümeleri ayrı ayrı tutulur, koda dokunan ve dokunmayan iki düzen aynı değişim dizisinde koşturulur ve iki sayı karşılaştırılır — kararın uygulanabilirlik oranı ve bir ihlalin fark edilmesine kadar geçen tur sayısı.
İlerlemeni kaydetmek ve not almak için Giriş yap
Notlarım
Not almak için giriş yapmalısın.