İçeriğe geç
academia.sh

Ders 21 / 21

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ı.

İçindekiler

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.

mkdir -p alan bagli
// 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.

// 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");
});
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ı.

// 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.

// 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");
});
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.

// 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`);
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.

// 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(", ")}`);
}
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.

İlerlemeni kaydetmek ve not almak için Giriş yap

Notlarım

Not almak için giriş yapmalısın.

Aramak için yazmaya başlayın.

↑↓ Esc gezin · aç · kapat