İçeriğe geç
academia.sh

Ders 01 / 10

Nitelik Ağacı

Kalite niteliklerinin alt niteliklere ve yapraklara ayrılması: otuz yaprağın kaçının bir sayıya bağlandığı, kaçının koşturulabilir denetime çevrildiği, bilinen ihlal kümesinde kaç ihlalin yakalanıp kaçtığı ve çevrilemeyen yaprakların yerine konan düzenin kişi-saat bedeli.

İçindekiler

Önceki kurs bağları kurdu, sahipliği ayırdı, dışarıdan alınacak ile içeride geliştirilecek arasındaki sınırı çizdi. Kararlar gerekçeyle yazıldı; ama gerekçeler yan yana konduğunda ortak bir boşluk görünür: hiçbiri hangi niteliği koruduğunu yazmadı. “Katalog dışarıdan alınır” kararı neyi savunuyor — geliştirme süresini mi, sürdürülebilirliği mi, taşınabilirliği mi? Yanıt yazılı değilse karar sonradan tartışılamaz, çünkü tartışmanın ölçeği yoktur.

Kalite niteliğinin tanımı ve nitelik senaryosunun alanları Mimari Karar ve Dokümantasyon kursunda kuruldu, sınanabilirliği orada ölçüldü; burada tekrarlanmaz. Buradaki soru bir adım geridedir: elde hangi nitelikler var, hangi alt niteliklere ayrılıyor, uçtaki her yaprak bir sayıya bağlanabiliyor mu. Kursun ayırt edici ölçüsü de buradan çıkar — bir nitelik koşturulabilir bir denetime çevrilebiliyor mu, çevrilemiyorsa yerine ne konuyor.

Ağacın Kurulması

Aşağıdaki blok, kurgusal bölgesel kütüphane ağının nitelik ağacını modeller: beş kök nitelik, her biri alt niteliklere, onlar da yapraklara ayrılır. Yaprak, ağacın ölçü taşıyan tek yeridir; kök ile alt nitelik yalnız katalog başlığıdır.

// agac.mjs — nitelik agacini modeller ve her yapragin olculebilirligini sayar
import { mkdirSync, writeFileSync } from "node:fs";

// KN1: bolgesel kutuphane agi kurgudur (subeler, disaridan alinmis katalog, icerde yazilan
// odunc ve ucretlendirme servisleri, ayri uyelik sistemi, belediyedeki kimlik servisi). Agac
// bir modeldir: [kod, kok/alt, yaprak, gozlem, birim, esik, yon, kaynak]; kaynak "oto" =
// kayittan okunur, "elle" = olcum oturumu ister, "-" = sayiya baglanmaz.
const TANIM = [
  ["B1", "basarim/yanit", "katalog arama gecikmesi", "arama_ms", "ms", 400, "kucuk", "oto"],
  ["B2", "basarim/yanit", "odunc islemi gecikmesi", "odunc_ms", "ms", 600, "kucuk", "oto"],
  ["B3", "basarim/yanit", "rapor ekrani acilisi", "rapor_sn", "sn", 8, "kucuk", "oto"],
  ["B8", "basarim/yanit", "yavasligin uyeye hissettirdigi", "", "", null, "", "-"],
  ["B4", "basarim/hacim", "saatlik odunc islemi", "odunc_saat", "islem", 1200, "buyuk", "oto"],
  ["B5", "basarim/hacim", "toplu katalog yuklemesi", "yukleme_dk", "dk", 90, "kucuk", "oto"],
  ["B6", "basarim/kaynak", "uc birim bellegi", "bellek_mb", "MB", 512, "kucuk", "oto"],
  ["B7", "basarim/kaynak", "baglanti havuzu dolulugu", "havuz", "%", 80, "kucuk", "oto"],
  ["E1", "erisilebilirlik/kesinti", "aylik merkez kesintisi", "kesinti_dk", "dk", 45, "kucuk", "oto"],
  ["E2", "erisilebilirlik/kesinti", "kopukken odunc surmesi", "kopuk_dk", "dk", 120, "buyuk", "elle"],
  ["E3", "erisilebilirlik/kurtarma", "yedege gecis suresi", "gecis_sn", "sn", 60, "kucuk", "elle"],
  ["E4", "erisilebilirlik/kurtarma", "veri kaybi penceresi", "kayip_dk", "dk", 5, "kucuk", "oto"],
  ["E5", "erisilebilirlik/yayilim", "cokmede etkilenen sube", "etkilenen", "sube", 1, "kucuk", "elle"],
  ["E6", "erisilebilirlik/yayilim", "kesintide uyeye verilen bilgi", "", "", null, "", "-"],
  ["G1", "guvenlik/kimlik", "dogrulamasiz uc nokta", "acik_uc", "uc", 0, "kucuk", "oto"],
  ["G2", "guvenlik/kimlik", "rolsuz personel islemi", "rolsuz", "islem", 0, "kucuk", "oto"],
  ["G3", "guvenlik/gizlilik", "depoda acik sir degeri", "acik_sir", "deger", 0, "kucuk", "oto"],
  ["G4", "guvenlik/gizlilik", "gecmisin sinir disina cikmasi", "sinir_disi", "alan", 0, "kucuk", "oto"],
  ["G5", "guvenlik/izlenebilirlik", "kaydi tutulmayan yonetici islemi", "kayitsiz", "islem", 0, "kucuk", "oto"],
  ["G6", "guvenlik/izlenebilirlik", "guven sinirinin dogru yerde olmasi", "", "", null, "", "-"],
  ["S1", "surdurulebilirlik/degisim", "ucretlendirmede dokunulan dosya", "dosya", "dosya", 6, "kucuk", "oto"],
  ["S2", "surdurulebilirlik/degisim", "yeni sube ekleme elle adimi", "adim", "adim", 3, "kucuk", "elle"],
  ["S3", "surdurulebilirlik/anlasilirlik", "modul bagimlilik derinligi", "derinlik", "duzey", 5, "kucuk", "oto"],
  ["S4", "surdurulebilirlik/anlasilirlik", "kodun okunur olmasi", "", "", null, "", "-"],
  ["S5", "surdurulebilirlik/sinanabilirlik", "odunc kurali kapsamasi", "kapsama", "%", 70, "buyuk", "oto"],
  ["S6", "surdurulebilirlik/sinanabilirlik", "sinama takimi kosumu", "sinama_dk", "dk", 12, "kucuk", "oto"],
  ["T1", "tasinabilirlik/kurulum", "uc birim kurulum suresi", "kurulum_dk", "dk", 45, "kucuk", "elle"],
  ["T2", "tasinabilirlik/kurulum", "ortama ozgu cagri", "ozgu_cagri", "cagri", 0, "kucuk", "oto"],
  ["T3", "tasinabilirlik/veri", "aktarimda kaybolan alan", "kaybolan", "alan", 0, "kucuk", "oto"],
  ["T4", "tasinabilirlik/veri", "uyelik verisinin devri", "", "", null, "", "-"],
];

const ALAN = ["kod", "dal", "ad", "gozlem", "birim", "esik", "yon", "kaynak"];
const YAPRAK = TANIM.map((t) => Object.fromEntries(ALAN.map((a, i) => [a, t[i]])));

// Olculebilirlik iki basamakta olculur: yaprak bir sayiya baglaniyor mu (birimi ve esigi
// var mi), o sayi kosturulabilir denetime cevriliyor mu (gozlemi bir kayittan okunuyor mu).
const sayili = (y) => y.esik !== null;
const kosar = (y) => sayili(y) && y.kaynak === "oto";

mkdirSync("agac", { recursive: true });
writeFileSync("agac/agac.mjs", `export const YAPRAK = ${JSON.stringify(YAPRAK)};\n`);

const kok = (y) => y.dal.split("/")[0];
const say = (l, f) => String(l.filter(f).length).padStart(9);
console.log(`${"kok nitelik".padEnd(20)}${"alt".padStart(4)}${"yaprak".padStart(8)}` +
  `${"denetim".padStart(9)}${"elle".padStart(9)}${"sayisiz".padStart(9)}`);
for (const k of [...new Set(YAPRAK.map(kok))]) {
  const y = YAPRAK.filter((n) => kok(n) === k);
  console.log(`${k.padEnd(20)}${String(new Set(y.map((n) => n.dal)).size).padStart(4)}` +
    `${String(y.length).padStart(8)}${say(y, kosar)}` +
    `${say(y, (n) => n.kaynak === "elle")}${say(y, (n) => !sayili(n))}`);
}
const s = YAPRAK.filter(sayili), o = YAPRAK.filter(kosar);
console.log(`toplam ${YAPRAK.length} yaprak: ${s.length} sayiya baglanir, ` +
  `${YAPRAK.length - s.length} baglanmaz; ${o.length} tanesi kosturulabilir denetime ` +
  `cevrilir, ${s.length - o.length} tanesi elle olcum ister`);
const dizi = (f) => YAPRAK.filter(f).map((y) => `${y.kod} ${y.ad}`).join("; ");
console.log(`\nsayiya baglanamayan: ${dizi((y) => !sayili(y))}`);
console.log(`esigi olup kaydi olmayan: ${dizi((y) => sayili(y) && y.kaynak === "elle")}`);
kok nitelik          alt  yaprak  denetim     elle  sayisiz
basarim                3       8        7        0        1
erisilebilirlik        3       6        2        3        1
guvenlik               3       6        5        0        1
surdurulebilirlik      3       6        4        1        1
tasinabilirlik         2       4        2        1        1
toplam 30 yaprak: 25 sayiya baglanir, 5 baglanmaz; 20 tanesi kosturulabilir denetime cevrilir, 5 tanesi elle olcum ister

sayiya baglanamayan: B8 yavasligin uyeye hissettirdigi; E6 kesintide uyeye verilen bilgi; G6 guven sinirinin dogru yerde olmasi; S4 kodun okunur olmasi; T4 uyelik verisinin devri
esigi olup kaydi olmayan: E2 kopukken odunc surmesi; E3 yedege gecis suresi; E5 cokmede etkilenen sube; S2 yeni sube ekleme elle adimi; T1 uc birim kurulum suresi

Otuz yaprağın 25’i bir sayıya bağlanıyor, beşi bağlanmıyor. Asıl ayrım ikinci basamakta: bu 25’in yalnız 20’si koşturulabilir bir denetime çevriliyor. Aradaki beş yaprağın eşiği de birimi de yazılı — eksik olan gözlem. Yedeğe geçişin 60 saniyenin altında kalıp kalmadığı bir tatbikat kurulmadan öğrenilemez. Eşiği yazmak ile ölçümü bir kayda bağlamak ayrı işlerdir, ve ikincisi ödenmediğinde nitelik ölçülü görünüp denetimsiz kalır.

Kök başına dağılım eşit değil. Güvenliğin altı yaprağının beşi denetime çevriliyor, çünkü çoğu bir sayımdır: kaç uç nokta kimlik doğrulamasız, depoda kaç açık sır değeri var. Erişilebilirliğin altı yaprağının yalnız ikisi çevriliyor; kalanı sistemi bozmayı gerektiriyor. Bu, hangi niteliğin daha önemli olduğunu söylemez; hangisinin daha ucuz denetlendiğini söyler.

Bilinen İhlal Kümesinde Denetim

Yirmi denetim yazıldı; sıradaki soru bunların gerçekte ne yakaladığıdır. Aşağıdaki blok yirmi dört gözlem penceresini ve bu pencerelerde kayıtlı on sekiz ihlali modelliyor, denetimleri kümeye uyguluyor, sonra çevrilemeyenin yerine konan düzeni aynı kaçan ihlaller üzerinde ölçüyor.

// denetim.mjs — yapraklardan denetim uretip bilinen ihlal kumesine uygular, sonra denetime
// cevrilemeyen yapraklarin yerine konani olcer
import { YAPRAK } from "./agac/agac.mjs";

// KN2: iki ceyreklik 24 gozlem penceresinde 18 ihlal kayitli (kurgu). Ucuncu alan ihlalin
// gozlem akisina yansiyip yansimadigi: G4 ihlali kayda gecmeyen bir yoldan olmus. Dorduncu
// alan ihlalin kac pencere surdugu; yapisal kusurlar duzeltilene dek surer (99).
const IHLAL = [
  [2, "B1", true, 1], [3, "G3", true, 4], [4, "E3", false, 20], [5, "S1", true, 1],
  [6, "B5", true, 2], [7, "G6", false, 99], [8, "E1", true, 1], [9, "B7", true, 3],
  [10, "T1", false, 1], [11, "G4", false, 99], [12, "S4", false, 99], [13, "B1", true, 1],
  [14, "S5", true, 6], [15, "E4", true, 1], [16, "S2", false, 10], [17, "G1", true, 5],
  [18, "B8", false, 99], [20, "S3", true, 8],
];
const PENCERE = 24;

// KN3: gurultu modeli. Her otomatik yapragin pencere degeri esigin cevresinden duzgun
// dagilimla cekilir; esik dagilimin ust ucuna yakindir, boylece ihlal olmadan da esigin
// asildigi pencereler dogar. Uretec kendi yazilmistir, tohum gorunurdur.
const uretec = (tohum) => () => {
  tohum = (tohum + 0x6d2b79f5) | 0;
  let t = Math.imul(tohum ^ (tohum >>> 15), 1 | tohum);
  t = (t + Math.imul(t ^ (t >>> 7), 61 | t)) ^ t;
  return ((t ^ (t >>> 14)) >>> 0) / 4294967296;
};
const rastgele = uretec(41307);

const OTO = YAPRAK.filter((y) => y.kaynak === "oto");
const bul = (kod) => YAPRAK.find((y) => y.kod === kod);
const cek = (y, r) => (y.esik === 0 ? (r < 0.06 ? 1 : 0)
  : y.esik * (y.yon === "buyuk" ? 0.95 + r * 0.65 : 0.4 + r * 0.65));
const ihlalDegeri = (y) => (y.esik === 0 ? 2 : y.esik * (y.yon === "buyuk" ? 0.8 : 1.3));

const kayit = [];
for (let p = 1; p <= PENCERE; p += 1) {
  const gozlem = {};
  for (const y of OTO) gozlem[y.gozlem] = cek(y, rastgele());
  const ih = IHLAL.find(([n]) => n === p);
  if (ih && ih[2]) gozlem[bul(ih[1]).gozlem] = ihlalDegeri(bul(ih[1]));
  kayit.push({ p, gozlem, ihlal: ih ? ih[1] : null });
}

// Denetim yapragin kendisinden uretilir: gozlem alani, esik ve yon disinda bilgi almaz.
const denetim = (y) => (g) => (y.yon === "buyuk" ? g[y.gozlem] < y.esik : g[y.gozlem] > y.esik);
const atesleme = [];
for (const k of kayit)
  for (const y of OTO) if (denetim(y)(k.gozlem)) atesleme.push([k.p, y.kod, k.ihlal === y.kod]);

const yakalanan = atesleme.filter(([, , d]) => d);
const yanlis = atesleme.filter(([, , d]) => !d);
const kacan = IHLAL.filter(([p, kod]) => !yakalanan.some(([q, k]) => q === p && k === kod));
console.log(`${PENCERE} pencere, ${IHLAL.length} bilinen ihlal, ${OTO.length} kosturulabilir denetim`);
console.log(`yakalanan ${yakalanan.length}, kacan ${kacan.length}, yanlis alarm ${yanlis.length}\n`);

const alarm = {};
for (const [, kod] of yanlis) alarm[kod] = (alarm[kod] || 0) + 1;
const sirali = Object.entries(alarm).sort((a, b) => b[1] - a[1]);
console.log(`${sirali.length} denetim en az bir kez bosa otmus; en cok oten ucu: ` +
  sirali.slice(0, 3).map(([k, n]) => `${k} (${n})`).join(", "));

// KN4: ekip davranisi. Iki ceyrekte ikiden cok yanlis alarm ureten denetim kapatilir.
const kapali = sirali.filter(([, n]) => n > 2).map(([k]) => k);
const kalan = yakalanan.filter(([, kod]) => !kapali.includes(kod));
console.log(`kapatma esigi 2: kapanan denetim ${kapali.length} (${kapali.join(", ")}); ` +
  `sonrasinda yakalanan ${kalan.length}, kacan ${IHLAL.length - kalan.length}, ` +
  `yanlis alarm ${yanlis.filter(([, kod]) => !kapali.includes(kod)).length}`);
const tablo = OTO.reduce((s, y) => s + `${y.gozlem}${y.birim}${y.esik}${y.yon}`.length, 0);
console.log(`denetim maliyeti: kural govdesi 1 satir (hepsi icin ayni), esik tablosu ` +
  `${OTO.length} satir / ${tablo} karakter, kosum ${PENCERE * OTO.length} karsilastirma, ` +
  `doldurulan gozlem alani ${PENCERE * OTO.length}`);

// KN5: cevrilemeyenin yerine iki duzen konur; oturumlar 12. ve 24. pencerede kosar. Esigi
// olup kaydi olmayan bes yaprak icin olcum oturumu (6 kisi-saat), sayiya baglanamayan bes
// yaprak icin alanin %35'ini orneklem alan gozden gecirme (4 kisi-saat). Otomatik yapraga
// dusen kacan ihlal hicbir duzenin kapsaminda degildir.
const OTURUM = [12, 24], ORNEKLEM = 0.35, SAAT = { olcum: 6, gozden: 4 };
const duzen = (y) => (y.kaynak === "elle" ? "olcum" : y.esik === null ? "gozden" : "kapsam disi");
const ikinci = uretec(9152);

console.log(`\n${"pencere".padStart(7)}  ${"kod".padEnd(4)}${"yerine konan".padEnd(14)}` +
  `${"sonuc".padEnd(11)}gecikme`);
let bulunan = 0, gecikme = 0;
for (const [p, kod, , surme] of kacan) {
  const d = duzen(bul(kod));
  let o = OTURUM.find((n) => n >= p && n <= p + surme &&
    (d === "olcum" || (d === "gozden" && ikinci() < ORNEKLEM)));
  if (d === "kapsam disi") o = undefined;
  if (o) { bulunan += 1; gecikme += o - p; }
  console.log(`${String(p).padStart(7)}  ${kod.padEnd(4)}${d.padEnd(14)}` +
    `${(o ? "yakalandi" : "kacti").padEnd(11)}${o ? o - p : "-"}`);
}
const kapsam = YAPRAK.filter((y) => y.kaynak !== "oto");
const saat = kapsam.reduce((s, y) => s + SAAT[duzen(y)], 0) * OTURUM.length;
console.log(`\nkacan ${kacan.length} ihlalin ${kacan.length - 1} tanesi yerine konanin kapsaminda: ` +
  `${bulunan} yakalandi, ${kacan.length - 1 - bulunan} kacti; biri hicbir duzende degil`);
console.log(`ortalama gecikme ${(gecikme / bulunan).toFixed(1)} pencere ` +
  `(kosturulabilir denetimde 0), maliyet ${saat} kisi-saat, ` +
  `yakalanan basina ${(saat / bulunan).toFixed(0)} kisi-saat`);
24 pencere, 18 bilinen ihlal, 20 kosturulabilir denetim
yakalanan 11, kacan 7, yanlis alarm 23

15 denetim en az bir kez bosa otmus; en cok oten ucu: B1 (3), B4 (3), G3 (2)
kapatma esigi 2: kapanan denetim 2 (B1, B4); sonrasinda yakalanan 9, kacan 9, yanlis alarm 17
denetim maliyeti: kural govdesi 1 satir (hepsi icin ayni), esik tablosu 20 satir / 359 karakter, kosum 480 karsilastirma, doldurulan gozlem alani 480

pencere  kod yerine konan  sonuc      gecikme
      4  E3  olcum         yakalandi  8
      7  G6  gozden        kacti      -
     10  T1  olcum         kacti      -
     11  G4  kapsam disi   kacti      -
     12  S4  gozden        yakalandi  12
     16  S2  olcum         yakalandi  8
     18  B8  gozden        yakalandi  6

kacan 7 ihlalin 6 tanesi yerine konanin kapsaminda: 4 yakalandi, 2 kacti; biri hicbir duzende degil
ortalama gecikme 8.5 pencere (kosturulabilir denetimde 0), maliyet 100 kisi-saat, yakalanan basina 25 kisi-saat

On sekiz ihlalin 11’i yakalanıyor, yedisi kaçıyor. Kaçanların üçü eşiği olup kaydı olmayan, üçü sayıya bağlanamayan yapraklarda: bu altısı beklenen kayıp, ağaç haber vermişti. Yedincisi başkadır. On birinci penceredeki ihlal, denetimi yazılı ve eşiği sıfır olan bir yaprakta gerçekleşti, yine de kaçtı — ihlal o yaprağın gözlem alanından geçmedi. Bir denetimin kapsamı, beslendiği gözlem alanının kapsamı kadardır; eşik doğru yazıldığı için denetimin doğru çalıştığı sanılır.

Yanlış alarm 23, yakalanan ihlalin iki katından fazla; on beş denetim boşa öttü. Bu, denetimin hatası değil eşiğin dağılıma göre konumunun sonucu: eşik gözlenen değerlerin üst ucuna yakınsa ihlal olmayan pencerelerde de aşılır. Modelde ekip iki çeyrekte ikiden çok yanlış alarm üreten denetimi kapatıyor; iki denetim kapanıyor ve yakalanan ihlal 11’den 9’a düşüyor. Yanlış alarmın bedeli harcanan inceleme zamanı değil, kapanan denetimin bundan sonra yakalamayacağı ihlallerdir. Bu üçlü — yakalanan, kaçan, yanlış alarm — sınama kurslarındaki yanlış geçme ve yanlış kalma ikilisiyle aynı olgu; ölçülen sınama durumu değil mimari kuraldır.

Denetimin kendi maliyeti dört kalemde duruyor: kural gövdesi bir satır ve yirmi yaprağın hepsinde aynı, çünkü kural yaprağın eşiğinden üretiliyor; eşik tablosu yirmi satır ve 359 karakter; koşum 480 karşılaştırma; dördüncü ve büyük kalem, 480 gözlem alanının doldurulması. Kuralın pahalı yeri metni değil beslendiği veridir.

Çevrilemeyenin Yerine Konan

Denetime çevrilemeyen on yaprak boşta bırakılmıyor: eşiği olup kaydı olmayan beşi için çeyrekte bir ölçüm oturumu, sayıya bağlanamayan beşi için gözden geçirme konuyor. Kaçan yedi ihlalin altısı bu iki düzenin kapsamında; dördü yakalanıyor, ikisi kaçıyor. Biri tek pencere sürüp kapandı: oturum on ikinci pencerede koştuğunda ortada bir şey kalmamıştı. Örneklemle çalışan gözden geçirme de bir kusuru atladı — inceleme alanın üçte birine bakıyor, kusur oraya düşmedi.

Ortalama gecikme 8,5 pencere; koşturulabilir denetimde gecikme sıfırdır, ihlal olduğu pencerede görünür. Maliyet iki çeyrekte 100 kişi-saat, yakalanan ihlal başına 25 kişi-saat; yirmi denetim aynı sürede insan emeği harcamadan 11 ihlal yakaladı. Elle düzenin karşılığı da var: yanlış alarm üretmiyor, kararı veren insan bağlamı görüyor. Geriye kimsenin kapsamadığı bir ihlal kalıyor; ağaç bunu da adıyla yazmayı sağlıyor — kapsanmayan yaprak değil, kapsanmayan yol var.

Özet

  • Nitelik ağacı kök, alt nitelik ve yapraktan oluşur; ölçü yalnız yaprakta durur ve otuz yaprağın 25’i bir sayıya bağlanır, beşi bağlanmaz.
  • Sayıya bağlanmak denetlenebilmek değildir: 25 sayılı yaprağın 20’si denetime çevrilir, beşi eşiği yazılı olduğu halde gözlemi olmadığından elle ölçüm ister.
  • Yirmi denetim, on sekiz ihlalin 11’ini yakalıyor, yedisini kaçırıyor, 23 yanlış alarm üretiyor; biri denetimi yazılı olduğu halde gözlem alanına yansımadığı için kaçıyor.
  • Yanlış alarmın bedeli ölçülür: ikiden çok alarm üreten iki denetim kapatıldığında yakalanan ihlal 11’den 9’a iniyor.
  • Çevrilemeyenin yerine konan düzen kaçan altı ihlalin dördünü 8,5 pencere gecikme ve 100 kişi-saate yakalıyor; koşturulabilir denetimin bedeli bir satır kural ve 480 gözlem alanıdır.

Sonraki Adım

Ağaç kurulduğunda her yaprak kendi eşiğiyle tek başına denetleniyormuş gibi durur. Sonraki ders bu görüntüyü bozar: yapraklar birbirinden bağımsız değil. Bağlantı havuzunun doluluğunu düşüren karar yedeğe geçiş süresini uzatır, sınama kapsamasını yükselten karar toplu yükleme penceresini taşırır. Bu ilişki tahminle değil ölçüyle bulunur — bir gerilim matrisi kurulur, bir niteliği yükselten kararlar sırayla uygulanır, her uygulamadan sonra öteki niteliklerde ölçülen düşüş sayılır. Sonuçta kaç çiftin çeliştiği, en çok bastırılan niteliğin hangisi olduğu ve hiçbir kararın iyileştiremediği bir niteliğin bulunup bulunmadığı çıkar.

İ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