Ders 17 / 17
Bağımlılık Kaynaklı Riskler
Bağımlılık çizgesinin kapsama ölçüsü: bildirim dosyasında sekiz ad geçerken süreçte otuz dört paketin bulunması, geçişli derinliğin altıya çıkması, tek bir bileşenin yirmi paketi etkilemesi, sekiz doğrudan bağımlılığın üçünün hiç çağrılmaması ve aynı önem derecesiyle gelen altı açık kaydının dördünün erişilebilir, ikisinin erişilmeyen bileşende olması.
İçindekiler
Önceki ders sürecin dışarı konuştuğu noktaları saydı ve hepsinde ölçülen şey kendi yazdığımız kodun davranışıydı: hangi satır yığıt izini yanıta koyuyor, hangi alan maskeleniyor. Oysa bir isteği karşılayan kodun büyük bölümü ekibin yazdığı satırlar değildir. Portal servisinin süreci ayağa kalktığında onlarca bileşen yüklenir; bir bölümü bir bildirim dosyasında adıyla geçer, geri kalanı yalnızca başka bir bileşenin bağımlılığı olduğu için gelir.
Bağımlılık Riski dersi bu kümeyi bir yapılandırma kararı olarak ele almıştı: yükseltme politikası ne kadar açık gün biriktiriyor, kaç sürüm kırıyor. Burada politika hiç konuşulmaz. Ölçülen şey çizgenin kendi yapısıdır — kaç bileşen var, ne kadar uzakta duruyorlar, biri düştüğünde kaçı etkileniyor ve kaçı süreçte yüklü olduğu hâlde hiç çağrılmıyor.
Bağımlılık Çizgesi
KI13 — bildirim dosyasında adı geçen bileşen sayısı, süreçte yüklü olan bileşen sayısını vermez; ikincisi geçişli kapanıştır ve ayrı bir niceliktir. KI14 — bir bileşenin etkilediği alan, ona geçişli olarak bağlı olan paket sayısıyla ölçülür ve derinlikten bağımsızdır. KI15 — yüklü olmak çağrılmak değildir; kod yolundan erişilmeyen bir bileşen çizgede durur, süreçte yer kaplar ve hiç çalışmaz.
// bagimlilik/cizge.mjs — kurgu olcum agi portal servisinin bagimlilik cizgesi (model). // Sekiz bilesen bildirim dosyasinda adiyla gecer; kalanlar gecisli olarak gelir. Kenarlar // kendi uretecimizle uretilir, tohum gorunur. Paket adlari kurgudur (p01, p02, ...). const TOHUM = 91237; let d = TOHUM; const rast = () => (d = (d * 1103515245 + 12345) % 2 ** 31) / 2 ** 31; const N = 44, DOGRUDAN = 8; const ad = (i) => `p${String(i).padStart(2, '0')}`; const kenar = new Map(Array.from({ length: N }, (_, i) => [i, []])); kenar.set(-1, Array.from({ length: DOGRUDAN }, (_, i) => i)); // -1 = bizim kodumuz for (let i = 0; i < N; i++) { const sayi = i < DOGRUDAN ? 1 + Math.floor(rast() * 4) : Math.floor(rast() * 3); for (let k = 0; k < sayi; k++) { const hedef = DOGRUDAN + Math.floor(rast() * (N - DOGRUDAN)); if (hedef !== i && !kenar.get(i).includes(hedef)) kenar.get(i).push(hedef); } } // Derinlik: bizim kodumuzdan en kisa uzaklik. Hic ulasilmayan paket cizgede yoktur. const derinlik = new Map(); let sinir = [-1]; for (let seviye = 0; sinir.length; seviye++) { const sonraki = []; for (const u of sinir) for (const v of kenar.get(u) ?? []) { if (!derinlik.has(v)) { derinlik.set(v, seviye + 1); sonraki.push(v); } } sinir = sonraki; } const paketler = [...derinlik.keys()].sort((a, b) => a - b); // Tek bilesenin etkiledigi paket: ona gecisli olarak bagli olan paket sayisi. const tersErisim = (hedef) => { const gorulen = new Set(); let degisti = true; while (degisti) { degisti = false; for (const u of paketler) { if (gorulen.has(u)) continue; if ((kenar.get(u) ?? []).some((v) => v === hedef || gorulen.has(v))) { gorulen.add(u); degisti = true; } } } return gorulen.size; }; // Kod yolumuz sekiz dogrudan bilesenin besini gercekten cagiriyor; ucu yuklu ama cagrilmiyor. const CAGRILAN = [0, 1, 3, 4, 6]; const erisilen = new Set(); sinir = [...CAGRILAN]; while (sinir.length) { const s = sinir.pop(); if (erisilen.has(s)) continue; erisilen.add(s); for (const v of kenar.get(s) ?? []) sinir.push(v); } 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 dagilim = {}; for (const p of paketler) dagilim[derinlik.get(p)] = (dagilim[derinlik.get(p)] ?? 0) + 1; console.log(`tohum ${TOHUM}: cizgede ${paketler.length} paket, ${DOGRUDAN} tanesi bildirim ` + `dosyasinda adiyla geciyor, ${paketler.length - DOGRUDAN} tanesi gecisli`); console.log(`derinlige gore dagilim: ${Object.entries(dagilim).map(([k, v]) => `${k}: ${v}`).join(', ')}`); console.log(`en buyuk derinlik ${Math.max(...derinlik.values())}, ` + `kenar sayisi ${paketler.reduce((a, p) => a + (kenar.get(p) ?? []).length, 0)}`); console.log(`kod yolumuzdan erisilen paket ${erisilen.size}, yuklu ama erisilmeyen ` + `${paketler.length - erisilen.size}`); console.log(`kimsenin secmedigi derinlik: ${paketler.filter((p) => derinlik.get(p) >= 3).length} paket ` + `uc ve daha uzak, ${paketler.filter((p) => derinlik.get(p) >= 5).length} paket bes ve daha uzak`); const etki = paketler.map((p) => [p, tersErisim(p)]).sort((a, b) => b[1] - a[1]); console.log('\nen cok pakete dokunan bes bilesen:'); const D = [-10, 10, 12, 18]; yaz(D, 'paket', 'derinlik', 'etkilenen', 'erisilebilir mi'); for (const [p, n] of etki.slice(0, 5)) { yaz(D, ad(p), derinlik.get(p), n, erisilen.has(p) ? 'evet' : 'hayir'); } // Alti kurgu acik kaydi: hangi pakette oldugu disinda hicbir sey verilmemistir. const acikPaketleri = [17, 29, 12, 4, 27, 7]; // kurgu kayitlar; yalnizca paket adi verilmistir console.log('\nalti acik kaydi, ayni onem derecesiyle geldi:'); const E = [-10, 10, 12, 18, 8]; yaz(E, 'paket', 'derinlik', 'etkilenen', 'erisilebilir mi', 'sira'); const sirali = acikPaketleri .map((p) => ({ p, e: erisilen.has(p), n: tersErisim(p) })) .sort((a, b) => (b.e - a.e) || (b.n - a.n)); sirali.forEach((s, i) => yaz(E, ad(s.p), derinlik.get(s.p), s.n, s.e ? 'evet' : 'hayir', i + 1)); console.log(`erisilebilir pakette ${sirali.filter((s) => s.e).length}, erisilmeyen pakette ` + `${sirali.filter((s) => !s.e).length}; ikisi de ayni onem derecesiyle geldi`);
tohum 91237: cizgede 34 paket, 8 tanesi bildirim dosyasinda adiyla geciyor, 26 tanesi gecisli derinlige gore dagilim: 1: 8, 2: 15, 3: 6, 4: 2, 5: 2, 6: 1 en buyuk derinlik 6, kenar sayisi 44 kod yolumuzdan erisilen paket 28, yuklu ama erisilmeyen 6 kimsenin secmedigi derinlik: 11 paket uc ve daha uzak, 3 paket bes ve daha uzak en cok pakete dokunan bes bilesen: paket derinlik etkilenen erisilebilir mi p17 3 20 evet p24 3 20 evet p36 6 19 evet p10 5 18 evet p13 2 18 evet alti acik kaydi, ayni onem derecesiyle geldi: paket derinlik etkilenen erisilebilir mi sira p17 3 20 evet 1 p29 4 18 evet 2 p12 2 6 evet 3 p04 1 0 evet 4 p27 2 3 hayir 5 p07 1 0 hayir 6 erisilebilir pakette 4, erisilmeyen pakette 2; ikisi de ayni onem derecesiyle geldi
Kimsenin Seçmediği Derinlik
İlk satır iki sayıyı yan yana koyuyor: bildirim dosyasında sekiz ad geçiyor, süreçte otuz dört paket duruyor. Aradaki yirmi altı bileşeni kimse seçmemiştir; hiçbiri bir kararın konusu olmamış, hiçbirinin adı ekibin yazdığı bir dosyada geçmemiştir. Kapsama açısından bu sayı belirleyicidir: kod tabanında yapılan her denetim — gözden geçirme, kural, inceleme — sekiz adı kapsar ve yirmi altısına dokunmaz.
Derinlik dağılımı uzaklığı ayrıntılandırıyor. Birinci düzeyde sekiz, ikincide on beş, üçüncüde altı paket var; dördüncü, beşinci ve altıncı düzeylerde beş paket daha. On bir paket üç ve daha uzak düzeyde, üçü beş ve daha uzakta. Altıncı düzeydeki bir bileşene ulaşmak için beş ayrı bileşenin bağımlılık listesini izlemek gerekir; o listelerin hiçbiri bizim değildir ve her biri bağımsız olarak değişebilir.
Derinliğin kendi başına bir risk ölçüsü olmadığını da yazmak gerekiyor. Derinlik yalnızca kararı kimin verdiğini söyler: birinci düzey bizim kararımız, ikinci düzey doğrudan bağımlılığımızın kararı, altıncı düzey beş kararın bileşkesidir. Riski ölçen sütun bir sonrakidir.
Tek Bileşenin Dokunduğu Alan
İkinci tablo ters yönde bakıyor: bir bileşen kaç paketin bağımlılık zincirinde geçiyor. En üstteki iki bileşen otuz dört paketin yirmisini etkiliyor; birinde bir açık bulunduğunda yirmi paket birden ilgili hâle geliyor. Üçüncü satır bu ölçünün derinlikten bağımsız olduğunu gösteriyor: altıncı düzeydeki bileşen on dokuz paketi etkiliyor, yani çizgedeki en uzak bileşen aynı zamanda en çok dokunanlardan biridir. Uzaklık ile etki birbirini izlemez ve ikisi ayrı ayrı ölçülmelidir.
Çizgenin kenar sayısı bu yığılmanın nereden geldiğini söylüyor: otuz dört paket arasında kırk dört kenar var, yani paket başına ortalama 1,3 çıkan kenar. Sayı küçüktür, ama çizge bir ağaç değildir — aynı bileşene birden fazla yoldan gelinir. Bir ağaçta bir yaprağın etkilediği paket sayısı sıfır, kökün etkilediği sayı ise tamamıdır ve arada düzgün bir azalma olur. Paylaşımlı bir çizgede ortadaki bir düğüm de yirmi pakete dokunabilir; etki sütunundaki yığılma bu paylaşımın doğrudan sonucudur ve az sayıda kenarla da doğar.
Birinci düzeydeki doğrudan bağımlılıkların etkilenen sayısı sıfırdır; bu bir kusur değil, ölçünün tanımıdır. Onlara bağlı bir paket yoktur, yalnızca bizim kodumuz vardır. Bir doğrudan bağımlılıktaki sorun tek bir bileşeni ilgilendirir, derin bir ortak bileşendeki sorun yirmi bileşeni — ve ikisi aynı kayıt biçiminde, aynı önem derecesiyle gelir. Kaydın kendisi bu farkı taşımaz; farkı yalnızca çizge verir.
Çağrılmayan Bileşendeki Açık
Son ölçüm çizgeye ikinci bir süzgeç ekliyor. Sekiz doğrudan bağımlılığın beşi kod yolumuz tarafından gerçekten çağrılıyor, üçü yüklü ama çağrılmıyor. Bu üçün geçişli kapanışıyla birlikte altı paket süreçte durup hiç çalışmıyor; erişilen paket sayısı yirmi sekiz.
Altı açık kaydı aynı önem derecesiyle geldiğinde tablo bir sıralama üretiyor ve sıralamayı iki sütun belirliyor: önce erişilebilirlik, sonra etkilenen paket sayısı. İlk sıradaki kayıt hem erişilebilir bir bileşende hem de yirmi paketi etkiliyor. Dördüncü sıradaki kayıt da erişilebilir bir bileşende ama etkilenen paket sayısı sıfır — birinci düzey bir bağımlılık. Beşinci ve altıncı sıradaki iki kayıt hiç çağrılmayan bileşenlerde; biri üç paketi etkiliyor, öteki hiçbirini.
Erişilmeyen bileşendeki açığın neden farklı önceliklendiğini açıkça yazmak gerekir, çünkü bu ayrım kolaylıkla yanlış okunur. Erişilmeyen bileşendeki açık yok sayılmaz: bileşen süreçte yüklüdür, yarın bir kod değişikliği onu çağırabilir ve erişilebilirlik ölçümü bizim çizgemize göre yapılmış bir kestirimdir, kesin bir sonuç değil. Ayrım kapatma kararında değil, kapatma sırasındadır. Altı kaydın altısı da kapatılır; ilk üçü önce kapatılır, çünkü onların açık kalması bugün çalışan bir kod yolunu ilgilendirir.
Kapsama açısından asıl sayı şudur: aynı önem derecesiyle gelen altı kaydın dördü erişilebilir, ikisi erişilmeyen bileşendedir. Ayrımı yapmayan bir kurulum altı kaydı da eşit görür ve elindeki inceleme zamanının üçte birini hiç çalışmayan koda harcar. Ayrımı yapan bir kurulum ise iki soruyu birden yanıtlamak zorunda kalır: hangi bileşen çağrılıyor ve bu ölçüm en son ne zaman tazelendi. İkinci soru bu kursun kapsamının dışındadır.
Özet
- Bildirim dosyasında sekiz ad geçerken süreçte otuz dört paket duruyor; yirmi altı bileşen hiçbir kararın konusu olmamıştır ve kod tabanındaki hiçbir denetim onlara dokunmaz.
- Derinlik dağılımı birinci düzeyde sekiz, ikincide on beş paket veriyor; on bir paket üç ve daha uzak, üçü beş ve daha uzak düzeyde. Derinlik riski değil, kararı kimin verdiğini ölçer.
- Tek bir bileşen otuz dört paketin yirmisini etkiliyor ve altıncı düzeydeki bileşen on dokuzunu; uzaklık ile etki birbirini izlemez.
- Sekiz doğrudan bağımlılığın üçü yüklü ama çağrılmıyor; geçişli kapanışıyla birlikte altı paket süreçte durup hiç çalışmıyor.
- Aynı önem derecesiyle gelen altı açık kaydının dördü erişilebilir, ikisi erişilmeyen bileşende; ayrım kapatma kararını değil, kapatma sırasını belirler.
Kurs Kapanışı
| Ders | Kaç nokta | Kalıbın örttüğü | Dışarıda kalan |
|---|---|---|---|
| Girdi Doğrulama Kalıpları | 15 alan noktası | izin listesi 15 | 0 nokta (ret listesi 14) |
| Çıktı Kodlama | 14 çıkış noktası | bildirimden 14 | 0 nokta (dağınık 5) |
| Enjeksiyon Savunması | 16 sorgu noktası | parametreli 11 | 5 kenar akış |
| Şablon ve İfade Enjeksiyonu | 12 şablon, 65 ad | dar ortam 40 ad | 25 ad, 5 şablon |
| Dosya Yükleme Güvenliği | 5 yükleme noktası | merkezî 5 nokta | 4 nokta, 10 katman |
| Sunucu Tarafı İstek Sahteciliği | 12 giden hedef | adres kısıtı 8 | 0 hedef (ad listesi 3) |
| Güvensiz Seri Durumdan Çıkarma | 9 tür, 11 düğüm | izin listesi 5 tür | 0 yan etkili (açık 4) |
| Kimlik Doğrulama Gerçekleştirim Hataları | 8 nokta, 3 kanal | merkezî doğrulayıcı 8 | 0 nokta (dağıtık 6) |
| Oturum Yönetimi Hataları | 7 akış | 3 akış | 4 akış |
| Bozuk Erişim Denetimi | 14 uç | 9 uç | 5 uç |
| İş Mantığı Açıkları | 625 yol | durum makinesi 625 | 0 yol (adım başına 501) |
| Yarış Koşulları | 7 kontrol noktası | 3 nokta | 4 nokta, 27 fazla geçiş |
| Kriptografi Kötüye Kullanımı | 14 çağrı noktası | 7 nokta | 7 nokta, 5 kusurlu |
| Rastgelelik | 9 belirteç noktası | 3 nokta | 6 nokta, 5 sonuçlu |
| Kodda Gömülü Sırlar | 5 sır, 60 işlem | desen taraması 4 | 1 sır, 198 açık işlem |
| Hata Mesajları ve Günlük Sızıntısı | 8 uç, 11 kalem | 6 uç, 9 kalem | 2 uç, 2 kalem |
| Bağımlılık Kaynaklı Riskler | 34 paket | 8 doğrudan ad | 26 geçişli, 6 erişilmeyen |
Tablo aynı soruyu on yedi kez soruyor ve on yedi kez farklı bir birimle yanıtlıyor: alan noktası, çıkış noktası, sorgu noktası, şablon, yükleme noktası, giden hedef, akış, uç, yol, kontrol noktası, çağrı noktası, sır, günlük kalemi, paket. Birimlerin farklı olması ölçünün değişmesi değildir — üçüncü sütun her satırda aynı şeyi söyler: bugün savunmasız olan değil, yarın savunmasız olabilecek nokta sayısı.
Orta sütun da tek başına okunmamalıdır. Bazı satırlarda kalıbın örttüğü sayı ilk sütuna eşittir — izin listesi on beş alan noktasının on beşini, durum makinesi 625 yolun 625’ini örter. Bazı satırlarda ise eşit değildir ve fark, kalıbın kapsamadığı bir nokta sınıfını gösterir: parametreli arayüz on altı sorgu noktasının on birini örter, çünkü beş kenar akış onu hiç çağırmaz. İlk durumda savunma bir yol kapatmıştır, ikincisinde bir seçenek sunmuştur.
Kursun kuralı da buradan okunur. Güvenli kodlama bir kural listesi değil, bir kalıbın kaç noktayı kendiliğinden kapattığıdır. Tablonun üçüncü sütununda sıfır yazan satırların hiçbirinde kural sayısı fazla değildi; hepsinde savunma, noktanın dışına çıkmanın mümkün olmadığı bir yere konmuştu — tür çizelgesine, bağlam bildirimine, parametreli arayüze, durum makinesine, tek yazarlı kuyruğa, tek dosyaya kapatılmış ilkel çağrıya. Sıfır olmayan satırlarda ise savunma doğru yazılmıştı ama her yeni noktada elden geçmesi gerekiyordu. Her yeni noktada elle tekrarlanması gereken savunma, eninde sonunda unutulacak savunmadır; tablonun dışarıda kalan sütunu o unutmanın bugünkü sayısıdır.
Bu kursun sormadığı iki soru var. Birincisi, bütün bu kapsamayı her değişiklikte kimin sayacağıdır: buradaki on yedi ölçüm elle kurulmuş envanterler üzerinde koştu ve envanterin kendisi kod değiştikçe eskir. İkincisi, ölçümlerin tamamının kod tabanının içinde kalmasıdır. Son dersin çizgesi bunun sınırını gösterdi: yirmi altı bileşen bizim yazmadığımız satırlardan gelir ve bir kod incelemesi onlara ulaşmaz. Aynı şey yapının çıktısı, dağıtılan imaj ve o imajın içine giren her katman için de geçerlidir; hiçbiri bu kursta sayılmadı. M25/K03 Güvenlik Otomasyonu ve Tedarik Zinciri bu iki soruyu birlikte ele alır: kapsamayı her değişiklikte kim sayar ve kodun dışında kalan katman nasıl ölçülür.
İlerlemeni kaydetmek ve not almak için Giriş yap
Notlarım
Not almak için giriş yapmalısın.