İçeriğe geç
academia.sh

Ders 11 / 12

Bağımlılık Politikası

Bağımlılık politikası kural kümesi olarak koşturulur ve iki sayı ayrılır: yedi kuralın kaçı envanterin alanlarıyla koşabiliyor, kırk altı işaret kaç bileşene düşüyor, işaretlerin kaçı gerçek ve kaçı yanlış, hiçbir kuralın görmediği aykırı bileşen kaç tane ve kural kapıya dönüştüğünde kaç yapı yanlış yere duruyor.

İçindekiler

Önceki ders derleme ortamının yetkisini kalem kalem saydı ve hattın ilk adımını dışarıda bıraktı. Bağımlılık çekme adımı envanterdeki yetmiş üç kaydı hatta getiren adımdır ve yetki daraltma o kayıtların hiçbirine dokunmaz. Ortam ne kadar dar olursa olsun, içeri giren bileşenin ne olduğu ayrı bir sorudur.

Bu ders o soruyu bir kural kümesine çevirir. Ölçü iki sayıdır: politika kaç bileşeni işaretliyor ve işaretlerin kaçı yanlış. Bağımlılık riski ve sürüm sabitleme daha önce iki kursta ölçülmüştü; o pratik tekrarlanmaz. Buradaki nesne kural kümesinin kendisidir — hangi kural hangi alanla koşuyor ve işaretinin karşılığı ne.

TZ20. Envanter ilk dersteki modelle aynı tohumdan yeniden üretilir: 73 kayıt, 48 benzersiz bileşen. Politika bileşen üzerinde koşar; kayıtlar benzersiz ad altında toplanır. TZ21. Politika iki kaynağı birleştirir: envanterin beş alanı ve dış paket kaydının iki alanı — son yayın ayı ve bakımcı sayısı. İkisi de envanterde yoktur; dış kaydın tohumu 660418 görünürdür.

Politikayı Kural Olarak Koşturmak

// olcum-agi/politika.mjs — bagimlilik politikasi kural olarak kosturulur: kac bileseni isaretliyor
import { mkdirSync, writeFileSync } from "node:fs";
import { join } from "node:path";

const KOK = join(process.env.TMPDIR ?? "/tmp", "olcum-agi-tz");
mkdirSync(KOK, { recursive: true });
const uretec = (tohum) => () =>
  (tohum = (tohum * 1103515245 + 12345) % 2147483648) / 2147483648;
const r = uretec(20260731);                                  // envanter tohumu gorunur
const sec = (d) => d[Math.floor(r() * d.length)];

// Envanter ilk dersteki modelle ayni tohumdan yeniden uretilir: 73 kayit, 48 benzersiz bilesen.
const DEPO = [["abone-portali", 11], ["sayac-alim", 9], ["ortak-kitaplik", 6]];
const HAVUZ = Array.from({ length: 70 }, (_, i) => `bilesen-${String(i + 1).padStart(2, "0")}`);
const SURUM = ["1.2", "1.9", "2.0", "2.4", "3.0", "3.6", "4.1"];
const LISANS = ["izin-veren", "izin-veren", "izin-veren", "zayif-karsilikli", "karsilikli"];
const kayit = [];
for (const [depo, dogrudanSayi] of DEPO) {
  const alinan = new Set();
  const yeni = () => { let a; do { a = sec(HAVUZ); } while (alinan.has(a)); alinan.add(a); return a; };
  const ekle = (ad, getiren) => kayit.push({ ad, surum: sec(SURUM), depo,
    lisans: r() < 0.18 ? "" : sec(LISANS),
    getiren: getiren === null ? depo : (r() < 0.12 ? "" : getiren) });
  for (let i = 0; i < dogrudanSayi; i++) {
    const kok = yeni();
    ekle(kok, null);
    for (let k = 0, n = Math.floor(r() * 4); k < n; k++) {
      const cocuk = yeni();
      ekle(cocuk, kok);
      if (r() < 0.35) ekle(yeni(), cocuk);
    }
  }
}

// Bilesen gorunumu: yetmis uc kayit benzersiz ad altinda toplanir.
const DEPO_AD = new Set(DEPO.map(([ad]) => ad));
const BILESEN = new Map();
for (const k of kayit) {
  const b = BILESEN.get(k.ad) ?? { ad: k.ad, lisans: "", dogrudan: false, getirenBos: false };
  if (b.lisans === "") b.lisans = k.lisans;
  if (DEPO_AD.has(k.getiren)) b.dogrudan = true;
  if (k.getiren === "") b.getirenBos = true;
  BILESEN.set(k.ad, b);
}

// Dis paket kaydi ayri bir kaynaktir: son yayin ayi ve bakimci sayisi envanterde yoktur.
const d = uretec(660418);                                    // dis kayit tohumu gorunur
for (const b of BILESEN.values()) {
  b.disKayit = d() < 0.9;
  b.sonYayinAy = 1 + Math.floor(d() * 47);
  b.bakimci = 1 + Math.floor(d() * d() * 5);
  b.yerineGecenVar = d() < 0.55;                             // gizli: kurallar bunu gormez
  b.devredilmis = d() < 0.07;                                // gizli: hicbir alan gostermez
  b.gizliLisans = b.lisans === "" ? (d() < 0.45 ? "karsilikli" : "izin-veren") : b.lisans;
}
const B = [...BILESEN.values()];

// Yedi kural. Her kural gereksindigi alani bildirir; alan yoksa kural kosamaz.
const ALAN = new Set(["ad", "surum", "depo", "lisans", "getiren", "sonYayinAy", "bakimci"]);
const KURAL = [
  ["kisitli lisans", ["lisans"], (b) => b.lisans === "karsilikli"],
  ["lisans bilinmiyor", ["lisans"], (b) => b.lisans === ""],
  ["terkedilmis paket", ["sonYayinAy", "bakimci"],
    (b) => b.disKayit && b.sonYayinAy >= 24 && b.bakimci <= 1],
  ["tek bakimci", ["bakimci"], (b) => b.disKayit && b.bakimci === 1],
  ["dis kayitta karsiligi yok", ["sonYayinAy"], (b) => b.disKayit === false],
  ["getiren kenari bos", ["getiren"], (b) => b.getirenBos],
  ["kosumda cagrilan kisitli lisansli", ["cagrilir", "lisans"], null],
];

const S = [36, 22, 11, 0];
const satir = (s) => console.log(s.map((v, i) => String(v).padEnd(S[i])).join(""));
satir(["kural", "gereken alan", "kosabildi", "isaretlenen bilesen"]);
const isaret = {};
for (const [ad, gereken, sina] of KURAL) {
  const kosar = gereken.every((a) => ALAN.has(a));
  if (kosar) isaret[ad] = B.filter(sina).map((b) => b.ad);
  satir([ad, gereken.join("+"), kosar ? "evet" : "HAYIR",
    kosar ? isaret[ad].length : "alan yok"]);
}
const birlesim = new Set(Object.values(isaret).flat());
writeFileSync(join(KOK, "politika.json"), JSON.stringify({ B, isaret }));
console.log("");
console.log(`kayit ${kayit.length}, benzersiz bilesen ${B.length}; dis kayitta karsiligi olan ` +
  `${B.filter((b) => b.disKayit).length}; tohum 20260731 ve 660418`);
console.log(`yedi kuralin ${Object.keys(isaret).length}'si kosuyor, biri envanterde alan ` +
  `olmadigi icin kosmuyor; isaret ${Object.values(isaret).flat().length}, ` +
  `isaretlenen benzersiz bilesen ${birlesim.size}/${B.length}`);
kural                               gereken alan          kosabildi  isaretlenen bilesen
kisitli lisans                      lisans                evet       5
lisans bilinmiyor                   lisans                evet       6
terkedilmis paket                   sonYayinAy+bakimci    evet       9
tek bakimci                         bakimci               evet       18
dis kayitta karsiligi yok           sonYayinAy            evet       2
getiren kenari bos                  getiren               evet       6
kosumda cagrilan kisitli lisansli   cagrilir+lisans       HAYIR      alan yok

kayit 73, benzersiz bilesen 48; dis kayitta karsiligi olan 46; tohum 20260731 ve 660418
yedi kuralin 6'si kosuyor, biri envanterde alan olmadigi icin kosmuyor; isaret 46, isaretlenen benzersiz bilesen 30/48

Yedi kuralın altısı koşar, biri koşamaz. Koşamayanın nedeni bir yapılandırma eksiği değildir: “koşumda çağrılan kısıtlı lisanslı bileşen” kuralı cagrilir alanını gereksinir ve o alan ne envanterde ne dış kayıttadır. İlk ders bu soruyu cevaplanmayan dört sorudan biri olarak saymıştı; burada aynı boşluk bir kuralın hiç yazılamaması olarak görünür. Bir politika, dayandığı alan kümesi kadar yazılabilir.

Koşan altı kural 46 işaret üretir ve bu işaretler 48 bileşenin 30’una düşer: envanterin üçte ikisi işaretlenmiştir. Dağılım eşit değildir — tek bakımcı kuralı tek başına 18 işaret üretir. Birleştirme de kusursuz değildir: iki bileşen dış kayıtta hiç bulunmaz ve o ikisi için terkedilmişlik ile bakımcı sayısı kuralları hiç değerlendirilemez.

İşaretin Kaçı Yanlış

Otuz işaretli bileşen tek başına bir sayı değildir. Ölçünün ikinci yarısı, bu işaretlerin kaçının gerçekten bir politika aykırılığına karşılık geldiğidir.

TZ22. Gerçekten aykırı küme kurgudur ve dört kaynaktan gelir: karşılıklı lisanslı doğrudan bağımlılık, yerine geçen sürümü olmayan terkedilmiş paket, lisansı bilinmeyen ama gerçekte kısıtlı olan bileşen ve bakımı devredilmiş paket. Kurallar bu kümeyi görmez. Devir üç bileşende olmuştur ve devri gösteren alan hiçbir kaynakta yoktur; bu üçü kuralların işaretlemediği kümeden seçilir.

// olcum-agi/yanlis-isaret.mjs — politikanin isaretlerinin kaci gercek, kaci yanlis
import { readFileSync, writeFileSync } from "node:fs";
import { join } from "node:path";

const KOK = join(process.env.TMPDIR ?? "/tmp", "olcum-agi-tz");
const { B, isaret } = JSON.parse(readFileSync(join(KOK, "politika.json")));
const birlesim = new Set(Object.values(isaret).flat());

// Kurgu gercek durum. Kurallar bu kumeyi gormez; gizli alanlar yalniz burada okunur.
const GERCEK = new Set();
const SEBEP = { lisans: 0, bakimsiz: 0, gizliLisans: 0, devir: 0 };
for (const b of B) {
  // (a) Karsilikli lisansli ve dogrudan bagimlilik: lisans yukumlulugu gercekten doguyor.
  if (b.lisans === "karsilikli" && b.dogrudan) { GERCEK.add(b.ad); SEBEP.lisans++; }
  // (b) Terkedilmis ve yerine gecen surumu olmayan paket: bakimsizlik gercekten risk.
  else if (b.disKayit && b.sonYayinAy >= 24 && b.bakimci <= 1 && !b.yerineGecenVar) {
    GERCEK.add(b.ad); SEBEP.bakimsiz++;
  }
  // (c) Lisansi bilinmeyen ama gercekte kisitli olan bilesen: bos alanin arkasindaki durum.
  else if (b.lisans === "" && b.gizliLisans === "karsilikli") {
    GERCEK.add(b.ad); SEBEP.gizliLisans++;
  }
}
// (d) Kurgu: hicbir kuralin isaretlemedigi kumeden uc bilesende bakim devri olmustur.
// Devri gosteren alan ne envanterde ne dis kayitta vardir: kurallarin gorus alani disi.
const temizGorunen = B.filter((b) => !birlesim.has(b.ad)).map((b) => b.ad);
for (const ad of [0, 6, 12].map((i) => temizGorunen[i])) { GERCEK.add(ad); SEBEP.devir++; }

writeFileSync(join(KOK, "gercek.json"), JSON.stringify([...GERCEK]));

const S = [30, 9, 9, 15, 0];
const satir = (s) => console.log(s.map((v, i) => String(v).padEnd(S[i])).join(""));
satir(["kural", "isaret", "gercek", "yanlis isaret", "yanlis oran"]);
for (const [ad, liste] of Object.entries(isaret)) {
  const gercek = liste.filter((a) => GERCEK.has(a)).length;
  satir([ad, liste.length, gercek, liste.length - gercek,
    `%${Math.round((100 * (liste.length - gercek)) / liste.length)}`]);
}

const gorulen = [...GERCEK].filter((a) => birlesim.has(a));
const gorulmeyen = [...GERCEK].filter((a) => !birlesim.has(a));
console.log("");
console.log(`gercekten aykiri ${GERCEK.size}/${B.length} bilesen: lisans ${SEBEP.lisans}, ` +
  `bakimsiz ${SEBEP.bakimsiz}, bilinmeyen lisans ${SEBEP.gizliLisans}, devir ${SEBEP.devir}`);
console.log(`isaret ${Object.values(isaret).flat().length}, isaretlenen benzersiz bilesen ` +
  `${birlesim.size}: ${gorulen.length} gercek, ${birlesim.size - gorulen.length} yanlis isaret`);
console.log(`hicbir kuralin gormedigi gercek aykiri ${gorulmeyen.length}/${GERCEK.size}; ` +
  `temiz gorunen ${temizGorunen.length} bilesenin icinden`);
kural                         isaret   gercek   yanlis isaret  yanlis oran
kisitli lisans                5        3        2              %40
lisans bilinmiyor             6        1        5              %83
terkedilmis paket             9        6        3              %33
tek bakimci                   18       7        11             %61
dis kayitta karsiligi yok     2        0        2              %100
getiren kenari bos            6        1        5              %83

gercekten aykiri 13/48 bilesen: lisans 3, bakimsiz 6, bilinmeyen lisans 1, devir 3
isaret 46, isaretlenen benzersiz bilesen 30: 10 gercek, 20 yanlis isaret
hicbir kuralin gormedigi gercek aykiri 3/13; temiz gorunen 18 bilesenin icinden

Otuz işaretli bileşenin 10’u gerçek, 20’si yanlış işarettir. Politika envanterin üçte ikisini işaretliyor, gerçekten aykırı olansa sekizde biridir.

Kural bazında dağılım bir sıralama verir. Terkedilmiş paket kuralı en az gürültülüsüdür: 9 işaretin 6’sı gerçektir, çünkü iki alanı birlikte arar — hem yayın yaşı hem bakımcı sayısı. Yanlış üçü, yayını eskimiş ama yerine geçen sürümü bulunan paketlerdir; tarih alanının eskimesi tek başına bakımsızlık anlamına gelmiyor. Tek bakımcı kuralı ise 18 işaretle en çok konuşan kuraldır ve 11’i yanlıştır: bakımcı sayısı bir aykırılık değil, bir dağılım özelliğidir.

Son satır ölçünün eksik yarısını yazar. Gerçekten aykırı 13 bileşenin 3’ü hiçbir kural tarafından görülmez ve üçü de kuralların “temiz” saydığı 18 bileşenin içindedir. Nedeni bir eşik ayarı değildir: bakım devrini gösteren alan hiçbir kaynakta bulunmaz, dolayısıyla o üçünü gösterecek bir kural yazılamaz. Yanlış negatifi yazılmayan bir politika ölçümü, işaretlediği otuz bileşeni bir güvence gibi sunar.

Kural Kapı Olduğunda

Bir işaret listesiyle duran bir yapı aynı şey değildir. Durdurulan iş ancak kural bir kapıya dönüştüğünde ölçülebilir.

TZ23. Otuz yapı kurgudur; her yapı bir ile dört bileşeni değiştirir, tohum 9143205 görünürdür. Bir yapı yalnız yanlış işaretlerle duruyorsa ekip o bileşenleri istisna listesine yazar ve bileşen bir daha durdurmaz. TZ24. Süreler veridir: değerlendirme 9 saniye, duran yapı başına 4 dakika müdahale.

// olcum-agi/kapi.mjs — politika kapi oldugunda: kac yapi duruyor, kaci yanlis yere duruyor
import { readFileSync } from "node:fs";
import { join } from "node:path";

const KOK = join(process.env.TMPDIR ?? "/tmp", "olcum-agi-tz");
const { B, isaret } = JSON.parse(readFileSync(join(KOK, "politika.json")));
const GERCEK = new Set(JSON.parse(readFileSync(join(KOK, "gercek.json"))));
const isaretli = new Map(B.map((b) => [b.ad, Object.entries(isaret)
  .filter(([, l]) => l.includes(b.ad)).map(([k]) => k)]));
const dogrudan = new Map(B.map((b) => [b.ad, b.dogrudan]));

const uretec = (tohum) => () =>
  (tohum = (tohum * 1103515245 + 12345) % 2147483648) / 2147483648;
// Kurgu: otuz yapi, her biri bir ile dort bileseni degistiriyor. Tohum gorunur.
const r = uretec(9143205);
const YAPI = Array.from({ length: 30 }, () =>
  Array.from({ length: 1 + Math.floor(r() * 4) }, () => B[Math.floor(r() * B.length)].ad));

// Sureler VERI olarak verilmistir: degerlendirme 9 s, duran yapi basina mudahale 4 dk.
const [DEGER_S, MUDAHALE_DK] = [9, 4];
const KIP = [
  ["yalniz uyar", () => false],
  ["dogrudan bagimlilikta dur", (a) => dogrudan.get(a) && isaretli.get(a).length > 0],
  ["her isarette dur", (a) => isaretli.get(a).length > 0],
];

const S = [28, 11, 14, 11, 0];
const satir = (s) => console.log(s.map((v, i) => String(v).padEnd(S[i])).join(""));
satir(["kapi kipi", "duran yapi", "yanlis duran", "istisna", "hat + mudahale"]);
for (const [ad, durdurur] of KIP) {
  const istisna = new Set();
  let duran = 0, yanlisDuran = 0;
  for (const bilesenler of YAPI) {
    const sebep = bilesenler.filter((a) => durdurur(a) && !istisna.has(a));
    if (sebep.length === 0) continue;
    duran++;
    if (sebep.every((a) => !GERCEK.has(a))) {         // hepsi yanlis isaret: istisna yazilir
      yanlisDuran++;
      for (const a of sebep) istisna.add(a);
    }
  }
  satir([ad, duran, yanlisDuran, istisna.size,
    `${YAPI.length * DEGER_S} s + ${duran * MUDAHALE_DK} dk`]);
}

// Yanlis orani yuksek kural toptan bastirilirsa gorulen gercek kac tane kalir.
const ESIK = 0.6;
const kalanKural = Object.entries(isaret).filter(([, l]) =>
  l.filter((a) => !GERCEK.has(a)).length / l.length <= ESIK);
const kalanIsaret = new Set(kalanKural.flatMap(([, l]) => l));
const tumIsaret = new Set(Object.values(isaret).flat());
console.log("");
console.log(`otuz yapi ${YAPI.flat().length} bilesen dokunusu; isaretli bilesen ` +
  `${[...isaretli.values()].filter((k) => k.length > 0).length}/${B.length}; tohum 9143205`);
console.log(`yanlis orani %${ESIK * 100} ustundeki kural bastirilirsa: kural ` +
  `${Object.keys(isaret).length} -> ${kalanKural.length}, isaretlenen bilesen ` +
  `${tumIsaret.size} -> ${kalanIsaret.size}`);
console.log(`gorulen gercek aykiri ${[...GERCEK].filter((a) => tumIsaret.has(a)).length} -> ` +
  `${[...GERCEK].filter((a) => kalanIsaret.has(a)).length}/${GERCEK.size}`);
kapi kipi                   duran yapi yanlis duran  istisna    hat + mudahale
yalniz uyar                 0          0             0          270 s + 0 dk
dogrudan bagimlilikta dur   16         5             5          270 s + 64 dk
her isarette dur            24         9             14         270 s + 96 dk

otuz yapi 85 bilesen dokunusu; isaretli bilesen 30/48; tohum 9143205
yanlis orani %60 ustundeki kural bastirilirsa: kural 6 -> 2, isaretlenen bilesen 30 -> 14
gorulen gercek aykiri 10 -> 9/13

Üç satır aynı kural kümesinin üç ayarıdır. Yalnız uyaran kip hattan 270 saniye alır ve hiçbir yapıyı durdurmaz; bulduğu her şey bir listeye yazılır ve listeyi okumak kimsenin işi değildir. Her işarette duran kip otuz yapının 24’ünü durdurur, 96 dakika geliştirici zamanı yer ve 14 bileşenlik bir istisna listesi bırakır. Doğrudan bağımlılıkla sınırlı kip ortadadır: 16 duran yapı, 5 yanlış duran, 5 istisna.

İstisna sütunu asıl sonucu taşır. On dört bileşen yanlış yere durdurdukları için listeye yazılmıştır ve liste bir daha küçülmez. Kural kendi ürettiği yanlış işaretle kendini kapatır: kırk altı işaretin yirmisi yanlışsa kapı, çalıştıkça etkisizleşen bir kapıdır.

Son iki satır bunun toplu biçimini ölçer. Yanlış oranı %60’ı geçen dört kural toptan bastırılırsa işaretlenen bileşen 30’dan 14’e iner ve görülen gerçek aykırı 10’dan 9’a düşer. Dört gürültülü kural, tek bir gerçek bileşen dışında yeni hiçbir şey göstermiyordu; on altı yanlış işaretin karşılığı bir bileşendi. Bir kuralın değeri işaret sayısında değil, kendinden başka hiçbir kuralın göstermediği gerçek kalem sayısındadır.

Özet

  • Yedi kuralın 6’sı koşar, biri koşamaz: cagrilir alanı ne envanterde ne dış kayıttadır. Bir politika, dayandığı alan kümesi kadar yazılabilir.
  • Koşan altı kural 46 işaret üretir ve 48 bileşenin 30’una düşer; iki bileşenin dış kayıtta karşılığı yoktur ve o ikisi için iki kural hiç değerlendirilemez.
  • İşaretlenen 30 bileşenin 10’u gerçek, 20’si yanlış işarettir. Terkedilmiş paket kuralı iki alanı birlikte aradığı için en az gürültülüsüdür (%33); tek bakımcı kuralı 18 işaretin 11’inde yanılır.
  • Gerçekten aykırı 13 bileşenin 3’ü hiçbir kural tarafından görülmez, çünkü bakım devrini gösteren alan hiçbir kaynakta yoktur.
  • Her işarette duran kip 30 yapının 24’ünü durdurur, 96 dakika müdahale ister ve 14 bileşenlik bir istisna listesi bırakır. Gürültülü dört kural bastırılırsa işaret 30’dan 14’e iner, görülen gerçek aykırı yalnız 10’dan 9’a düşer.

Sonraki Adım

Politika koşturuldu, işaretler sayıldı ve işaretin karşılığı yazıldı. Elde otuz işaretli bileşen, on gerçek aykırılık ve on dört bileşenlik bir istisna listesi var. Bu kursun önceki dersleri de kendi listelerini bıraktı: denetimlerin bulguları, bağımlılık eşleştirmesinin kalemleri, envanterin eksik alanları, köken belgesinin sınanamayan beyanları. Hepsi ayrı listelerdir ve hepsi aynı geliştirici kuyruğuna düşer.

Kuyruk sonlu olduğuna göre sıra bir yerden gelmek zorundadır. Sonraki ders bu bulguları tek bir kümede toplar ve üç kez sıralar: önce ciddiyetle, sonra sömürülebilirlikle, sonra maruziyetle. Ölçü sıralamanın kendisi değil, sıralamalar arasındaki farktır — ilk ona giren kalemler kaç yerde değişiyor ve hangi kalem üçünde de üstte kalıyor?

İ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