---
title: 'Kalıcılık Bağımsız Alan Modeli'
source: 'https://academia.sh/tr/kurslar/veri-erisim-katmani/kaliciliktan-bagimsiz-alan-modeli'
course: 'Veri Erişim Katmanı ve İş Mantığı'
language: tr
updated: '2026-08-17T18:06:50+00:00'
license: 'CC BY-SA 4.0'
---

# Kalıcılık Bağımsız Alan Modeli

İş kurallarının saf fonksiyonlarla yazılması: veritabanısız ve veritabanına bağlı iki sürümün karar eşitliği, 64 durumluk taramada süre oranı ve alan modülündeki kalıcılık izinin sayılması.

Bu konudaki dört ders alan katmanını adım adım yalnızlaştırdı: bağımlılık yönü kuralıyla
altyapıdan, veri aktarım nesneleriyle dış sözleşmeden, doğrulama ayrımıyla girdi biçiminden,
olaylarla yan etkilerden ayrıldı.

Geriye son bir bağ kalıyor. Kurallar hâlâ bir depo alıyor ve sınanmak için bir veritabanı
bekliyor. Depo bir sözleşmedir; ama kural onu **çağırdığı** sürece hangi sorguların hangi
sırayla doğacağı kuralın parçası olmayı sürdürür. Bu ders son bağı keser: kural veriyi
kendisi istemez, kendisine verilir.

## Kuralın Girdisi Durumun Kendisi

Aşağıdaki modülde kural bir depo değil, kararı vermek için gereken bilginin tamamını taşıyan
düz bir nesne alır. Bileşen Tabanlı Arayüz Geliştirme kursunda tanımlanan **saf fonksiyon**
(pure function) tanımına uyar: aynı girdiye aynı çıktıyı verir, dışarıda bir şey değiştirmez.
Dersin dosyaları iki dizine yerleşir.

```sh
mkdir -p alan bagli
```

```js
// alan/odunc-kurallari.mjs — is kurallari saf islevler olarak
export const UYE_SINIRI = 3;
export const ODUNC_GUNU = 14;
export const GUNLUK_CEZA = 2;

export function gunEkle(tarih, gun) {
  return new Date(Date.parse(tarih) + gun * 86400000).toISOString().slice(0, 10);
}

// durum: { uyeVarMi, uyeDurumu, uyeAcikSayisi, kitapVarMi, kitapAcikMi }
export function oduncKarari(durum, bugun) {
  if (!durum.uyeVarMi) return { sonuc: "reddedildi", sebep: "uye_yok" };
  if (durum.uyeDurumu === "askida") return { sonuc: "reddedildi", sebep: "uye_askida" };
  if (!durum.kitapVarMi) return { sonuc: "reddedildi", sebep: "kitap_yok" };
  if (durum.kitapAcikMi) return { sonuc: "reddedildi", sebep: "kitap_oduncte" };
  if (durum.uyeAcikSayisi >= UYE_SINIRI) return { sonuc: "reddedildi", sebep: "uye_siniri" };
  return { sonuc: "kabul", sonTeslimTarihi: gunEkle(bugun, ODUNC_GUNU) };
}

// kayit: { sonTeslimTarihi, iadeTarihi }
export function gecikmeGunu(kayit, bugun) {
  const bitis = kayit.iadeTarihi ?? bugun;
  return Math.max(0, Math.round((Date.parse(bitis) - Date.parse(kayit.sonTeslimTarihi)) / 86400000));
}

export function ceza(kayit, bugun) {
  return gecikmeGunu(kayit, bugun) * GUNLUK_CEZA;
}
```

İki ayrıntı önemlidir. Bugünün tarihi de dışarıdan geliyor; kural sistem saatini okumaz,
yoksa çıktısı çalıştırma anına bağlı olurdu. `durum` nesnesi ise bir **anlık görüntüdür**
(snapshot): veriyi toplamak uygulama katmanının işidir, kural toplanmış bilgiyi yorumlar.

## Veritabanısız Sınama

Kuralın sınanması için kurulacak hiçbir şey yoktur.

```js
// saf.test.mjs — kurallar veritabani olmadan sinanir
import { test } from "node:test";
import assert from "node:assert/strict";
import { oduncKarari, gecikmeGunu, ceza, gunEkle } from "./alan/odunc-kurallari.mjs";

const UYGUN = { uyeVarMi: true, uyeDurumu: "aktif", uyeAcikSayisi: 0,
                kitapVarMi: true, kitapAcikMi: false };
const BUGUN = "2025-06-20";

test("uygun durumda odunc verilir ve son teslim tarihi hesaplanir", () => {
  assert.deepEqual(oduncKarari(UYGUN, BUGUN),
                   { sonuc: "kabul", sonTeslimTarihi: "2025-07-04" });
});

test("askiya alinmis uye odunc alamaz", () => {
  assert.equal(oduncKarari({ ...UYGUN, uyeDurumu: "askida" }, BUGUN).sebep, "uye_askida");
});

test("acik kaydi olan kitap yeniden verilemez", () => {
  assert.equal(oduncKarari({ ...UYGUN, kitapAcikMi: true }, BUGUN).sebep, "kitap_oduncte");
});

test("uye siniri asilinca reddedilir, sinirin altinda kabul edilir", () => {
  assert.equal(oduncKarari({ ...UYGUN, uyeAcikSayisi: 3 }, BUGUN).sebep, "uye_siniri");
  assert.equal(oduncKarari({ ...UYGUN, uyeAcikSayisi: 2 }, BUGUN).sonuc, "kabul");
});

test("ret sebepleri oncelik sirasina gore verilir", () => {
  const hepsiBozuk = { uyeVarMi: true, uyeDurumu: "askida", uyeAcikSayisi: 9,
                       kitapVarMi: false, kitapAcikMi: true };
  assert.equal(oduncKarari(hepsiBozuk, BUGUN).sebep, "uye_askida");
});

test("gecikme ve ceza iade tarihine gore hesaplanir", () => {
  const kayit = { sonTeslimTarihi: "2025-06-15", iadeTarihi: null };
  assert.equal(gecikmeGunu(kayit, BUGUN), 5);
  assert.equal(ceza(kayit, BUGUN), 10);
  assert.equal(ceza({ ...kayit, iadeTarihi: "2025-06-14" }, BUGUN), 0);
});

test("gun ekleme ay sinirini gecer", () => {
  assert.equal(gunEkle("2025-06-25", 14), "2025-07-09");
});
```

```sh
node --test saf.test.mjs
```

```
✔ uygun durumda odunc verilir ve son teslim tarihi hesaplanir (2.14ms)
✔ askiya alinmis uye odunc alamaz (0.062375ms)
✔ acik kaydi olan kitap yeniden verilemez (0.041792ms)
✔ uye siniri asilinca reddedilir, sinirin altinda kabul edilir (0.045375ms)
✔ ret sebepleri oncelik sirasina gore verilir (0.042625ms)
✔ gecikme ve ceza iade tarihine gore hesaplanir (0.052542ms)
✔ gun ekleme ay sinirini gecer (0.032916ms)
ℹ tests 7
ℹ suites 0
ℹ pass 7
ℹ fail 0
ℹ cancelled 0
ℹ skipped 0
ℹ todo 0
ℹ duration_ms 36.177083
```

Süre alanları makineye ve o anki yüke bağlıdır; anlamlı olan `pass 7` satırıdır. Her
sınamanın kurulumu tek bir nesne değişikliğidir.

## Aynı Kural, Veritabanına Bağlı

Aynı kurallar veriyi kendisi çeken bir sürümle de yazıldı.

```js
// bagli/odunc-kurallari.mjs — ayni kurallar, dogrudan veritabanina bagli
import { DatabaseSync } from "node:sqlite";

export const UYE_SINIRI = 3;
export const ODUNC_GUNU = 14;
export const GUNLUK_CEZA = 2;

export class BagliKurallar {
  constructor(dosya) { this.db = new DatabaseSync(dosya); }

  oduncKarari(uyeId, kitapId, bugun) {
    const uye = this.db.prepare("SELECT durum FROM uye WHERE uye_id = ?").get(uyeId);
    if (uye === undefined) return { sonuc: "reddedildi", sebep: "uye_yok" };
    if (uye.durum === "askida") return { sonuc: "reddedildi", sebep: "uye_askida" };
    const kitap = this.db.prepare("SELECT kitap_id FROM kitap WHERE kitap_id = ?").get(kitapId);
    if (kitap === undefined) return { sonuc: "reddedildi", sebep: "kitap_yok" };
    const acik = this.db.prepare(
      "SELECT odunc_id FROM odunc WHERE kitap_id = ? AND iade_tarihi IS NULL").get(kitapId);
    if (acik !== undefined) return { sonuc: "reddedildi", sebep: "kitap_oduncte" };
    const sayi = this.db.prepare(
      "SELECT count(*) AS n FROM odunc WHERE uye_id = ? AND iade_tarihi IS NULL").get(uyeId).n;
    if (sayi >= UYE_SINIRI) return { sonuc: "reddedildi", sebep: "uye_siniri" };
    return { sonuc: "kabul", sonTeslimTarihi: this.db.prepare(
      "SELECT date(?, ?) AS t").get(bugun, `+${ODUNC_GUNU} days`).t };
  }

  ceza(oduncId, bugun) {
    const k = this.db.prepare(
      "SELECT son_teslim_tarihi, iade_tarihi FROM odunc WHERE odunc_id = ?").get(oduncId);
    const gun = this.db.prepare("SELECT max(0, julianday(coalesce(?, ?)) - julianday(?)) AS g")
      .get(k.iade_tarihi, bugun, k.son_teslim_tarihi).g;
    return Math.round(gun) * GUNLUK_CEZA;
  }
}
```

Aynı yedi sınama bu sürüm için yazıldığında kurulum büyür: her durum için şema kurulur ve
satırlar yazılır.

```js
// bagli.test.mjs — ayni kurallar; her sinama once semayi ve satirlari kurar
import { test } from "node:test";
import assert from "node:assert/strict";
import { DatabaseSync } from "node:sqlite";
import { rmSync } from "node:fs";
import { BagliKurallar } from "./bagli/odunc-kurallari.mjs";

const BUGUN = "2025-06-20";
const SEMA = `
CREATE TABLE uye (uye_id INTEGER PRIMARY KEY, ad TEXT NOT NULL, durum TEXT NOT NULL);
CREATE TABLE kitap (kitap_id INTEGER PRIMARY KEY, baslik TEXT NOT NULL);
CREATE TABLE odunc (odunc_id INTEGER PRIMARY KEY, kitap_id INTEGER NOT NULL,
                    uye_id INTEGER NOT NULL, alis_tarihi TEXT NOT NULL,
                    son_teslim_tarihi TEXT NOT NULL, iade_tarihi TEXT);`;

let sayac = 0;
function kur(satirlar = []) {
  const dosya = `sinama-${sayac++}.db`;
  rmSync(dosya, { force: true });
  const db = new DatabaseSync(dosya);
  db.exec(SEMA);
  db.exec(`INSERT INTO uye VALUES (1,'Ayse Demir','aktif'),(2,'Bora Kaya','askida');
           INSERT INTO kitap VALUES (1,'Korluk'),(2,'Tutunamayanlar'),(3,'Kum Kitabi'),
                                    (4,'Puslu Kitalar');`);
  for (const s of satirlar) {
    db.prepare(`INSERT INTO odunc (kitap_id, uye_id, alis_tarihi, son_teslim_tarihi, iade_tarihi)
                VALUES (?,?,?,?,?)`).run(...s);
  }
  return new BagliKurallar(dosya);
}

test("uygun durumda odunc verilir ve son teslim tarihi hesaplanir", () => {
  assert.deepEqual(kur().oduncKarari(1, 1, BUGUN),
                   { sonuc: "kabul", sonTeslimTarihi: "2025-07-04" });
});

test("askiya alinmis uye odunc alamaz", () => {
  assert.equal(kur().oduncKarari(2, 1, BUGUN).sebep, "uye_askida");
});

test("acik kaydi olan kitap yeniden verilemez", () => {
  const k = kur([[1, 2, "2025-06-01", "2025-06-15", null]]);
  assert.equal(k.oduncKarari(1, 1, BUGUN).sebep, "kitap_oduncte");
});

test("uye siniri asilinca reddedilir, sinirin altinda kabul edilir", () => {
  const uc = [[1, 1, "2025-06-01", "2025-06-15", null], [2, 1, "2025-06-02", "2025-06-16", null],
              [3, 1, "2025-06-03", "2025-06-17", null]];
  assert.equal(kur(uc).oduncKarari(1, 4, BUGUN).sebep, "uye_siniri");
  assert.equal(kur(uc.slice(0, 2)).oduncKarari(1, 4, BUGUN).sonuc, "kabul");
});

test("ret sebepleri oncelik sirasina gore verilir", () => {
  const k = kur([[1, 2, "2025-06-01", "2025-06-15", null]]);
  assert.equal(k.oduncKarari(2, 9, BUGUN).sebep, "uye_askida");
});

test("gecikme ve ceza iade tarihine gore hesaplanir", () => {
  const k = kur([[1, 1, "2025-06-01", "2025-06-15", null],
                 [2, 1, "2025-06-01", "2025-06-15", "2025-06-14"]]);
  assert.equal(k.ceza(1, BUGUN), 10);
  assert.equal(k.ceza(2, BUGUN), 0);
});

test("gun ekleme ay sinirini gecer", () => {
  assert.equal(kur().oduncKarari(1, 1, "2025-06-25").sonTeslimTarihi, "2025-07-09");
});
```

```sh
node --test bagli.test.mjs
```

```
✔ uygun durumda odunc verilir ve son teslim tarihi hesaplanir (2.6345ms)
✔ askiya alinmis uye odunc alamaz (1.349208ms)
✔ acik kaydi olan kitap yeniden verilemez (1.527292ms)
✔ uye siniri asilinca reddedilir, sinirin altinda kabul edilir (3.39825ms)
✔ ret sebepleri oncelik sirasina gore verilir (1.243084ms)
✔ gecikme ve ceza iade tarihine gore hesaplanir (1.518125ms)
✔ gun ekleme ay sinirini gecer (1.096625ms)
ℹ tests 7
ℹ suites 0
ℹ pass 7
ℹ fail 0
ℹ cancelled 0
ℹ skipped 0
ℹ todo 0
ℹ duration_ms 47.056833
```

İki toplam süre yakın, çünkü ikisinde de sürenin çoğunu çalışma ortamının açılışı alıyor.
Fark tek tek sınamalarda: saf sınamalar milisaniyenin onda biri altında, bağlı sınamalar bir
ile üç milisaniye arasında. Yedi sınamada bu önemsizdir; asıl soru sayı büyüdüğünde ne
olduğudur.

## Bütün Durumların Taranması

Kuralın beş girdisinin birleşimi altmış dört durum üretiyor. Saf sürüm bu durumları doğrudan
üretebilir; bağlı sürüm her durum için veritabanını o duruma getirmek zorundadır. Aşağıdaki
betik ikisini de çalıştırır, kararları karşılaştırır ve süreyi ölçer.

```js
// tarama.mjs — ayni 64 durumun iki surumle taranmasi: karar esitligi ve sure
import { DatabaseSync } from "node:sqlite";
import { rmSync } from "node:fs";
import { oduncKarari } from "./alan/odunc-kurallari.mjs";
import { BagliKurallar } from "./bagli/odunc-kurallari.mjs";

const BUGUN = "2025-06-20";
const DURUMLAR = [];
for (const uyeVarMi of [true, false])
  for (const uyeDurumu of ["aktif", "askida"])
    for (const kitapVarMi of [true, false])
      for (const kitapAcikMi of [true, false])
        for (const uyeAcikSayisi of [0, 1, 2, 3])
          DURUMLAR.push({ uyeVarMi, uyeDurumu, kitapVarMi, kitapAcikMi, uyeAcikSayisi });

rmSync("tarama.db", { force: true });
const db = new DatabaseSync("tarama.db");
db.exec(`CREATE TABLE uye (uye_id INTEGER PRIMARY KEY, durum TEXT NOT NULL);
         CREATE TABLE kitap (kitap_id INTEGER PRIMARY KEY, baslik TEXT NOT NULL);
         CREATE TABLE odunc (odunc_id INTEGER PRIMARY KEY, kitap_id INTEGER NOT NULL,
                             uye_id INTEGER NOT NULL, alis_tarihi TEXT NOT NULL,
                             son_teslim_tarihi TEXT NOT NULL, iade_tarihi TEXT);`);
const bagli = new BagliKurallar("tarama.db");

function durumuKur(d) {
  db.exec("DELETE FROM odunc; DELETE FROM uye; DELETE FROM kitap;");
  if (d.uyeVarMi) db.prepare("INSERT INTO uye VALUES (1,?)").run(d.uyeDurumu);
  if (d.kitapVarMi) db.prepare("INSERT INTO kitap VALUES (1,'Korluk')").run();
  const ekle = db.prepare(`INSERT INTO odunc (kitap_id, uye_id, alis_tarihi,
                           son_teslim_tarihi, iade_tarihi)
                           VALUES (?,?,'2025-06-01','2025-06-15',NULL)`);
  if (d.kitapAcikMi) ekle.run(1, 2);                      // kitap 1 baska bir uyede
  for (let i = 0; i < d.uyeAcikSayisi; i++) ekle.run(100 + i, 1);
}

const olc = (islev) => { const t = performance.now(); islev(); return performance.now() - t; };

let safKararlar, bagliKararlar;
const safSure = olc(() => { safKararlar = DURUMLAR.map((d) => oduncKarari(d, BUGUN)); });
const bagliSure = olc(() => {
  bagliKararlar = DURUMLAR.map((d) => { durumuKur(d); return bagli.oduncKarari(1, 1, BUGUN); });
});

const ayrilan = DURUMLAR.filter((_, i) =>
  JSON.stringify(safKararlar[i]) !== JSON.stringify(bagliKararlar[i]));

console.log(`durum sayisi = ${DURUMLAR.length}`);
console.log(`iki surumun ayrildigi durum = ${ayrilan.length}`);
console.log(`saf surum   : ${safSure.toFixed(1)} ms  (durum basina ${(safSure / DURUMLAR.length).toFixed(4)} ms)`);
console.log(`bagli surum : ${bagliSure.toFixed(1)} ms  (durum basina ${(bagliSure / DURUMLAR.length).toFixed(4)} ms)`);
console.log(`oran = ${(bagliSure / safSure).toFixed(0)}x`);
```

```sh
node tarama.mjs
```

```
durum sayisi = 64
iki surumun ayrildigi durum = 0
saf surum   : 0.6 ms  (durum basina 0.0097 ms)
bagli surum : 71.4 ms  (durum basina 1.1153 ms)
oran = 115x
```

Birinci sonuç doğrulukla ilgilidir: altmış dört durumun hiçbirinde iki sürüm ayrılmadı. Saf
sürüm bir sadeleştirme değil, aynı kuralın başka bir yazımıdır.

İkincisi süredir. Mutlak değerler makineye ve dosya sistemine bağlıdır; aynı betiğin ikinci
çalıştırmasında oran 127 kat çıktı. Değişmeyen, oranın büyüklük mertebesidir: durum başına
maliyet iki basamak farklıdır. Pratik karşılığı, sınanacak durum sayısının serbest
kalmasıdır. Kural karmaşıklaştıkça durum sayısı katlanarak büyür ve bu fark, hangi
durumların sınanacağını belirlemeye başlar.

## Kalıcılık İzinin Ölçülmesi

Bağımsızlık iddiası taranarak denetlenir. Depo Kalıbı dersindeki sayım burada üç ölçüte
ayrılıyor: SQL deyimi, tablo adı ve sürücü ithali.

```js
// iz-tara.mjs — modul basina kalicilik izi: SQL, tablo adi, surucu ithali
import { readFileSync } from "node:fs";

const SQL = /\b(SELECT|INSERT INTO|UPDATE|DELETE FROM|CREATE TABLE)\b/g;
const TABLO = /\b(?:FROM|INTO|UPDATE|TABLE)\s+([a-z_]+)/g;
const SURUCU = /node:sqlite/g;

const DOSYALAR = ["alan/odunc-kurallari.mjs", "saf.test.mjs",
                  "bagli/odunc-kurallari.mjs", "bagli.test.mjs"];

console.log("dosya                        SQL  tablo  surucu  tablo adlari");
for (const dosya of DOSYALAR) {
  const metin = readFileSync(dosya, "utf8");
  const sql = (metin.match(SQL) ?? []).length;
  const tablolar = [...new Set([...metin.matchAll(TABLO)].map((m) => m[1]))].sort();
  const surucu = (metin.match(SURUCU) ?? []).length;
  console.log(`${dosya.padEnd(28)}${String(sql).padStart(3)}  ${String(tablolar.length).padStart(5)}` +
              `  ${String(surucu).padStart(6)}  ${tablolar.join(", ")}`);
}
```

```sh
node iz-tara.mjs
```

```
dosya                        SQL  tablo  surucu  tablo adlari
alan/odunc-kurallari.mjs      0      0       0  
saf.test.mjs                  0      0       0  
bagli/odunc-kurallari.mjs     7      3       1  kitap, odunc, uye
bagli.test.mjs                6      3       1  kitap, odunc, uye
```

Alan modülünde üç ölçüt de sıfır. Sınama dosyasında da sıfır olması ayrıca anlamlıdır:
kuralın sınanması için kalıcılık bilgisi gerekmedi. Bağlı sürümde tablo
adları hem kural modülüne hem sınama dosyasına yayılmış; şemada `odunc` tablosuna bir sütun
eklendiğinde iki dosya birden etkilenir.

Ölçüm kaba bir araçtır. Bir modül SQL yazmadan da kalıcılığa bağlanabilir: satır sırasının
veritabanının döndürdüğü sıra olduğunu varsaymak ya da kimliğin veritabanı tarafından
üretileceğini beklemek de birer bağımlılıktır. Sayının işlevi, bağın nereye kadar çekildiğini
görünür kılmaktır.

## Anlık Görüntünün Sınırı

Saf kural bedelsiz değildir; anlık görüntüyü toplama sorumluluğunu uygulama katmanına taşır.
İki tuzağı vardır: kararın kullanmayacağı alanların da çekilmesi (Aşırı Veri Çekme dersindeki
maliyet) ve anlık görüntünün bayatlaması — okunduğu andaki durum, yazma yapılana kadar
değişmiş olabilir. İkincisi Doğrulama Katmanları dersindeki denetle–sonra–yaz açığıdır;
çözümü aynıdır: karar ile yazma aynı işlem sınırında kalır, kritik değişmezler veritabanı
kısıtıyla güvenceye alınır.

Karşı uç da vardır. Alan modeli yalnızca veri taşıyan, hiçbir karar vermeyen bir kabuğa
indirgenirse kurallar yeniden çağrı noktalarına dağılır. Ölçüt şudur: **kararı veren kod ile
kararın dayandığı veriyi tanımlayan kod aynı modülde olmalıdır.**

## Özet

- Kural, depo çağırmak yerine kararı vermek için gereken bilgiyi taşıyan bir anlık görüntü
  alır; bugünün tarihi de dışarıdan geldiği için işlev saf kalır.
- Yedi sınama veritabanı, şema ve bağlantı olmadan çalıştı; her kurulum tek bir nesne
  değişikliğidir.
- Altmış dört durumun tamamında saf sürüm ile bağlı sürüm aynı kararı verdi; saf sürüm bir
  sadeleştirme değil, aynı kuralın başka yazımıdır.
- Durum başına maliyet iki basamak farklı çıktı (ölçülen oran 115 ve 127 kat); mutlak süreler
  ortama bağlıdır, değişmeyen büyüklük mertebesidir.
- Alan modülünde ve sınamasında SQL, tablo adı ve sürücü ithali sayısı sıfır; bağlı sürümde
  tablo adları hem kural hem sınama dosyasına yayılmış durumda.

## Kurs Kapanışı

Kurs veri erişimini dört soruyla ele aldı ve her birini ölçerek yanıtladı.

**Veri erişim yaklaşımları** sorgunun nerede yazılacağını sordu: doğrudan sorgu ile eşleyici
ödünleşimi, nesne–ilişki uyumsuzluğu, kararları tek yerde toplayan depo, ölçütü nesneleştiren
belirtimler, bağlantı havuzunun doygunluk davranışı ve genişlet–daralt göçü.

**İşlemler ve tutarlılık** iş biriminin sınırını sordu: sınırın servis katmanında tutulması,
yalıtım düzeyinin uygulamadan görünen etkisi, iyimser ve kötümser kilitlemenin deneme ve
süre farkı, atomikliğin servis sınırını geçememesi ve yeniden denemeyi güvenli kılan etkisiz
biçimler.

**Başarım sorunları** katmanın maliyetini sordu: N+1 sorgu sorunu, aşırı veri çekme, toplu
işlemler, uygulamadan görülen sorgu planı ve derin sayfalamanın maliyeti.

**İş mantığı yerleşimi** ise kuralın nerede duracağını sordu. Bağımlılık yönü ithal grafiği
üzerinden denetlendi, dış sözleşme iç modelden ayrıldı, girdi doğrulaması ile alan kuralı
ürettikleri yanıt ve maliyetle ayrıştırıldı, yan etkiler olaylara bağlandı ve kurallar
kalıcılıktan koparıldı.

Kursun bıraktığı yerde bir varsayım duruyor: her istek verinin kaynağına gidiyor ve her iş
isteğin içinde bitiyor. İkisi de her zaman tutmaz. Aynı sorgunun yanıtı defalarca
üretiliyorsa saklanabilir; bildirim gönderme, rapor üretme, dosya işleme gibi işler isteğin
yanıtını bekletmeden yürütülebilir. Alan Olayları dersindeki giden kutusu bunun ilk adımıydı.

Sonraki kurs olan **Önbellekleme, Kuyruklar ve Eşzamansız İşleme** bu iki yolu ele alır:
önbellek katmanları ve geçersizleştirme stratejileri, mesaj kuyruğu ile akış arasındaki fark,
arka plan işlerinin yeniden deneme ve ölü mektup kutusuyla dayanıklı kurulması. Bu kursta
ölçülen kavramlar orada yeniden karşımıza çıkar: işlem sınırı, etkisizlik ve kalıcılıktan
bağımsız kurallar, eşzamansız işlemenin ön koşuludur.
