---
title: 'Depo Tabanlı İstenen Durum'
source: 'https://academia.sh/tr/kurslar/ci-cd/depo-tabanli-istenen-durum'
course: 'Sürekli Tümleştirme ve Teslimat'
language: tr
updated: '2026-08-17T18:09:03+00:00'
license: 'CC BY-SA 4.0'
---

# Depo Tabanlı İstenen Durum

Aynı değişiklik akışı iki düzende koşturulur — elden uygulama ve depoya işleme — ve iki düzenin izlenebilirliği, kayıtsız değişiklik oranı, dönem sonu sapması ve değişiklik başına adım sayısı 180 değişiklikte sayılır. Gözden geçirme kapısının yalnız kendi yakaladığı kusur, yanlış tuttuğu temiz değişiklik ve eklediği 796 saat ayrı ayrı ölçülür.

Önceki konular yayının nasıl verileceğini kurdu: hangi ölçüte bakılarak terfi edileceği, yüzdelik
dağıtımın hangi eşikte durdurulacağı, geri alma planının kaç adım olduğu. Bu kararların hepsinin
ortak bir yanı vardı — sonunda biri bir arayüzde bir düğmeye basıyor ya da bir kabuk komutu
yazıyordu. Kararın kendisi kayıt altındaydı; kararın **uygulanması** değildi.

Bu ders o boşluğu ölçer. Soru şudur: kümenin uyguladığı istenen durum bir yerde **yazılı olarak**
duruyor mu, yoksa yalnız çalışan sistemin belleğinde mi? **Depo tabanlı istenen durum** ilkesi tek
bir cümledir — bir ortamda ne çalışacağının tanımı bir depoda durur ve o depo dışında hiçbir yoldan
değiştirilmez. İlkenin kendisi kısa, faturası uzundur; ders faturayı çıkarır.

Ölçüm **bölgesel ölçüm ağı** üzerindedir ve **kurgudur**: su sayacı okuma toplayıcısı, doğrulayıcı,
faturalama ve iş emri servisleri, üç ortam. Koşan şey `node` ile kurulmuş bir **modeldir**, gerçek
bir sistem değil.

**DD1.** İstenen durum 60 kalemdir: dört servis × üç ortam × beş alan (kopya sayısı, eşik, sürüm,
ağ kuralı, zamanlama).
**DD2.** Doksan günde 180 değişiklik üretilir; üreteç kendi yazılmıştır, tohum 20260801 görünürdür.
**DD3.** Değişikliklerin bir bölümü **acil**dir (vardiya dışı müdahale); %20'si bilinen bir kusur
taşır: biçim, eşik, ortam, koşum anı.
**DD4.** Elden düzende kayıt gönüllüdür — uygulayan isterse bir yere yazar. Depo düzeninde işleme
kaydı kim, ne zaman ve gerekçe alanlarını zorunlu taşır.
**DD5.** Depo düzeninde de acil değişikliklerin bir bölümü depoyu atlar; ilke %100 uygulanmaz.
**DD6.** İki kapı vardır ve ikisi de yalnız depo yolundadır: şema doğrulayıcısı (otomatik) ve
gözden geçirme (insan).

## Aynı Değişiklik İki Yolla

```js
// akis.mjs — bolgesel olcum agi (kurgu) uzerinde 90 gunluk degisiklik akisi modeli.
// Ayni akis iki duzende uygulanir: elden uygulama ve depoya isleme. Kosan sey bir
// modeldir, gercek bir sistem degil. Rastgelelik kendi uretecimizden gelir, tohum gorunur.
export const uretec = (t) => { let s = t >>> 0;
  return () => (s = (s * 1664525 + 1013904223) >>> 0) / 4294967296; };

const SERVIS = ["toplayici", "dogrulayici", "faturalama", "isemri"];
const ORTAM = ["gelistirme", "hazirlik", "uretim"];
const ALAN = ["kopya", "esik", "surum", "ag-kurali", "zamanlama"];
export const KALEM = SERVIS.flatMap((s) => ORTAM.flatMap((o) => ALAN.map((a) => `${s}/${o}/${a}`)));

export function akis(tohum = 20260801, adet = 180) {          // 90 gunluk degisiklik akisi
  const r = uretec(tohum), liste = [];
  for (let i = 0; i < adet; i++) {
    const kalem = KALEM[Math.floor(r() * KALEM.length)];
    const acil = r() < 0.22;                                   // vardiya disi mudahale
    const p = r();                                             // bilinen kusur kumesi: %20
    const kusur = p < 0.06 ? "bicim" : p < 0.12 ? "esik" : p < 0.16 ? "ortam"
                : p < 0.20 ? "kosum" : null;
    liste.push({ i, gun: Math.floor(r() * 90), kalem, acil, kusur });
  }
  return liste;
}

// depo=false: her degisiklik elden uygulanir, kayit gonullu.
// depo=true : degisiklik depoya islenir; acil olanlarin bir kismi yine de depoyu atlar.
export function duzen(liste, { depo, tohum = 7717 }) {
  const r = uretec(tohum);
  const gercek = new Map(), defter = new Map();                // kalem -> surum numarasi
  let kim = 0, gerekce = 0, kayitsiz = 0, atlayan = 0, adim = 0, incelenen = 0;
  for (const d of liste) {
    const depoYolu = depo && !(d.acil && r() < 0.35);
    const s = (gercek.get(d.kalem) ?? 0) + 1;
    gercek.set(d.kalem, s);
    if (depoYolu) {                                            // dal, degisiklik, isleme,
      defter.set(d.kalem, s);                                  // oneri, gozden gecirme,
      kim++; gerekce++; incelenen++; adim += 7;                // birlestirme, uygulama
    } else {
      atlayan++; adim += 2;                                    // komut yaz, uygula
      const kaydeder = r() < (d.acil ? 0.25 : 0.7);
      if (kaydeder) { kim++; if (r() < 0.45) gerekce++; } else kayitsiz++;
      if (r() < (d.acil ? 0.1 : 0.3)) defter.set(d.kalem, s);  // sonradan deftere gecirme
    }
  }
  let sapan = 0;
  for (const [k, s] of gercek) if (defter.get(k) !== s) sapan++;
  return { n: liste.length, kim, gerekce, kayitsiz, atlayan, incelenen, sapan,
    dokunulan: gercek.size, adim: adim / liste.length };
}

if (import.meta.url === `file://${process.argv[1]}`) {
  const liste = akis();
  const acil = liste.filter((d) => d.acil).length;
  const kusurlu = liste.filter((d) => d.kusur).length;
  console.log(`tohum 20260801 | ${liste.length} degisiklik / 90 gun | ${KALEM.length} kalem`);
  console.log(`acil: ${acil} | bilinen kusur tasiyan: ${kusurlu}`);
  const BAS = ["duzen", "kim", "gerekce", "kayitsiz", "atlayan", "incelenen", "sapan kalem", "adim"];
  const G = [16, 5, 9, 10, 9, 11, 13, 7];
  const satir = (h) => h.map((v, j) => j ? String(v).padStart(G[j]) : String(v).padEnd(G[0])).join("");
  console.log("\n" + satir(BAS));
  for (const depo of [false, true]) {
    const x = duzen(liste, { depo });
    console.log(satir([depo ? "depoya isleme" : "elden uygulama", x.kim, x.gerekce, x.kayitsiz,
      x.atlayan, x.incelenen, `${x.sapan}/${x.dokunulan}`, x.adim.toFixed(2)]));
  }
}
```

```
tohum 20260801 | 180 degisiklik / 90 gun | 60 kalem
acil: 35 | bilinen kusur tasiyan: 36

duzen             kim  gerekce  kayitsiz  atlayan  incelenen  sapan kalem   adim
elden uygulama    117       54        63      180          0        45/56   2.00
depoya isleme     175      172         5        9        171         1/56   6.75
```

İzlenebilirlik sütunları beklenen yönde ayrışıyor. Elden düzende 180 değişikliğin 117'sinde kim ve
ne zaman bilgisi bir yere düşmüş, yalnız 54'ünde gerekçe var; 63 değişiklik — akışın %35'i — hiçbir
iz bırakmadan uygulanmış. Depo düzeninde gerekçe 172'ye çıkıyor, çünkü işleme kaydı boş
bırakılamıyor: kim, ne zaman ve niçin alanları değişikliğin taşıyıcısının kendisidir, ayrıca
doldurulan bir form değil.

Asıl sayı sondan üçüncü sütundadır. Doksan gün boyunca 60 kalemin 56'sına dokunulmuş; elden düzende
dönem sonunda bu 56 kalemin **45'i** depodaki değerden farklıdır. Yani sistemi anlatan belge,
sistemin dörtte üçünde yanlıştır. Depo düzeninde sapan kalem sayısı 1'dir ve o bir kalem depoyu
atlayan dokuz acil değişiklikten arta kalandır.

Bu farkın işletim karşılığı, belgenin eskimesinden ağırdır. Elden düzende bir kalemin doğru
değerini bilen tek yer çalışan sistemin kendisidir; ortam yeniden kurulduğunda ya da bir kalem
sıfırlandığında geri dönülecek bir kaynak yoktur. Faturalama servisinin üretimdeki eşiği bir gece
elle değiştirilmiş ve kimse yazmamışsa, o eşik artık kimsenin kararı değil, bir kazadır. Depo
tabanlı istenen durumun ilk kazancı denetim değil, **geri dönülebilirliktir**: 56 kalemin 55'i için
depodaki değer, sistemin son bilinen doğru hâlidir.

## Gözden Geçirme Kapısı Neyi Yalnız Kendisi Tutuyor

```js
// kapi.mjs — depo yolundaki gozden gecirme kapisinin defteri: tuttugu, YALNIZ kendisinin
// tuttugu, kacirdigi, yanlis tuttugu, ekledigi sure. Ayni akis modeli, ayri tohum.
import { akis, uretec } from "./akis.mjs";
const SEMA = { bicim: 1, esik: 0, ortam: 0, kosum: 0 };             // sema dogrulayicisi
const GOZ = { bicim: 0.85, esik: 0.55, ortam: 0.75, kosum: 0.05 };  // gozden gecirme

function kos(liste, { kacis, tohum = 4231 }) {
  const r = uretec(tohum), gercek = new Map(), defter = new Map();
  const ortam = {}, sinif = {};
  let atlayan = 0, kapiya = 0, semaYalniz = 0, marjinal = 0, ikisi = 0,
    gecen = 0, yanlis = 0, dakika = 0, tetikli = false;
  const uygula = (d, depoyla) => { const s = (gercek.get(d.kalem) ?? 0) + 1;
    gercek.set(d.kalem, s); if (depoyla) defter.set(d.kalem, s); return s; };
  for (const d of liste) {
    const o = (ortam[d.kalem.split("/")[1]] ??= { kapiya: 0, marjinal: 0, yanlis: 0, dk: 0 });
    const k = d.kusur ? (sinif[d.kusur] ??= { n: 0, goz: 0, sema: 0, gecen: 0 }) : null;
    if (k) k.n++;
    const atla = r() < (d.acil ? 0.35 : (kacis && tetikli ? 0.5 : 0));
    tetikli = false;
    if (atla) {                                                     // kapisiz yol
      atlayan++; const s = uygula(d, false);
      if (k) { gecen++; k.gecen++; }
      if (r() < 0.2) defter.set(d.kalem, s);
      continue;
    }
    kapiya++; o.kapiya++;
    const bekle = d.acil ? 5 + r() * 55 : 25 + r() * 575;           // gozden gecirme beklemesi
    dakika += bekle; o.dk += bekle;
    const sema = d.kusur ? r() < SEMA[d.kusur] : false;
    const goz = d.kusur ? r() < GOZ[d.kusur] : false;
    if (k && (sema || goz)) {                                       // durduruldu, uygulanmadi
      if (sema) k.sema++;
      if (goz) k.goz++;
      if (sema && goz) ikisi++; else if (sema) semaYalniz++; else { marjinal++; o.marjinal++; }
      continue;
    }
    if (!k && r() < 0.06) {                                         // temiz ama durduruldu
      yanlis++; o.yanlis++; tetikli = true;
      dakika += bekle * 0.6; o.dk += bekle * 0.6;                   // ikinci tur
    }
    uygula(d, true);
    if (k) { gecen++; k.gecen++; }
  }
  let sapan = 0; for (const [a, s] of gercek) if (defter.get(a) !== s) sapan++;
  return { atlayan, kapiya, semaYalniz, marjinal, ikisi, gecen, yanlis, sapan,
    dk: dakika / kapiya, saat: dakika / 60, ortam, sinif };
}

const yaz = (g, h) => h.map((v, j) => j ? String(v).padStart(g[j]) : String(v).padEnd(g[0])).join("");

if (import.meta.url === `file://${process.argv[1]}`) {
  const liste = akis(), kusurlu = liste.filter((d) => d.kusur).length;
  const G = [7, 9, 8, 13, 15, 8, 8, 8, 8, 12];
  console.log(`${liste.length} degisiklik, ${kusurlu} bilinen kusur; iki kapi: sema + gozden gecirme`);
  console.log("\n" + yaz(G, ["kacis", "atlayan", "kapiya", "yalniz sema", "yalniz gozden",
    "ikisi", "gecen", "yanlis", "sapan", "dk/inceleme"]));
  for (const kacis of [false, true]) {
    const x = kos(liste, { kacis });
    console.log(yaz(G, [kacis ? "var" : "yok", x.atlayan, x.kapiya, x.semaYalniz, x.marjinal,
      x.ikisi, x.gecen, x.yanlis, x.sapan, x.dk.toFixed(0)]));
  }
  const x = kos(liste, { kacis: false });
  const S = [12, 7, 7, 8, 8];
  console.log("\n" + yaz(S, ["kusur", "adet", "sema", "gozden", "gecen"]));
  for (const [ad, k] of Object.entries(x.sinif))
    console.log(yaz(S, [ad, k.n, k.sema, k.goz, k.gecen]));
  const O = [13, 8, 15, 15, 13, 15];
  console.log("\n" + yaz(O, ["ortam", "kapiya", "yalniz gozden", "yanlis tuttu",
    "toplam saat", "saat/marjinal"]));
  for (const [ad, o] of Object.entries(x.ortam))
    console.log(yaz(O, [ad, o.kapiya, o.marjinal, o.yanlis, (o.dk / 60).toFixed(1),
      o.marjinal ? (o.dk / 60 / o.marjinal).toFixed(1) : "-"]));
  console.log(`\ntoplam gozden gecirme yuku: ${x.saat.toFixed(0)} saat / 90 gun`);
}
```

```
180 degisiklik, 36 bilinen kusur; iki kapi: sema + gozden gecirme

kacis    atlayan  kapiya  yalniz sema  yalniz gozden   ikisi   gecen  yanlis   sapan dk/inceleme
yok           13     167            1             13      11      11       7       4         286
var           20     160            1             15       9      11       9       7         270

kusur          adet   sema  gozden   gecen
esik              8      0       3       5
bicim            12     12      11       0
ortam            11      0       9       2
kosum             5      0       1       4

ortam          kapiya  yalniz gozden   yanlis tuttu  toplam saat  saat/marjinal
hazirlik           67              6              2        312.5           52.1
gelistirme         44              1              2        193.7          193.7
uretim             56              6              3        289.9           48.3

toplam gozden gecirme yuku: 796 saat / 90 gun
```

İki kapı da iş görüyor, ama defterleri birbirine benzemiyor. Şema doğrulayıcısı 12 biçim kusurunu
tuttu; bunların 11'ini gözden geçirme de yakalardı, dolayısıyla **yalnız şemanın** tuttuğu kusur
sayısı 1'dir. Gözden geçirme 24 kusur tuttu ve bunların 13'ünü tek başına yakaladı — öteki kapı
olsa da olmasa da geçecek olan kusurlar bunlardır. Marjinal değer sıralaması nettir: şema kapısı 1,
gözden geçirme 13.

Kusur sınıfı tablosu bu sıralamanın nedenini gösteriyor. Biçim kusurunun 12'si de tutuldu, hiçbiri
geçmedi; bu sınıfı iki kapı da görüyor ve şema kapısı bunu saniyeler içinde yapıyor. Eşik ve ortam
kusurları şema için görünmezdir: değer geçerli, alan doğru, yalnız sayı ya da hedef yanlıştır.
Bunları yalnız okuyan bir insan yakalar — 8 eşik kusurunun 3'ü, 11 ortam kusurunun 9'u tutuldu.

Kapının kaçırdığı 11 kusur da sınıfına göre okunur: 5 eşik, 2 ortam, 4 koşum anı. Koşum anı sınıfı
beş kusurun dördünü geçirdi, çünkü bu sınıf yazılı metne bakarak görülmez — değer ancak servis
gerçek veriyle karşılaştığında yanlış olur. Statik bir kapının önünde duran bir sınır burasıdır ve
gözden geçirmenin süresini uzatmak bu sınırı geriye itmez.

Yanlış tutma sütunu kapının öteki yüzüdür: 7 temiz değişiklik durduruldu ve her biri ikinci bir tur
üretti. İnceleme başına ortalama bekleme 286 dakikadır; doksan günde toplam **796 saat**, günde
yaklaşık dokuz saatlik bir bekleme yükü. Bu süre bir işgücü maliyeti değil, öncü sürenin kendisidir:
değişiklik yazıldıktan sonra ortalama dört saat kırk beş dakika boyunca hiçbir yere gitmez.

## Kapıdan Kaçmanın Ölçülen İzi

Tablonun ikinci satırı, yanlış tutmanın ekipte ürettiği davranışı modelliyor: boşuna durdurulan bir
değişikliğin ardından gelen değişikliğin acil olmasa bile kapısız yoldan gitme olasılığı artıyor.
Kapıyı atlayan değişiklik 13'ten 20'ye, dönem sonunda sapan kalem 4'ten 7'ye çıkıyor. Üretime geçen
kusur sayısı iki koşumda da 11'dir; 180 değişiklik ölçeğinde bu fark üretecin gürültüsünün altında
kalır ve öyle sunulmalıdır. Ölçülebilen etki kusur sayısında değil, **kapının kendi ürettiği
sapmada**dır: bir kapıya güven azaldığında kayıp önce izlenebilirlikte görünür.

Ortam tablosu ise kaldırılması gereken kapıyı doğrudan işaret ediyor. Geliştirme ortamına giden 44
değişiklik gözden geçirildi, bu incelemelerin toplamı 193,7 saat sürdü ve **yalnız 1** kusur
marjinal olarak yakalandı — kusur başına 193,7 saat. Aynı ölçü üretimde 48,3, hazırlıkta 52,1
saattir. Üstelik geliştirme ortamındaki 2 yanlış tutma, marjinal yakalamanın iki katıdır: kapı
burada tuttuğundan çok boşuna durduruyor.

Buradan çıkan karar ilkeye dokunmaz, kapıya dokunur: geliştirme ortamının değişiklikleri depoya
işlenmeye devam eder, gözden geçirme kapısı kalkar. Ayrım bu dersin taşıdığı en pratik sonuçtur —
**depoya işleme ile gözden geçirme aynı şey değildir.** İzlenebilirlik, gerekçe ve geri
dönülebilirlik kazancı işleme kaydından gelir; kapıdan gelen tek şey tutulan kusurdur ve o da
ortama göre çok farklı fiyatlanır.

## İlkenin Bedeli: Değişiklik Başına Ek Adım

İlk tablonun son sütunu ilkenin doğrudan faturasıdır. Elden uygulama değişiklik başına 2 adımdır:
komut yazılır, uygulanır. Depo yolu 7 adımdır — dal açılır, dosya değiştirilir, işlenir, öneri
açılır, gözden geçirme beklenir, birleştirilir, uygulanır. Karışım ortalaması 6,75'tir; fark
değişiklik başına 4,75 adım, doksan günde 855 ek adımdır.

Bu adımların hepsi aynı ağırlıkta değildir. Altısı yazan kişinin dakikalarıdır; yalnız biri —
gözden geçirme beklemesi — başkasının takvimine bağlıdır ve ölçülen 286 dakikanın tamamı oradan
gelir. Acil yolun varlığı da bu yüzden sürüyor: 35 acil değişikliğin 13'ü kapıyı atladı, çünkü
gece yarısı dört saatlik bir bekleme kesintiyi uzatır. İlkeyi %100 uygulamak, ölçülen kayıtsız
değişiklik oranını 5'ten 0'a indirir ama acil müdahalenin süresine dört saat ekler; hangi tarafın
seçildiği ölçülmeden savunulamaz.

## Özet

- Elden düzende 180 değişikliğin 63'ü (%35) hiçbir iz bırakmadan uygulandı ve gerekçe yalnız 54
  değişiklikte vardı; depo düzeninde kayıtsız değişiklik 5'e, gerekçesiz değişiklik 8'e indi.
- Dönem sonunda dokunulan 56 kalemin elden düzende 45'i depodaki değerden sapmıştı, depo düzeninde
  1'i; ilkenin ilk kazancı denetim değil, geri dönülebilirliktir.
- Şema kapısı 12 kusur tuttu ama yalnız 1'ini tek başına yakaladı; gözden geçirme 24 tuttu, 13'ünü
  tek başına — marjinal değer sıralaması 1'e karşı 13'tür.
- Kapı 11 kusuru kaçırdı (5 eşik, 2 ortam, 4 koşum anı) ve 7 temiz değişikliği boşuna durdurdu;
  inceleme başına 286 dakika, doksan günde 796 saat ekledi.
- Geliştirme ortamında kapı 193,7 saatte 1 marjinal kusur yakaladı ve 2 temiz değişikliği durdurdu;
  aynı ölçü üretimde 48,3 saat. Bu kapı geliştirme ortamında kaldırılır, işleme kaydı kalır.
- İlkenin adım maliyeti değişiklik başına 2'den 6,75'e çıkıyor; ek adımların yalnız biri başkasının
  takvimine bağlıdır ve ölçülen beklemenin tamamı oradan gelir.

## Sonraki Adım

Bu ders istenen durumun **nerede yazılı olduğunu** ölçtü ve depodaki yazının değerini sapan kalem
sayısıyla gösterdi. Açık kalan soru bir sonraki dersin konusudur: depoda duran o yazıyı kümeye kim
taşıyor? Şimdiye kadarki düzende taşıyan taraf hattır — hat kümeye bağlanır ve yazar. Bunun bir
alternatifi vardır: küme içinde çalışan bir ajanın depoyu okuyup farkı kendisinin kapatması.
Ölçülecek kalemler bellidir: hattın küme üzerindeki yetki yüzeyi, elle yapılan bir değişikliğin
fark edilme gecikmesi, ağ bağlantısının yönü ve hat düştüğünde ne olduğu.
