---
title: 'Veri Ambarı ve Dönüştürme Hatları'
source: 'https://academia.sh/tr/kurslar/kurumsal-baglam/veri-ambari-ve-donusturme-hatlari'
course: 'Kurumsal Bağlam ve Tümleştirme'
language: tr
updated: '2026-08-17T18:10:34+00:00'
license: 'CC BY-SA 4.0'
---

# Veri Ambarı ve Dönüştürme Hatları

Çözümleme yükünün işletim yükünden ayrılması: beş raporun işletim sistemine günde 163 sorgu ve 5.354.308 okunan kayıt bindirmesi, ambarın bu yükü tazelik gecikmesi karşılığında devralması, sekiz adımlık dönüştürme hattının bir çevrimde 523.341 kayıt taşıması ve kaynak şemasındaki tek bir alan değişiminin bir adımı kırıp dört adımı durdurarak beş raporun beşini birden düşürmesi.

Önceki ders aynı varlığı birden çok sistemin yazdığı durumu ele aldı: bir kaynak sistem seçildi
ve kayıtlar arasındaki tutarsızlık sayıldı. Orada bütün taraflar veriyi **yazıyordu**. Bu derste
hiç yazmayan bir taraf var. Bölgesel kütüphane ağının yönetim birimi yalnız soru sorar: hangi
şube doluyor, hangi eser gecikmede, üyelik nasıl akıyor. Soru veriyi değiştirmez ama bedelsiz de
değildir; her soru bir sorguya, her sorgu okunan kayda dönüşür ve o kayıtlar ödünç işlemlerini
yürüten sistemin diskinde durur.

Bu ders çözümleme yükünün işletim yükünden ayrılmasını ölçer. Ağ, sahipleri ve bütçeleri ayrı
olan bir **kurgudur**.

## Soru Soran Taraf Sayılabilir Bir Yük Getirir

Modelde dört kaynak vardır ve dördünün sahibi ayrıdır: ödünç servisi, üyelik sistemi, dışarıdan
alınmış katalog ve şube sistemleri. Yönetim biriminin beş sorusu bunları okur.

**TM10: kayıt sayıları, koşum sıklıkları ve tazelik gereksinimleri kurgudur** ve hiçbir gerçek
kurumdan alınmamıştır. **TM11: bir raporun bir varlığa dokunması bir sorgudur; olay varlığı
pencereye göre, boyut varlığı tam taranır.** **TM14: okuduğu alanı bulamayan adım kırılır;
girdisi sağlam olmayan adım durur.**

```js
// ambar/model.mjs — bolgesel kutuphane aginin kurgu modeli ve donusturme hatti. Kayitlar
// gercekten uretilir; sonraki bloklarin sayilari bu dizileri tarayarak olculur.
export const TOHUM = 7391, GUN = 180, SON = GUN * 24 - 1;
export const SAHIP = { odunc: "odunc servisi (iceride)", uye: "uyelik sistemi",
  eser: "katalog (disaridan alinmis)", sube: "sube sistemleri" };

export function uret(t = TOHUM) {
  let s = t;
  const r = () => (s = (s * 48271) % 2147483647) / 2147483647, n = (k) => Math.floor(r() * k);
  const dizi = (k, f) => Array.from({ length: k }, (_, i) => f(i));
  return {
    sube: dizi(12, (i) => ({ id: i, bolge: `b${i % 4}` })),
    eser: dizi(128_000, (i) => ({ id: i, tur: ["kitap", "sureli", "isitsel"][n(3)], degisim: n(SON) })),
    uye: dizi(46_000, (i) => ({ id: i, kayit_gun: n(GUN), sube_id: n(12), degisim: n(SON) })),
    odunc: dizi(240_000, (i) => ({ id: i, uye_id: n(46_000), eser_id: n(128_000),
      sube_id: r() < 0.008 ? null : n(12), gun: n(GUN), saat: n(24) })),
  };
}

// Raporlar: varlik -> pencere (gun) ya da tam tarama; gunluk kosum; kabul edilen en buyuk
// gecikme (saat); ambardaki dayanak; kirilmayi belirleyen alan.
export const RAPORLAR = {
  doluluk: { okur: { odunc: 1, sube: "tam" }, kosum: 48, tazelik: 1, dayanak: "ozet-sube", alan: "odunc.sube_id" },
  "gecikmis-eser": { okur: { odunc: 30, eser: "tam" }, kosum: 24, tazelik: 4, dayanak: "zengin", alan: "eser.tur" },
  "yeni-uye": { okur: { uye: "tam" }, kosum: 12, tazelik: 14, dayanak: "ozet-uye", alan: "uye.kayit_gun" },
  etkinlik: { okur: { odunc: 90, uye: "tam" }, kosum: 2, tazelik: 36, dayanak: "ozet-uye", alan: "uye.kayit_gun" },
  devir: { okur: { odunc: 180, eser: "tam", sube: "tam" }, kosum: 1, tazelik: 72, dayanak: "zengin", alan: "eser.tur" },
};

// Tek kosumda okunan kayit ve acilan sorgu.
export function raporOku(veri, r) {
  let okunan = 0, sorgu = 0;
  for (const [varlik, pencere] of Object.entries(r.okur)) {
    sorgu += 1;
    if (pencere === "tam") { okunan += veri[varlik].length; continue; }
    for (const k of veri[varlik]) if (k.gun >= GUN - pencere) okunan += 1;
  }
  return { okunan, sorgu };
}

// Bir cevrimde cekilen dilim: olaydan donem icindeki kayit, boyuttan ya tamami ya da
// degisim damgasi doneme dusen kayit (TM13).
export function cek(veri, donem, boyut) {
  const esik = SON - donem;
  const degisen = (d) => boyut === "tam" ? d : d.filter((k) => k.degisim > esik);
  const dilim = { odunc: veri.odunc.filter((k) => k.gun * 24 + k.saat > esik),
    uye: degisen(veri.uye), eser: degisen(veri.eser), sube: veri.sube };
  return { dilim, okunan: Object.values(dilim).reduce((t, d) => t + d.length, 0), sorgu: 4 };
}

// Hattin sekiz adimi; her adim okudugu alani bildirir.
export const ADIMLAR = [
  { ad: "cek-odunc", kaynak: "odunc", girdi: [], okur: ["uye_id", "eser_id", "sube_id", "gun"] },
  { ad: "cek-uye", kaynak: "uye", girdi: [], okur: ["kayit_gun", "sube_id"] },
  { ad: "cek-eser", kaynak: "eser", girdi: [], okur: ["tur"] },
  { ad: "cek-sube", kaynak: "sube", girdi: [], okur: ["bolge"] },
  { ad: "temiz", girdi: ["cek-odunc"], okur: ["sube_id", "gun"] },
  { ad: "zengin", girdi: ["temiz", "cek-eser", "cek-sube"], okur: ["eser_id", "tur", "bolge"] },
  { ad: "ozet-sube", girdi: ["zengin"], okur: ["bolge", "gun"] },
  { ad: "ozet-uye", girdi: ["temiz", "cek-uye"], okur: ["uye_id", "kayit_gun"] },
];

const grupla = (d, f) => [...new Set(d.map(f))].map((a) => ({ a }));
const ISLEM = {
  temiz: ([o]) => o.filter((k) => k.sube_id !== null),
  zengin: ([o, e, s]) => {
    const t = new Map(e.map((k) => [k.id, k.tur])), b = new Map(s.map((k) => [k.id, k.bolge]));
    return o.map((k) => ({ ...k, tur: t.get(k.eser_id) ?? "yok", bolge: b.get(k.sube_id) ?? "yok" }));
  },
  "ozet-sube": ([o]) => grupla(o, (k) => `${k.bolge}|${k.gun}`),
  "ozet-uye": ([o]) => grupla(o, (k) => `${k.uye_id}|${Math.floor(k.gun / 30)}`),
};

// Hatti kostur: hata firlatan adim "kirik", girdisi saglam olmayan adim "durdu" olur.
export function kostur(dilim) {
  const cikti = new Map(), durum = new Map(), sayim = new Map();
  let tasinan = 0;
  for (const a of ADIMLAR) {
    if (a.girdi.some((g) => durum.get(g) !== "tamam")) { durum.set(a.ad, "durdu"); continue; }
    const girdiler = a.kaynak ? [dilim[a.kaynak]] : a.girdi.map((g) => cikti.get(g));
    const ornek = girdiler.filter((d) => d.length > 0).map((d) => d[0]);
    try {
      for (const alan of a.okur)
        if (ornek.every((k) => (alan in k) === false)) throw new Error(`eksik alan ${alan}`);
      const sonuc = a.kaynak ? girdiler[0] : ISLEM[a.ad](girdiler);
      const giren = girdiler.reduce((t, d) => t + d.length, 0);
      cikti.set(a.ad, sonuc); durum.set(a.ad, "tamam");
      sayim.set(a.ad, { giren, cikan: sonuc.length });
      tasinan += giren + sonuc.length;
    } catch (e) { durum.set(a.ad, `kirik: ${e.message}`); }
  }
  return { durum, sayim, tasinan };
}
```

## Ambar Yükü Alır, Karşılığında Gecikme Verir

Ambar bir çevrimde kaynakları okur, dönüştürür ve raporların okuyacağı özetleri bırakır. Bir
rapor ancak kabul ettiği gecikme ambarınkinden büyükse ambardan cevap alır. **TM12: hat saniyede
4.000 kayıt taşır; tazelik gecikmesi dönem ile koşum süresinin toplamıdır.** **TM13: artımlı
boyut yüklemesi değişim damgası üzerinde bir dizin varsayar.**

```js
// ambar/yuk.mjs — isletim sistemine dusen sorgu ve okunan kayit: ambarsiz ve ambarli
import { uret, RAPORLAR, raporOku, cek, kostur, GUN } from "./model.mjs";

const veri = uret();
const HIZ = 4000; // TM12: hat saniyede 4.000 kayit tasir
const olcum = Object.fromEntries(Object.entries(RAPORLAR).map(([a, r]) => [a, raporOku(veri, r)]));

console.log(`model: ${Object.entries(veri).map(([a, d]) => `${a} ${d.length}`).join(", ")}; ${GUN} gun`);
console.log("\nrapor          kosum/gun  sorgu/kosum  okunan/kosum  okunan/gun  tazelik (saat)");
console.log("-------------- ---------- ------------ ------------- ----------- ---------------");
let hamOkunan = 0, hamSorgu = 0;
for (const [ad, r] of Object.entries(RAPORLAR)) {
  const o = olcum[ad];
  hamOkunan += o.okunan * r.kosum; hamSorgu += o.sorgu * r.kosum;
  console.log(`${ad.padEnd(14)} ${String(r.kosum).padStart(10)} ${String(o.sorgu).padStart(12)} ` +
    `${String(o.okunan).padStart(13)} ${String(o.okunan * r.kosum).padStart(11)} ${String(r.tazelik).padStart(15)}`);
}
console.log(`ambarsiz toplam: ${hamSorgu} sorgu/gun, ${hamOkunan} okunan kayit/gun`);

console.log("\ndonem  boyut     kosum (sn)  gecikme  ambarda  isletimde  sorgu/gun  okunan/gun  ambarsiza gore");
console.log("------ --------- ---------- -------- -------- ---------- ---------- ----------- --------------");
const kalanlar = {};
for (const boyut of ["tam", "artimli"]) for (const donem of [24, 12, 3, 1]) {
  const c = cek(veri, donem, boyut);
  const kosum = kostur(c.dilim).tasinan / HIZ;
  const gecikme = donem + kosum / 3600, cevrim = 24 / donem;
  let sorgu = c.sorgu * cevrim, okunan = c.okunan * cevrim;
  const kalan = [];
  for (const [ad, r] of Object.entries(RAPORLAR)) {
    if (r.tazelik >= gecikme) continue;
    kalan.push(ad);
    sorgu += olcum[ad].sorgu * r.kosum; okunan += olcum[ad].okunan * r.kosum;
  }
  kalanlar[donem] = kalan;
  console.log(`${String(donem).padStart(6)} ${boyut.padEnd(9)} ${kosum.toFixed(1).padStart(10)} ` +
    `${gecikme.toFixed(2).padStart(8)} ${String(5 - kalan.length).padStart(8)} ${String(kalan.length).padStart(10)} ` +
    `${String(Math.round(sorgu)).padStart(10)} ${String(Math.round(okunan)).padStart(11)} ` +
    `${`${(okunan / hamOkunan * 100).toFixed(1)}%`.padStart(14)}`);
}
console.log(`\n24 saatlik donemde isletimde kalan rapor: ${kalanlar[24].join(", ")}`);
console.log(`3 saatlik donemde isletimde kalan rapor: ${kalanlar[3].join(", ")}`);
```

```
model: sube 12, eser 128000, uye 46000, odunc 240000; 180 gun

rapor          kosum/gun  sorgu/kosum  okunan/kosum  okunan/gun  tazelik (saat)
-------------- ---------- ------------ ------------- ----------- ---------------
doluluk                48            2          1326       63648               1
gecikmis-eser          24            2        168293     4039032               4
yeni-uye               12            1         46000      552000              14
etkinlik                2            2        165808      331616              36
devir                   1            3        368012      368012              72
ambarsiz toplam: 163 sorgu/gun, 5354308 okunan kayit/gun

donem  boyut     kosum (sn)  gecikme  ambarda  isletimde  sorgu/gun  okunan/gun  ambarsiza gore
------ --------- ---------- -------- -------- ---------- ---------- ----------- --------------
    24 tam            133.4    24.04        2          3        160     4830006          90.2%
    12 tam            131.9    12.04        3          2        152     4451992          83.1%
     3 tam            130.8     3.04        4          1        128     1456912          27.2%
     1 tam            130.6     1.04        4          1        192     4241160          79.2%
    24 artimli          3.6    24.00        2          3        160     4656902          87.0%
    12 artimli          1.8    12.00        3          2        152     4104854          76.7%
     3 artimli          0.4     3.00        4          1        128       65392           1.2%
     1 artimli          0.1     1.00        4          1        192       65160           1.2%

24 saatlik donemde isletimde kalan rapor: doluluk, gecikmis-eser, yeni-uye
3 saatlik donemde isletimde kalan rapor: doluluk
```

İlk tablo yükün nerede olduğunu gösteriyor. Günde 163 sorgu ve 5.354.308 okunan kayıt var; bunun
4.039.032'si, yani yüzde yetmiş beşi **tek bir rapordan** geliyor. Sebebi koşum sayısı değil,
koşum başına okunan kayıt: gecikmiş eser listesi her koşumda katalogun 128.000 satırını tarıyor.
Günde 48 kez koşan doluluk raporu toplamın yüzde birini bile bulmuyor.

İkinci tablo ambarın devraldığı payı dönem dönem sayıyor ve iki yönlü bir eğri çıkarıyor. Dönem
kısaldıkça gecikme düşüyor, gecikme düştükçe daha çok rapor ambardan cevap alabiliyor: ikiden
dörde. Ama çevrim sayısı da artıyor ve her çevrim kaynakları yeniden okuyor. Tam boyut
yüklemesinde okunan kayıt 24 saatlik dönemde yüzde 90,2, 3 saatlikte yüzde 27,2, 1 saatlikte
yeniden yüzde 79,2. En ucuz nokta uçlarda değil, ortada.

Asıl belirleyici sütun **boyut**. Aynı dönemde artımlı yükleme yüzde 27,2'yi yüzde 1,2'ye
indiriyor, çünkü katalogun 128.000 satırı her çevrimde değil yalnız değişen kısmıyla okunuyor.
İşletim yükünün düşüp düşmeyeceğini ambarın varlığı değil, kaynakları nasıl okuduğu belirliyor.

Bir rapor hiçbir dönemde ambara geçmiyor: doluluk raporunun kabul ettiği gecikme bir saat, en
kısa dönemin gecikmesi 1,04 saat. Tazelik gereksinimi, ambarın kapsayamadığı yolu tanımlar.

## Hattın Adımları ve Kaynak Şemasındaki Değişim

Hat sekiz adımdır ve her adım okuduğu alanı bildirir. Kaynak şemasındaki bir alan değişimi
gerçekten uygulanır: alan yeniden adlandırılır ya da kaldırılır, hat koşturulur ve kırılan
adım sayılır.

```js
// ambar/kirilma.mjs — adim adim tasinan kayit ve kaynak sema degisiminin kirdigi adim
import { uret, RAPORLAR, cek, kostur, ADIMLAR, SAHIP } from "./model.mjs";

const veri = uret(), DONEM = 3;
const { dilim } = cek(veri, DONEM, "tam");
const temiz = kostur(dilim);
const gecikme = DONEM + temiz.tasinan / 4000 / 3600;

console.log("adim         girdi                       giren    cikan");
console.log("------------ ------------------------ -------- --------");
for (const a of ADIMLAR) {
  const s = temiz.sayim.get(a.ad);
  console.log(`${a.ad.padEnd(12)} ${(a.kaynak ?? a.girdi.join(",")).padEnd(24)} ` +
    `${String(s.giren).padStart(8)} ${String(s.cikan).padStart(8)}`);
}
console.log(`bir cevrimde ${ADIMLAR.length} adim ${temiz.tasinan} kayit tasidi; gecikme ${gecikme.toFixed(2)} saat`);

// Uc sema degisimi uygulanir: alan yeniden adlandirilir ya da kaldirilir.
const DEGISIM = {
  "eser.tur -> eser.tur_kodu": { varlik: "eser", alan: "tur", yeni: "tur_kodu" },
  "odunc.sube_id -> odunc.sube": { varlik: "odunc", alan: "sube_id", yeni: "sube" },
  "uye.kayit_gun kaldirildi": { varlik: "uye", alan: "kayit_gun", yeni: null },
};
const uygula = (d, g) => ({ ...d, [g.varlik]: d[g.varlik].map((k) => {
  const y = { ...k }; delete y[g.alan]; if (g.yeni) y[g.yeni] = k[g.alan]; return y; }) });

console.log("\ndegisim                       sahip                        kirik  duran  saglam  ambarda dusen  ambarsiz kirilan");
console.log("----------------------------- --------------------------- ------ ------ ------- -------------- -----------------");
for (const [ad, g] of Object.entries(DEGISIM)) {
  const d = [...kostur(uygula(dilim, g)).durum];
  const say = (f) => d.filter(([, v]) => f(v)).length;
  const bozuk = new Set(d.filter(([, v]) => v !== "tamam").map(([k]) => k));
  const dusen = Object.values(RAPORLAR).filter((r) => bozuk.has(r.dayanak)).length;
  const ambarsiz = Object.values(RAPORLAR).filter((r) => r.alan === `${g.varlik}.${g.alan}`).length;
  console.log(`${ad.padEnd(29)} ${SAHIP[g.varlik].padEnd(27)} ${String(say((v) => v.startsWith("kirik"))).padStart(6)} ` +
    `${String(say((v) => v === "durdu")).padStart(6)} ${String(say((v) => v === "tamam")).padStart(7)} ` +
    `${String(dusen).padStart(14)} ${String(ambarsiz).padStart(17)}`);
}

// Bag: ambarsiz rapor okudugu her kaynaga baglanir; ambarli kaynak yalniz hatta baglanir.
const bagsiz = Object.values(RAPORLAR).flatMap((r) => Object.keys(r.okur));
const kalan = Object.values(RAPORLAR).filter((r) => r.tazelik < gecikme);
const kalanBag = kalan.flatMap((r) => Object.keys(r.okur));
console.log(`\nbag: ambarsiz ${bagsiz.length} (rapor -> kaynak); ambarli ${4 + (5 - kalan.length) + kalanBag.length} ` +
  `(4 cekim + ${5 - kalan.length} ambar okumasi + ${kalanBag.length} kalan dogrudan okuma)`);
console.log(`yonetim biriminin konustugu sahip: ambarsiz ${new Set(bagsiz).size}, ` +
  `ambarli ${new Set(["ambar", ...kalanBag]).size}`);
```

```
adim         girdi                       giren    cikan
------------ ------------------------ -------- --------
cek-odunc    odunc                         146      146
cek-uye      uye                         46000    46000
cek-eser     eser                       128000   128000
cek-sube     sube                           12       12
temiz        cek-odunc                     146      144
zengin       temiz,cek-eser,cek-sube    128156      144
ozet-sube    zengin                        144        4
ozet-uye     temiz,cek-uye               46144      143
bir cevrimde 8 adim 523341 kayit tasidi; gecikme 3.04 saat

degisim                       sahip                        kirik  duran  saglam  ambarda dusen  ambarsiz kirilan
----------------------------- --------------------------- ------ ------ ------- -------------- -----------------
eser.tur -> eser.tur_kodu     katalog (disaridan alinmis)      1      2       5              3                 2
odunc.sube_id -> odunc.sube   odunc servisi (iceride)          1      4       3              5                 1
uye.kayit_gun kaldirildi      uyelik sistemi                   1      1       6              2                 2

bag: ambarsiz 10 (rapor -> kaynak); ambarli 10 (4 cekim + 4 ambar okumasi + 2 kalan dogrudan okuma)
yonetim biriminin konustugu sahip: ambarsiz 4, ambarli 3
```

Adım tablosu maliyetin nereden geldiğini gösteriyor. Üç saatlik çevrimde ödünç tarafından yalnız
146 kayıt geliyor, ama taşınan toplam 523.341. Farkın tamamı boyut okumasıdır: `zengin` adımına
128.156 kayıt giriyor, çünkü 144 ödünç kaydını zenginleştirmek için katalogun tamamı okunuyor.
`temiz` adımı 146 kayıttan 144'ünü geçiriyor; şubesi boş kalan iki kayıt düşüyor.

Kırılma tablosu bu kursun sorusunu veriyor. Üç değişimin üçü de tek bir alanı ilgilendiriyor ve
üçü de hattın **tek** adımını kırıyor. Fark, kırığın nerede durduğudur. Katalogun alanı
kırıldığında iki adım daha duruyor ve üç rapor cevapsız kalıyor; ambarsız durumda o alanı iki
rapor kullanıyordu. Ödünç servisinin alanı kırıldığında dört adım duruyor ve **beş raporun beşi**
düşüyor — oysa o alanı doğrudan okuyan tek rapor vardı. Üyelik alanında iki sayı eşitleniyor.

Ambar, aynı kaynağı okuyan raporları birbirine bağlar. Doluluk raporu katalogun tür alanını hiç
kullanmaz; ambarsız durumda o değişimden etkilenmezdi, ambarlı durumda `ozet-sube` adımı `zengin`
adımının ardında durduğu için etkilenir. Karşılığı düzeltmenin yerindedir: kırık tek bir adımdır
ve tek bir ekibin sorumluluğundadır. Ambarsız durumda aynı düzeltme, ayrı yazılmış rapor
sorgularının her birinde ayrı ayrı yapılır.

Son satırlar bağı sayıyor. Bağ sayısı değişmiyor: ambarsız 10, ambarlı 10. Değişen yönü ve
sahibi. Yönetim birimi ambarsız durumda dört sahiple, ambarlı durumda üçüyle konuşur; kalan iki
sahip ambarın karşılayamadığı doluluk raporu yüzündendir. Tümleştirme noktası bağ sayısını
azaltmaz, koordinasyonun kiminle yapılacağını değiştirir.

## Özet

- Beş rapor işletim sistemine günde 163 sorgu ve 5.354.308 okunan kayıt bindiriyor; bunun yüzde
  yetmiş beşi tek bir rapordan geliyor, çünkü o rapor her koşumda katalogun 128.000 satırını
  tarıyor (TM10, TM11).
- Dönem kısaldıkça ambardan cevaplanan rapor ikiden dörde çıkıyor, ama çevrim sayısı arttığı için
  okunan kayıt yüzde 27,2'den yüzde 79,2'ye geri tırmanıyor; en ucuz dönem uçlarda değil ortadadır.
- Artımlı boyut yüklemesi aynı dönemde işletim yükünü yüzde 27,2'den yüzde 1,2'ye indiriyor;
  belirleyici olan ambarın varlığı değil kaynakları nasıl okuduğudur (TM13).
- Tazelik gereksinimi bir saat olan rapor hiçbir dönemde ambara geçmiyor, çünkü en kısa dönemin
  gecikmesi 1,04 saat. Ambar kapsayamadığı yolu böyle bildirir (TM12).
- Sekiz adımlık hat bir çevrimde 523.341 kayıt taşıyor; kaynaktaki tek bir alan değişimi tek bir
  adımı kırıyor, ama ödünç alanında kırığın ardında dört adım durduğu için beş raporun beşi
  düşüyor — o alanı doğrudan okuyan tek rapor vardı (TM14).

## Sonraki Adım

Bu dersin ölçümleri bir varsayıma yaslanıyordu: kaynak sistemlerin alanları biliniyor ve şema
değişimi bir hata iletisiyle görünüyor. Ağdaki her sistem böyle değil. Ödünç geçmişini yıllardır
tutan, kaynak koduna kimsenin erişemediği bir kayıt sistemi duruyor. Sıradaki ders bunu ele alır:
değiştirilemeyen bir sistemin çağrı yüzeyi sarmalanınca kaç yol kapanır, kaç yol sarmalayıcının
dışında kalır, veri sahipliği devredilirken iki sistemin birlikte yazdığı pencere ne kadar sürer.
