Ders 16 / 21
Depo Tabanlı İstenen Durum
Aynı değişiklik akışı iki düzende koşturulur — elden uygulama ve depoya işleme — ve iki düzenin izlenebilirliği, kayıtsız değişiklik oranı, dönem sonu sapması ve değişiklik başına adım sayısı 180 değişiklikte sayılır. Gözden geçirme kapısının yalnız kendi yakaladığı kusur, yanlış tuttuğu temiz değişiklik ve eklediği 796 saat ayrı ayrı ölçülür.
İçindekiler
Önceki konular yayının nasıl verileceğini kurdu: hangi ölçüte bakılarak terfi edileceği, yüzdelik dağıtımın hangi eşikte durdurulacağı, geri alma planının kaç adım olduğu. Bu kararların hepsinin ortak bir yanı vardı — sonunda biri bir arayüzde bir düğmeye basıyor ya da bir kabuk komutu yazıyordu. Kararın kendisi kayıt altındaydı; kararın uygulanması değildi.
Bu ders o boşluğu ölçer. Soru şudur: kümenin uyguladığı istenen durum bir yerde yazılı olarak duruyor mu, yoksa yalnız çalışan sistemin belleğinde mi? Depo tabanlı istenen durum ilkesi tek bir cümledir — bir ortamda ne çalışacağının tanımı bir depoda durur ve o depo dışında hiçbir yoldan değiştirilmez. İlkenin kendisi kısa, faturası uzundur; ders faturayı çıkarır.
Ölçüm bölgesel ölçüm ağı üzerindedir ve kurgudur: su sayacı okuma toplayıcısı, doğrulayıcı,
faturalama ve iş emri servisleri, üç ortam. Koşan şey node ile kurulmuş bir modeldir, gerçek
bir sistem değil.
DD1. İstenen durum 60 kalemdir: dört servis × üç ortam × beş alan (kopya sayısı, eşik, sürüm, ağ kuralı, zamanlama). DD2. Doksan günde 180 değişiklik üretilir; üreteç kendi yazılmıştır, tohum 20260801 görünürdür. DD3. Değişikliklerin bir bölümü acildir (vardiya dışı müdahale); %20’si bilinen bir kusur taşır: biçim, eşik, ortam, koşum anı. DD4. Elden düzende kayıt gönüllüdür — uygulayan isterse bir yere yazar. Depo düzeninde işleme kaydı kim, ne zaman ve gerekçe alanlarını zorunlu taşır. DD5. Depo düzeninde de acil değişikliklerin bir bölümü depoyu atlar; ilke %100 uygulanmaz. DD6. İki kapı vardır ve ikisi de yalnız depo yolundadır: şema doğrulayıcısı (otomatik) ve gözden geçirme (insan).
Aynı Değişiklik İki Yolla
// akis.mjs — bolgesel olcum agi (kurgu) uzerinde 90 gunluk degisiklik akisi modeli. // Ayni akis iki duzende uygulanir: elden uygulama ve depoya isleme. Kosan sey bir // modeldir, gercek bir sistem degil. Rastgelelik kendi uretecimizden gelir, tohum gorunur. export const uretec = (t) => { let s = t >>> 0; return () => (s = (s * 1664525 + 1013904223) >>> 0) / 4294967296; }; const SERVIS = ["toplayici", "dogrulayici", "faturalama", "isemri"]; const ORTAM = ["gelistirme", "hazirlik", "uretim"]; const ALAN = ["kopya", "esik", "surum", "ag-kurali", "zamanlama"]; export const KALEM = SERVIS.flatMap((s) => ORTAM.flatMap((o) => ALAN.map((a) => `${s}/${o}/${a}`))); export function akis(tohum = 20260801, adet = 180) { // 90 gunluk degisiklik akisi const r = uretec(tohum), liste = []; for (let i = 0; i < adet; i++) { const kalem = KALEM[Math.floor(r() * KALEM.length)]; const acil = r() < 0.22; // vardiya disi mudahale const p = r(); // bilinen kusur kumesi: %20 const kusur = p < 0.06 ? "bicim" : p < 0.12 ? "esik" : p < 0.16 ? "ortam" : p < 0.20 ? "kosum" : null; liste.push({ i, gun: Math.floor(r() * 90), kalem, acil, kusur }); } return liste; } // depo=false: her degisiklik elden uygulanir, kayit gonullu. // depo=true : degisiklik depoya islenir; acil olanlarin bir kismi yine de depoyu atlar. export function duzen(liste, { depo, tohum = 7717 }) { const r = uretec(tohum); const gercek = new Map(), defter = new Map(); // kalem -> surum numarasi let kim = 0, gerekce = 0, kayitsiz = 0, atlayan = 0, adim = 0, incelenen = 0; for (const d of liste) { const depoYolu = depo && !(d.acil && r() < 0.35); const s = (gercek.get(d.kalem) ?? 0) + 1; gercek.set(d.kalem, s); if (depoYolu) { // dal, degisiklik, isleme, defter.set(d.kalem, s); // oneri, gozden gecirme, kim++; gerekce++; incelenen++; adim += 7; // birlestirme, uygulama } else { atlayan++; adim += 2; // komut yaz, uygula const kaydeder = r() < (d.acil ? 0.25 : 0.7); if (kaydeder) { kim++; if (r() < 0.45) gerekce++; } else kayitsiz++; if (r() < (d.acil ? 0.1 : 0.3)) defter.set(d.kalem, s); // sonradan deftere gecirme } } let sapan = 0; for (const [k, s] of gercek) if (defter.get(k) !== s) sapan++; return { n: liste.length, kim, gerekce, kayitsiz, atlayan, incelenen, sapan, dokunulan: gercek.size, adim: adim / liste.length }; } if (import.meta.url === `file://${process.argv[1]}`) { const liste = akis(); const acil = liste.filter((d) => d.acil).length; const kusurlu = liste.filter((d) => d.kusur).length; console.log(`tohum 20260801 | ${liste.length} degisiklik / 90 gun | ${KALEM.length} kalem`); console.log(`acil: ${acil} | bilinen kusur tasiyan: ${kusurlu}`); const BAS = ["duzen", "kim", "gerekce", "kayitsiz", "atlayan", "incelenen", "sapan kalem", "adim"]; const G = [16, 5, 9, 10, 9, 11, 13, 7]; const satir = (h) => h.map((v, j) => j ? String(v).padStart(G[j]) : String(v).padEnd(G[0])).join(""); console.log("\n" + satir(BAS)); for (const depo of [false, true]) { const x = duzen(liste, { depo }); console.log(satir([depo ? "depoya isleme" : "elden uygulama", x.kim, x.gerekce, x.kayitsiz, x.atlayan, x.incelenen, `${x.sapan}/${x.dokunulan}`, x.adim.toFixed(2)])); } }
tohum 20260801 | 180 degisiklik / 90 gun | 60 kalem acil: 35 | bilinen kusur tasiyan: 36 duzen kim gerekce kayitsiz atlayan incelenen sapan kalem adim elden uygulama 117 54 63 180 0 45/56 2.00 depoya isleme 175 172 5 9 171 1/56 6.75
İzlenebilirlik sütunları beklenen yönde ayrışıyor. Elden düzende 180 değişikliğin 117’sinde kim ve ne zaman bilgisi bir yere düşmüş, yalnız 54’ünde gerekçe var; 63 değişiklik — akışın %35’i — hiçbir iz bırakmadan uygulanmış. Depo düzeninde gerekçe 172’ye çıkıyor, çünkü işleme kaydı boş bırakılamıyor: kim, ne zaman ve niçin alanları değişikliğin taşıyıcısının kendisidir, ayrıca doldurulan bir form değil.
Asıl sayı sondan üçüncü sütundadır. Doksan gün boyunca 60 kalemin 56’sına dokunulmuş; elden düzende dönem sonunda bu 56 kalemin 45’i depodaki değerden farklıdır. Yani sistemi anlatan belge, sistemin dörtte üçünde yanlıştır. Depo düzeninde sapan kalem sayısı 1’dir ve o bir kalem depoyu atlayan dokuz acil değişiklikten arta kalandır.
Bu farkın işletim karşılığı, belgenin eskimesinden ağırdır. Elden düzende bir kalemin doğru değerini bilen tek yer çalışan sistemin kendisidir; ortam yeniden kurulduğunda ya da bir kalem sıfırlandığında geri dönülecek bir kaynak yoktur. Faturalama servisinin üretimdeki eşiği bir gece elle değiştirilmiş ve kimse yazmamışsa, o eşik artık kimsenin kararı değil, bir kazadır. Depo tabanlı istenen durumun ilk kazancı denetim değil, geri dönülebilirliktir: 56 kalemin 55’i için depodaki değer, sistemin son bilinen doğru hâlidir.
Gözden Geçirme Kapısı Neyi Yalnız Kendisi Tutuyor
// kapi.mjs — depo yolundaki gozden gecirme kapisinin defteri: tuttugu, YALNIZ kendisinin // tuttugu, kacirdigi, yanlis tuttugu, ekledigi sure. Ayni akis modeli, ayri tohum. import { akis, uretec } from "./akis.mjs"; const SEMA = { bicim: 1, esik: 0, ortam: 0, kosum: 0 }; // sema dogrulayicisi const GOZ = { bicim: 0.85, esik: 0.55, ortam: 0.75, kosum: 0.05 }; // gozden gecirme function kos(liste, { kacis, tohum = 4231 }) { const r = uretec(tohum), gercek = new Map(), defter = new Map(); const ortam = {}, sinif = {}; let atlayan = 0, kapiya = 0, semaYalniz = 0, marjinal = 0, ikisi = 0, gecen = 0, yanlis = 0, dakika = 0, tetikli = false; const uygula = (d, depoyla) => { const s = (gercek.get(d.kalem) ?? 0) + 1; gercek.set(d.kalem, s); if (depoyla) defter.set(d.kalem, s); return s; }; for (const d of liste) { const o = (ortam[d.kalem.split("/")[1]] ??= { kapiya: 0, marjinal: 0, yanlis: 0, dk: 0 }); const k = d.kusur ? (sinif[d.kusur] ??= { n: 0, goz: 0, sema: 0, gecen: 0 }) : null; if (k) k.n++; const atla = r() < (d.acil ? 0.35 : (kacis && tetikli ? 0.5 : 0)); tetikli = false; if (atla) { // kapisiz yol atlayan++; const s = uygula(d, false); if (k) { gecen++; k.gecen++; } if (r() < 0.2) defter.set(d.kalem, s); continue; } kapiya++; o.kapiya++; const bekle = d.acil ? 5 + r() * 55 : 25 + r() * 575; // gozden gecirme beklemesi dakika += bekle; o.dk += bekle; const sema = d.kusur ? r() < SEMA[d.kusur] : false; const goz = d.kusur ? r() < GOZ[d.kusur] : false; if (k && (sema || goz)) { // durduruldu, uygulanmadi if (sema) k.sema++; if (goz) k.goz++; if (sema && goz) ikisi++; else if (sema) semaYalniz++; else { marjinal++; o.marjinal++; } continue; } if (!k && r() < 0.06) { // temiz ama durduruldu yanlis++; o.yanlis++; tetikli = true; dakika += bekle * 0.6; o.dk += bekle * 0.6; // ikinci tur } uygula(d, true); if (k) { gecen++; k.gecen++; } } let sapan = 0; for (const [a, s] of gercek) if (defter.get(a) !== s) sapan++; return { atlayan, kapiya, semaYalniz, marjinal, ikisi, gecen, yanlis, sapan, dk: dakika / kapiya, saat: dakika / 60, ortam, sinif }; } const yaz = (g, h) => h.map((v, j) => j ? String(v).padStart(g[j]) : String(v).padEnd(g[0])).join(""); if (import.meta.url === `file://${process.argv[1]}`) { const liste = akis(), kusurlu = liste.filter((d) => d.kusur).length; const G = [7, 9, 8, 13, 15, 8, 8, 8, 8, 12]; console.log(`${liste.length} degisiklik, ${kusurlu} bilinen kusur; iki kapi: sema + gozden gecirme`); console.log("\n" + yaz(G, ["kacis", "atlayan", "kapiya", "yalniz sema", "yalniz gozden", "ikisi", "gecen", "yanlis", "sapan", "dk/inceleme"])); for (const kacis of [false, true]) { const x = kos(liste, { kacis }); console.log(yaz(G, [kacis ? "var" : "yok", x.atlayan, x.kapiya, x.semaYalniz, x.marjinal, x.ikisi, x.gecen, x.yanlis, x.sapan, x.dk.toFixed(0)])); } const x = kos(liste, { kacis: false }); const S = [12, 7, 7, 8, 8]; console.log("\n" + yaz(S, ["kusur", "adet", "sema", "gozden", "gecen"])); for (const [ad, k] of Object.entries(x.sinif)) console.log(yaz(S, [ad, k.n, k.sema, k.goz, k.gecen])); const O = [13, 8, 15, 15, 13, 15]; console.log("\n" + yaz(O, ["ortam", "kapiya", "yalniz gozden", "yanlis tuttu", "toplam saat", "saat/marjinal"])); for (const [ad, o] of Object.entries(x.ortam)) console.log(yaz(O, [ad, o.kapiya, o.marjinal, o.yanlis, (o.dk / 60).toFixed(1), o.marjinal ? (o.dk / 60 / o.marjinal).toFixed(1) : "-"])); console.log(`\ntoplam gozden gecirme yuku: ${x.saat.toFixed(0)} saat / 90 gun`); }
180 degisiklik, 36 bilinen kusur; iki kapi: sema + gozden gecirme kacis atlayan kapiya yalniz sema yalniz gozden ikisi gecen yanlis sapan dk/inceleme yok 13 167 1 13 11 11 7 4 286 var 20 160 1 15 9 11 9 7 270 kusur adet sema gozden gecen esik 8 0 3 5 bicim 12 12 11 0 ortam 11 0 9 2 kosum 5 0 1 4 ortam kapiya yalniz gozden yanlis tuttu toplam saat saat/marjinal hazirlik 67 6 2 312.5 52.1 gelistirme 44 1 2 193.7 193.7 uretim 56 6 3 289.9 48.3 toplam gozden gecirme yuku: 796 saat / 90 gun
İki kapı da iş görüyor, ama defterleri birbirine benzemiyor. Şema doğrulayıcısı 12 biçim kusurunu tuttu; bunların 11’ini gözden geçirme de yakalardı, dolayısıyla yalnız şemanın tuttuğu kusur sayısı 1’dir. Gözden geçirme 24 kusur tuttu ve bunların 13’ünü tek başına yakaladı — öteki kapı olsa da olmasa da geçecek olan kusurlar bunlardır. Marjinal değer sıralaması nettir: şema kapısı 1, gözden geçirme 13.
Kusur sınıfı tablosu bu sıralamanın nedenini gösteriyor. Biçim kusurunun 12’si de tutuldu, hiçbiri geçmedi; bu sınıfı iki kapı da görüyor ve şema kapısı bunu saniyeler içinde yapıyor. Eşik ve ortam kusurları şema için görünmezdir: değer geçerli, alan doğru, yalnız sayı ya da hedef yanlıştır. Bunları yalnız okuyan bir insan yakalar — 8 eşik kusurunun 3’ü, 11 ortam kusurunun 9’u tutuldu.
Kapının kaçırdığı 11 kusur da sınıfına göre okunur: 5 eşik, 2 ortam, 4 koşum anı. Koşum anı sınıfı beş kusurun dördünü geçirdi, çünkü bu sınıf yazılı metne bakarak görülmez — değer ancak servis gerçek veriyle karşılaştığında yanlış olur. Statik bir kapının önünde duran bir sınır burasıdır ve gözden geçirmenin süresini uzatmak bu sınırı geriye itmez.
Yanlış tutma sütunu kapının öteki yüzüdür: 7 temiz değişiklik durduruldu ve her biri ikinci bir tur üretti. İnceleme başına ortalama bekleme 286 dakikadır; doksan günde toplam 796 saat, günde yaklaşık dokuz saatlik bir bekleme yükü. Bu süre bir işgücü maliyeti değil, öncü sürenin kendisidir: değişiklik yazıldıktan sonra ortalama dört saat kırk beş dakika boyunca hiçbir yere gitmez.
Kapıdan Kaçmanın Ölçülen İzi
Tablonun ikinci satırı, yanlış tutmanın ekipte ürettiği davranışı modelliyor: boşuna durdurulan bir değişikliğin ardından gelen değişikliğin acil olmasa bile kapısız yoldan gitme olasılığı artıyor. Kapıyı atlayan değişiklik 13’ten 20’ye, dönem sonunda sapan kalem 4’ten 7’ye çıkıyor. Üretime geçen kusur sayısı iki koşumda da 11’dir; 180 değişiklik ölçeğinde bu fark üretecin gürültüsünün altında kalır ve öyle sunulmalıdır. Ölçülebilen etki kusur sayısında değil, kapının kendi ürettiği sapmadadır: bir kapıya güven azaldığında kayıp önce izlenebilirlikte görünür.
Ortam tablosu ise kaldırılması gereken kapıyı doğrudan işaret ediyor. Geliştirme ortamına giden 44 değişiklik gözden geçirildi, bu incelemelerin toplamı 193,7 saat sürdü ve yalnız 1 kusur marjinal olarak yakalandı — kusur başına 193,7 saat. Aynı ölçü üretimde 48,3, hazırlıkta 52,1 saattir. Üstelik geliştirme ortamındaki 2 yanlış tutma, marjinal yakalamanın iki katıdır: kapı burada tuttuğundan çok boşuna durduruyor.
Buradan çıkan karar ilkeye dokunmaz, kapıya dokunur: geliştirme ortamının değişiklikleri depoya işlenmeye devam eder, gözden geçirme kapısı kalkar. Ayrım bu dersin taşıdığı en pratik sonuçtur — depoya işleme ile gözden geçirme aynı şey değildir. İzlenebilirlik, gerekçe ve geri dönülebilirlik kazancı işleme kaydından gelir; kapıdan gelen tek şey tutulan kusurdur ve o da ortama göre çok farklı fiyatlanır.
İlkenin Bedeli: Değişiklik Başına Ek Adım
İlk tablonun son sütunu ilkenin doğrudan faturasıdır. Elden uygulama değişiklik başına 2 adımdır: komut yazılır, uygulanır. Depo yolu 7 adımdır — dal açılır, dosya değiştirilir, işlenir, öneri açılır, gözden geçirme beklenir, birleştirilir, uygulanır. Karışım ortalaması 6,75’tir; fark değişiklik başına 4,75 adım, doksan günde 855 ek adımdır.
Bu adımların hepsi aynı ağırlıkta değildir. Altısı yazan kişinin dakikalarıdır; yalnız biri — gözden geçirme beklemesi — başkasının takvimine bağlıdır ve ölçülen 286 dakikanın tamamı oradan gelir. Acil yolun varlığı da bu yüzden sürüyor: 35 acil değişikliğin 13’ü kapıyı atladı, çünkü gece yarısı dört saatlik bir bekleme kesintiyi uzatır. İlkeyi %100 uygulamak, ölçülen kayıtsız değişiklik oranını 5’ten 0’a indirir ama acil müdahalenin süresine dört saat ekler; hangi tarafın seçildiği ölçülmeden savunulamaz.
Özet
- Elden düzende 180 değişikliğin 63’ü (%35) hiçbir iz bırakmadan uygulandı ve gerekçe yalnız 54 değişiklikte vardı; depo düzeninde kayıtsız değişiklik 5’e, gerekçesiz değişiklik 8’e indi.
- Dönem sonunda dokunulan 56 kalemin elden düzende 45’i depodaki değerden sapmıştı, depo düzeninde 1’i; ilkenin ilk kazancı denetim değil, geri dönülebilirliktir.
- Şema kapısı 12 kusur tuttu ama yalnız 1’ini tek başına yakaladı; gözden geçirme 24 tuttu, 13’ünü tek başına — marjinal değer sıralaması 1’e karşı 13’tür.
- Kapı 11 kusuru kaçırdı (5 eşik, 2 ortam, 4 koşum anı) ve 7 temiz değişikliği boşuna durdurdu; inceleme başına 286 dakika, doksan günde 796 saat ekledi.
- Geliştirme ortamında kapı 193,7 saatte 1 marjinal kusur yakaladı ve 2 temiz değişikliği durdurdu; aynı ölçü üretimde 48,3 saat. Bu kapı geliştirme ortamında kaldırılır, işleme kaydı kalır.
- İlkenin adım maliyeti değişiklik başına 2’den 6,75’e çıkıyor; ek adımların yalnız biri başkasının takvimine bağlıdır ve ölçülen beklemenin tamamı oradan gelir.
Sonraki Adım
Bu ders istenen durumun nerede yazılı olduğunu ölçtü ve depodaki yazının değerini sapan kalem sayısıyla gösterdi. Açık kalan soru bir sonraki dersin konusudur: depoda duran o yazıyı kümeye kim taşıyor? Şimdiye kadarki düzende taşıyan taraf hattır — hat kümeye bağlanır ve yazar. Bunun bir alternatifi vardır: küme içinde çalışan bir ajanın depoyu okuyup farkı kendisinin kapatması. Ölçülecek kalemler bellidir: hattın küme üzerindeki yetki yüzeyi, elle yapılan bir değişikliğin fark edilme gecikmesi, ağ bağlantısının yönü ve hat düştüğünde ne olduğu.
İlerlemeni kaydetmek ve not almak için Giriş yap
Notlarım
Not almak için giriş yapmalısın.