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.