Ders 17 / 27
Çalışma Alanları ve Ortamlar
Üç ortamın iki ayrı kurulumu: tek tanım artı çalışma alanı ile ayrı dizin, ortama özgü fark sayısı, hangi ortamda olunduğunu söyleyen işaret sayısı ve yanlış ortama uygulama, tanım değiştiğinde birlikte değişen ortam sayısı ile ayrışma.
İçindekiler
Önceki ders durumu parçalara böldü ve parça adlarında ortam da geçti. Ortam ayrımının nasıl kurulduğuna ise hiç bakılmadı. Üç ortamın tanımı büyük ölçüde aynıysa iki yol vardır: tek tanım yazıp ortamı bir ayarla seçmek ya da her ortam için ayrı dizin tutmak. Bu ders ikisini de gerçekten kurar ve aralarındaki farkı üç sayıyla ölçer.
Ortamların birbirine ne kadar benzediği — ortam denkliği — daha önce ölçüldü ve burada tekrarlanmaz. Buradaki soru benzerlik değil, benzerliğin nerede yazıldığıdır.
Aynı Tanımın Üç Örneği
DM19. Aşağıdaki yapılandırma dili bu ders için tanımlanan küçük bir biçimdir; ortam(...)
ifadesi seçili ortama göre değer seçer. Betik iki kurulumu da diske yazar: tek tanım artı çalışma
alanı, bir de üç ayrı dizin.
// kurulum.mjs — uc ortam iki bicimde kurulur: tek tanim + calisma alani, bir de ayri dizin. // Yapilandirma dili bu ders icin tanimlanan kucuk bicimdir; ortam(...) ifadesi ortama gore secer. import { writeFileSync, mkdirSync, rmSync } from "node:fs"; const ortamlar = ["deneme", "hazirlik", "uretim"]; const TANIM = `kaynak alt_ag omurga { blok = ortam(deneme="10.0.0.0/16", hazirlik="10.1.0.0/16", uretim="10.2.0.0/16") } kaynak makine toplayici { sayi = ortam(deneme=1, hazirlik=2, uretim=6) cekirdek = ortam(deneme=2, hazirlik=2, uretim=8) bellek_gb = ortam(deneme=8, hazirlik=8, uretim=32) imaj = "olcum-toplayici-4.2" } kaynak kuyruk okuma { saklama_saat = ortam(deneme=6, hazirlik=24, uretim=168) bolum = ortam(deneme=1, hazirlik=4, uretim=12) } kaynak veri_deposu olcum { boyut_gb = ortam(deneme=20, hazirlik=100, uretim=2000) yedek = ortam(deneme=false, hazirlik=false, uretim=true) }`; // ortam(...) ifadesini verilen ortam icin cozer; kosullu olmayan satir oldugu gibi kalir. const coz = (metin, ortam) => metin.replace(/ortam\(([^)]*)\)/g, (_, ic) => { const esles = new RegExp(`${ortam}=([^,]+)`).exec(ic); return esles[1].trim(); }); rmSync("calisma-alani", { recursive: true, force: true }); rmSync("ayri-dizin", { recursive: true, force: true }); mkdirSync("calisma-alani/durum", { recursive: true }); writeFileSync("calisma-alani/tanim.txt", TANIM); writeFileSync("calisma-alani/.secili", "deneme"); for (const o of ortamlar) writeFileSync(`calisma-alani/durum/${o}.json`, JSON.stringify({ ortam: o, kalemler: [] })); for (const o of ortamlar) { mkdirSync(`ayri-dizin/${o}`, { recursive: true }); writeFileSync(`ayri-dizin/${o}/tanim.txt`, coz(TANIM, o)); writeFileSync(`ayri-dizin/${o}/durum.json`, JSON.stringify({ ortam: o, kalemler: [] })); } const satirlar = TANIM.split("\n"); const kosullu = satirlar.filter((s) => s.includes("ortam(")).length; const alan = satirlar.filter((s) => s.includes("=")).length; const ayriSatir = ortamlar.reduce((t, o) => t + coz(TANIM, o).split("\n").length, 0); const ortakAlan = alan - kosullu; console.log(`calisma alani: 1 tanim dosyasi, ${satirlar.length} satir, ` + `${alan} alan (${kosullu} ortama ozgu, ${ortakAlan} ortak), 3 durum dosyasi`); console.log(`ayri dizin : 3 tanim dosyasi, ${ayriSatir} satir, ` + `${alan * 3} alan (${kosullu * 3} ayri yazilmis, ${ortakAlan * 3} yinelenmis), 3 durum dosyasi`); console.log(`ortama ozgu fark: ${kosullu} alan; uc ortamda ayni kalan: ${ortakAlan} alan`);
calisma alani: 1 tanim dosyasi, 17 satir, 9 alan (8 ortama ozgu, 1 ortak), 3 durum dosyasi ayri dizin : 3 tanim dosyasi, 51 satir, 27 alan (24 ayri yazilmis, 3 yinelenmis), 3 durum dosyasi ortama ozgu fark: 8 alan; uc ortamda ayni kalan: 1 alan
İki kurulum da aynı altyapıyı anlatıyor, aynı üç durum dosyasını tutuyor ve aynı ortam ayrımını üretiyor. Fark yazılan metnin miktarında ve farkın nerede durduğundadır.
Çalışma alanı biçiminde ortama özgü sekiz fark tek bir dosyada, sekiz koşullu ifadenin içinde duruyor. Ayrı dizin biçiminde aynı sekiz fark yirmi dört ayrı satıra dağılmış — her ortam kendi değerini kendi dosyasında taşıyor — ve üç ortamda aynı kalan tek alan üç kez yinelenmiş.
Bu ilk sayı çiftinin söylediği şudur: farkın tek yerde toplanması onu görünür kılar. Üç ortamın hangi noktalarda ayrıştığını öğrenmek için çalışma alanı biçiminde bir dosyaya bakmak yeterlidir; ayrı dizin biçiminde üç dosya karşılaştırılır. Buna karşılık ayrı dizin biçiminde her ortamın tanımı kendi başına okunabilir: üretimin ne olduğunu anlamak için koşulları zihinde çözmek gerekmez.
Durum tarafında ise iki kurulum arasında hiçbir fark yok: ikisi de ortam başına bir durum dosyası tutuyor, toplam üç. Önceki iki dersin sayıları bu yüzden ikisinde de aynı biçimde geçerlidir — kilit ortam başına alınır, üç ortam birbirini beklemeden uygulanabilir, bir ortamın durumunun kaybı yalnız o ortamı yönetilemez kılar. Çalışma alanı tanımı paylaştırır; paylaştırmadığı tek şey durumdur ve bu ayrım dersin sonunda yeniden karşımıza çıkacak.
Hangi Ortamdayım
İkinci ölçü işletmeye aittir. Uygulamayı başlatan kişi, düğmeye basmadan önce hangi ortamda olduğunu kaç işaretten okuyabiliyor?
DM20. Çalışma alanı biçiminde seçili ortam gizli bir dosyada durur ve ayrı bir komutla değiştirilir; komut satırında hiçbir izi yoktur. Ayrı dizin biçiminde seçim, komutun çalıştırıldığı dizindir ve yol adında görünür. DM21. Seçimi atlama olasılığı işaret sayısına bağlanır: işaret yoksa yüzde on beş, varsa yüzde üç. DM22. Uygulamadan önce ortam adını ekrana basıp onay isteyen bir adım, atlanan seçimlerin onda dokuzunu yakalıyor. Üreteç ders içinde yazılmıştır, tohum görünür.
// ortam-secimi.mjs — hangi ortamda olundugunu bilme adimi ve yanlis ortama uygulama modeli. import { readFileSync, writeFileSync } from "node:fs"; let x = 20260801 >>> 0; // tohum gorunur const rast = () => { x = (Math.imul(x, 1664525) + 1013904223) >>> 0; return x / 4294967296; }; const ortamlar = ["deneme", "hazirlik", "uretim"]; // Uygulamayi baslatan kisi hangi ortamda oldugunu kac isaretten okuyabiliyor? console.log("hangi ortamdayim: calisma alani -> ekranda 0 isaret, 1 ek komut (secili dosyasi)"); console.log(" ayri dizin -> yolda 1 isaret, 0 ek komut"); const kos = (etiket, unutmaOlasiligi, onayYakalama) => { writeFileSync("calisma-alani/.secili", "deneme"); let yanlis = 0, uretimeDusen = 0; for (let i = 0; i < 200; i++) { const hedef = ortamlar[Math.floor(rast() * 3)]; const gecerli = readFileSync("calisma-alani/.secili", "utf8"); let secildi = hedef; if (rast() < unutmaOlasiligi) { // secim adimi atlandi: onceki ortam gecerli secildi = gecerli; if (rast() < onayYakalama) secildi = hedef; // onay adimi yakaladi } writeFileSync("calisma-alani/.secili", secildi); if (secildi !== hedef) { yanlis++; if (secildi === "uretim") uretimeDusen++; } } console.log(`${etiket.padEnd(28)}: 200 uygulamada ${String(yanlis).padStart(2)} yanlis ortam, ` + `${uretimeDusen} tanesi uretime dustu`); }; kos("calisma alani", 0.15, 0); kos("ayri dizin", 0.03, 0); kos("calisma alani + zorunlu onay", 0.15, 0.9);
hangi ortamdayim: calisma alani -> ekranda 0 isaret, 1 ek komut (secili dosyasi)
ayri dizin -> yolda 1 isaret, 0 ek komut
calisma alani : 200 uygulamada 23 yanlis ortam, 8 tanesi uretime dustu
ayri dizin : 200 uygulamada 4 yanlis ortam, 1 tanesi uretime dustu
calisma alani + zorunlu onay: 200 uygulamada 2 yanlis ortam, 1 tanesi uretime dustu
İki yüz uygulamada çalışma alanı biçimi yirmi üç kez yanlış ortama gitti, sekizi üretime düştü. Ayrı dizin biçiminde sayı dörde, üretime düşen bire indi. Aradaki farkın kaynağı tek bir şeydir: ekranda ortamı söyleyen bir işaretin olup olmaması.
Üçüncü satır daha önemlidir. Çalışma alanı biçimine uygulamadan önce ortam adını basan bir onay adımı eklendiğinde yanlış uygulama yirmi üçten ikiye indi — ayrı dizin biçiminden de iyi. Sonuç, iki kurulumdan birinin doğası gereği güvenli olmadığını söylüyor: güvenli olan, ortamın görünür olmasıdır. Ayrı dizin bunu bedavaya verir çünkü yol zaten ekrandadır; çalışma alanı biçiminde aynı görünürlük ayrıca kurulmak zorundadır.
Yanlış ortama uygulamanın bedeli bu kursun ilk dersindeki ölçüme bağlanır. Üretime düşen sekiz uygulamanın her biri, üretim durumuna deneme değerlerini yazar: makine sayısı altıdan bire iner, veri deposu iki bin gigabayttan yirmiye. Kayıt ile gerçek arasındaki fark burada sapmayla değil, kaydın kendisiyle üretilmiştir — ve uygulama bittiği anda kayıt da gerçek de yanlıştır.
Tanım Değişince Kaç Ortam Değişir
Üçüncü ölçü zamanla ilgilidir. Tanıma bir alan eklendiğinde kaç ortam zorunlu olarak birlikte değişir? DM23. On iki değişikliğin sekizi üç ortamı da ilgilendiriyor, dördü tek ortama özgü; ayrı dizin biçiminde her elle taşıma dörtte bir olasılıkla atlanıyor. DM24. Uygulama yalnız deneme ortamında koşturuldu.
// degisiklik.mjs — tanim degistiginde kac ortamin zorunlu birlikte degistigi ve ayrisma. import { readFileSync, writeFileSync, appendFileSync } from "node:fs"; let x = 991 >>> 0; // tohum gorunur const rast = () => { x = (Math.imul(x, 1664525) + 1013904223) >>> 0; return x / 4294967296; }; const ortamlar = ["deneme", "hazirlik", "uretim"]; // On iki degisiklik: sekizi uc ortami da ilgilendiriyor, dordu tek ortama ozgu. const degisiklikler = []; for (let i = 1; i <= 8; i++) degisiklikler.push({ no: i, kapsam: "hepsi" }); for (let i = 9; i <= 12; i++) degisiklikler.push({ no: i, kapsam: ortamlar[(i - 9) % 3] }); let yeniKosul = 0, tasimaGereken = 0, tasimaAtlanan = 0; for (const d of degisiklikler) { if (d.kapsam === "hepsi") { // tek tanim: bir satir, uc ortam birden appendFileSync("calisma-alani/tanim.txt", `\n yeni_alan_${d.no} = "d${d.no}"`); for (const o of ortamlar) { // ayri dizin: her dizine elle tasinir tasimaGereken++; if (rast() < 0.25) { tasimaAtlanan++; continue; } appendFileSync(`ayri-dizin/${o}/tanim.txt`, `\n yeni_alan_${d.no} = "d${d.no}"`); } } else { // tek ortama ozgu: kosullu ifade gerekiyor yeniKosul++; const ic = ortamlar.map((o) => `${o}=${o === d.kapsam ? `"d${d.no}"` : '""'}`).join(", "); appendFileSync("calisma-alani/tanim.txt", `\n yeni_alan_${d.no} = ortam(${ic})`); appendFileSync(`ayri-dizin/${d.kapsam}/tanim.txt`, `\n yeni_alan_${d.no} = "d${d.no}"`); } } const kosullu = (s) => s.split("\n").filter((l) => l.includes("ortam(")).length; const alan = (dosya) => new Set(readFileSync(dosya, "utf8").split("\n") .filter((l) => l.includes("yeni_alan_")).map((l) => /yeni_alan_\d+/.exec(l)[0])); const beklenen = (o) => degisiklikler.filter((d) => d.kapsam === "hepsi" || d.kapsam === o).length; const eksik = ortamlar.map((o) => beklenen(o) - alan(`ayri-dizin/${o}/tanim.txt`).size); console.log(`calisma alani: 1 tanim dosyasi, ${degisiklikler.length} degisiklik islendi`); console.log(` kosullu ifade 8 -> ${kosullu(readFileSync("calisma-alani/tanim.txt", "utf8"))} ` + `(tek ortama ozgu her degisiklik bir kosul ekliyor)`); console.log(` ortak degisiklikte zorunlu birlikte degisen ortam: 3/3, ayrisan alan: 0`); console.log(`ayri dizin: 3 tanim dosyasi, ${degisiklikler.length} degisiklik islendi`); console.log(` ortak degisiklik ${tasimaGereken} tasima gerektirdi, ${tasimaAtlanan} tasima atlandi`); console.log(` ortak degisiklikte zorunlu birlikte degisen ortam: 1/3, kalan 2 elle`); console.log(` ayrisan alan: ${eksik.reduce((a, b) => a + b, 0)} ` + `(${ortamlar.map((o, i) => `${o} ${eksik[i]}`).join(", ")})`); // Tanim degisti, uygulama yalniz deneme ortaminda kosturuldu. const geride = (bicim) => ortamlar.filter((o) => o !== "deneme") .map((o) => `${o} ${beklenen(o) - (bicim === "ayri" ? eksik[ortamlar.indexOf(o)] : 0)}`).join(", "); console.log(`kayit ile gercek (yalniz deneme uygulandi), uygulanmayi bekleyen alan:`); console.log(` calisma alani -> ${geride("tek")} | ayri dizin -> ${geride("ayri")}`);
calisma alani: 1 tanim dosyasi, 12 degisiklik islendi kosullu ifade 8 -> 12 (tek ortama ozgu her degisiklik bir kosul ekliyor) ortak degisiklikte zorunlu birlikte degisen ortam: 3/3, ayrisan alan: 0 ayri dizin: 3 tanim dosyasi, 12 degisiklik islendi ortak degisiklik 24 tasima gerektirdi, 2 tasima atlandi ortak degisiklikte zorunlu birlikte degisen ortam: 1/3, kalan 2 elle ayrisan alan: 2 (deneme 0, hazirlik 2, uretim 0) kayit ile gercek (yalniz deneme uygulandi), uygulanmayi bekleyen alan: calisma alani -> hazirlik 9, uretim 9 | ayri dizin -> hazirlik 7, uretim 9
Çalışma alanı biçiminde ortak bir değişiklik tek satırdır ve üç ortamın tanımını zorunlu olarak birlikte değiştirir: 3/3. Ayrışan alan sıfırdır, çünkü ayrışacak ikinci bir dosya yoktur. Bedeli öteki uçta ödenir: tek ortama özgü dört değişiklik dört yeni koşullu ifade doğurdu; koşul sayısı sekizden on ikiye çıktı ve dosya her ortam farkında biraz daha okunmaz oldu.
Ayrı dizin biçiminde aynı sekiz ortak değişiklik yirmi dört elle taşıma gerektirdi ve ikisi atlandı. Sonuç, hazırlık ortamında iki alanlık bir ayrışmadır. Bu ayrışmayı kimse bildirmez; iki tanım da kendi içinde geçerlidir, iki uygulama da hatasız koşar. Fark yalnız üç dosya karşılaştırıldığında görünür.
Atlama oranının kendisi de bir ölçüdür. Dörtte bir olasılık, on iki değişikliklik bir dönemde iki alanlık ayrışma üretti; oran aynı kalırsa fark her dönemde biraz daha büyür ve hiçbir uygulama bunu bildirmediği için birikir. Ayrışmanın bu koşuda hazırlık ortamında toplanması modelin rastlantısıdır — hangi ortamın ayrışacağı önceden bilinmez, ayrışacağı bilinir. Bu da ayrı dizin biçiminin taşımayı denetleyen bir adım gerektirdiği anlamına gelir: üç tanımı karşılaştıran ve ortama özgü olmayan farkları bildiren bir denetim yoksa, ayrışma ancak üretimde bir davranış farkı olarak ortaya çıkar.
Son iki sayı kaydın kendi riskini gösteriyor. Tanım her iki biçimde de değişti, uygulama yalnız deneme ortamında koşturuldu. Çalışma alanı biçiminde hazırlık ve üretim dokuzar alan geride; ayrı dizin biçiminde hazırlık yedi, üretim dokuz. Kayıt üç ortam için de değişmiş durumda, gerçek yalnız biri için. Tek tanım, farkın birikmesini engellemez; yalnız tek yerde yazılı olmasını sağlar. Ortamlar arası fark tanımda değil, uygulama gecikmesinde doğar.
Seçim
Üç ölçüm üç ayrı yöne işaret ediyor ve tek bir kazanan yok. Ortama özgü fark azsa çalışma alanı biçimi kazanır: tek dosya, sıfır ayrışma, sekiz koşul. Ortama özgü fark çoğaldıkça koşullu ifade sayısı tanımı yutar ve ayrı dizin okunabilir kalır. Yanlış ortama uygulama riski çalışma alanı biçiminde beş kat yüksektir, ama bir onay adımıyla ikiye iner — yani bu fark kurulumun değil, kurulumun etrafına konan korumanın işidir.
Üzerinde durulması gereken tek şey, iki biçimde de değişmeyendir: üç ortamın durumu üç ayrı dosyadır. Çalışma alanı tek tanımı paylaştırır, durumu paylaştırmaz. Bu yüzden bir ortamda uygulanan değişiklik ötekilerde kendiliğinden gerçekleşmez ve kaydın üç ortam için aynı olması, gerçeğin aynı olduğu anlamına gelmez.
Özet
- Aynı altyapı iki biçimde kuruldu: tek tanım dosyası on yedi satır ve sekiz koşullu ifade; üç ayrı dizin elli bir satır, yirmi dört ayrı yazılmış ve üç yinelenmiş alan.
- Ortama özgü fark sekiz alan, üç ortamda aynı kalan bir alan; fark çalışma alanı biçiminde tek dosyada toplanıyor, ayrı dizin biçiminde üç dosyaya dağılıyor.
- İki yüz uygulamada yanlış ortama gitme sayısı çalışma alanı biçiminde yirmi üç, ayrı dizin biçiminde dört; ortam adını basan bir onay adımı sayıyı ikiye indirdi.
- Ortak bir değişiklik çalışma alanı biçiminde üç ortamı birlikte değiştiriyor ve sıfır ayrışma üretiyor; ayrı dizin biçiminde yirmi dört elle taşımanın ikisi atlandı ve iki alan ayrıştı.
- Tek ortama özgü dört değişiklik çalışma alanı biçiminde koşul sayısını sekizden on ikiye çıkardı; ayrı dizin biçiminde tek dosyada tek satır kaldı.
- Tanım üç ortam için değişti, uygulama bir ortamda koştu: iki ortam dokuzar alan geride kaldı. Ortamlar arası fark tanımda değil, uygulama gecikmesinde doğuyor.
Sonraki Adım
Bu dersin iki kurulumu da bir tekrarı çözmeye çalıştı: aynı altyapının üç kez anlatılması. Çalışma alanı tekrarı koşullu ifadeye çevirdi, ayrı dizin ise açıkça yineledi. İkisi de tekrarı ortadan kaldırmadı, yalnız yerini değiştirdi. Üç ortam yerine on ekip aynı kuyruğu, aynı toplayıcı makineyi, aynı arşivi kurmak istediğinde iki biçim de yetmez; gereken şey tanımın kendisinin paketlenmesi, girdilerinin adlandırılması ve sürümlenmesidir. Konunun bundan sonraki derslerinde altyapı modülü ele alınır: girdi yüzeyi, sürüm sabitleme ve kırıcı değişikliğin bağlı olan her kullanıcıya nasıl yayıldığı.
İlerlemeni kaydetmek ve not almak için Giriş yap
Notlarım
Not almak için giriş yapmalısın.