---
title: 'Yaşam Döngüsü Modelleri'
source: 'https://academia.sh/tr/kurslar/surec-ve-ekip/yasam-dongusu-modelleri'
course: 'Süreç, Ekip ve Teslimat'
language: tr
updated: '2026-08-17T18:10:34+00:00'
license: 'CC BY-SA 4.0'
---

# Yaşam Döngüsü Modelleri

Şelale, V, spiral ve artımlı yaşam döngülerinin aynı on sekiz iş kalemi üzerinde koşturulması: el değiştirme, kapıda bekleme, geri bildirim gecikmesi ve yeniden iş sayılır, her modelin kazandığı yerde neyi kaybettiği yazılır.

Önceki kurs mimari kuralı bir nesneye çevirdi: kural yazıldı, denetime dönüştürüldü, yakaladığı ve
kaçırdığı sayıldı. O ölçümlerin tamamı bir şeyi sessizce dışarıda bıraktı. Kuralı yazan, denetimi
koşturan, yanlış alarm karşısında kuralı devre dışı bırakan ve bir sonraki değişikliği yapan
**insanlardır**; bu kişilerin hangi sırayla çalıştığı, işi kime devrettiği ve bir hatayı ne zaman
öğrendiği mimariye doğrudan yazılır.

Bu kursun ölçü birimi **iş kalemi**dir: bir değişiklik isteğinin doğduğu andan işletime geçtiği ana
kadarki yol. Her ders üçünü sayar — kalemin kaç sınır geçtiği ve her geçişte kaç tur beklediği, kaç
kalemin geri döndüğü ve neden, ekip sınırı ile modül sınırının örtüşmediği yerde bunların ne kadar
büyüdüğü. Through-line **bölgesel kütüphane ağıdır**: şube sistemleri, dışarıdan alınmış katalog,
içeride yazılmış ödünç ve ücretlendirme servisleri, ayrı bir üyelik sistemi ve belediyedeki kimlik
servisi. Kurgudur.

## Ölçülecek İş Kalemi Kümesi

Aşağıdaki blok bir **modeldir**, ölçüm değil: aynı iş kalemi kümesini dört yaşam döngüsünde
koşturulabilir hâle getiren bir veri yapısıdır.

**SM1 — on sekiz iş kalemi beş adımdan geçer ve tek bir ekip çalışır.** Her kalem her adımda 3 iş
birimi tüketir, ekip tur başına 9 iş birimi işler. Gerekçe: modeller ancak aynı iş yükü ve aynı
kapasite altında karşılaştırılabilir; farkı yaratan şey işin miktarı değil, **partileme** olmalıdır.

**SM2 — on kalemde bir kusur doğar, doğduğu adım ile türü girdi olarak bilinmektedir.** Türler
ayrılır: **eksik bilgi** (bir ayrıntı hiç sorulmamıştır), **yanlış sınır** (iki kalem aynı veriyi
farklı yerde tutar, hata ancak ikincisi yazılınca görünür), **geç öğrenilen kısıt** (kısıt yalnız
işletimde çıkar). Geri bildirim gecikmesi ancak bilinen bir kusur kümesine karşı sayılabilir.

**SM3 — partileme kuralı modelin kendisidir.** Şelale ve V tek parti koşar, spiral risk sırasına
göre üç döngüye, artımlı bağımlılık sırasına göre altı artıma böler.

**SM4 — kusurun bulunduğu adım modele göre değişir.** Eksik bilgi ile yanlış sınır sınamada, geç
öğrenilen kısıt işletimde görünür. V modelinde sınama tasarımı üretim adımıyla birlikte yapıldığı
için eksik bilgi **doğduğu adımda** göze çarpar. Bir kısıt işletimde öğrenildikten sonra **sonraki
partilerde** aynı kısıtı taşıyan kalem kusurlu doğmaz; aynı partidekiler çoktan yazılmıştır.

**SM5 — sabit maliyetler modele bağlıdır.** V modelinde ilk üç adım kalem başına 1 iş birimi daha
tüketir. Her partinin işletime alınması, kalem sayısından bağımsız 6 iş birimi tutar.

```js
// yasam-dongusu.mjs — ayni 18 is kalemini dort yasam dongusunde kosturur (model)
// kusur kodu: e eksik bilgi, s yanlis sinir, k gec ogrenilen kisit; rakam kusurun dogdugu adim
import { writeFileSync } from "node:fs";

const ADIM = ["cozumleme", "tasarim", "gerceklestirme", "sinama", "isletim"];
const BIRIM = 3;      // bir is kaleminin bir adimda tukettigi is birimi
const KAPASITE = 9;   // tur basina is birimi (tek ekip)
const YAYIM = 6;      // her partinin isletime alma yuku, kalem sayisindan bagimsiz

const KALEM = [
  "uye dogrulama ucu    |uyelik |2|e0",
  "katalog arama ucu    |katalog|1|-",
  "odunc kaydi olusturma|odunc  |2|s1 S1",
  "raf durumu sorgusu   |katalog|0|-",
  "gecikme ucreti hesabi|ucret  |2|k0 K1",
  "sube stok devri      |sube   |1|e2",
  "uyelik dondurma      |uyelik |1|s1 S1",
  "ceza bildirimi       |ucret  |0|-",
  "sube raf etiketi     |sube   |0|-",
  "ayirtma kuyrugu      |odunc  |2|s1 S2",
  "kimlik eslestirme    |uyelik |2|k0 K1",
  "katalog ice aktarma  |katalog|1|-",
  "ucret iadesi         |ucret  |1|e2",
  "subeler arasi tasima |sube   |2|s1 S2",
  "odunc uzatma         |odunc  |0|-",
  "gecikme raporu       |ucret  |0|-",
  "uye bildirimi        |uyelik |0|k0 K2",
  "sube gunluk kapanis  |sube   |1|-",
].map((satir, i) => {
  const [ad, birim, risk, kusur] = satir.split("|").map((x) => x.trim());
  const [kod, anahtar = null] = kusur.split(" ");
  const TUR = { e: "eksik bilgi", s: "yanlis sinir", k: "gec kisit" };
  return { ad, birim, risk: +risk, artim: (i / 3) | 0, anahtar,
           tur: kod === "-" ? null : TUR[kod[0]], dogum: kod === "-" ? -1 : +kod[1] };
});

// SM3: partileme kurali modelin kendisidir; selale ve V tek parti, spiral risk sirali uc dongu,
// artimli bagimlilik sirali alti artim.
const riskli = [...KALEM].sort((a, b) => b.risk - a.risk);
const PARTI = {
  selale:  [KALEM],
  V:       [KALEM],
  spiral:  [0, 1, 2].map((c) => riskli.slice(c * 6, c * 6 + 6)),
  artimli: [0, 1, 2, 3, 4, 5].map((a) => KALEM.filter((k) => k.artim === a)),
};
const maliyet = (model, k, s) => (k.yayim ? YAYIM : BIRIM + (model === "V" && s <= 2 ? 1 : 0));
// V'de sinama tasarimi uretim adimiyla birlikte yapilir: eksik bilgi dogdugu adimda goze carpar.
const bulusAdimi = (model, k) =>
  (model === "V" && k.tur === "eksik bilgi") ? k.dogum : (k.tur === "gec kisit" ? 4 : 3);

function kostur(model) {
  const partiler = PARTI[model];
  const durum = new Map(KALEM.map((k) => [k.ad, { adimBitis: new Map(), parti: 0 }]));
  partiler.forEach((p, i) => p.forEach((k) => { durum.get(k.ad).parti = i; }));
  const ogrenilen = new Set(), cozulen = new Set(), bulgu = [];
  let tur = 0, bekleme = 0, elDegistirme = 0, yeniden = 0, toplam = 0;

  const segment = (liste, birimBasi) => {                 // her segment yeni bir turda baslar
    tur += 1;
    let kap = KAPASITE;
    const bitis = new Map();
    for (const k of liste) {
      let kalan = birimBasi(k);
      toplam += kalan;
      while (kalan > 0) {
        if (kap === 0) { tur += 1; kap = KAPASITE; }
        const al = Math.min(kap, kalan); kap -= al; kalan -= al;
      }
      bitis.set(k.ad, tur);
    }
    return bitis;
  };

  partiler.forEach((parti, p) => {
    for (let s = 0; s < ADIM.length; s++) {
      const liste = s === 4 ? [...parti, { ad: "__yayim", yayim: true }] : parti;
      const bitis = segment(liste, (k) => maliyet(model, k, s));
      for (const k of parti) {
        bekleme += tur - bitis.get(k.ad);
        durum.get(k.ad).adimBitis.set(s, bitis.get(k.ad));
      }
      elDegistirme += parti.length;

      const bulunan = KALEM.filter((k) => {               // bu adimda ortaya cikan kusurlar
        if (k.dogum < 0) return false;
        if (k.tur === "eksik bilgi") return parti.includes(k) && s === bulusAdimi(model, k);
        if (k.tur === "gec kisit") return s === 4 && parti.includes(k) && !ogrenilen.has(k.anahtar);
        const grup = KALEM.filter((x) => x.anahtar === k.anahtar);   // yanlis sinir: es kalem
        return s === 3 && !cozulen.has(k.anahtar) &&
          grup.every((x) => durum.get(x.ad).parti <= p) && grup.some((x) => durum.get(x.ad).parti === p);
      });
      for (const k of bulunan) {
        const adimlar = [...Array(s - k.dogum + 1)].map((_, i) => k.dogum + i);
        const bedel = adimlar.reduce((a, x) => a + maliyet(model, k, x), 0);
        const bulusTur = s === k.dogum ? bitis.get(k.ad) : tur;   // ayni adimda bulundu ise kapida degil
        bulgu.push({ model, kalem: k.ad, tur: k.tur, dogum: k.dogum, bulus: s, bedel,
          gecikmeAdim: (p - durum.get(k.ad).parti) * ADIM.length + s - k.dogum,
          gecikmeTur: bulusTur - durum.get(k.ad).adimBitis.get(k.dogum),
          ustune: KALEM.filter((x) => durum.get(x.ad).adimBitis.get(k.dogum) <= bulusTur).length });
        yeniden += bedel;
        elDegistirme += adimlar.length;
        if (k.tur === "yanlis sinir") cozulen.add(k.anahtar);
      }
      if (bulunan.length) segment(bulunan, (k) =>
        [...Array(s - k.dogum + 1)].reduce((a, _, i) => a + maliyet(model, k, k.dogum + i), 0));
      if (s === 4) for (const k of parti) if (k.tur === "gec kisit") ogrenilen.add(k.anahtar);
    }
  });
  return { model, tur, bekleme, elDegistirme, yeniden, toplam, bulgu };
}

const SONUC = ["selale", "V", "spiral", "artimli"].map(kostur);
writeFileSync("bulgu.json", JSON.stringify(SONUC.flatMap((s) => s.bulgu)));

const TUR3 = ["eksik bilgi", "yanlis sinir", "gec kisit"];
const tablo = (basliklar, satirlar, ust) => {             // negatif genislik sola yaslar
  const yaz = (h) => console.log(h.map((c, i) =>
    basliklar[i][1] < 0 ? String(c).padEnd(-basliklar[i][1]) : String(c).padStart(basliklar[i][1])).join(""));
  console.log();
  if (ust) console.log(ust);
  yaz(basliklar.map((b) => b[0]));
  satirlar.forEach(yaz);
};
const ort = (g, f) => (g.length ? (g.reduce((a, b) => a + f(b), 0) / g.length) : null);

console.log(`is kalemi: ${KALEM.length}, adim: ${ADIM.length}, kusurlu kalem: ` +
  `${KALEM.filter((k) => k.dogum >= 0).length} ` +
  `(${TUR3.map((t) => `${KALEM.filter((k) => k.tur === t).length} ${t}`).join(", ")})`);

tablo([["model", -9], ["parti", 7], ["tur", 6], ["bekleme", 9], ["el degistirme", 15], ["toplam is birimi", 18]],
  SONUC.map((s) => [s.model, PARTI[s.model].length, s.tur, s.bekleme, s.elDegistirme, s.toplam]));

tablo([["model", -9], ["bulunan kusur", 14], ["ort. gecikme (adim)", 21], ["ort. gecikme (tur)", 20],
       ["ort. ustune kurulan", 21], ["yeniden is", 12]],
  SONUC.map((s) => [s.model, s.bulgu.length, ort(s.bulgu, (b) => b.gecikmeAdim).toFixed(2),
    ort(s.bulgu, (b) => b.gecikmeTur).toFixed(2), ort(s.bulgu, (b) => b.ustune).toFixed(2), s.yeniden]));

tablo([["model", -9], ["eksik bilgi", 13], ["yanlis sinir", 14], ["gec kisit", 11]],
  SONUC.map((s) => [s.model, ...TUR3.map((t) => {
    const o = ort(s.bulgu.filter((b) => b.tur === t), (b) => b.gecikmeTur);
    return o === null ? "-" : o.toFixed(1);
  })]), "kusur turune gore ortalama gecikme (tur):");
```

```
is kalemi: 18, adim: 5, kusurlu kalem: 10 (3 eksik bilgi, 4 yanlis sinir, 3 gec kisit)

model      parti   tur  bekleme  el degistirme  toplam is birimi
selale         1    43      243            125               381
V              1    50      288            120               440
spiral         3    47       63            125               393
artimli        6    48       18            120               396

model     bulunan kusur  ort. gecikme (adim)  ort. gecikme (tur)  ort. ustune kurulan  yeniden is
selale               10                 2.50               20.10                18.00         105
V                    10                 2.00               19.00                14.70         110
spiral               10                 3.00                8.50                 9.60         105
artimli               9                 4.00                5.22                10.67          90

kusur turune gore ortalama gecikme (tur):
model      eksik bilgi  yanlis sinir  gec kisit
selale            13.3          14.8       34.0
V                  0.0          18.5       38.7
spiral             4.0           9.3       12.0
artimli            1.7           7.8        5.5
```

## Dört Modelin Okunması

İlk tablo akışı, ikincisi öğrenmeyi ölçer ve ikisi ters yönde hareket eder.

**Şelale** en az turda biter (43) çünkü sabit yükü bir kez öder. Bedeli ikinci sütundadır: **243 tur
bekleme** birikir, çünkü kalem kendi adımını bitirince partinin son kalemini bekler ve her kapıda
yeniden bekler. Öğrenme tarafı daha serttir — gecikme **20,1 tur** ve bir kusur bulunduğunda **on
sekiz kalemin on sekizi** o yanlış varsayımın üstündedir. Geç öğrenilen kısıtta gecikme 34 tura
çıkar, çünkü işletime alma sonda tek seferdir.

**V modeli** tek bir kusur türünde kesin kazanç sağlar: eksik bilginin gecikmesi **13,3 turdan 0
tura** iner, soru cevabın gerekli olduğu adımda sorulur. Bedeli iki yerdedir. Toplam iş gücü
381'den **440 birime** çıkar (270 temel iş, 54 birim sınama tasarımı eki, 6 birim yayım, 110 birim
yeniden iş) ve akış 50 tura uzar. Diğer iki türde ise V hiçbir şey yapmaz — yanlış sınır 14,8'den
18,5 tura, geç öğrenilen kısıt 34'ten 38,7 tura **çıkar**, çünkü koşumun tamamı uzamıştır.

**Spiral** partiyi risk sırasına böler; en riskli altı kalem ilk döngüde işletime kadar gittiği için
geç öğrenilen kısıt 34 turdan **12 tura**, ortalama gecikme 8,5 tura, bekleme 63'e iner. Bedeli üç
kez ödenen yayım yükü (18 birim) ve kaçırılan bir öğrenmedir: risk sırası aynı kısıtı taşıyan iki
kalemi (`gecikme ucreti hesabi` ve `kimlik eslestirme`) **aynı döngüye** koyduğu için kısıt ikisi de
yazıldıktan sonra öğrenilir ve ikisi de yeniden işe girer.

**Artımlı** model bağımlılık sırasına göre altı artıma böler. Bekleme 18 tura, gecikme 5,22 tura
iner ve **bulunan kusur ona değil dokuza** düşer: birinci artımda öğrenilen kısıt üçüncü artımdaki
eş kalemi kusursuz doğurur, yeniden iş 90 birime iner. Bedeli turlardadır — altı yayım yükü akışı
dört modelin en uzunu olan 48 tura çıkarır — ve **adım cinsinden gecikme en yüksek burada**dır
(4,00): artım sınırını kesen yanlış sınır ancak ikinci artımda görünür, birincinin teslim edilmiş
kalemi geri açılır.

## Gecikme Yeniden İşe Nasıl Dönüşür

**SM6 — yeniden işin bedeli iki çarpandan gelir:** yeniden yapılan adım sayısı ve aynı varsayımın
üstüne kurulmuş kalem sayısı. Aşağıdaki blok dört koşumun otuz dokuz bulgusunu tek havuzda toplar
ve bu iki çarpanı gecikmeye karşı ayırır.

```js
// gecikme.mjs — yasam-dongusu.mjs'in yazdigi bulgulari okur; gecikme ile yeniden is baginti
import { readFileSync } from "node:fs";

const BULGU = JSON.parse(readFileSync("bulgu.json", "utf8"));
const KOVA = [[0, 0], [1, 5], [6, 12], [13, 24], [25, 99]];

console.log(`dort modelde toplam ${BULGU.length} kusur bulgusu; kova = geri bildirim gecikmesi (tur)\n`);
console.log(`${"gecikme".padStart(9)}${"bulgu".padStart(7)}${"ort. yeniden is (birim)".padStart(25)}` +
  `${"ort. yeniden adim".padStart(19)}${"ort. ustune kurulan kalem".padStart(27)}`);
for (const [a, b] of KOVA) {
  const g = BULGU.filter((x) => x.gecikmeTur >= a && x.gecikmeTur <= b);
  if (!g.length) continue;
  const o = (f) => (g.reduce((s, x) => s + f(x), 0) / g.length).toFixed(1);
  console.log(`${(a === b ? `${a}` : `${a}-${b}`).padStart(9)}${String(g.length).padStart(7)}` +
    `${o((x) => x.bedel).padStart(25)}${o((x) => x.bulus - x.dogum + 1).padStart(19)}` +
    `${o((x) => x.ustune).padStart(27)}`);
}

// SM6: yeniden isin bedeli iki carpandan gelir; yeniden yapilan adim sayisi ve ayni varsayimin
// ustune kurulmus kalem sayisi. Ikisi de gecikmeyle birlikte buyur.
const ADI = (i) => ["cozumleme", "tasarim", "gerceklestirme", "sinama", "isletim"][i];
const kume = (g, f) => [...new Set(g.map(f))].join(" ve ");
const pahali = [...BULGU].sort((a, b) => b.bedel - a.bedel).slice(0, 5);
console.log(`\nen pahali bes bulgu: tur ${kume(pahali, (x) => x.tur)}, ` +
  `dogum ${kume(pahali, (x) => ADI(x.dogum))}, bulus ${kume(pahali, (x) => ADI(x.bulus))}, ` +
  `ort. ${(pahali.reduce((a, x) => a + x.bedel, 0) / 5).toFixed(1)} birim yeniden is`);
```

```
dort modelde toplam 39 kusur bulgusu; kova = geri bildirim gecikmesi (tur)

  gecikme  bulgu  ort. yeniden is (birim)  ort. yeniden adim  ort. ustune kurulan kalem
        0      3                      4.0                1.0                        7.0
      1-5     11                      8.7                2.9                       10.4
     6-12      6                     10.5                3.5                       13.5
    13-24     13                     10.8                3.4                       15.0
    25-99      6                     16.5                5.0                       18.0

en pahali bes bulgu: tur gec kisit, dogum cozumleme, bulus isletim, ort. 16.8 birim yeniden is
```

Kovalar tek yönde ilerler: gecikme sıfırken yeniden iş 4 birim, yirmi beş turun üstünde 16,5
birimdir. Aradaki fark iki çarpandan gelir. Yeniden yapılan adım 1,0'dan 5,0'a çıkar, çünkü geç
bulunan kusur daha çok adımı geçersiz kılar; aynı varsayımın üstüne kurulmuş kalem 7,0'dan 18,0'a
çıkar, çünkü bu arada kusurun etrafında iş birikmiştir. En pahalı beş bulgunun beşi de aynı
türdendir — çözümlemede doğup işletimde bulunan geç öğrenilen kısıt.

Temel iş dört modelde de 270 birimdir; farkı sabit yük ile yeniden iş yaratır. Bir modelin "daha
iyi" olduğunu söyleyen tek bir sayı yoktur: geç öğrenilen kısıt ağır basıyorsa küçük parti, eksik
bilgi ağır basıyorsa erken doğrulama, sabit yayım maliyeti yüksekse büyük parti kazanır.

## Özet

- Aynı 18 iş kalemi dört yaşam döngüsünde koşturuldu; 270 birimlik temel iş sabit tutuldu, farkı
  yalnız partileme kuralı ile sabit yük yarattı.
- Şelale en kısa akışı verir (43 tur) ama 243 tur bekleme biriktirir, gecikmeyi 20,1 tura çıkarır
  ve her kusurda 18 kalemin tamamı yanlış varsayımın üstündedir.
- V modeli eksik bilgi gecikmesini 13,3 turdan 0'a indirir; karşılığında toplam iş gücü 381'den
  440 birime çıkar ve diğer iki kusur türünde gecikme artar.
- Spiral gecikmeyi 8,5 tura indirir ama aynı kısıtın iki kalemini aynı döngüye koyup partiler arası
  öğrenmeyi kaçırır; artımlı beklemeyi 18 tura, yeniden işi 90 birime indirir ve bir kusuru hiç
  doğurmaz, bedeli 48 turluk en uzun akıştır.
- Havuzlanmış 39 bulguda gecikme 25 turun üstüne çıktığında yeniden iş 4 birimden 16,5 birime
  yükselir; yeniden yapılan adım 1,0'dan 5,0'a, üstüne kurulmuş kalem 7,0'dan 18,0'a çıkar.

## Sonraki Adım

Bu dersin en güçlü tek değişkeni parti büyüklüğüydü: on sekiz kalemlik tek parti ile üç kalemlik
altı parti arasındaki fark beklemeyi on üç kat, geri bildirim gecikmesini dört kat değiştirdi.
Fakat parti büyüklüğü burada elle seçildi — altı artımın neden altı olduğu hiçbir yerde ölçülmedi.
Sonraki ders yinelemeli teslimatın çerçevelerini ortak yapısıyla ele alır ve asıl değişkeni tarar:
yineleme uzunluğu bir haftadan dört haftaya çıkarıldığında akış süresi, yeniden iş ve **törene
giden süre** nasıl değişir. Kısa yineleme gecikmeyi düşürür, ama her yinelemenin planlama ve gözden
geçirme yükü sabittir ve yinelemeye sığmayan kalem yarım kalıp sonrakine devrolur. İki maliyet
ters yönde büyüdüğü için taramadan tek bir en iyi uzunluk çıkmaz.
