İçeriğe geç
academia.sh

Ders 02 / 10

Çevik Çerçeveler

Yinelemeli teslimat çerçevelerinin ortak yapısı ve yineleme uzunluğunun taranması: bir haftadan altı haftaya kadar her uzunlukta akış süresi, geri bildirim gecikmesi, yeniden iş, törene giden süre ve yarım kalan iş kalemi sayılır.

İçindekiler

Önceki ders parti büyüklüğünün ne kadar güçlü bir değişken olduğunu gösterdi: on sekiz kalemlik tek parti ile üç kalemlik altı parti arasında bekleme on üç kat, geri bildirim gecikmesi dört kat değişti. Ama o partiler elle seçilmişti. Yinelemeli teslimat çerçeveleri tam olarak bu seçimi kurumsallaştırır — parti büyüklüğünü sabit bir süreye bağlarlar ve o süreyi bir ritim hâline getirirler.

Bu ders çerçeveleri ortak yapısıyla ele alır, çünkü ölçülebilir olan yapıdır: bir biriktirme listesi, sabit uzunlukta bir yineleme, yinelemenin başında bir planlama ve sonunda bir gözden geçirme töreni, ve işi yapan ile kabul edeni ayıran bir rol ayrımı. Bu dört öge seçildiğinde geri kalan sayılar kendiliğinden çıkar. Through-line bölgesel kütüphane ağıdır ve kurgudur; bu derste ağın ödünç, ücretlendirme, üyelik ve şube servislerine gelen değişiklik istekleri tek bir biriktirme listesinde toplanır.

Ortak İskelet

Aşağıdaki blok bir modeldir, ölçüm değil. Bir çerçevenin adını değil, iskeletini koşturur.

SM7 — otuz iş kalemi bir üreteçle türetilir, üreteç kendi yazılır ve tohum görünürdür. Aynı kalem kümesi bütün yineleme uzunluklarında kullanılır; uzunluklar arası fark yalnız ritimden gelir. Her kalemin bir boyutu (2–8 adam-gün), bir geliş günü ve aynı veriye dokunduğu önceki kalemler vardır.

SM8 — ekip dört kişidir, günde 4 adam-gün iş çıkarır. Yineleme başına tören maliyeti 4 + L adam-gündür: sabit bir planlama ve değerlendirme yükü artı yineleme uzunluğuyla büyüyen bir gözden geçirme payı. Bu, kısa yinelemenin bedelini taşıyan tek sayıdır.

SM9 — kabul yalnızca gözden geçirme töreninde verilir. Rol ayrımının ölçülebilir sonucu budur: işi yapan ile kabul eden farklı kişilerdir ve kabul eden yalnız törende masadadır. Bir kalem yinelemenin ilk günü bittiğinde bile kabulünü yinelemenin son günü alır.

SM10 — kusur o kabul anında görünür. Yeniden işin boyutu kalemin üçte biri artı, kusurlu kalem bittikten sonra aynı yinelemede tamamlanmış ve ona dokunan her kalem için 1 adam-gündür. Uzun yinelemede kusurlu kalemden sonra daha çok kalem tamamlandığı için bu ek büyür.

SM11 — yinelemeye sığmayan kalem yarım kalır ve sonraki yinelemede 1 adam-günlük bir geçiş maliyeti öder. Kısa yinelemenin ikinci bedeli budur.

// cevik.mjs — yinelemeli teslimatin ortak iskeleti (model); tek uzunlukta ayrintili kosum
import { writeFileSync } from "node:fs";

const KISI = 4;        // ekip; gunde KISI adam-gun is cikar
const GECIS = 1;       // yarim kalan kalemin sonraki yinelemede odedigi geri donus maliyeti
const toren = (L) => 4 + L;                 // planlama + gozden gecirme + degerlendirme (adam-gun)

// SM7: uretec kendi yazilir, tohum gorunur; kalem kumesi butun yineleme uzunluklarinda aynidir.
let tohum = 20250401;
const rast = () => (tohum = (tohum * 1103515245 + 12345) % 2147483648) / 2147483648;
const KALEM = [...Array(30)].map((_, no) => ({
  no, boyut: 2 + Math.floor(rast() * 7), gelis: Math.floor(rast() * 40),
  kusur: rast() < 0.35, bagli: [],
}));
for (const k of KALEM)                      // ayni veriye dokunan onceki kalemler
  for (const o of KALEM) if (o.no < k.no && rast() < 0.18) k.bagli.push(o.no);

function kostur(L) {
  const gun = 5 * L, net = KISI * gun - toren(L);
  const havuz = KALEM.map((k) => ({ ...k, kalan: k.boyut, tamam: -1, baslandi: false, yeniden: false }));
  const kayit = [], gecikmeler = [];
  let n = 0, yarim = 0, gecis = 0, torenToplam = 0, yeniden = 0;

  while (havuz.some((k) => k.tamam < 0)) {
    const bas = n * gun, bit = bas + gun - 1;          // gozden gecirme toreni son gunde
    torenToplam += toren(L);
    let kap = net, harcanan = 0;
    const aday = havuz.filter((k) => k.tamam < 0 && k.gelis <= bas)
      .sort((a, b) => (b.baslandi - a.baslandi) || (a.gelis - b.gelis) || (a.no - b.no));
    const biten = [];
    let calisilan = 0, buYarim = 0;
    for (const k of aday) {                              // planlamada kapasite kadari cekilir
      const ek = k.baslandi ? GECIS : 0;
      if (kap <= ek) break;
      if (ek) { kap -= ek; harcanan += ek; gecis += ek; }
      k.baslandi = true; calisilan += 1;
      const al = Math.min(kap, k.kalan);
      k.kalan -= al; kap -= al; harcanan += al;
      if (k.kalan === 0) { k.tamam = bas + Math.min(gun - 1, Math.floor(harcanan / KISI)); biten.push(k); }
      else { yarim += 1; buYarim += 1; }
    }
    // SM10: kabul yalnizca gozden gecirme toreninde verilir; kusur o gun gorunur.
    let bulunan = 0;
    for (const k of biten) {
      if (!k.kusur || k.yeniden) continue;
      const dokunan = biten.filter((x) => x.bagli.includes(k.no) && x.tamam >= k.tamam).length;
      const boy = Math.ceil(k.boyut / 3) + dokunan;
      havuz.push({ no: 100 + k.no, boyut: boy, kalan: boy, gelis: bit + 1, tamam: -1,
                   baslandi: false, kusur: false, yeniden: true, bagli: [] });
      yeniden += boy; bulunan += 1;
      gecikmeler.push(bit - k.tamam);
    }
    kayit.push({ n: n + 1, bas, bit, cekilen: calisilan, biten: biten.length,
                 yarim: buYarim, bekleyen: aday.length - calisilan, bulunan });
    n += 1;
  }
  const asil = havuz.filter((k) => !k.yeniden);
  const ort = (a) => a.reduce((x, y) => x + y, 0) / a.length;
  const temel = KALEM.reduce((a, k) => a + k.boyut, 0);
  return { L, yineleme: n, gun: Math.max(...havuz.map((k) => k.tamam)) + 1,
    akis: ort(asil.map((k) => k.tamam - k.gelis + 1)), gecikme: ort(gecikmeler),
    kusurlu: gecikmeler.length, yeniden, yarim, gecis, toren: torenToplam,
    temel, toplam: temel + yeniden + gecis + torenToplam, kayit };
}

const TARAMA = [1, 2, 3, 4, 6].map(kostur);
writeFileSync("tarama.json", JSON.stringify(TARAMA.map(({ kayit, ...r }) => r)));

console.log(`is kalemi: ${KALEM.length}, temel is: ${KALEM.reduce((a, k) => a + k.boyut, 0)} adam-gun, ` +
  `kusurlu kalem: ${KALEM.filter((k) => k.kusur).length}, ` +
  `bagimlilik bagi: ${KALEM.reduce((a, k) => a + k.bagli.length, 0)} (tohum ${20250401})`);

const iki = TARAMA[1];
console.log(`\niki haftalik yineleme, ayrintili kosum (toren ${toren(2)} adam-gun, ` +
  `net kapasite ${KISI * 10 - toren(2)} adam-gun):`);
console.log(`${"yineleme".padStart(9)}${"is gunu".padStart(9)}${"cekilen".padStart(9)}` +
  `${"biten".padStart(7)}${"yarim kalan".padStart(13)}${"listede kalan".padStart(15)}` +
  `${"bulunan kusur".padStart(15)}`);
for (const r of iki.kayit)
  console.log(`${String(r.n).padStart(9)}${`${r.bas}-${r.bit}`.padStart(9)}` +
    `${String(r.cekilen).padStart(9)}${String(r.biten).padStart(7)}` +
    `${String(r.yarim).padStart(13)}${String(r.bekleyen).padStart(15)}` +
    `${String(r.bulunan).padStart(15)}`);
console.log(`toplam ${iki.gun} is gunu, ${iki.yineleme} yineleme; ` +
  `${iki.kusurlu} kusur ortalama ${iki.gecikme.toFixed(1)} is gunu gecikmeyle bulundu`);
is kalemi: 30, temel is: 152 adam-gun, kusurlu kalem: 8, bagimlilik bagi: 75 (tohum 20250401)

iki haftalik yineleme, ayrintili kosum (toren 6 adam-gun, net kapasite 34 adam-gun):
 yineleme  is gunu  cekilen  biten  yarim kalan  listede kalan  bulunan kusur
        1      0-9        1      1            0              0              0
        2    10-19        8      8            0              5              1
        3    20-29        8      7            1              3              2
        4    30-39        7      6            1              3              1
        5    40-49        8      8            0              4              2
        6    50-59        6      6            0              0              2
        7    60-69        2      2            0              0              0
toplam 62 is gunu, 7 yineleme; 8 kusur ortalama 5.5 is gunu gecikmeyle bulundu

İki haftalık ritimde ilk yineleme neredeyse boştur: sıfırıncı gün biriktirme listesinde yalnız bir kalem vardır, sonradan gelenler bir sonraki planlamayı bekler. Üçüncü yinelemeden itibaren listede kalan üç ile beş arasında bir kuyruk oluşur ve her yinelemede bir kalem yarım kalır. Sekiz kusurun tamamı gözden geçirme törenlerinde bulunur ve ortalama 5,5 iş günü bekledikten sonra görünür.

Yineleme Uzunluğunun Taranması

Ritim tek başına bir değer değil, bir ayardır. Aşağıdaki blok aynı otuz kalemi bir, iki, üç, dört ve altı haftalık yinelemelerde koşturur.

SM12 — iki maliyet ters yönde büyür. Kısa yineleme gecikmeyi ve yarım kalan kalemin süresini düşürür ama tören payını yükseltir; uzun yineleme tören payını düşürür ama kalemi hem başlamak için hem kabul için bekletir.

// tarama.mjs — cevik.mjs'in yazdigi tarama sonucunu okur; yineleme uzunlugu taranir
import { readFileSync } from "node:fs";

const T = JSON.parse(readFileSync("tarama.json", "utf8"));
const tablo = (baslik, satir, ust) => {
  const yaz = (h) => console.log(h.map((c, i) => String(c).padStart(baslik[i][1])).join(""));
  console.log(); console.log(ust); yaz(baslik.map((b) => b[0])); satir.forEach(yaz);
};

tablo([["uzunluk", 8], ["yineleme", 10], ["is gunu", 9], ["ort. akis suresi", 18],
       ["ort. gecikme", 14], ["yeniden is", 12], ["yarim kalan", 13]],
  T.map((r) => [`${r.L} hafta`, r.yineleme, r.gun, r.akis.toFixed(1), r.gecikme.toFixed(1),
                r.yeniden, r.yarim]),
  "yineleme uzunlugu taramasi (akis suresi ve gecikme is gunu):");

tablo([["uzunluk", 8], ["temel is", 10], ["toren", 8], ["gecis", 7], ["yeniden is", 12],
       ["toplam", 9], ["toren payi", 12]],
  T.map((r) => [`${r.L} hafta`, r.temel, r.toren, r.gecis, r.yeniden, r.toplam,
                `%${((100 * r.toren) / r.toplam).toFixed(1)}`]),
  "is gucunun dagilimi (adam-gun):");

// SM12: iki maliyet ters yonde buyur; uzunlugu bir kademe artirmanin net bedeli asagida.
const im = (x, d = 0) => (x > 0 ? "+" : "") + x.toFixed(d);
console.log(`\nbir kademe uzatmanin bedeli:`);
for (let i = 1; i < T.length; i++) {
  const a = T[i - 1], b = T[i];
  console.log(`  ${a.L} -> ${b.L} hafta: toren ${im(b.toren - a.toren)}, ` +
    `gecis ${im(b.gecis - a.gecis)}, yeniden is ${im(b.yeniden - a.yeniden)}, ` +
    `net ${im(b.toplam - a.toplam)} adam-gun; akis suresi ${im(b.akis - a.akis, 1)}, ` +
    `gecikme ${im(b.gecikme - a.gecikme, 1)} is gunu`);
}
const enAz = T.reduce((a, b) => (b.toplam < a.toplam ? b : a));
const enHizli = T.reduce((a, b) => (b.akis < a.akis ? b : a));
console.log(`\nen az is gucu ${enAz.L} haftada (${enAz.toplam} adam-gun), ` +
  `en kisa akis suresi ${enHizli.L} haftada (${enHizli.akis.toFixed(1)} is gunu)`);
yineleme uzunlugu taramasi (akis suresi ve gecikme is gunu):
 uzunluk  yineleme  is gunu  ort. akis suresi  ort. gecikme  yeniden is  yarim kalan
 1 hafta        13       63              12.5           2.3          19            8
 2 hafta         7       62              13.8           5.5          21            2
 3 hafta         5       63              17.6           4.9          20            1
 4 hafta         5       81              21.6          10.6          22            1
 6 hafta         4       93              31.2          17.0          23            0

is gucunun dagilimi (adam-gun):
 uzunluk  temel is   toren  gecis  yeniden is   toplam  toren payi
 1 hafta       152      65      8          19      244       %26.6
 2 hafta       152      42      2          21      217       %19.4
 3 hafta       152      35      1          20      208       %16.8
 4 hafta       152      40      1          22      215       %18.6
 6 hafta       152      40      0          23      215       %18.6

bir kademe uzatmanin bedeli:
  1 -> 2 hafta: toren -23, gecis -6, yeniden is +2, net -27 adam-gun; akis suresi +1.3, gecikme +3.3 is gunu
  2 -> 3 hafta: toren -7, gecis -1, yeniden is -1, net -9 adam-gun; akis suresi +3.8, gecikme -0.6 is gunu
  3 -> 4 hafta: toren +5, gecis 0, yeniden is +2, net +7 adam-gun; akis suresi +4.0, gecikme +5.8 is gunu
  4 -> 6 hafta: toren 0, gecis -1, yeniden is +1, net 0 adam-gun; akis suresi +9.6, gecikme +6.4 is gunu

en az is gucu 3 haftada (208 adam-gun), en kisa akis suresi 1 haftada (12.5 is gunu)

İki Ölçü Farklı Uzunluğu Gösterir

Tarama tek bir kazanan üretmez, iki ayrı kazanan üretir. Akış süresi bir haftada en kısadır (12,5 iş günü) ve uzunluk arttıkça tek yönde bozulur: altı haftada 31,2 iş gününe, iki buçuk katına çıkar. Geri bildirim gecikmesi de aynı yöndedir — 2,3 iş gününden 17,0 iş gününe, yedi katına. Sebebi ikilidir: kalem hem başlamak için bir sonraki planlamayı, hem kabul için yinelemenin sonunu bekler ve iki bekleme de yineleme uzunluğuyla doğru orantılıdır.

Toplam iş gücü ise üç haftada en azdır (208 adam-gün). Bir haftalık ritim 244 adam-gün harcar ve bunun 65’i törendir — toplamın %26,6’sı. Aynı ritim sekiz kez yarım kalan kalem üretir ve 8 adam-gün geçiş maliyeti öder; altı haftalık ritimde hiç yarım kalan yoktur. Bir haftadan iki haftaya çıkmak 23 adam-gün tören ve 6 adam-gün geçiş tasarrufu sağlar, karşılığında akış süresine yalnız 1,3 iş günü ekler — bu kademe ucuzdur. Üç haftadan dört haftaya çıkmak ise 7 adam-gün ekler ve akış süresine 4,0 iş günü bindirir; bu kademede kazanılacak bir şey kalmamıştır.

Yeniden iş sayısı beklenenden az hareket eder: 19’dan 23 adam-güne, yalnızca beşte bir oranında. Kusurlu kalemin ardından tamamlanan bağlı kalem sayısı uzun yinelemede artar, ama otuz kalemlik bir kümede bu ek küçük kalır. Uzun yinelemenin asıl bedeli yeniden işin hacmi değil, gecikmenin kendisidir; iki hafta ile üç hafta arasında yeniden işin bir birim azalması da bu gürültünün içindedir ve bir eğilim olarak okunmamalıdır.

İş günü sütunu ayrı bir uyarı taşır: bir haftalık ritim 63 iş gününde, iki haftalık ritim 62 iş gününde biter. Kısa yineleme akış süresini kısaltır ama işin tamamını daha erken bitirmez, çünkü kaybettiği kapasiteyi törene verir.

Özet

  • Yinelemeli çerçeveler ortak dört ögeye indirgendi — biriktirme listesi, sabit uzunlukta yineleme, planlama ve gözden geçirme töreni, kabul yetkisini ayıran rol ayrımı — ve bu iskelet koşturuldu.
  • Aynı 30 kalem beş uzunlukta koşturuldu; akış süresi bir haftada 12,5, altı haftada 31,2 iş günü, geri bildirim gecikmesi 2,3’ten 17,0 iş gününe çıktı.
  • Toplam iş gücü üç haftada en azdır (208 adam-gün); bir haftalık ritim 244 adam-gün harcar ve bunun %26,6’sı törendir, ayrıca 8 kalemi yarım bırakıp 8 adam-gün geçiş maliyeti öder.
  • İki ölçü iki farklı uzunluğu gösterdiği için taramadan tek bir en iyi çıkmaz: akış süresi bir haftayı, toplam iş gücü üç haftayı işaret eder.
  • Yeniden iş 19’dan 23 adam-güne çıkarak en az hareket eden sütundur; uzun yinelemenin bedeli yeniden işin hacminden çok gecikmenin kendisidir.

Sonraki Adım

Bu dersin bütün ölçümleri sabit bir ritim varsayımına dayandı: iş kalemi ancak bir sonraki planlamada başlar, ancak yinelemenin sonunda kabul edilir. Ritim kaldırıldığında elde kalan tek denetim aracı aynı anda kaç kalemin açık olduğudur. Sonraki ders bu sınırı tarar: iş sınırı birden yukarı çıktıkça çevrim süresi ve akış süresinin ne kadarının bekleme olduğu nasıl değişiyor, iş çıkarma hangi sınırdan sonra artmayı bırakıyor ve sınır fazla düşük tutulduğunda ne kayboluyor. Aynı koşumda akış ölçütleri tanımlanır — teslim süresi, çevrim süresi ve iş çıkarma — ve her birinin hangi kararı verdirdiği ayrı ayrı yazı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