Ders 07 / 12
Ortamlar
Geliştirme, sınama, hazırlık ve üretim arasındaki farkın nerede saklandığı sayılır: on boyutun kaçı üretimden ayrılıyor, kaçı ortam künyesinde yazıyor, hangi fark hangi hata sınıfını gizliyor ve bir halkayı atlamak kaç hata sınıfını üretime taşıyor.
İçindekiler
Önceki konu geri bildirim döngülerini kurdu ve bir olgunun hangi role kaç adımda ulaştığını saydı. O ölçümlerin hepsi tek bir sessiz varsayım taşıyordu: geliştiricinin makinesinde koşan yazılım ile gece yarısı üretimde koşan yazılım aynı yazılımdır. Varsayım doğru olsaydı, üretimde ilk kez görülen bir hatanın geliştirme makinesinde de görülmesi gerekirdi.
Fark bir yerde saklıdır ve adı konmadıkça ölçülmez. Bu ders farkın saklandığı ilk yeri ele alır: yazılımın koştuğu ortam. Ortam burada sınamanın yapıldığı yer değil, üretime giden zincirin bir halkasıdır; sorulan soru da her halkanın neyi görebildiğidir.
Konu boyunca tek bir kurgu sürer: bir belediyenin bölgesel ölçüm ağı. Yazılım su sayaçlarından okuma toplar, okumaları doğrular, faturaya çevirir ve saha ekiplerine iş emri açar. Bir gecelik toplu iş bütün günün okumalarını işler. Kurgudur; aşağıdaki sayılar da bu kurgunun modelinden gelir, ölçülmüş bir kurulumdan değil.
DK1. Ağı yazan ekip ile işleten ekip ayrıdır. Ağda üç ortam işletilir: geliştirme, sınama ve üretim. Dördüncü halka olan hazırlık ortamı kurulu değildir; bu dersin ölçtüğü şey tam olarak o halkanın ne kazandırdığıdır.
Zincirin Dört Halkası
Ortam, bir değişikliğin üretime giderken uğradığı duraktır. Dört durak birbirinden amaçla ayrılır, adla değil.
Geliştirme ortamı yazanın makinesidir. Tek süreç koşar, dış bağımlılıkların hepsi taklittir, veri elle üretilmiş birkaç yüz kayıttır. Amacı değişikliğin biçimini görmektir: kod derleniyor mu, işlev beklenen değeri döndürüyor mu.
Sınama ortamı değişikliği yazandan bağımsız çalıştırır. Otomatik sınamalar burada koşar, veri gerçek biçimlidir ama küçüktür, bağımlılıkların bir kısmı gerçektir. Amacı değişikliğin kendi başına doğru olup olmadığını yazanın makinesinden bağımsız doğrulamaktır.
Hazırlık ortamı üretime en yakın halkadır. Dış bağımlılıklar gerçektir, kaynak sınırları üretimin sınırlarıdır, sürümler üretimin sürümleridir. Amacı doğrulamak değil, üretime özgü hata sınıflarını üretime varmadan görmektir.
Üretim ortamı gerçek sayaç okumalarının işlendiği, gerçek faturaların üretildiği ve gerçek saha ekiplerine iş emri açılan yerdir. Buradaki bir hatanın bedeli yanlış faturadır.
Bu dört durağın hangisinin neyi görebildiği, o durağın üretime ne kadar benzediğine bağlıdır. Benzerliğin ölçüsünün adı ortam denkliği (environment parity), ölçülemez hâline gelmesinin adı ise yapılandırma sapmasıdır (configuration drift): halkalar zamanla birbirinden ayrılır ve ayrıldıkları yer kayda geçmez.
Denklik Neyle Ölçülür
Denkliğin sayılabilmesi için boyutların adlandırılması gerekir. Kurgudaki ağın ortam belgesi yedi boyut bildirir: iki paket sürümü, bir kaynak sınırı, bir eşzamanlılık ayarı, bir veri hacmi ve iki dış bağımlılığın gerçek mi taklit mi olduğu.
DK2. Yedi boyut ortam künyesinde yazılıdır ve iki ekip de bu belgeyi okuyabilir. DK3. Üç boyut daha vardır — saat dilimi, dosya sisteminin harf duyarlılığı, ağ gecikmesi — ve bunlar hiçbir belgede yazmaz; yalnız süreç koşarken ölçülebilir.
// olcum-agi/ortamlar.mjs — dort ortamin kunyesi ve kosum yoklamasi (model, kurgu veri) // Ortam belgesinde yazan yedi boyut. Degerler bolgesel olcum agi kurgusuna aittir. export const KUNYE = { gelistirme: { cozumleyiciSurumu: "3.2.1", kuralPaketiSurumu: "9.1.0", bellekMB: 512, esZamanliIsci: 1, sayacSayisi: 120, faturaKapisi: "taklit", isEmriKuyrugu: "taklit" }, sinama: { cozumleyiciSurumu: "3.2.1", kuralPaketiSurumu: "9.1.0", bellekMB: 1024, esZamanliIsci: 2, sayacSayisi: 5000, faturaKapisi: "taklit", isEmriKuyrugu: "gercek" }, hazirlik: { cozumleyiciSurumu: "3.4.0", kuralPaketiSurumu: "9.1.0", bellekMB: 4096, esZamanliIsci: 8, sayacSayisi: 180000, faturaKapisi: "gercek", isEmriKuyrugu: "gercek" }, uretim: { cozumleyiciSurumu: "3.4.0", kuralPaketiSurumu: "9.1.0", bellekMB: 4096, esZamanliIsci: 8, sayacSayisi: 1240000, faturaKapisi: "gercek", isEmriKuyrugu: "gercek" }, }; // Kunyede yazmayan, yalniz surecin icinden olculebilen uc boyut. export const YOKLAMA = { gelistirme: { saatDilimi: "+03:00", harfDuyarliDosyaSistemi: false, agGecikmeMs: 0 }, sinama: { saatDilimi: "+03:00", harfDuyarliDosyaSistemi: true, agGecikmeMs: 2 }, hazirlik: { saatDilimi: "+00:00", harfDuyarliDosyaSistemi: true, agGecikmeMs: 11 }, uretim: { saatDilimi: "+00:00", harfDuyarliDosyaSistemi: true, agGecikmeMs: 34 }, }; // Her boyutun, uretimden farkli oldugunda gizledigi hata sinifi. export const GIZLENEN = { cozumleyiciSurumu: "cozumleme sapmasi", kuralPaketiSurumu: "tutar hatasi", bellekMB: "bellek tukenmesi", esZamanliIsci: "yaris durumu", sayacSayisi: "olcek cokusu", faturaKapisi: "sozlesme sapmasi", isEmriKuyrugu: "sozlesme sapmasi", saatDilimi: "gun siniri kaymasi", harfDuyarliDosyaSistemi: "yol cozumleme hatasi", agGecikmeMs: "zaman asimi", }; export const BILDIRILEN = Object.keys(KUNYE.uretim); export const YOKLANAN = Object.keys(YOKLAMA.uretim); export const BOYUTLAR = [...BILDIRILEN, ...YOKLANAN]; export const tam = (ortam) => ({ ...KUNYE[ortam], ...YOKLAMA[ortam] }); export const farklar = (ortam) => BOYUTLAR.filter((b) => tam(ortam)[b] !== tam("uretim")[b]);
Ölçüm her ortamı üretimle karşılaştırır ve farkı boyut boyut yazar.
// olcum-agi/denklik.mjs — ortam denkligini boyut boyut sayar import { BOYUTLAR, YOKLANAN, GIZLENEN, tam, farklar } from "./ortamlar.mjs"; const HALKA = ["gelistirme", "sinama", "hazirlik"]; const yildiz = (b) => (YOKLANAN.includes(b) ? b + " *" : b); console.log("uretime gore denklik (* = kunyede yazmaz, yalniz kosumda gorunur)"); console.log("boyut".padEnd(26) + HALKA.map((o) => o.padEnd(11)).join("") + "gizledigi hata sinifi"); for (const b of BOYUTLAR) { const hucre = HALKA.map((o) => (tam(o)[b] === tam("uretim")[b] ? "ayni" : "FARK").padEnd(11)); console.log(yildiz(b).padEnd(26) + hucre.join("") + GIZLENEN[b]); } const sayim = HALKA.map((o) => farklar(o)); const toplam = sayim.flat().length; const kosumda = sayim.flat().filter((b) => YOKLANAN.includes(b)).length; console.log("\nfark sayisi: " + HALKA.map((o, i) => `${o} ${sayim[i].length}/${BOYUTLAR.length}`).join(", ")); console.log(`toplam ${toplam} fark; kunyede yazan ${toplam - kosumda}, yalniz kosumda goruneni ${kosumda}`); console.log("hazirligin uretimden ayrildigi boyut: " + farklar("hazirlik").join(", ")); console.log("hicbir ortamda uretime denk olmayan boyut: " + BOYUTLAR.filter((b) => HALKA.every((o) => tam(o)[b] !== tam("uretim")[b])).join(", "));
uretime gore denklik (* = kunyede yazmaz, yalniz kosumda gorunur) boyut gelistirme sinama hazirlik gizledigi hata sinifi cozumleyiciSurumu FARK FARK ayni cozumleme sapmasi kuralPaketiSurumu ayni ayni ayni tutar hatasi bellekMB FARK FARK ayni bellek tukenmesi esZamanliIsci FARK FARK ayni yaris durumu sayacSayisi FARK FARK FARK olcek cokusu faturaKapisi FARK FARK ayni sozlesme sapmasi isEmriKuyrugu FARK ayni ayni sozlesme sapmasi saatDilimi * FARK FARK ayni gun siniri kaymasi harfDuyarliDosyaSistemi * FARK ayni ayni yol cozumleme hatasi agGecikmeMs * FARK FARK FARK zaman asimi fark sayisi: gelistirme 9/10, sinama 7/10, hazirlik 2/10 toplam 18 fark; kunyede yazan 12, yalniz kosumda goruneni 6 hazirligin uretimden ayrildigi boyut: sayacSayisi, agGecikmeMs hicbir ortamda uretime denk olmayan boyut: sayacSayisi, agGecikmeMs
Üç ortam ile üretim arasında 18 fark vardır. Bunların 12’si künyede yazar: bir okuyan için görünür durumdadır, tartışılabilir ve kapatılabilir. Kalan 6’sı hiçbir belgede yazmaz; ancak süreç o ortamda koşarken görülebilir. Bu ayrım dersin ölçü eksenidir: bildirilmiş fark bir karar konusudur, yalnız koşumda görünen fark ise bir sürprizdir.
Bu 18 farkın hiçbiri bir kararla konmuş değildir. Ortamlar farklı tarihlerde kurulmuş, farklı zamanlarda yükseltilmiş ve bakımları ayrı ayrı yapılmıştır: üretimin paket sürümü yükseltilince geliştirme makinesi geride kalmış, sınamaya gerçek iş emri kuyruğu bağlanınca fatura kapısı taklit bırakılmıştır. Yapılandırma sapmasının anlamı budur — fark, kimsenin karar vermediği yerde birikir. Sapmanın ölçülebilir olması için de tek koşul vardır: boyutların adlandırılmış ve künyenin okunabilir olması.
Gradyan da okunabilir: geliştirme üretimden on boyutun dokuzunda ayrılır, sınama yedisinde, hazırlık ikisinde. Halkalar üretime yaklaştıkça fark sayısı düşer — zincirin sıralı olmasının nedeni budur. Ayrıca iki boyut — veri hacmi ve ağ gecikmesi — hiçbir ortamda üretime denk değildir. Bir buçuk milyon sayaç ile yüz yirmi sayaç arasındaki farkı taşımayan hiçbir halka yoktur.
Farkın Gizlediği Hata Sınıfı
Fark sayısı tek başına karar taşımaz; farkın neyi gizlediği taşır. Aşağıdaki model her boyuta bir kusur bağlar ve kusurun zincirin hangi halkasında ilk kez görüneceğini hesaplar.
DK4. Model kuralı tektir: bir kusur, bağlı olduğu boyutta ortam üretimle aynı değeri taşıyorsa görünür, taşımıyorsa görünmez. DK5. Her boyut tek bir hata sınıfı taşır; on boyut on kusur demektir. DK6. Zincir sırayla geçilir ve kusur ilk görüldüğü halkada durur.
// olcum-agi/zincir.mjs — bir kusurun zincirin hangi halkasinda gorundugunu sayar import { GIZLENEN, tam } from "./ortamlar.mjs"; // Model kurali: kusur, bagli oldugu boyutta ortam uretimle ayni degeri tasiyorsa gorunur. const KUSURLAR = [ ["bos okuma alani cozumlenemiyor", "cozumleyiciSurumu"], ["yeni tarife dilimi yanlis yuvarlaniyor", "kuralPaketiSurumu"], ["toplu is butun okumalari bellege aliyor", "bellekMB"], ["ayni sayac icin iki fatura satiri", "esZamanliIsci"], ["dogrulama sorgusu sayac sayisinin karesinde", "sayacSayisi"], ["fatura kapisinin ret kodu islenmiyor", "faturaKapisi"], ["is emri kuyruguna ayni emir iki kez", "isEmriKuyrugu"], ["gecelik is gun sinirini yerel saatle kesiyor", "saatDilimi"], ["tarife dosyasi buyuk harfle araniyor", "harfDuyarliDosyaSistemi"], ["toplayici yaniti zaman asimini asiyor", "agGecikmeMs"], ]; const DORT = ["gelistirme", "sinama", "hazirlik", "uretim"]; const UC = ["gelistirme", "sinama", "uretim"]; const ilkGoren = (zincir, boyut) => zincir.find((o) => tam(o)[boyut] === tam("uretim")[boyut]); console.log("kusur".padEnd(45) + "dort halka".padEnd(12) + "uc halka"); for (const [ad, boyut] of KUSURLAR) { console.log(ad.padEnd(45) + ilkGoren(DORT, boyut).padEnd(12) + ilkGoren(UC, boyut)); } const say = (zincir) => { const d = Object.fromEntries(zincir.map((o) => [o, 0])); for (const [, boyut] of KUSURLAR) d[ilkGoren(zincir, boyut)] += 1; return zincir.map((o) => `${o} ${d[o]}`).join(", "); }; console.log("\ndort halkali zincir: " + say(DORT)); console.log("uc halkali zincir : " + say(UC)); const kacan = (zincir) => KUSURLAR.filter(([, b]) => ilkGoren(zincir, b) === "uretim"); const dortKacan = kacan(DORT).map(([, b]) => GIZLENEN[b]); const ucKacan = kacan(UC).map(([, b]) => GIZLENEN[b]); const ek = ucKacan.filter((s) => !dortKacan.includes(s)); console.log(`hazirlik dururken de uretime kacan ${dortKacan.length} sinif: ` + dortKacan.join(", ")); console.log(`hazirlik atlandiginda kacan ${ucKacan.length} sinif; eklenen ${ek.length}:`); for (let i = 0; i < ek.length; i += 3) console.log(" " + ek.slice(i, i + 3).join(", ")); console.log("\nzincir uzunlugu tarandi (halkalar sirayla eklenir):"); let onceki = 0; for (let n = 0; n <= 3; n++) { const z = [...DORT.slice(0, n), "uretim"]; const yakalanan = KUSURLAR.filter(([, b]) => ilkGoren(z, b) !== "uretim").length; console.log(`${n} halka + uretim`.padEnd(20) + `uretimden once yakalanan ${yakalanan}` + ` (son halkanin katkisi ${yakalanan - onceki})`); onceki = yakalanan; }
kusur dort halka uc halka bos okuma alani cozumlenemiyor hazirlik uretim yeni tarife dilimi yanlis yuvarlaniyor gelistirme gelistirme toplu is butun okumalari bellege aliyor hazirlik uretim ayni sayac icin iki fatura satiri hazirlik uretim dogrulama sorgusu sayac sayisinin karesinde uretim uretim fatura kapisinin ret kodu islenmiyor hazirlik uretim is emri kuyruguna ayni emir iki kez sinama sinama gecelik is gun sinirini yerel saatle kesiyor hazirlik uretim tarife dosyasi buyuk harfle araniyor sinama sinama toplayici yaniti zaman asimini asiyor uretim uretim dort halkali zincir: gelistirme 1, sinama 2, hazirlik 5, uretim 2 uc halkali zincir : gelistirme 1, sinama 2, uretim 7 hazirlik dururken de uretime kacan 2 sinif: olcek cokusu, zaman asimi hazirlik atlandiginda kacan 7 sinif; eklenen 5: cozumleme sapmasi, bellek tukenmesi, yaris durumu sozlesme sapmasi, gun siniri kaymasi zincir uzunlugu tarandi (halkalar sirayla eklenir): 0 halka + uretim uretimden once yakalanan 0 (son halkanin katkisi 0) 1 halka + uretim uretimden once yakalanan 1 (son halkanin katkisi 1) 2 halka + uretim uretimden once yakalanan 3 (son halkanin katkisi 2) 3 halka + uretim uretimden once yakalanan 8 (son halkanin katkisi 5)
Tablo bir kuralı görünür kılar: bir ortam, yalnız üretimle aynı olduğu boyutlardaki kusurları görebilir. Geliştirme ortamı on kusurdan yalnız birini yakalar, çünkü üretimle yalnız tek bir boyutta — kural paketi sürümünde — aynıdır. Sınama iki kusur yakalar; ikisi de sınamanın üretimle aynı olduğu boyutlara bağlıdır: gerçek iş emri kuyruğu ve harf duyarlı dosya sistemi.
Ters yönde okumak daha çok şey söyler: bir ortamın yakalayamadığı hata sınıflarının listesi, o ortamın üretimden ayrıldığı boyutların listesidir. Hazırlık ortamı iki boyutta ayrılıyordu; hazırlık dururken üretime kaçan iki hata sınıfı da tam olarak o iki boyuta bağlı olanlardır. Bu, modelin bir çıkarımı değil, tanımının sonucudur — ama tanımı sayıya çevirdiği için ortam tartışmasını fikirden çıkarır: “hazırlık ortamına gerek var mı” sorusunun yerine “hangi boyutlarda denklik satın alıyoruz” sorusu geçer.
Çıktının son bölümü zincir uzunluğunu tarar: halkalar sırayla eklendiğinde üretimden önce yakalanan sınıf sayısı 0, 1, 3 ve 8 olur. Halka başına katkı eşit değildir — birinci halka bir sınıf, ikincisi iki, üçüncüsü beş sınıf ekler. Sıralama bunun nedenini de verir: her halka bir öncekinin göremediği boyutları kapatır ve üretime en yakın halka en çok boyutu kapatan halkadır. Zincirin başına yeni bir ortam eklemek katkının küçük olduğu yere yatırım yapmaktır; kapatılan boyut sayısı, halkanın adından değil künyesinden okunur.
Halkayı Atlamanın Bedeli
Kurgudaki ağ hazırlık ortamını işletmiyordu. Modelin iki koşumu bu kararın bedelini sayar.
Dört halkalı zincirde üretime iki hata sınıfı kaçar: ölçek çöküşü ve zaman aşımı. Üç halkalı zincirde yediye çıkar. Hazırlık halkası beş hata sınıfını üretimin önünde yakalar: çözümleme sapması, bellek tükenmesi, yarış durumu, sözleşme sapması ve gün sınırı kayması. Bu beşi, ağın hazırlığı kurmadığı sürece ilk kez gerçek fatura üretilirken görünen sınıflardır.
Atlamanın kazandırdığı da sayılabilir: zincir dört duraktan üçe iner, yani bir yayım daha az bekleme ve bir devir daha az el değiştirme demektir. Bu kazanç öncü süreye yazılır; bedel ise geri dönüş oranına ve kurtarma süresine yazılır, çünkü kaçan beş sınıfın her biri üretimde görüldüğünde geri alınacak bir değişiklik ve onarılacak bir kesinti üretir. Tek ölçüte bakan bir cümle burada karar taşımaz: hızlanma bir yerden alınıp başka bir yere konur.
Kaçan iki sınıf ise hazırlık kurulsa bile yerinde kalır, çünkü hiçbir halka bir buçuk milyon sayaçlık veri hacmini ve otuz dört milisaniyelik ağ gecikmesini taşımaz. Bu iki boyutu kapatmanın yolu vardır — üretim ölçeğinde biçimlendirilmiş veri kümesi ve yapay gecikme eklenmesi — ve her ikisinin de bir bedeli vardır: ortamın kurulum maliyeti ve koşum süresi. Ölçüm bu tartışmayı da somutlaştırır: kapatılacak boyut iki tanedir, ikisinin adı bellidir ve kapatıldığında hangi hata sınıfının önünün alınacağı yazılıdır.
Son olarak künye ile koşum arasındaki altı farkın anlamı buradadır. Künyede yazan on iki fark bir toplantıda gündeme gelebilir; yazmayan altısı gelemez. Saat diliminin geliştirme ile üretim arasında ayrılması, gecelik toplu işin gün sınırını yanlış yerden kesmesi olarak ortaya çıkar ve nedeninin ortam farkı olduğu, hata bulunana kadar kimsenin aklına gelmez. Ortam künyesinin kapsamını genişletmek — koşumda ölçülen üç boyutu da bildirmek — bu altı farkın altısını da tartışılabilir hâle getirir.
Özet
- Ortam, üretime giden zincirin bir halkasıdır; dört halka amaçla ayrılır ve her halka yalnız üretimle aynı olduğu boyutlardaki kusurları görebilir.
- Ortam denkliği boyut boyut sayılır. Kurgu modelinde on boyut vardır; üç ortam ile üretim arasında 18 fark ölçülmüştür: geliştirme 9, sınama 7, hazırlık 2.
- Bu 18 farkın 12’si ortam künyesinde bildirilmiştir, 6’sı yalnız süreç koşarken görünür; bildirilmemiş fark tartışılamadığı için karar konusu olamaz.
- Her farkın gizlediği bir hata sınıfı vardır ve bir ortamın yakalayamadığı sınıfların listesi, o ortamın üretimden ayrıldığı boyutların listesine eşittir.
- Hazırlık halkası beş hata sınıfını üretimin önünde yakalar; atlanması bu beşini üretime taşır. Veri hacmi ve ağ gecikmesi hiçbir halkada denk olmadığı için iki sınıf her koşulda üretime kalır.
Sonraki Adım
Bu dersin zinciri bir şeyi varsaydı: halkalar arasında yolculuk eden nesne hep aynı nesnedir. Oysa ortam künyeleri bunu doğrulamıyor — her halkanın kendi paket sürümleri, kendi dosya yolları ve kendi ortam değişkenleri var. Değişiklik her durakta kaynaktan yeniden derleniyorsa zincirde dolaşan tek bir nesne değil, dört ayrı nesne vardır ve hangisinin hangisiyle aynı olduğu ölçülmemiştir. Sonraki ders bu nesneyi adlandırır ve ölçer: aynı kaynaktan iki kez üretilen çıktı gerçekten aynı mı, değilse farkı hangi kaynaklar sokuyor ve ortam başına yeniden derleme kaç ayrı ikili doğuruyor?
İlerlemeni kaydetmek ve not almak için Giriş yap
Notlarım
Not almak için giriş yapmalısın.