İçeriğe geç
academia.sh

Ders 02 / 12

Duvar Üzerinden Atma

Ayrık ekiplerin ürettiği gecikme ve risk: aynı 18 değişikliğin taşıdığı 29 bağlam kaleminin 21'inin yazılı olmaması, ayrık düzende 14 kalemin sınırda düşüp 10 sınırdan dönüş ile 4 üretim hatası üretmesi, paylaşılan sorumlulukta düşen kalemin 5'e, dönüşün 3'e, üretim hatasının 2'ye inmesi ve geri dönüş oranının %22'den %11'e düşmesi, buna karşılık dağıtım sıklığının 9,5'ten 7,9'a, iç geçiş beklemesinin 8,1'den 12,2 adıma ve kurtarma süresinin 61,0'dan 65,0 adıma çıkması, sessiz bağlam taşıyan 7 değişiklikte iki düzenin de aynı 3 dönüş ve 2 hatayı üretmesi.

İçindekiler

Önceki ders gözlem alanının bölünmesini ölçtü: yirmi iki olgunun dördü sahibine hiç ulaşmadı, üç yüzeyin paylaşılması ulaşma süresini 7,0 adımdan 5,0 adıma indirdi. Bölünen yalnız gözlem değildir. Bir değişikliğin fikirden üretime giden yolu da bölünmüştür ve değişiklik o bölünmenin üstünden atılır.

Duvar üzerinden atma, bir değişikliğin taşıdığı bağlam yazıya dökülmeden bir ekip sınırının ötesine verilmesidir. Atılan şey değişikliğin kendisi değil, onun hakkında bilinenlerdir: hangi ayarın değiştiği, hangi veri biçiminin beklendiği, geri almanın nasıl yapılacağı. Bu ders aynı değişiklik kümesini iki düzende koşturur ve sınırda düşen bağlamı sayar. M20/K05 el değiştirmeyi bir iş kaleminin ekipler arası yolunda saymıştı; buradaki ölçek başkadır — sayılan şey bir değişikliğin fikirden üretime giden yolundaki ekip sınırı ve o sınırda düşen bağlamdır.

Değişikliğin Yolu ve Taşıdığı Bağlam

Örnek yine kurgu bölgesel ölçüm ağıdır; ağ da ekipler de kurgudur. KA7: bir değişikliğin yolu yedi adımdır — tanım, yazma, gözden geçirme, sınama kurulumu, kabul sınaması, üretim kurulumu, üretim doğrulaması; ayrık düzende son dört adım işleten ekiptedir. KA8: on sekiz değişiklik sekizer adım arayla akışa girer ve her ekip aynı anda tek değişiklik yürütür. KA9: her değişiklik bağlam kalemi taşır; kalemin durduğu yer sınıfına bağlıdır — ayar, veri biçimi, bağımlılık ve geri alma yazan ekipte, zamanlama ile kaynak işleten ekipte durur. KA10: kalem üç durumdan birindedir: yazılı (her rolde elde), sorulabilir (yazılı değil ama ötekine sorulabilir), sessiz (yazılı değil ve kimse eksik olduğunu bilmiyor). KA11: adımı yürüten rol kalemin durduğu rol değilse ve kalem yazılı değilse, paylaşılan düzende sorulabilir kalem 2 adım sorma bedeliyle geçer, sessiz kalem düşer; ayrık düzende ikisi de düşer. Düşen kalem o koşumda öğrenilir. KA12: düşen kalem üretim doğrulamasından önceyse değişiklik gözden geçirmeye döner ve 3 adım yeniden iş yazar; üretim doğrulamasındaysa üretimde hata olur, 4 adım tutar ve düzeltme yolu baştan yürür. Ekip sınırı geçişi 5, iç geçiş 1 adım devir beklemesi yazar.

Paylaşılan düzende sınama kurulumu ile üretim doğrulaması yazan ekibe geçer. Yol ve iki düzen süreç içi bir modeldir; gerçek bir hat ya da değişiklik kaydı yoktur.

// duvar/akis.mjs — bir degisikligin fikirden uretime giden yolu (model): gercek bir hat ya da
// degisiklik kaydi yok, adimlar veri yapisidir. Rastgelelik yok.

export const SINIR = 5, IC = 1, SORMA = 2, YENIDEN = 3, KURTARMA = 4, VARIS = 8, LIMIT = 900;
export const DONUS = 2;                       // sinirdan donen degisiklik gozden-gecirmeye doner
export const ROL = ["yazan", "isleten"];

export const ADIM = [["tanim", "yazan", 2], ["yazma", "yazan", 0], ["gozden-gecirme", "yazan", 2],
  ["sinama-kurulumu", "isleten", 2], ["kabul-sinamasi", "isleten", 3],
  ["uretim-kurulumu", "isleten", 2], ["uretim-dogrulama", "isleten", 2]]
  .map(([ad, rol, sure]) => ({ ad, rol, sure }));
export const PAYLASILAN = new Set(["sinama-kurulumu", "uretim-dogrulama"]);
const KISA = { k: "sinama-kurulumu", s: "kabul-sinamasi", u: "uretim-kurulumu",
  d: "uretim-dogrulama" };
// baglam sinifinin kaynagi: ayar/veri-bicimi/bagimlilik/geri-alma yazan ekipte, zamanlama ve
// kaynak isleten ekipte durur. Kalem durumu: y yazili, h yazili degil ama sorulabilir,
// x yazili degil ve sessiz (kimse eksik oldugunu bilmiyor).
export const SAHIP = { ayar: "yazan", "veri-bicimi": "yazan", bagimlilik: "yazan",
  "geri-alma": "yazan", zamanlama: "isleten", kaynak: "isleten" };

// degisiklik: ad, yazma adimi, tasidigi baglam kalemleri (sinif/gerektigi adim/durum)
export const DEGISIKLIK = `
  d01  5  ayar/k/h         veri-bicimi/s/y
  d02  3  zamanlama/u/h
  d03  6  bagimlilik/k/y   kaynak/u/h
  d04  4  ayar/s/h         geri-alma/d/h
  d05  7  veri-bicimi/k/x
  d06  3  zamanlama/d/x    ayar/u/y
  d07  5  kaynak/s/y       bagimlilik/u/h
  d08  4  geri-alma/d/h
  d09  6  ayar/k/h         zamanlama/s/h
  d10  3  veri-bicimi/u/h
  d11  5  bagimlilik/d/x   kaynak/k/y
  d12  4  ayar/s/y
  d13  6  zamanlama/k/x    geri-alma/u/h
  d14  3  kaynak/d/x
  d15  5  veri-bicimi/s/h  bagimlilik/k/y
  d16  4  ayar/u/x         zamanlama/d/y
  d17  6  geri-alma/s/h
  d18  3  kaynak/k/x       veri-bicimi/d/h`
  .trim().split("\n").map((r) => r.trim().split(/\s+/)).map(([ad, boyut, ...k]) => ({
    ad, boyut: +boyut, kalem: k.map((p) => { const [sinif, a, y] = p.split("/");
      return { sinif, adim: KISA[a], durum: y, sahip: SAHIP[sinif] }; }) }));

export function kos(duzen) {
  const adim = ADIM.map((a) => ({ ...a,
    rol: duzen === "paylasilan" && PAYLASILAN.has(a.ad) ? "yazan" : a.rol }));
  const D = DEGISIKLIK.map((d, i) => ({ ...d, i, adim: 0, hazir: i * VARIS, ek: 0, gecis: null,
    bilinen: new Set(d.kalem.filter((k) => k.durum === "y").map((k) => k.sinif)),
    kayip: null, dusen: [], bitti: false, uretimBitis: null, hataAt: null,
    kurtarma: null, hata: false, donus: 0 }));
  const sunucu = { yazan: null, isleten: null };
  const S = { kayip: 0, donus: 0, uretimHata: 0, dagitim: 0, sorma: 0, yenidenIs: 0,
    sinirGecis: 0, sinirBekleme: 0, icGecis: 0, icBekleme: 0 };

  const ilerle = (d, hedef, t, ek) => {
    const sinirMi = adim[hedef].rol !== adim[d.adim].rol;
    if (sinirMi) { S.sinirGecis++; S.sinirBekleme += SINIR; d.gecis = "sinir"; }
    else { S.icGecis++; S.icBekleme += IC; d.gecis = "ic"; }
    d.hazir = t + (sinirMi ? SINIR : IC); d.adim = hedef; d.ek = ek;
  };

  const basla = (d, r) => {
    const a = adim[d.adim];
    let sure = (a.ad === "yazma" ? d.boyut : a.sure) + d.ek;
    d.ek = 0; d.kayip = null;
    for (const k of d.kalem.filter((k) => k.adim === a.ad && !d.bilinen.has(k.sinif))) {
      d.bilinen.add(k.sinif);                 // kalem her durumda burada ogrenilir
      if (k.sahip === r) continue;            // adimi yuruten rol kalemi zaten tasiyor
      if (duzen === "paylasilan" && k.durum === "h") {   // otekine sorulur, bedeli adimdir
        sure += SORMA; S.sorma += SORMA; continue;
      }
      S.kayip++; d.kayip = k; d.dusen.push(k);          // sinirda duser
    }
    d.kalan = sure;
  };

  const bitir = (d, t) => {
    const a = adim[d.adim];
    if (a.ad === "uretim-kurulumu") { S.dagitim++; if (d.uretimBitis === null) d.uretimBitis = t; }
    if (d.kayip) {
      const uretimde = a.ad === "uretim-dogrulama";
      if (uretimde) { S.uretimHata++; d.hata = true; d.hataAt = t; } else { S.donus++; d.donus++; }
      S.yenidenIs += uretimde ? KURTARMA : YENIDEN;
      return ilerle(d, DONUS, t, uretimde ? KURTARMA : YENIDEN);
    }
    if (d.adim < adim.length - 1) return ilerle(d, d.adim + 1, t, 0);
    if (d.hata && d.kurtarma === null) d.kurtarma = t - d.hataAt;
    d.bitti = true;
  };

  for (let t = 0; t < LIMIT; t++) for (const r of ROL) {
    if (sunucu[r] === null) {
      const aday = D.filter((d) => !d.bitti && d !== sunucu.yazan && d !== sunucu.isleten
        && d.hazir <= t && adim[d.adim].rol === r).sort((a, b) => a.hazir - b.hazir || a.i - b.i)[0];
      if (aday) {
        if (aday.gecis === "sinir") S.sinirBekleme += t - aday.hazir;
        else if (aday.gecis === "ic") S.icBekleme += t - aday.hazir;
        basla(aday, r); sunucu[r] = aday;
      }
    }
    const d = sunucu[r];
    if (d && --d.kalan === 0) { sunucu[r] = null; bitir(d, t + 1); }
  }
  return { D, S, pencere: Math.max(...D.map((d) => d.uretimBitis ?? 0)) };
}

export const ort = (a) => (a.length ? (a.reduce((s, v) => s + v, 0) / a.length).toFixed(1) : "-");

export function olc(duzen) {
  const { D, S, pencere } = kos(duzen);
  const oncu = D.map((d) => d.uretimBitis - d.i * VARIS);
  return { D, S, pencere,
    sinirGecis: S.sinirGecis, sinirBasinaBekleme: (S.sinirBekleme / S.sinirGecis).toFixed(1),
    icBasinaBekleme: (S.icBekleme / S.icGecis).toFixed(1), bilgiKaybi: S.kayip,
    sorma: S.sorma, sinirdanDonen: S.donus, uretimHata: S.uretimHata, yenidenIs: S.yenidenIs,
    onculSure: ort(oncu), dagitimSikligi: (100 * S.dagitim / pencere).toFixed(1),
    geriDonusOrani: (100 * D.filter((d) => d.hata).length / D.length).toFixed(0) + "%",
    kurtarma: ort(D.filter((d) => d.hata).map((d) => d.kurtarma)),
    bitmeyen: D.filter((d) => !d.bitti).length };
}

Dört teslimat ölçütü aynı koşumdan okunur: dağıtım sıklığı 100 adımda tamamlanan üretim kurulumu (yeniden dağıtımlar dahil), öncü süre değişikliğin akışa girişinden ilk kez üretime kurulmasına kadar geçen adım, geri dönüş oranı üretimde hata çıkaran değişikliğin payı, kurtarma süresi hatanın çıktığı andan düzeltmenin üretimde doğrulanmasına kadar geçen adımdır.

// duvar/olc.mjs — ayni 18 degisiklik iki duzende: sinir beklemesi, bilgi kaybi, uretim hatasi.
import { DEGISIKLIK, ADIM, PAYLASILAN, VARIS, olc, ort } from "./akis.mjs";

const yaz = (g, ...s) => console.log(s.map((v, i) =>
  (g[i] < 0 ? String(v).padEnd(-g[i]) : String(v).padStart(g[i]))).join(""));
const kalem = DEGISIKLIK.flatMap((d) => d.kalem);
const say = (f) => kalem.filter(f).length;
const R = { ayrik: olc("ayrik"), paylasilan: olc("paylasilan") };

console.log(`${DEGISIKLIK.length} degisiklik, ${ADIM.length} adim, ${kalem.length} baglam kalemi: ` +
  `${say((k) => k.durum === "y")} yazili, ${say((k) => k.durum === "h")} sorulabilir, ` +
  `${say((k) => k.durum === "x")} sessiz`);
console.log(`  kalemin durdugu yer: ` + ["yazan", "isleten"].map((r) =>
  `${r} ${say((k) => k.sahip === r)}`).join(", "));
console.log(`  ayrik: ${ADIM.filter((a) => a.rol === "isleten").length} adim isletende; ` +
  `paylasilan: ${[...PAYLASILAN].join(" ve ")} yazana gecer`);
console.log(`  penceresinde bitmeyen degisiklik: ayrik ${R.ayrik.bitmeyen}, ` +
  `paylasilan ${R.paylasilan.bitmeyen}`);

const A = [-31, 9, 13];
console.log("\n1. ayni degisiklik kumesi iki duzende");
yaz(A, "olcu", "ayrik", "paylasilan");
for (const [ad, k] of [["ekip siniri gecisi", "sinirGecis"],
  ["sinir basina bekleme (adim)", "sinirBasinaBekleme"],
  ["ic gecis basina bekleme (adim)", "icBasinaBekleme"],
  ["bilgi kaybi (dusen kalem)", "bilgiKaybi"], ["sorma maliyeti (adim)", "sorma"],
  ["sinirdan donen degisiklik", "sinirdanDonen"], ["uretimde cikan hata", "uretimHata"],
  ["yeniden is (adim)", "yenidenIs"]]) yaz(A, ad, R.ayrik[k], R.paylasilan[k]);

console.log("\n2. dort teslimat olcutu");
yaz(A, "olcut", "ayrik", "paylasilan");
for (const [ad, k] of [["dagitim sikligi (100 adimda)", "dagitimSikligi"],
  ["oncu sure (ort. adim)", "onculSure"], ["geri donus orani", "geriDonusOrani"],
  ["kurtarma suresi (ort. adim)", "kurtarma"], ["son degisikligin uretime girisi", "pencere"]])
  yaz(A, ad, R.ayrik[k], R.paylasilan[k]);

const B = [-18, 7, 12, 9, 13, 16];
console.log("\n3. kalem hangi adimda dustu (dusen: ayrik / paylasilan)");
yaz(B, "adim", "kalem", "yazilmamis", "yazan", "sessiz", "dusen");
for (const a of ADIM.filter((a) => a.rol === "isleten")) {
  const g = kalem.filter((k) => k.adim === a.ad), h = g.filter((k) => k.durum !== "y");
  const d = (dz) => R[dz].D.flatMap((x) => x.dusen ?? []).filter((k) => k.adim === a.ad).length;
  yaz(B, a.ad, g.length, h.length, h.filter((k) => k.sahip === "yazan").length,
    h.filter((k) => k.durum === "x").length, `${d("ayrik")} / ${d("paylasilan")}`);
}

const C = [-21, -12, 11, 16, 15];
console.log("\n4. degisiklik basina yol");
yaz(C, "degisiklik", "duzen", "oncu sure", "sinirdan donus", "uretim hatasi");
for (const [ad, f] of [["yalniz yazili", (d) => d.kalem.every((k) => k.durum === "y")],
  ["sorulabilir var", (d) => d.kalem.some((k) => k.durum === "h") &&
    !d.kalem.some((k) => k.durum === "x")],
  ["sessiz var", (d) => d.kalem.some((k) => k.durum === "x")]])
  for (const dz of ["ayrik", "paylasilan"]) {
    const g = R[dz].D.filter(f);
    if (!g.length) continue;
    yaz(C, dz === "ayrik" ? `${ad} (${g.length})` : "", dz,
      ort(g.map((d) => d.uretimBitis - d.i * VARIS)),
      g.reduce((s, d) => s + d.donus, 0), g.filter((d) => d.hata).length);
  }
18 degisiklik, 7 adim, 29 baglam kalemi: 8 yazili, 14 sorulabilir, 7 sessiz
  kalemin durdugu yer: yazan 19, isleten 10
  ayrik: 4 adim isletende; paylasilan: sinama-kurulumu ve uretim-dogrulama yazana gecer
  penceresinde bitmeyen degisiklik: ayrik 0, paylasilan 0

1. ayni degisiklik kumesi iki duzende
olcu                               ayrik   paylasilan
ekip siniri gecisi                    46           42
sinir basina bekleme (adim)         11.2         11.0
ic gecis basina bekleme (adim)       8.1         12.2
bilgi kaybi (dusen kalem)             14            5
sorma maliyeti (adim)                  0           12
sinirdan donen degisiklik             10            3
uretimde cikan hata                    4            2
yeniden is (adim)                     46           17

2. dort teslimat olcutu
olcut                              ayrik   paylasilan
dagitim sikligi (100 adimda)         9.5          7.9
oncu sure (ort. adim)               85.6         87.2
geri donus orani                     22%          11%
kurtarma suresi (ort. adim)         61.0         65.0
son degisikligin uretime girisi      275          267

3. kalem hangi adimda dustu (dusen: ayrik / paylasilan)
adim                kalem  yazilmamis    yazan       sessiz           dusen
sinama-kurulumu         8           5        3            3           3 / 2
kabul-sinamasi          7           4        3            0           3 / 0
uretim-kurulumu         7           6        4            1           4 / 1
uretim-dogrulama        7           6        4            3           4 / 2

4. degisiklik basina yol
degisiklik           duzen         oncu sure  sinirdan donus  uretim hatasi
yalniz yazili (1)    ayrik              93.0               0              0
                     paylasilan        115.0               0              0
sorulabilir var (10) ayrik              77.2               7              2
                     paylasilan         70.0               0              0
sessiz var (7)       ayrik              96.4               3              2
                     paylasilan        107.7               3              2

Sayılar ölçüm sınıfındadır; girdileri yukarıdaki varsayımlardır.

Sınırda Ne Düşüyor

Ayrık düzende on dört kalem sınırda düşer: yazan ekipte duran ve işleten ekibin yürüttüğü adımda gereken her yazılmamış kalem kaybolur. Sonucu on sınırdan dönüş, dört üretim hatası ve 46 adım yeniden iştir.

Paylaşılan sorumlulukta düşen kalem 5’e, sınırdan dönüş 3’e, üretim hatası 2’ye iner; karşılığında 12 adım sorma bedeli ödenir. Ama üçüncü tablo asıl değişimin bir yön değişimi olduğunu gösterir. Ayrık düzende düşenler yazan ekipte duran kalemlerdir: sınama kurulumunda 3, kabul sınamasında 3, üretim kurulumunda 4, üretim doğrulamasında 4. Paylaşılan düzende sınama kurulumu ile üretim doğrulaması yazan ekibe geçtiği için o adımlarda artık işleten ekipte duran kalemler düşer — zamanlama ve kaynak. Duvarı kaldırmak bilgi kaybını yok etmez, ters yöne çevirir; kalan beş kaybın tamamı işletenin bildiği ve yazanın bilmediği şeydir.

Dördüncü tablo ayrımı keskinleştirir. Sorulabilir bağlam taşıyan on değişiklikte paylaşılan düzen sınırdan dönüşü 7’den 0’a, üretim hatasını 2’den 0’a indirir ve öncü süreyi 77,2’den 70,0 adıma düşürür. Sessiz bağlam taşıyan yedi değişiklikte hiçbir şey değişmez: iki düzen de aynı 3 dönüşü ve aynı 2 hatayı üretir, üstelik öncü süre 96,4’ten 107,7 adıma çıkar. Sorma ancak eksik olduğu bilinen şey için işler.

Duvarı Kaldırmanın Bedeli

İkinci tablo dört ölçütü yan yana koyar. Geri dönüş oranı %22’den %11’e iner; paylaşılan düzenin kazandığı tek ölçüt budur. Dağıtım sıklığı 9,5’ten 7,9’a, öncü süre 85,6’dan 87,2 adıma, kurtarma süresi 61,0’dan 65,0 adıma gider. Dört ölçütün biri iyileşir, üçü bozulur.

Nedeni birinci tablonun üçüncü satırındadır: iç geçiş başına bekleme 8,1 adımdan 12,2 adıma çıkar. Paylaşılan düzende yazan ekip yedi adımın beşini yürütür ve darboğaz oraya taşınır. Ekip sınırı geçişi değişiklik başına 1’den 2’ye çıkmasına karşın toplamda 46’dan 42’ye iner, çünkü geri dönüş azalmıştır; sınır başına bekleme ise 11,2 adımdan 11,0 adıma, yani neredeyse hiç değişmez. Duvarı kaldırmak sınırı ucuzlatmaz, sınırdan geçen iş sayısını azaltır.

Farkın Saklandığı Yer

Bu derste fark yazılmamış bağlamda saklıdır: yirmi dokuz kalemin yirmi biri yazılı değildir — on dördü sorulabilir, yedisi sessiz. Bildirilmiş kısım yalnız sekiz kalemdir. On dördü ancak koşumda, düştüğü adımda görünür; yedisi düştüğünde bile nedeni görünmez, çünkü kimse o kalemin gerektiğini bilmemektedir.

Sinyalin kime kaç adımda ulaştığı da buradan okunur: düşen kalem üretim doğrulamasından önceyse sinyal yazan ekibe bir sınır geçişi ve ortalama 11,2 adım beklemeyle döner; üretim doğrulamasında düşerse aynı sinyal ortalama 61,0 adım sonra, üretimde çıkmış bir hata olarak ulaşır. Aynı eksik kalem, düştüğü adıma göre beş kattan fazla pahalıdır.

Özet

  • Aynı 18 değişikliğin taşıdığı 29 bağlam kaleminin 21’i yazılı değildir: 14’ü sorulabilir, 7’si sessiz.
  • Ayrık düzende 14 kalem sınırda düşer, 10 sınırdan dönüş ve 4 üretim hatası üretir, 46 adım yeniden iş yazar; paylaşılan sorumlulukta bunlar 5, 3, 2 ve 17 olur, karşılığında 12 adım sorma bedeli ödenir.
  • Kayıp yok olmaz, yön değiştirir: paylaşılan düzende düşen beş kalemin tamamı işleten ekipte duran zamanlama ve kaynak kalemleridir.
  • Dört ölçütten yalnız geri dönüş oranı iyileşir (%22 → %11); dağıtım sıklığı 9,5’ten 7,9’a, öncü süre 85,6’dan 87,2 adıma, kurtarma süresi 61,0’dan 65,0 adıma gider — darboğaz yazan ekibe taşınır (iç geçiş beklemesi 8,1 → 12,2 adım).
  • Sorulabilir bağlam taşıyan 10 değişiklikte paylaşılan düzen dönüşü 7’den 0’a indirir; sessiz bağlam taşıyan 7 değişiklikte aynı 3 dönüş ve 2 hata iki düzende de çıkar.

Sonraki Adım

İki düzen de aynı yol üzerinde ölçüldü; yolun kendisi sabit tutuldu. Oysa asıl soru bu yolun neresinde ne kadar durulduğudur. Sonraki ders yolu bir değer akışı haritası olarak kurar: her adım için işlem süresi, bekleme süresi ve ilk seferde doğru oranı ölçülür; toplam öncü sürenin ne kadarının katma değerli olduğu, en uzun beklemenin nerede durduğu ve bir adımı iyileştirmenin toplam süreye neden çoğu zaman yansımadığı sayılır.

İ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