İçeriğe geç
academia.sh

Ders 14 / 17

Yama ve Değişiklik Yönetimi

Kırk duyuruluk bir kümede pencere uzunluğu bir karar değişkeni olarak koşturuluyor: pencere kısaldıkça yakalanan açık 23'ten 30'a çıkıyor ama plan dışı kesinti 9'dan 50'ye yükseliyor, iki eğri dokuzuncu günde kesişiyor ve kesintinin bedeli 900'den 14.000 risk birimine çıkarıldığında en iyi pencere 1 günden 17 güne kayıyor. Onay kapısı hata çarpanını düşürerek pencereyi kısaltıyor, iki yollu düzen tek pencereyi 207.637'den 130.159 risk birimine indiriyor ve on iki duyuruluk sınıflandırma hatası bu kazancın onda dokuzunu geri alıyor.

İçindekiler

Bir önceki ders düzeltmeyi tek boyutlu bir işlem saydı: bir kaleme adam-saat harcanır ve kalem kapanır. Gerçekte her düzeltme bir değişikliktir ve değişiklik üretim ortamına dokunur. Kalemi hızlı kapatmak onu eksik sınayıp uygulamak demektir; tam sınamak ise kalemi daha uzun süre açık tutar. Bu ders o dengeyi tek bir karar değişkeni üzerinde ölçer: yama penceresi, yani duyurunun yayımlandığı gün ile yamanın uygulandığı gün arasındaki süre.

Pencerenin filo tarafındaki mekaniği — bakım takvimi, turu kaçıran makine, nokta-günü — Uç Nokta ve Sistem Sertleştirme kursunda ölçüldü ve burada girdi olarak alınır. Buradaki soru program ölçeğindedir ve iki eğri arasındadır: pencere kısaldıkça istismar erişilebilir hâle gelmeden yakalanan açık sayısı artar, aynı daralma sınama kapsamını düşürüp plan dışı kesinti üretir. İki eğri aynı eksende çizilir ve kesiştikleri nokta hesaplanır.

  • GP7. Kırk duyuru, etkilenen varlık sayıları ve istismarın erişilebilir hâle geldiği gün kurgusal bölgesel ölçüm ağına aittir ve modeldir. Gerçek bir yama indirilmiyor.
  • GP8. Sınama kapsamı pencere uzunluğuyla doğrusal artar ve yirmi bir günde tamamlanır; hata oranı eksik kapsamın karesiyle büyür. Gerçekte eğri sıçramalıdır.
  • GP9. Risk birimi (rb) kurgudur; gerçek bir para birimi değildir. Bir plan dışı kesinti 3.600 rb sayıldı. Bu bir varsayımdır ve ikinci blok onu değiştirdiğinde sonucun ne olduğunu ölçer.
  • GP10. İstismarın erişilebilir olduğu gün modelde bilinir. Gerçekte kestirilir; son blok kestirimin yanlış olmasının bedelini ölçer.
  • GP11. Onay kapısının hata çarpanı sabittir ve kapının kendisi kusur üretmez.
  • GP12. Kusurlu yama, geri alma ve kademeli dağıtım modellenmedi; üçü de sabit sayılır.
// yama/model.mjs — pencere uzunlugunun MODELIDIR: kurgu duyuru kumesi, istismarin
// erisilebilir hale geldigi gun, sinama kapsami ve degisiklik basarisizlik orani.
// Gercek bir yama indirilmez; filo mekanigi girdi olarak alinir.
export const TOHUM = 20260811, DUYURU_SAYI = 40, DAGITIM = 6;
export const TAM_SINAMA = 21, HATA_TABAN = 0.01, HATA_ARTIS = 0.34;
export const KESINTI_RB = 3600;             // bir plan disi kesintinin bedeli (risk birimi, kurgu)
const uretec = (t) => { let s = t >>> 0;
  return () => (s = (s * 1664525 + 1013904223) >>> 0) / 4294967296; };

export const DUYURU = (() => {
  const r = uretec(TOHUM);
  return Array.from({ length: DUYURU_SAYI }, (_, i) => ({
    no: i + 1,
    puan: +(4 + r() * 5).toFixed(1),
    etkilenen: 20 + Math.round(r() * 280),
    // istismarin kullanilabilir hale geldigi gun: bir bolumu duyuru gununde hazir
    istismar: Math.round(Math.max(0, -6 + r() * 46)),
  }));
})();

export const kapsam = (W) => Math.min(1, W / TAM_SINAMA);
export const hataOrani = (W) => HATA_TABAN + HATA_ARTIS * (1 - kapsam(W)) ** 2;
export const kesinti = (W) => Math.round(DUYURU_SAYI * DAGITIM * hataOrani(W));
export const yakalanan = (W) => DUYURU.filter((d) => W <= d.istismar).length;
export const maruziyet = (W) => DUYURU.reduce((a, d) =>
  a + d.puan * d.etkilenen * Math.max(0, W - d.istismar), 0);
export const toplam = (W) => maruziyet(W) + kesinti(W) * KESINTI_RB;

// Duzen: her duyuruya bir pencere atayan islev. Kesinti sayisi duyuru basina hesaplanir.
export const DUZEN = { kapisiz: { gecikme: 0, carpan: 1.00 },
  'hafif onay': { gecikme: 2, carpan: 0.60 }, 'tam onay': { gecikme: 5, carpan: 0.35 } };
export function olc(pencere, duzenAd = 'kapisiz') {
  const d = DUZEN[duzenAd]; let mar = 0, kes = 0, yak = 0;
  for (const x of DUYURU) {
    const W = Math.max(pencere(x), d.gecikme);
    mar += x.puan * x.etkilenen * Math.max(0, W - x.istismar);
    kes += DAGITIM * hataOrani(W) * d.carpan;
    if (W <= x.istismar) yak += 1;
  }
  return { maruziyet: mar, kesinti: Math.round(kes), yakalanan: yak,
    toplam: mar + Math.round(kes) * KESINTI_RB };
}
export const enIyiTek = (duzenAd) => { let b = 1;
  for (let W = 1; W <= 40; W += 1)
    if (olc(() => W, duzenAd).toplam < olc(() => b, duzenAd).toplam) b = W;
  return b; };

İki Eğrinin Kesiştiği Nokta

// yama/pencere.mjs — pencere uzunlugu taramasi: yakalanan acik, maruziyet, kesinti ve
// bir gun kisaltmanin kazanci ile bedeli
import { DUYURU, DAGITIM, KESINTI_RB, kapsam, hataOrani, olc } from './model.mjs';

const y = (g, ...s) => console.log(s.map((v, i) =>
  (g[i] < 0 ? String(v).padEnd(-g[i]) : String(v).padStart(g[i]))).join('').trimEnd());
const tek = (W) => olc(() => W);

console.log(`${DUYURU.length} duyuru, duyuru basina ${DAGITIM} dagitim olayi; ` +
  `bir plan disi kesintinin bedeli ${KESINTI_RB} risk birimi (kurgu)`);
const A = [-9, 9, 11, 12, 10, 11, 11, 18];
y(A, 'pencere', 'sinama', 'yakalanan', 'maruziyet', 'kesinti', 'kesinti', 'toplam', '1 gun kisaltma');
y(A, 'gun', 'kapsami', 'acik', 'rb', 'olayi', 'rb', 'rb', 'kazanc - bedel');
for (let W = 5; W <= 15; W += 1) {
  const r = tek(W), onceki = tek(W - 1);
  const kazanc = r.maruziyet - onceki.maruziyet;                 // 1 gun kisaltmanin kazanci
  const bedel = (onceki.kesinti - r.kesinti) * KESINTI_RB;       // 1 gun kisaltmanin bedeli
  y(A, W, kapsam(W).toFixed(2), r.yakalanan, Math.round(r.maruziyet), r.kesinti,
    r.kesinti * KESINTI_RB, Math.round(r.toplam),
    `${Math.round(kazanc)} - ${Math.round(bedel)}`);
}

const enIyi = (k) => { let b = 1; const t = (W) => tek(W).maruziyet + tek(W).kesinti * k;
  for (let W = 1; W <= 40; W += 1) if (t(W) < t(b)) b = W; return b; };
const kesim = enIyi(KESINTI_RB);
const adim = (W) => `${W} -> ${W - 1}: kazanc ` +
  `${Math.round(tek(W).maruziyet - tek(W - 1).maruziyet)} rb, bedel ` +
  `${(tek(W - 1).kesinti - tek(W).kesinti) * KESINTI_RB} rb`;
console.log(`\nkesisme ${kesim}. gunde: ${adim(kesim + 1)} | ${adim(kesim)}`);
console.log('kesinti bedeli degisince en iyi pencere:');
for (const k of [900, 3600, 14000]) {
  const W = enIyi(k);
  console.log(`  ${String(k).padStart(5)} rb/kesinti -> ${String(W).padStart(2)} gun; ` +
    `yakalanan ${tek(W).yakalanan}/${DUYURU.length}, hata orani ${hataOrani(W).toFixed(3)}`);
}
40 duyuru, duyuru basina 6 dagitim olayi; bir plan disi kesintinin bedeli 3600 risk birimi (kurgu)
pencere     sinama  yakalanan   maruziyet   kesinti    kesinti     toplam    1 gun kisaltma
gun        kapsami       acik          rb     olayi         rb         rb    kazanc - bedel
5             0.24         30       48357        50     180000     228357     10800 - 21600
6             0.29         28       60960        44     158400     219360     12602 - 21600
7             0.33         27       74746        39     140400     215146     13787 - 18000
8             0.38         27       88533        34     122400     210933     13787 - 18000
9             0.43         26      103237        29     104400     207637     14704 - 18000
10            0.48         25      119524        25      90000     209524     16286 - 14400
11            0.52         24      137399        21      75600     212999     17876 - 14400
12            0.57         23      156171        17      61200     217371     18772 - 14400
13            0.62         23      174942        14      50400     225342     18771 - 10800
14            0.67         23      193714        11      39600     233314     18772 - 10800
15            0.71         23      212485         9      32400     244885      18772 - 7200

kesisme 9. gunde: 10 -> 9: kazanc 16286 rb, bedel 14400 rb | 9 -> 8: kazanc 14704 rb, bedel 18000 rb
kesinti bedeli degisince en iyi pencere:
    900 rb/kesinti ->  1 gun; yakalanan 34/40, hata orani 0.318
   3600 rb/kesinti ->  9 gun; yakalanan 26/40, hata orani 0.121
  14000 rb/kesinti -> 17 gun; yakalanan 22/40, hata orani 0.022

Tablonun iki sütunu ters yönde hareket ediyor. Pencere beş günden on beş güne uzarken maruziyet 48.357 risk biriminden 212.485’e çıkıyor, kesinti olayı ise 50’den 9’a iniyor. Hiçbiri tek başına karar taşımaz: yalnız maruziyete bakan bir program pencereyi bir güne indirir ve yılda elli plan dışı kesintinin üzerine çıkar; yalnız kesintiye bakan bir program pencereyi uzatır ve bunu görmez.

Son sütun kararı veriyor. On günden dokuza inmek 16.286 rb maruziyet kazandırıyor ve 14.400 rb kesinti bedeli ekliyor — kazanç büyük, kısaltma yapılır. Dokuzdan sekize inmek 14.704 rb kazandırıyor ve 18.000 rb’ye mal oluyor — bu adım geri alınır. İki eğri dokuzuncu günde kesişiyor ve toplam orada en düşük değerini alıyor (207.637 rb).

Yakalanan açık sütunu ayrı bir uyarı taşıyor. On ikinci günden on beşinci güne kadar sabit kalıyor (23), ama maruziyet aynı aralıkta yüzde otuz altı artıyor. Yakalanan açık sayısı kesikli bir ölçüttür ve pencere uzadıkça duyarlılığını yitirir; maruziyet süreklidir ve her günü sayar. “Kaç açığı zamanında kapattık” sorusu, aynı verinin en az bilgi taşıyan biçimidir.

Alt blok pencerenin nereden geldiğini gösteriyor. Kesintinin bedeli 900 rb sayıldığında en iyi pencere bir gün, 14.000 rb sayıldığında on yedi gündür; aynı kırk duyuru için on yedi kat fark. Pencere uzunluğu açığın bir özelliği değil, kesintinin bedelinin bir sonucudur. İki kurum aynı duyuru kümesine bakıp farklı pencere seçtiğinde bu bir tutarsızlık değildir — yeter ki bedel yazılı olsun. Yazılı değilse pencere bir sayı olarak tartışılır ve tartışma kapanmaz.

Onay Kapısı ve İki Yollu Pencere

// yama/duzen.mjs — degisiklik duzeni: onay kapisinin bedeli, iki yollu pencere ve
// siniflandirma hatasinin bedeli
import { DUYURU, DAGITIM, DUZEN, olc, enIyiTek } from './model.mjs';

const SAAT = { kapisiz: 0, 'hafif onay': 1.5, 'tam onay': 5 };   // dagitim olayi basina onay saati
const OLAY = DUYURU.length * DAGITIM;
const y = (g, ...s) => console.log(s.map((v, i) =>
  (g[i] < 0 ? String(v).padEnd(-g[i]) : String(v).padStart(g[i]))).join('').trimEnd());

const A = [-12, 9, 9, 9, 11, 9, 11, 12];
console.log('1. uc degisiklik duzeni, her biri kendi en iyi penceresinde');
y(A, 'duzen', 'gecikme', 'hata', 'pencere', 'yakalanan', 'kesinti', 'toplam', 'onay');
y(A, '', 'gun', 'carpani', 'gun', 'acik', 'olayi', 'rb', 'saati');
const sat = [];
for (const ad of Object.keys(DUZEN)) {
  const W = Math.max(enIyiTek(ad), DUZEN[ad].gecikme);
  const r = olc(() => W, ad), saat = OLAY * SAAT[ad];
  sat.push({ ad, W, r, saat });
  y(A, ad, DUZEN[ad].gecikme, DUZEN[ad].carpan.toFixed(2), W, r.yakalanan, r.kesinti,
    Math.round(r.toplam), saat);
}
console.log('\n2. bir ust duzene gecmenin birim cabaya dusen risk azalmasi');
for (let i = 1; i < sat.length; i += 1) {
  const d = sat[i - 1].r.toplam - sat[i].r.toplam, s = sat[i].saat - sat[i - 1].saat;
  console.log(`   ${sat[i - 1].ad} -> ${sat[i].ad}: ${Math.round(d)} rb / ${s} saat = ` +
    `${(d / s).toFixed(0)} rb/saat`);
}

// Iki yollu duzen: istismari erken hazir olan duyuru kisa pencereye, otekiler uzuna.
let en = null;
for (let esik = 2; esik <= 20; esik += 1)
  for (let k = 1; k <= 12; k += 1)
    for (let u = k; u <= 30; u += 1) {
      const r = olc((x) => (x.istismar <= esik ? k : u));
      if (!en || r.toplam < en.r.toplam) en = { esik, k, u, r };
    }
const B = [-38, 11, 10, 11, 11];
console.log('\n3. tek pencere yerine iki yollu duzen (kapisiz)');
y(B, 'duzen', 'yakalanan', 'kesinti', 'toplam rb');
const t9 = olc(() => enIyiTek('kapisiz'));
y(B, `tek pencere ${enIyiTek('kapisiz')} gun`, t9.yakalanan, t9.kesinti, Math.round(t9.toplam));
y(B, `iki yol: <=${en.esik} gun -> ${en.k}, digeri -> ${en.u}`, en.r.yakalanan, en.r.kesinti,
  Math.round(en.r.toplam));

// Siniflandirma hatasi: esige en yakin n duyuru ters yola konur.
const sirali = [...DUYURU].sort((a, b) =>
  Math.abs(a.istismar - en.esik) - Math.abs(b.istismar - en.esik) || a.no - b.no);
console.log('\n4. iki yolu ayiran karar yanlissa');
y(B, 'ters yola konan duyuru', 'yakalanan', 'kesinti', 'toplam rb');
for (const n of [0, 4, 12]) {
  const ters = new Set(sirali.slice(0, n).map((x) => x.no));
  const r = olc((x) => ((x.istismar <= en.esik) !== ters.has(x.no) ? en.k : en.u));
  y(B, `${n} duyuru`, r.yakalanan, r.kesinti, Math.round(r.toplam));
}
1. uc degisiklik duzeni, her biri kendi en iyi penceresinde
duzen         gecikme     hata  pencere  yakalanan  kesinti     toplam        onay
                  gun  carpani      gun       acik    olayi         rb       saati
kapisiz             0     1.00        9         26       29     207637           0
hafif onay          2     0.60        6         28       26     154560         360
tam onay            5     0.35        5         30       17     109557        1200

2. bir ust duzene gecmenin birim cabaya dusen risk azalmasi
   kapisiz -> hafif onay: 53078 rb / 360 saat = 147 rb/saat
   hafif onay -> tam onay: 45002 rb / 840 saat = 54 rb/saat

3. tek pencere yerine iki yollu duzen (kapisiz)
duzen                                   yakalanan   kesinti  toplam rb
tek pencere 9 gun                              26        29     207637
iki yol: <=11 gun -> 3, digeri -> 19           30        28     130159

4. iki yolu ayiran karar yanlissa
ters yola konan duyuru                  yakalanan   kesinti  toplam rb
0 duyuru                                       30        28     130159
4 duyuru                                       26        22     155943
12 duyuru                                      23        19     199971

İlk tablo beklenmedik bir yönde okunuyor. Tam onay kapısı her değişikliğe beş günlük bir gecikme ekliyor, buna karşın en iyi penceresi kapısız düzeninkinden kısadır (5 güne karşı 9) ve yakalanan açık sayısı daha yüksektir (30’a karşı 26). Nedeni ikinci sütundadır: kapı hata oranını 0,35 ile çarptığı için bir gün kısaltmanın kesinti bedeli düşer, dolayısıyla kısaltma daha uzun süre kârlı kalır. Onay kapısının bedeli gün olarak değil, saat olarak ödenir.

İkinci blok o saati sayıyor. Kapısız düzenden hafif onaya geçmek 53.078 rb kazandırıyor ve 360 saat tutuyor: saat başına 147 rb. Hafif onaydan tam onaya geçmek 45.002 rb kazandırıyor ve 840 saat tutuyor: 54 rb/saat. Toplam riske bakan sıralama tam onayı öne alır; birim çabaya düşen risk azalmasına bakan sıralama hafif onayda durur. Sıralama ölçü değişince değişiyor, ve hangisinin doğru olduğu 840 saatin başka nerede kullanılabileceğine bağlıdır — önceki dersteki düzeltme kapasitesi açıklığı bu saatlerin bir alıcısıdır.

Üçüncü blok saat harcamadan bir kazanç gösteriyor. Duyuruları ikiye ayırmak — istismarı on bir gün içinde hazır olanlara üç günlük, ötekilere on dokuz günlük pencere — toplamı 207.637’den 130.159 rb’ye indiriyor. Kazanç sıralamanın kendisinden geliyor: kısa pencerenin pahalı sınama bedeli yalnız gereken duyurulara ödeniyor.

Dördüncü blok bu kazancın neye dayandığını ölçüyor. Eşiğe en yakın dört duyuru ters yola konduğunda toplam 155.943’e çıkıyor — kazancın üçte biri gidiyor. On iki duyuru yanlış sınıflandırıldığında 199.971 kalıyor ve tek pencereye göre kazanç yalnız yüzde on. Aynı satırlarda ikinci bir şey oluyor: kesinti olayı 28’den 19’a iniyor. Yalnız plan dışı kesinti sayısını izleyen bir program bu bozulmayı bir iyileşme olarak okur.

Özet

  • Pencere beş günden on beş güne uzarken maruziyet 48.357 rb’den 212.485’e çıkıyor, kesinti olayı 50’den 9’a iniyor; iki sütun ters yönde hareket ettiği için hiçbiri tek başına karar taşımaz.
  • İki eğri dokuzuncu günde kesişiyor: 10’dan 9’a inmek 16.286 rb kazandırıp 14.400 rb’ye mal oluyor, 9’dan 8’e inmek 14.704 rb kazandırıp 18.000 rb’ye. Toplam 207.637 rb ile orada en düşüktür.
  • Yakalanan açık sayısı 12–15 gün arasında sabit kalırken maruziyet yüzde 36 artıyor: kesikli ölçüt pencere uzadıkça duyarlılığını yitirir.
  • En iyi pencere kesintinin bedeliyle birlikte kayıyor: 900 rb’de 1 gün, 14.000 rb’de 17 gün. Pencere açığın değil, bedelin bir sonucudur.
  • Tam onay kapısı beş gün gecikme eklediği hâlde en iyi penceresi kapısız düzeninkinden kısadır (5’e karşı 9) ve daha çok açık yakalar (30’a karşı 26); bedeli 1.200 onay saatidir.
  • Toplam riske göre tam onay, saat başına kazanca göre hafif onay önde (147’ye karşı 54 rb/saat). İki yollu pencere toplamı 130.159’a indiriyor, ama on iki duyuruluk sınıflandırma hatası kazancın onda dokuzunu geri alıyor ve bunu yaparken kesinti sayısını düşürüyor.

Sonraki Adım

İki ders de bir kuyruk ve bir takvim üzerinde çalıştı: kalemler sıraya girdi, pencereler ayarlandı ve her ikisinde de değişen şey bir yapılandırmaydı. Yapılandırma değiştiğinde değişmiş kalır. Bir sonraki dersin konusu ise ayarlandığı yerde durmayan tek kalemdir: insan davranışı. Bir eğitim oturumu bir ölçütü yükseltir, sonra ölçüt haftalar içinde eski değerine geri döner ve program aynı harcamayı yeniden yapmak zorunda kalır. Ölçülecek şey eğitimin ne kadar iyi olduğu değil, kazancın hangi haftada eridiğidir — ve bu erime her grupta aynı hızda olmadığı için, kıt eğitim saatinin hangi gruba gideceği yine bir sıralama sorusudur.

İlerlemeni kaydetmek ve not almak için Giriş yap

Notlarım

Not almak için giriş yapmalısın.

Aramak için yazmaya başlayın.

↑↓ Esc gezin · aç · kapat