İçeriğe geç
academia.sh

Ders 01 / 20

Arıza Kipleri

Parçaların çalıştığı varsayımının kaldırılması: kısmi arıza, yavaşlama, bayat içerik ve ağ bölünmesinin ayrı arıza kipleri olarak adlandırılması, kipin çağıran gözünden imzasıyla ayırt edilmesi, iki kipin aynı imzayı verdiği yerin gösterilmesi ve aynı bileşenin durmasıyla yavaşlamasının bulaşma kapsamı cinsinden karşılaştırılması.

İçindekiler

Dört kurs boyunca sistem bir kez bile bozulmadı. İstek uçtan girdi, önbellekten geçti, dengelendi, bir servise düştü, bir depoya vardı ve döndü; her hesap parçaların çalıştığını varsaydı. Bu varsayım kaldırıldığında ilk soru “ne yapmalı” değildir, “ne oldu”dur. Bir bağımlılık cevap vermediğinde çağıranın elinde yalnız kendi gözlemi vardır ve aynı gözlemin arkasında çok farklı bozulmalar durabilir; doğru tepki hangisinin olduğuna bağlıdır.

Bu ders bir kalıp kurmaz; kursun ilk kalıbı sonraki derstedir. Kurduğu şey bir sözlüktür: bozulma biçimleri adlandırılır, çağıranın gözünden nasıl göründükleri ölçülür ve her birinin sistemin kaçına bulaştığı sayılır.

Sözlük: Beş Bozulma Biçimi

Arıza kipi, bir bileşenin bozulma biçimidir: ne yaptığı değil, nasıl yanlış yaptığı. Sistemin kendi yapısından beş senaryo çıkar ve her biri bir kipin örneğidir.

  • Durma. Bir parça düğümü düşüyor; çağrı anında hata dönüyor.
  • Yavaşlama. Taşıyıcı bildirim ucu yavaşlıyor; yanıt geliyor ama çağıranın bekleyebileceğinden uzun sürede.
  • Kısmi arıza. Sekiz parçanın biri düşüyor; çağrıların bir bölümü hata alıyor, kalanı yanıt.
  • Bayat içerik. İzdüşümü besleyen kütük tüketicisi geri kalıyor; yanıt hızlı ve biçimi doğru, içeriği eski.
  • Ağ bölünmesi. İki bölge arasındaki bağ kopuyor; iki yan da ayakta, birbirini göremiyor.

Ağ bölünmesi burada yalnız bir arıza kipi olarak tanınır; bölünme altında tutarlılık ile hizmet erişilebilirliği arasında verilecek karar Sistem Tasarımına Giriş kursunda kuruldu. Ağ bölünmesi ile İlişkisel Veritabanı Yönetimi kursunun bölümlemesi ve Veri Katmanı Ölçekleme kursunun parçalaması ayrı kavramlardır: ilk ikisi veriyi bölme kararıdır, buradaki bölünme istenmeden olan bir kopmadır.

Beşine bir altıncı eklenir ve sözlüğün sınırını gösterir: gün sonu ücretlendirme işi yarıda kalıyor. Hiçbir çağrı hata vermez, hiçbiri yavaşlamaz; aşağıdaki ölçüm bu kipi hiç göremez. Bir kipi görebilmek için ona bakan bir gözlem gerekir.

Çağıranın Gördüğü İmza

Aşağıdaki koşum bir modeldir. Tur soyut bir adımdır; gerçek ağ, küme ya da kapsayıcı kurulmaz, bağımlılığın davranışı parametredir ve rastgelelik kendi yazılmış, tohumlanmış bir üreteçten gelir. Varsayımlar bu kursun kendi varsayımlarıdır, K01’in tablosuna eklenmez.

AY1 — tur–saniye çevrimi: 1 tur = 10 ms. Gerekçe: Uygulama Katmanı ve Servis Etkileşimi kursu bir adım çağrısının olağan süresini 8 ms saymıştı; iki turluk çağrı 20 ms eder.

AY2 — bileşen başına 32 eşzamanlı yuva, zaman aşımı 20 tur. Gerekçe: 20 tur AY1 ile tam 200 ms’dir, yani K01’in okuma eşiğinin kendisi; 32 yuva arızasız günde 0,78 tepe doluluk verir. Duyarlılıkları ikinci koşumda basılır.

AY4 — arızasız günde çağrıların 0,025’i zaman aşımına uğrar. Gerekçe: kısa gecikmeler arıza olmadan da olur. Duyarlılığı aşağıda 0,050 ile verilir.

// kipler/gorunum.mjs — alti ariza kipinin CAGIRAN gozunden imzasi. MODELDIR: tur soyut bir adim,
// bagimliligin davranisi parametre, rastgelelik tohumlu bir uretecten.
const N = 400, OLAGAN = 2, ZT = 20;   // cagri sayisi; olagan cagri 2 tur; AY2: zaman asimi 20 tur
const PARCA = 8, DUSEN = 1;           // kismi ariza: sekiz parcanin biri dustu (M19/K04)
const SEYREK = 0.025;                 // AY4: arizasiz gunde cagrilarin 1/40'i zaman asimina ugrar
let s = 20260730 % 2147483647;
const rast = () => (s = (s * 48271) % 2147483647) / 2147483647;
const YANIT = { sinif: "yanit", tur: OLAGAN, taze: true };
const HATA = { sinif: "hata", tur: 1, taze: null };
const ASIM = { sinif: "zamanAsimi", tur: ZT, taze: null };

function cagri(kip) {                 // tek cagrinin sonucu: sinif, tutulan tur, icerik tazeligi
  if (kip === "durma") return HATA;
  if (kip === "yavaslama" || kip === "bolunme") return ASIM;
  if (kip === "bayat") return { ...YANIT, taze: false };
  if (kip === "kismi") return rast() < DUSEN / PARCA ? HATA : YANIT;
  return rast() < SEYREK ? ASIM : YANIT;
}

function imza(kip) {                  // N cagrinin imza vektoru
  const c = Array.from({ length: N }, () => cagri(kip));
  const y = c.filter((x) => x.sinif === "yanit");
  const oran = (t) => c.filter((x) => x.sinif === t).length / N;
  return { yanit: y.length / N, hata: oran("hata"), asim: oran("zamanAsimi"),
    yuvaTur: c.reduce((t, x) => t + x.tur, 0) / N,
    taze: y.length === 0 ? null : y.filter((x) => x.taze).length / y.length };
}

const KIP = ["saglikli", "durma", "yavaslama", "kismi", "bayat", "bolunme"];
const b = (x) => (x === null ? "-" : x.toFixed(3));
const imzalar = Object.fromEntries(KIP.map((k) => [k, imza(k)]));

console.log(`model: kip basina ${N} cagri, olagan cagri ${OLAGAN} tur, zaman asimi ${ZT} tur, tohum 20260730`);
console.log(`\n${"kip".padEnd(11)}${"yanit".padStart(7)}${"hata".padStart(7)}${"zaman asimi".padStart(13)}` +
  `${"yuva-tur/cagri".padStart(16)}${"taze icerik".padStart(13)}`);
for (const k of KIP) {
  const i = imzalar[k];
  console.log(`${k.padEnd(11)}${b(i.yanit).padStart(7)}${b(i.hata).padStart(7)}${b(i.asim).padStart(13)}` +
    `${i.yuvaTur.toFixed(2).padStart(16)}${b(i.taze).padStart(13)}`);
}

const esit = (a, c, alan) => alan.every((k) => Math.abs((a[k] ?? -1) - (c[k] ?? -1)) < 0.02);
console.log("\nsinif oranlariyla ayrilamayan kip ciftleri:");
for (let i = 0; i < KIP.length; i += 1)
  for (let j = i + 1; j < KIP.length; j += 1)
    if (esit(imzalar[KIP[i]], imzalar[KIP[j]], ["yanit", "hata", "asim"]))
      console.log(`  ${KIP[i]} = ${KIP[j]} -> icerik denetimi ` +
        `${esit(imzalar[KIP[i]], imzalar[KIP[j]], ["taze"]) ? "de ayirmiyor" : "ayiriyor"}`);

const PENCERE = 20, DAMGA = 8, OLAY = 97.22, UCTA = 513.89, CEVRIM = 100;  // K01 hizlari; AY1
console.log(`\narizasiz gunun bedeli: yanit basina ${DAMGA} baytlik tazelik damgasi = ` +
  `${(DAMGA * UCTA).toFixed(2)} bayt/s (K01 uctaki ${UCTA} istek/s); adlandirma ${PENCERE} cagri = ` +
  `${(PENCERE / (OLAY / CEVRIM)).toFixed(1)} tur (${OLAY} olay/s) = ` +
  `${((PENCERE / (OLAY / CEVRIM) * 1000) / CEVRIM).toFixed(0)} ms`);
console.log(`duyarlilik: AY4 0,050 olsaydi yuva-tur/cagri ${imzalar.saglikli.yuvaTur.toFixed(2)} yerine ` +
  `${(OLAGAN + 0.05 * (ZT - OLAGAN)).toFixed(2)} olurdu`);
model: kip basina 400 cagri, olagan cagri 2 tur, zaman asimi 20 tur, tohum 20260730

kip          yanit   hata  zaman asimi  yuva-tur/cagri  taze icerik
saglikli     0.988  0.000        0.013            2.23        1.000
durma        0.000  1.000        0.000            1.00            -
yavaslama    0.000  0.000        1.000           20.00            -
kismi        0.880  0.120        0.000            1.88        1.000
bayat        1.000  0.000        0.000            2.00        0.000
bolunme      0.000  0.000        1.000           20.00            -

sinif oranlariyla ayrilamayan kip ciftleri:
  saglikli = bayat -> icerik denetimi ayiriyor
  yavaslama = bolunme -> icerik denetimi de ayirmiyor

arizasiz gunun bedeli: yanit basina 8 baytlik tazelik damgasi = 4111.12 bayt/s (K01 uctaki 513.89 istek/s); adlandirma 20 cagri = 20.6 tur (97.22 olay/s) = 206 ms
duyarlilik: AY4 0,050 olsaydi yuva-tur/cagri 2.23 yerine 2.90 olurdu

Bu sayılar ölçüm sınıfındadır: bu makinede koşan bir modelden çıkarlar, belirlenimlidirler.

Tablonun en önemli sütunu yuva-tur/çağrıdır: çağıranın o çağrı için eşzamanlılık yuvasını kaç tur tuttuğu. Durma 1,00, yavaşlama 20,00. Duran bir bağımlılık çağıranın kaynağını boşaltır, yavaşlayan bir bağımlılık onu tutar — aynı çağrı için yirmi kat fark. Kısmi arıza ikisinin arasındadır: hata oranı 0,120, yani sekizde bir; çağıran yeniden denerse sağlam bir parçaya düşme olasılığı vardır, durmada böyle bir umut yoktur. Bayat içerik ise sınıf oranlarında sağlıklıdan ayırt edilemez — onu ayıran tek şey yanıtın taşıdığı tazelik damgasıdır.

Son satır dersin ayırt etme sınırıdır. Yavaşlama ile ağ bölünmesi çağıran gözünden aynı şeydir ve içerik denetimi de onları ayırmaz: ikisinde de yanıt yoktur, ikisinde de yuva zaman aşımına kadar tutulur. Fark çağrının kendisinde değildir — bölünmede öteki yan ayaktadır ve isteği işlemiş olabilir. Yavaşlamada yeniden denenen bir yazma gecikir, bölünmede iki kez uygulanabilir.

Sözlüğün arızasız gündeki bedeli son iki satırdadır: bayat içeriği görebilmek için her yanıta 8 baytlık bir tazelik damgası eklenir (K01’in uçtaki 513,89 istek/s’sinde 4111,12 bayt/s) ve adlandırma yirmi çağrılık bir pencere ister — taşıyıcı olay hızında 20,6 tur, yani 206 ms.

Bulaşma Kapsamı

Bir arızanın bedeli bozulan bileşende değil, bulaştığı yerdedir. Bulaşma kapsamı (blast radius), arıza sırasında hizmet veremeyen bileşenlerin ve etkilenen istek hızının ölçüsüdür. İkinci koşum sistemi bir çağrı ağacı olarak modeller: bir akışın bir bileşende tuttuğu yuva sayısı akış hızı çarpı tutuş süresidir; toplam tutuş havuzu aşarsa bileşen doygun olur ve kendi çağıranına yavaş görünür.

// kipler/bulasma.mjs — ariza kipinin bulasma kapsami. MODELDIR: yayilma yuva dolulugundan cikar.
// Hizlar K01'in tepe hesabindan, yapi K02-K04'ten gelir.
const CEVRIM = 100, YUVA = 32, ZT = 20, OLAGAN = 2;   // AY1: 1 tur = 10 ms; AY2: yuva ve zaman asimi
const d = (ad, ...alt) => ({ ad, alt });
const AKIS = [                                        // K01 tepe: 416,67 + 97,22 = 513,89 istek/s
  { ad: "takip sorgusu", hiz: 416.67, kok: d("ag-gecidi", d("takip-servisi", d("izdusum-deposu"))) },
  { ad: "durum olayi", hiz: 97.22,
    kok: d("ag-gecidi", d("olay-ucu", d("tasiyici-dogrulama"), d("durum-deposu"))) },
  { ad: "gun sonu isi", hiz: 833.33, kok: d("gun-sonu-isi", d("durum-deposu")) },
  { ad: "kutuk tuketimi", hiz: 97.22, kok: d("kutuk-tuketicisi", d("durum-deposu"), d("izdusum-deposu")) },
];

function tut(n, ariza, kip) {           // tutulan tur; ilk basarisizlikta kalan cagri yapilmaz
  if (n.ad === ariza) return kip === "durma" ? { tur: 1, ok: false } : { tur: ZT, ok: false };
  if (n.alt.length === 0) return { tur: OLAGAN, ok: true };
  let tur = 1, ok = true;
  for (const c of n.alt) { const r = tut(c, ariza, kip); tur += r.tur; if (!r.ok) { ok = false; break; } }
  return { tur, ok };
}

function kosum(ariza, kip) {            // bilesen basina doluluk = akis hizi x tutus suresi
  const dolu = {}, gecen = {};
  const gez = (n, a) => {
    dolu[n.ad] = (dolu[n.ad] ?? 0) + (a.hiz / CEVRIM) * tut(n, ariza, kip).tur;
    (gecen[n.ad] ??= new Set()).add(a.ad);
    n.alt.forEach((c) => gez(c, a));
  };
  AKIS.forEach((a) => gez(a.kok, a));
  const doygun = Object.keys(dolu).filter((k) => dolu[k] >= YUVA);
  const vurulan = new Set(ariza ? [...doygun, ariza] : doygun);
  const akis = new Set([...vurulan].flatMap((v) => [...gecen[v]]));
  const hiz = [...akis].reduce((t, a) => t + AKIS.find((x) => x.ad === a).hiz, 0);
  return { dolu, doygun, bulasan: vurulan.size, akis: akis.size, hiz };
}

const t = kosum(null, null);
console.log(`model: ${Object.keys(t.dolu).length} bilesen, ${AKIS.length} akis, bilesen basina ${YUVA} ` +
  `yuva, zaman asimi ${ZT} tur, 1 tur = ${1000 / CEVRIM} ms\n`);
console.log(`arizasiz gun: ` + Object.entries(t.dolu)
  .map(([k, v]) => `${k} ${(v / YUVA).toFixed(3)}`).join(", "));

console.log(`\n${"arizali bilesen".padEnd(20)}${"kip".padEnd(11)}${"bulasan".padStart(8)}` +
  `${"doygun olan".padStart(42)}${"akis".padStart(6)}${"etkilenen istek/s".padStart(19)}`);
for (const bil of ["tasiyici-dogrulama", "izdusum-deposu", "durum-deposu"])
  for (const kip of ["durma", "yavaslama"]) {
    const r = kosum(bil, kip);
    console.log(`${bil.padEnd(20)}${kip.padEnd(11)}${String(r.bulasan).padStart(8)}` +
      `${(r.doygun.join(",") || "-").padStart(42)}${`${r.akis}/${AKIS.length}`.padStart(6)}` +
      `${r.hiz.toFixed(2).padStart(19)}`);
  }

const dur = kosum("tasiyici-dogrulama", "durma"), yav = kosum("tasiyici-dogrulama", "yavaslama");
const g = (r) => (r.dolu["ag-gecidi"] / YUVA).toFixed(3);
console.log(`\ntasiyici dogrulamasi: durma ${dur.hiz.toFixed(2)} istek/s ve ${dur.bulasan} bilesen, ` +
  `yavaslama ${yav.hiz.toFixed(2)} ve ${yav.bulasan} -> x${(yav.hiz / dur.hiz).toFixed(2)} istek`);
console.log(`ag gecidi dolulugu: arizasiz ${g(t)} -> durmada ${g(dur)} -> yavaslamada ${g(yav)}`);
console.log(`duyarlilik: yuva 48 olsaydi yavaslamada doluluk ${(yav.dolu["ag-gecidi"] / 48).toFixed(3)} ` +
  `(tasmaz), 1 tur 20 ms olsaydi ${(2 * yav.dolu["ag-gecidi"] / YUVA).toFixed(3)}`);

const SAYI = 3, SURE = 10, PAY = 28.2;  // AY3; K01 temel-nitelikler/04: aylik ariza payi (dakika)
console.log(`\nAY3: ayda ${SAYI} x ${SURE} dk = ${SAYI * SURE} dk, K01'in ${PAY} dk'lik ariza payinin ` +
  `%${((100 * SAYI * SURE) / PAY).toFixed(1)}'i (sure 5 dk olsaydi %${((100 * SAYI * 5) / PAY).toFixed(1)})`);
console.log(`ayni ${SAYI * SURE} dakika: durma ${(SAYI * SURE * 60 * dur.hiz).toFixed(0)} istek, ` +
  `yavaslama ${(SAYI * SURE * 60 * yav.hiz).toFixed(0)} istek, fark ${(SAYI * SURE * 60 * (yav.hiz - dur.hiz)).toFixed(0)}`);
model: 8 bilesen, 4 akis, bilesen basina 32 yuva, zaman asimi 20 tur, 1 tur = 10 ms

arizasiz gun: ag-gecidi 0.703, takip-servisi 0.391, izdusum-deposu 0.321, olay-ucu 0.152, tasiyici-dogrulama 0.061, durum-deposu 0.642, gun-sonu-isi 0.781, kutuk-tuketicisi 0.152

arizali bilesen     kip         bulasan                               doygun olan  akis  etkilenen istek/s
tasiyici-dogrulama  durma             1                                         -   1/4              97.22
tasiyici-dogrulama  yavaslama         2                                 ag-gecidi   2/4             513.89
izdusum-deposu      durma             1                                         -   2/4             513.89
izdusum-deposu      yavaslama         3    ag-gecidi,takip-servisi,izdusum-deposu   3/4             611.11
durum-deposu        durma             1                                         -   3/4            1027.77
durum-deposu        yavaslama         3       ag-gecidi,durum-deposu,gun-sonu-isi   4/4            1444.44

tasiyici dogrulamasi: durma 97.22 istek/s ve 1 bilesen, yavaslama 513.89 ve 2 -> x5.29 istek
ag gecidi dolulugu: arizasiz 0.703 -> durmada 0.612 -> yavaslamada 1.189
duyarlilik: yuva 48 olsaydi yavaslamada doluluk 0.793 (tasmaz), 1 tur 20 ms olsaydi 2.378

AY3: ayda 3 x 10 dk = 30 dk, K01'in 28.2 dk'lik ariza payinin %106.4'i (sure 5 dk olsaydi %53.2)
ayni 30 dakika: durma 174996 istek, yavaslama 925002 istek, fark 750006

Gün sonu işi kendi penceresinde koşar; çevrimiçi akışlarla birlikte gösterilmesi en kötü durumu verir.

Aynı Bileşen, İki Kip, Beş Kat Fark

Okuma tek bir satır çiftinden başlar. Taşıyıcı doğrulaması durduğunda olay ucu bir turda hata alır, yuvasını bırakır, isteği reddeder. Etkilenen tek akış durum olayıdır: 97,22 istek/s ve bir bileşen. Takip sorgusu hiç etkilenmez.

Aynı bağımlılık yavaşladığında olay ucu her çağrıda yuvasını yirmi tur tutar ve bu tutuş yukarı taşınır: ağ geçidinin olay ucunu çağıran bacağı 6 turdan 22 tura çıkar, doluluk 0,703’ten 1,189’a gider ve geçit doygun olur. O anda takip sorgusu da yanıtlanamaz — oysa bozuk bağımlılığa hiç dokunmaz. Etkilenen hız 513,89 istek/s, bulaşan bileşen 2: 5,29 kat istek.

Bu, kursun ilk yasasıdır ve sonraki üç dersin gerekçesidir: yavaşlama durmadan pahalıdır. Duran bir bağımlılık kendi akışını öldürür ve orada durur; yavaşlayan bir bağımlılık paylaşılan kaynağı tüketerek ilgisiz akışları da düşürür. Durma kipinde geçidin doluluğu 0,703’ten 0,612’ye iner — arıza geçidi rahatlatır, çünkü reddedilen istekler kaynak tutmaz.

Kalan satırlar aynı örüntüyü doğruluyor. İzdüşüm deposu durduğunda 513,89 istek/s etkilenir; yavaşladığında zincirin tamamı doyar ve hız 611,11 olur. Durum deposu durduğunda 1027,77 istek/s etkilenir ama hiçbir bileşen doymaz; yavaşladığında dört akış birden vurulur, 1444,44 istek/s.

Duyarlılık satırı doygunluğun neye bağlı olduğunu söylüyor. Havuz 48 yuva olsaydı yavaşlamada doluluk 0,793’te kalır, geçit taşmaz ve bulaşma iki bileşenden bire inerdi; tur 20 ms olsaydı doluluk 2,378 olurdu. Bulaşma kapsamı arızanın kendisinden değil, havuz boyutu ile zaman aşımının çarpımından çıkar.

Son iki satır iki günü kesinti bütçesine bağlıyor. AY3 — yavaşlama ayda 3 kez oluyor ve her biri 10 dakika sürüyor. Gerekçe: K01 kurtarma süresini 10 dakika varsaymış ve aylık 28,2 dakikalık arıza payına 2,82 arıza sığdırmıştı; üç arıza o payın yüzde 106,4’ünü yer. Duyarlılık: süre 5 dakika olsaydı pay yüzde 53,2’ye inerdi. Aynı 30 dakika durma kipinde 174.996, yavaşlama kipinde 925.002 isteği vurur — 750.006 istek fark. Sözlüğün arızalı gündeki kazancı budur: hiçbir arızayı kesmez, ama iki kipi karıştırmanın kaç istek ettiğini sayılabilir kılar.

Özet

  • Arıza kipi bir bileşenin bozulma biçimidir; senaryolar beş kipe karşılık gelir — durma, yavaşlama, kısmi arıza, bayat içerik, ağ bölünmesi. Yarıda kalan toplu iş çağrı gözlemiyle görülemez.
  • İmza kipleri kısmen ayırır: durma 1,00 yuva-tur ve 1,000 hata; yavaşlama 20,00 yuva-tur ve 1,000 zaman aşımı; kısmi arıza 0,120 hata; bayat içerik sağlıklıdan yalnız tazelik damgasıyla ayrılır.
  • Yavaşlama ile ağ bölünmesi çağıran gözünden aynıdır ve içerik denetimi de onları ayırmaz; fark bölünmede öteki yanın ayakta olması ve isteği işlemiş olabilmesidir.
  • Arızasız günün bedeli her yanıta eklenen 8 baytlık damga (4111,12 bayt/s) ve adlandırma için gereken 20 çağrılık penceredir (97,22 olay/s’de 20,6 tur, 206 ms).
  • Bulaşma kapsamı kipe bağlıdır: taşıyıcı doğrulaması durduğunda 97,22 istek/s ve 1 bileşen, yavaşladığında 513,89 istek/s ve 2 bileşen — 5,29 kat. Ağ geçidi doluluğu 0,703’ten durmada 0,612’ye iner, yavaşlamada 1,189’a çıkar.
  • AY3’ün 30 dakikasında iki kip arasındaki fark 750.006 istektir ve o 30 dakika K01’in aylık arıza payının yüzde 106,4’üdür.

Sonraki Adım

Ölçüm bir yön gösteriyor. Yavaşlamanın pahalı olmasının nedeni bağımlılığın bozuk olması değil, çağıranın bozuk bağımlılığı çağırmayı sürdürmesidir: her çağrı bir yuvayı yirmi tur tutar ve o yuvalar hiçbir işe yaramaz. Aynı tablo çareyi de gösteriyor — durma kipinde doluluk 0,612’ye iniyor, çünkü hızlı hata kaynak tutmaz. Yavaşlayan bir bağımlılığı çağırmayı bırakmak, yavaşlamayı durmaya çevirir ve bulaşmayı 513,89’dan 97,22 istek/s’ye indirir. Sonraki ders bu kararı veren bileşeni tasarlar: kesmeye hangi eşikte karar verildiği, kesikken kaç çağrının hiç yapılmadığı ve sağlıklı bir bağımlılığın yanlışlıkla kesilmesinin kaça mal olduğu orada sayılır.

İ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