İçeriğe geç
academia.sh

Ders 09 / 10

Evrimsel Mimari

Değişime dayanıklı yapının denetlenmesi: aynı üç değişikliğin bir yapıda 18, yalıtma noktalı yapıda 5 modüle dokunması, yalıtımın kalıcı olarak 5 düğüm ve 4 bağ pahalı olması, uygunluk işlevinin 8 ihlalin 7'sini yakalayıp 1 yanlış alarm vermesi ve bir bağımlılık içeri alınınca aynı kural kümesinin 5 doğru değişikliği ihlal olarak işaretlemesi.

İçindekiler

Önceki ders bağımlılık ve katman kurallarını koşturulabilir bir denetime çevirdi: kural artık bir belge cümlesi değil, ithal grafiği üzerinde çalışan bir yüklemdir. Ama bu kuralların hepsi bugünkü yapıyı korur: bugünkü katman ayrımını dondurur ve yapının kendisi değişmek zorunda kaldığında ya doğru değişimi ucuzlatır ya da onu ihlal olarak işaretler.

Evrimsel mimari (evolutionary architecture), değişimi ucuz tutan yapı kararlarını denetlenebilir hâle getirme uğraşıdır. Kursun sorusu bir adım kayar: değişimi ucuzlatan yapı kararı denetlenebilir mi? Dört ölçü alınır: dokunulan modül ve geri alma adımı; uygunluk işlevinin yakalaması, kaçırması ve yanlış alarmı; kuralın kendi eskimesi; çevrilemeyen kısım.

Aynı Değişiklik Kümesi, İki Yapı

Örnek, kursun kurgu bölgesel kütüphane ağıdır. YN12: altı iç modül (şube ön yüzü, şube terminali, ödünç, ücretlendirme, raporlama, bildirim) ve üç dış bağımlılık (dışarıdan alınmış katalog, ayrı üyelik sistemi, belediyedeki kimlik servisi); bugünkü yapı A bunları 16 bağla bağlar. YN13: bağ, iç biçime dayanıyorsa biçim bağı, bildirilmiş sözleşmeye dayanıyorsa sözleşme bağıdır. YN14 — sızan modül: A’da odunc ile ucret aldıkları kaydı olduğu gibi yeniden yayar; B’de her dış bağımlılığın önünde biçimi eşleyen bir yalıtma noktası (kapı) durur ve sızan modül kalmaz. YN15 — değişiklik kümesi: katalog kaydına alan eklemek, üyelik sistemini değiştirmek, ücretlendirmeyi ikiye ayırmak.

İki dosya grafı, yayılımı ve beş kuralı kuran süreç içi bir modeldir; ağ ya da depo yoktur.

// evrim/yapi.mjs — kurgu kutuphane aginin modul grafi ve kural denetleyicisi (model). Kenar
// yazimi "bagimli>bagimlilik:tur"; "b" bicim bagi, "s" sozlesme bagi.

export const bag = (s) => s.trim().split(/\s+/).map((e) => e.split(/[>:]/));

export const YAPI_A = bag(`
  sube-onyuz>katalog:b sube-onyuz>odunc:b sube-onyuz>kimlik:b
  sube-terminal>katalog:b sube-terminal>odunc:b sube-terminal>kimlik:b
  odunc>katalog:b odunc>uyelik:b odunc>ucret:b ucret>odunc:b ucret>uyelik:b
  rapor>odunc:b rapor>ucret:b rapor>katalog:b bildirim>odunc:b bildirim>uyelik:b`);

export const YAPI_B = bag(`
  sube-onyuz>katalog-kapisi:s sube-onyuz>odunc-kapisi:s sube-onyuz>kimlik-kapisi:s
  sube-terminal>katalog-kapisi:s sube-terminal>odunc-kapisi:s sube-terminal>kimlik-kapisi:s
  odunc>katalog-kapisi:s odunc>uyelik-kapisi:s odunc>ucret-kapisi:s ucret>uyelik-kapisi:s
  rapor>odunc-kapisi:s rapor>ucret:b rapor>katalog-kapisi:s
  bildirim>odunc-kapisi:s bildirim>uyelik-kapisi:s
  katalog-kapisi>katalog:b uyelik-kapisi>uyelik:b kimlik-kapisi>kimlik:b
  odunc-kapisi>odunc:b ucret-kapisi>ucret:b`);

// Aldigi bicimi oldugu gibi yeniden yayan moduller (kaba isaret)
export const SIZAN = { A: new Set(["odunc", "ucret"]), B: new Set() };
export const UC = ["sube-onyuz", "sube-terminal"];

// "dis" ve "kapi" yapinin degil, yapilandirmanin bildirdigi seylerdir.
export const ESKI = {
  dis: ["katalog", "uyelik", "kimlik"],
  kapi: { "katalog-kapisi": "katalog", "uyelik-kapisi": "uyelik", "kimlik-kapisi": "kimlik",
    "odunc-kapisi": "odunc", "ucret-kapisi": "ucret" },
  ucIzin: ["katalog-kapisi", "odunc-kapisi", "kimlik-kapisi"],
  istisna: [["rapor", "ucret"]],
};
const { "uyelik-kapisi": _, ...KAPI_YENI } = ESKI.kapi;      // uyelik ice alindiktan sonra
export const YENI = { ...ESKI, dis: ["katalog", "kimlik"], kapi: KAPI_YENI,
  ucIzin: [...ESKI.ucIzin, "uyelik"] };

export const modul = (k) => [...new Set(k.flatMap(([a, b]) => [a, b]))];

export const uygula = (k, o) => {
  const s = (o.sil ?? []).map((x) => `${x[0]}>${x[1]}`);
  return [...k.filter(([a, b]) => !s.includes(`${a}>${b}`)), ...(o.ek ?? [])];
};

// Bicim bagi degisen bicimi tasir; sozlesme bagi ancak sozlesme degisince gecer.
export function dokunulan(kenar, sizan, dis, d) {
  const kume = new Set([d.kok]);
  for (let ek = true; ek; ) {
    ek = false;
    for (const [a, b, tur] of kenar) {
      if (kume.has(a) || !kume.has(b)) continue;
      if (tur === "b" ? b === d.kok || sizan.has(b) : d.sozlesmeDegisen.includes(b)) {
        kume.add(a); ek = true;
      }
    }
  }
  return [...kume].filter((m) => !dis.includes(m));
}

// Tek kapida kalan degisiklik bir anahtarla geri alinir.
export const geriAlma = (d, kapi) => (d.length === 1 && d[0] in kapi ? 1 : d.length);

export function dongudekiler(kenar) {
  const m = modul(kenar), u = new Map(m.map((x) => [x, new Set()]));
  for (const [a, b] of kenar) u.get(a).add(b);
  for (let d = true; d; ) {                                  // gecisli kapanis
    d = false;
    for (const a of m) for (const b of [...u.get(a)]) for (const c of u.get(b) ?? [])
      if (!u.get(a).has(c)) { u.get(a).add(c); d = true; }
  }
  return m.filter((x) => u.get(x).has(x));
}

// Uygunluk islevi: degisime aciklik
export function uygunluk(kenar, y) {
  const kapiAdi = Object.keys(y.kapi);
  const tam = y.dis.filter((x) => {
    const g = kenar.filter(([, b]) => b === x).map(([a]) => a);
    return g.length === 1 && kapiAdi.includes(g[0]);
  });
  return { dugum: modul(kenar).length, bag: kenar.length,
    "dongudeki modul": dongudekiler(kenar).length,
    "yalitilmamis dis bag": kenar.filter(([a, b]) => y.dis.includes(b) && !kapiAdi.includes(a)).length,
    "tam yalitilmis dis": `${tam.length}/${y.dis.length}` };
}

// Bes mimari kural; her biri ihlal sayisi dondurur
export function kurallar(y) {
  const kapiAdi = Object.keys(y.kapi);
  const icHedef = Object.values(y.kapi).filter((m) => !y.dis.includes(m));
  return {
    K1: (k) => k.filter(([a, b]) => y.dis.includes(b) && !kapiAdi.includes(a)).length,
    K2: (k) => dongudekiler(k).length,
    K3: (k) => k.filter(([a, b, t]) => t === "b" && icHedef.includes(b) && !kapiAdi.includes(a)
      && !y.istisna.some(([x, z]) => x === a && z === b)).length,
    K4: (k) => k.filter(([a, b]) => UC.includes(a) && !y.ucIzin.includes(b)).length,
    K5: (k) => y.dis.filter((x) => k.filter(([, b]) => b === x).length !== 1
      || !kapiAdi.includes((k.find(([, b]) => b === x) ?? [])[0])).length,
  };
}
// evrim/olc.mjs — iki yapida ayni degisiklik kumesi, bilinen ihlal kumesi, kuralin eskimesi.
import { YAPI_A, YAPI_B, SIZAN, ESKI, YENI, bag, uygula, dokunulan, geriAlma, uygunluk, kurallar }
  from "./yapi.mjs";

const yaz = (g, ...s) => console.log(s.map((v, i) =>
  (g[i] < 0 ? String(v).padEnd(-g[i]) : String(v).padStart(g[i]))).join(""));

const uA = uygunluk(YAPI_A, ESKI), uB = uygunluk(YAPI_B, ESKI);
yaz([-24, 8, 8], "uygunluk islevi", "A", "B");
for (const k of Object.keys(uA)) yaz([-24, 8, 8], k, uA[k], uB[k]);

const DEGISIKLIK = [
  { ad: "yeni alan (katalog)", kok: "katalog", sozlesmeDegisen: [] },
  { ad: "bagimlilik degistir (uyelik)", kok: "uyelik", sozlesmeDegisen: [] },
  { ad: "ucret'i ikiye ayir", kok: "ucret", sozlesmeDegisen: ["ucret"] },
];
const D = [-30, 14, 14, 14, 14], T = { A: [0, 0], B: [0, 0] };
console.log();
yaz(D, "degisiklik", "A: dokunulan", "A: geri alma", "B: dokunulan", "B: geri alma");
for (const d of DEGISIKLIK) {
  const s = {};
  for (const [ad, kenar, sizan] of [["A", YAPI_A, SIZAN.A], ["B", YAPI_B, SIZAN.B]]) {
    const dk = dokunulan(kenar, sizan, ESKI.dis, d), g = geriAlma(dk, ESKI.kapi);
    s[ad] = [dk.length, g]; T[ad][0] += dk.length; T[ad][1] += g;
  }
  yaz(D, d.ad, s.A[0], s.A[1], s.B[0], s.B[1]);
}
yaz(D, "toplam", T.A[0], T.A[1], T.B[0], T.B[1]);

// Bilinen ihlal kumesi: her oneri elle etiketlenmistir (model girdisi).
const ONERI = [
  ["hizli arama", "sube-onyuz>katalog:b", "ihlal"],
  ["gece aktarimi", "rapor>katalog:b", "ihlal"],
  ["borc sorgusu", "ucret>odunc:b", "ihlal"],
  ["bildirimde ucret", "bildirim>ucret:b", "ihlal"],
  ["kapidan katalog", "odunc-kapisi>katalog:b", "ihlal"],
  ["yeni kiosk", "sube-kiosk>odunc:b", "ihlal"],
  ["bildirim kimlik", "bildirim>kimlik-kapisi:s", "temiz"],
  ["rapor uyelik", "rapor>uyelik-kapisi:s", "temiz"],
  ["arsiv modulu", "arsiv>odunc-kapisi:s arsiv>katalog-kapisi:s", "temiz"],
  ["kapi zinciri", "katalog-kapisi>uyelik-kapisi:s", "ihlal"],
  ["terminal uyelik", "sube-terminal>uyelik-kapisi:s", "temiz"],
  ["bildirim uyelik", "bildirim>uyelik:b", "ihlal"],
].map(([ad, e, gercek]) => ({ ad, ek: bag(e), gercek }));

function kos(taban, oneriler, y, kapali = []) {
  const K = kurallar(y), ad = Object.keys(K).filter((x) => !kapali.includes(x));
  const temel = Object.fromEntries(ad.map((x) => [x, K[x](taban)]));
  const satir = oneriler.map((o) => {
    const aten = ad.filter((x) => K[x](uygula(taban, o)) > temel[x]);
    const sonuc = o.gercek === "ihlal" ? (aten.length ? "yakalandi" : "kacti")
      : aten.length ? "yanlis alarm" : "dogru gecti";
    return { ad: o.ad, gercek: o.gercek, aten, sonuc };
  });
  const say = (s) => satir.filter((x) => x.sonuc === s).length;
  return { satir, temel, yakalandi: say("yakalandi"), kacti: say("kacti"),
    yanlis: say("yanlis alarm"), dogru: say("dogru gecti") };
}

const R = kos(YAPI_B, ONERI, ESKI), ihlal = ONERI.filter((o) => o.gercek === "ihlal").length;
console.log(`\nB tabani: ${Object.entries(R.temel).map(([a, b]) => `${a}=${b}`).join(" ")}`);
const O = [-18, 8, 14, 14];
yaz(O, "oneri", "gercek", "atesleyen", "sonuc");
for (const s of R.satir) yaz(O, s.ad, s.gercek, s.aten.join(",") || "-", s.sonuc);
console.log(`yakalanan ${R.yakalandi}/${ihlal}, kacan ${R.kacti}, ` +
  `yanlis alarm ${R.yanlis}/${ONERI.length - ihlal} temiz`);

// Kurallarin eskimesi: yapi ayni, yapilandirma degisti.
const SONRA = [
  ["odunc dogrudan", "odunc>uyelik:b", "", "temiz"],
  ["kapiyi kaldir", "odunc>uyelik:s ucret>uyelik:s bildirim>uyelik:s",
    "uyelik-kapisi>uyelik odunc>uyelik-kapisi ucret>uyelik-kapisi bildirim>uyelik-kapisi", "temiz"],
  ["bildirim dogrudan", "bildirim>uyelik:b", "", "temiz"],
  ["onyuz uyelik", "sube-onyuz>uyelik:s", "", "temiz"],
  ["uyelik kimlige", "uyelik>kimlik:b", "", "ihlal"],
  ["rapor uyelik", "rapor>uyelik:s", "", "temiz"],
].map(([ad, e, s, gercek]) => ({ ad, ek: bag(e), sil: s ? bag(s) : [], gercek }));

const KAPALI = ["K1", "K5"];                                 // dis listesini okuyan iki kural
console.log("\nuyelik ice alindiktan sonra, ayni alti oneri (5 temiz, 1 ihlal)");
const S = [-22, 11, 8, 14, 13];
yaz(S, "yapilandirma", "yakalanan", "kacan", "yanlis alarm", "dogru gecen");
for (const [ad, y, k] of [["eski (degismemis)", ESKI, []], ["guncellenmis", YENI, []],
  [`eski, ${KAPALI.join("+")} kapali`, ESKI, KAPALI]]) {
  const r = kos(YAPI_B, SONRA, y, k);
  yaz(S, ad, r.yakalandi, r.kacti, r.yanlis, r.dogru);
}
const eK = kurallar(ESKI), yK = kurallar(YENI);
const degisen = Object.keys(ESKI).filter((a) => JSON.stringify(ESKI[a]) !== JSON.stringify(YENI[a]));
const davranis = Object.keys(eK).filter((x) =>
  SONRA.some((o) => eK[x](uygula(YAPI_B, o)) !== yK[x](uygula(YAPI_B, o))));
console.log(`guncelleme: ${Object.keys(ESKI).length} yapilandirma girdisinin ${degisen.length}'i ` +
  `(${degisen.join(", ")}); ${Object.keys(eK).length} kuralin ${davranis.length}'i ` +
  `(${davranis.join(", ")}) ayni oneride baska sonuc veriyor`);

const gevsek = kos(YAPI_B, ONERI, ESKI, KAPALI);
console.log(`${KAPALI.join("+")} kapatilinca ilk ihlal kumesi: yakalanan ${R.yakalandi} -> ` +
  `${gevsek.yakalandi}, kacan ${R.kacti} -> ${gevsek.kacti}, yanlis alarm ${R.yanlis} -> ${gevsek.yanlis}`);

// Cevrilemeyen kisim: yazilmamis degisikligin ucuzlugu.
const [SENARYO, GOZDEN, GELEN, KAPSANAN] = [6, 4, 12, 5];    // model girdisi
console.log(`\ndegisim senaryosu ${SENARYO}, yilda ${GOZDEN} gozden gecirme -> ` +
  `${SENARYO * GOZDEN} elle inceleme kalemi`);
console.log(`bir yilda gelen ${GELEN} degisiklikten ${KAPSANAN}'i yazili senaryoya denk dustu ` +
  `(%${((100 * KAPSANAN) / GELEN).toFixed(2)}); kalan ${GELEN - KAPSANAN} degisiklik gelmeden sayilmadi`);
uygunluk islevi                A       B
dugum                          9      14
bag                           16      20
dongudeki modul                2       0
yalitilmamis dis bag           9       0
tam yalitilmis dis           0/3     3/3

degisiklik                      A: dokunulan  A: geri alma  B: dokunulan  B: geri alma
yeni alan (katalog)                        6             6             1             1
bagimlilik degistir (uyelik)               6             6             1             1
ucret'i ikiye ayir                         6             6             3             3
toplam                                    18            18             5             5

B tabani: K1=0 K2=0 K3=0 K4=0 K5=0
oneri               gercek     atesleyen         sonuc
hizli arama          ihlal      K1,K4,K5     yakalandi
gece aktarimi        ihlal         K1,K5     yakalandi
borc sorgusu         ihlal         K2,K3     yakalandi
bildirimde ucret     ihlal            K3     yakalandi
kapidan katalog      ihlal            K5     yakalandi
yeni kiosk           ihlal            K3     yakalandi
bildirim kimlik      temiz             -   dogru gecti
rapor uyelik         temiz             -   dogru gecti
arsiv modulu         temiz             -   dogru gecti
kapi zinciri         ihlal             -         kacti
terminal uyelik      temiz            K4  yanlis alarm
bildirim uyelik      ihlal         K1,K5     yakalandi
yakalanan 7/8, kacan 1, yanlis alarm 1/4 temiz

uyelik ice alindiktan sonra, ayni alti oneri (5 temiz, 1 ihlal)
yapilandirma            yakalanan   kacan  yanlis alarm  dogru gecen
eski (degismemis)               1       0             5            0
guncellenmis                    1       0             0            5
eski, K1+K5 kapali              0       1             1            4
guncelleme: 4 yapilandirma girdisinin 3'i (dis, kapi, ucIzin); 5 kuralin 3'i (K1, K4, K5) ayni oneride baska sonuc veriyor
K1+K5 kapatilinca ilk ihlal kumesi: yakalanan 7 -> 4, kacan 1 -> 4, yanlis alarm 1 -> 1

degisim senaryosu 6, yilda 4 gozden gecirme -> 24 elle inceleme kalemi
bir yilda gelen 12 degisiklikten 5'i yazili senaryoya denk dustu (%41.67); kalan 7 degisiklik gelmeden sayilmadi

Sayılar ölçüm sınıfındadır; girdileri yukarıdaki varsayımlardır. A’da üç değişikliğin üçü de altı iç modülün altısına dokunuyor: biçim bağı odunc ile ucret üzerinden sızdığı için katalog kaydına alan eklemek bildirime kadar gidiyor. B’de aynı üç değişiklik 1, 1 ve 3 modüle dokunuyor — 18’e karşı 5. Geri alma sütunu ikinci ayrımı verir: A’da dokunulan her modül tek tek geri alınır, B’de ilk iki değişiklik tek kapının içinde kaldığı için birer anahtar çevrilir. Bu yapısal bir geri alınabilirliktir, Servis Mimarileri kursundaki boğucu incir geçişinin geçiş turu değil. Yalıtımın bedeli de tabloda: B, A’nın 9 düğüm ve 16 bağına karşılık 14 ve 20 taşır. Üçüncü değişikliğin B’de üç modüle dokunması yalıtımın kısmi olduğunu gösterir: rapor ücretlendirmeye biçim bağıyla bağlı ve o bağ istisna listesinde.

Uygunluk İşlevi ve Bilinen İhlal Kümesi

Uygunluk işlevi (fitness function) burada değişime açıklığı ölçer ve üç nicelik sayar: döngüdeki modül, yalıtılmamış dış bağ, tam yalıtılmış dış bağımlılık. A’da odunc ile ucret karşılıklı bağlıdır, dokuz bağ dış bağımlılığa doğrudan gider ve hiçbir dış bağımlılığın tek kapısı yoktur; B’de sırasıyla 0, 0 ve 3/3.

Beş mimari kural bu niceliklerin eşiğidir: K1 iç modülün dış bağımlılığa doğrudan bağlanmasını, K2 döngüyü, K3 kapısı olan iç modüle biçim bağını, K4 uç katmanın izin listesi dışına çıkmasını, K5 bir dış bağımlılığın tam kapısı olmamasını yasaklar; beşi de B tabanında sıfır verir. YN16 — bilinen ihlal kümesi: on iki öneri elle etiketlenmiştir, sekizi değişim maliyetini artırır.

Denetim sekiz ihlalin yedisini yakalar, birini kaçırır, dört temiz önerinin birine yanlış alarm verir. Kaçan öneri kapı zinciridir: kapının başka bir kapıya bağlanması. Kapı, biçim eşleyen katman olmaktan çıkıp alan modülüne döner, ama hiçbir kural bunu yasaklamaz — denetim yalnız yazılmış olanı görür. Yanlış alarm terminal üyeliktir; kusur önerinin değil K4’ün izin listesinindir. Yakalama ile yanlış alarm, sınama kurslarındaki yanlış kalma ile yanlış geçme ikilisinin aynı olgusudur; burada sınanan kod değil graftır.

Kuralın Kendisi Eskiyor

YN17 — evrim olayı: ayrı üyelik sistemi içeri alınır ve ağın kendi modülü olur. Grafta tek bir kenar değişmez; değişen şey kural yapılandırmasının “dış” listesidir. Aynı beş kural, üyelik içeri alındıktan sonra doğru olan altı öneriye uygulanır: beş temiz önerinin beşini de ihlal işaretler. Kapıyı kaldırmak, ödüncün üyeliği doğrudan çağırması, raporun üyelikten okuması — hepsi K1 ile K5’e takılır, çünkü ikisi de üyeliği hâlâ dışarıda sanır. Kural bozulmadı; dünyası değişti.

Düzeltme yapılandırmadadır: dört girdinin üçü (dış, kapı ve uç izin listeleri) güncellenir, beş kuralın üçü aynı öneride başka sonuç verir. Sonrasında yanlış alarm sıfırlanır, tek gerçek ihlal — içeri alınan üyeliğin kimlik servisini kapısız çağırması — yakalanmayı sürdürür.

İkinci yol gevşetmektir: dış listesini okuyan iki kuralı kapatmak; alt satır bedeli veriyor. Evrim sonrası kümede yanlış alarm beşten bire iner ama tek gerçek ihlal kaçar; ilk ihlal kümesinde yakalanan yediden dörde düşer, kaçan birden dörde çıkar, yanlış alarm birde kalır — kalan yanlış alarm K4’ündü ve K4 açık kaldı. Yanlış alarmın ekipte ürettiği davranış kuralı kapatmaktır; kapatma da yanlış alarmı doğuran kuralı değil, en çok ihlal yakalayan kuralı götürür.

Çevrilemeyen Kısım

Bir sayıya bağlanamayan şey henüz istenmemiş değişikliğin ucuzluğudur: uygunluk işlevi yapıyı yazılmış bir değişiklik kümesine karşı ölçer, kümede olmayan için ürettiği sayı yoktur. Yerine konan şey dönem dönem gözden geçirilen değişim senaryosudur. YN18: altı senaryo ve yılda dört gözden geçirme, yılda 24 elle inceleme kalemi eder; bir yılda gelen on iki değişikliğin beşi yazılı bir senaryoya denk düşer (yüzde 41,67), kalan yedisi ancak geldikten sonra fiyatlanır. Bu oran geriye bakılarak sayılır; on üçüncü, yazılmamış değişikliğin bedeli önceden sayılamaz.

Özet

  • Aynı üç değişiklik A’da altı iç modülün altısına dokunuyor (18 dokunuş, 18 geri alma adımı); yalıtma noktalı B’de 1, 1 ve 3 modüle (5 ve 5).
  • Uygunluk işlevi açıklığı üç nicelikle sayar (döngüdeki modül 2 → 0, yalıtılmamış dış bağ 9 → 0, tam yalıtılmış dış bağımlılık 0/3 → 3/3); yalıtımın kalıcı bedeli, A’nın 9 düğüm ve 16 bağına karşılık B’nin 14 düğümü ve 20 bağıdır.
  • Denetim sekiz ihlalin yedisini yakalar, kapıdan kapıya bağı kaçırır, bir temiz öneriye yanlış alarm verir; ikisi de kuralın yazılışındandır.
  • Bir bağımlılık içeri alınınca graf değişmeden kural eskir: beş doğru değişikliğin beşi ihlal işaretlenir; dört yapılandırma girdisinden üçü güncellenince yanlış alarm sıfırlanır, güncelleme yerine iki kural kapatılırsa yakalanan 7’den 4’e iner.
  • Çevrilemeyen kısım henüz istenmemiş değişikliğin ucuzluğudur; yerine konan altı senaryo ve yılda dört gözden geçirme (24 kalem) gelen on iki değişikliğin beşini kapsar.

Sonraki Adım

Bu dersteki kuralların hepsi içeriden geldi: kapı, izin ve istisna listelerini mimarinin kendisi seçti, eskidiklerinde yine kendisi güncelledi; gevşetmek de onun elindeydi. Bazı kısıtlar ise dışarıdan gelir ve pazarlığa açık değildir — verinin nerede duracağı, ne kadar saklanacağı, silme isteğinin nasıl karşılanacağı gibi. Sonraki ders bunları ele alır: kaldırılması seçenek olmayan bir kısıt denetime çevrildiğinde ne oluyor, çevrilemeyen kısmın yerine ne konuyor?

İ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