---
title: 'Sürdürülebilirlik Ölçütleri'
source: 'https://academia.sh/tr/kurslar/mimari-yonetisim/surdurulebilirlik-olcutleri'
course: 'Kalite Nitelikleri ve Yönetişim'
language: tr
updated: '2026-08-17T18:10:34+00:00'
license: 'CC BY-SA 4.0'
---

# Sürdürülebilirlik Ölçütleri

Değişim maliyetinin doğrudan gözlenmesi: aynı on iki değişikliğin iki yapıda koşturulup değişiklik başına dokunulan dosya, dokunulan modül ve yayılma derinliğinin sayılması, altı çeyreklik bozulmada ölçütlerin bozulmayı gösterip göstermediğinin sınanması ve eşik kuralının gerçek maliyet kaydında yakaladığı, kaçırdığı, boşa öttüğü durumlar.

Bu konudaki her ölçü bir değişiklik önerdi. Nitelik ağacı eksik denetimleri gösterdi, gerilim
matrisi hangi kararın neyi bastırdığını, güven sınırı grafiği hangi geçişin denetimsiz olduğunu,
ölçek birimi neyin kopyalanacağını. Hepsinin ortak varsayımı, sistemin değiştirilebilir olduğuydu
ve bu varsayım hiç ölçülmedi. Sürdürülebilirlik ağaçta bir kök nitelikti, gerilim matrisinde en çok
bastırılan nitelikti; ama iki yerde de yaprak değerlerinden dolaylı olarak okundu. Bu ders onu
doğrudan ölçer: aynı değişiklik kümesi iki ayrı yapı üzerinde koşturulur.

Teknik borcun faizi Mimari Karar ve Dokümantasyon kursunda, karar kaydı konusunda ölçüldü ve
burada tekrarlanmaz. Değişim maliyeti, o faizin
gözlenen yüzüdür — faiz bir hesap kalemi olarak değil, her değişiklikte fazladan dokunulan dosya
olarak görünür. Ölçülecek üç büyüklük var: değişiklik başına dokunulan dosya, dokunulan modül ve
değişikliğin kaç adım öteye yayıldığı.

## İki Yapıda Aynı Değişiklik

Aşağıdaki blok iki yapıyı **modelliyor**. Modül kümesi ikisinde de aynı; ayrılan iki şey var —
bağımlılık grafiği ve kavramların modüllere yerleşimi. Aynı on iki değişiklik isteği iki yapıda da
koşturuluyor. Yüzeyi değiştiren bir istek, dokunulan modüle bağımlı modülleri de dokundurur.

```js
// yapi.mjs — ayni degisiklik kumesini iki yapida kosturur ve degisim maliyetini olcer
import { mkdirSync, writeFileSync } from "node:fs";

// KN25: kurgusal bolgesel kutuphane aginin ayni islevi tasiyan iki yapisi. Modul kumesi ayni,
// bagimlilik grafigi ve kavramlarin yerlesimi farkli. Model.
const MODUL = ["odunc", "ucret", "uyelik", "katalog", "bildirim", "rapor", "sube", "ortak"];
const BAGIMLILIK = {
  A: [["odunc", "ortak"], ["odunc", "ucret"], ["odunc", "uyelik"], ["ucret", "ortak"],
    ["ucret", "uyelik"], ["uyelik", "ortak"], ["katalog", "ortak"], ["bildirim", "odunc"],
    ["bildirim", "uyelik"], ["rapor", "odunc"], ["rapor", "ucret"], ["rapor", "uyelik"],
    ["sube", "odunc"], ["sube", "ucret"], ["sube", "katalog"]],
  B: [["odunc", "ortak"], ["ucret", "ortak"], ["uyelik", "ortak"], ["katalog", "ortak"],
    ["bildirim", "ortak"], ["rapor", "ortak"], ["sube", "ortak"], ["rapor", "odunc"],
    ["sube", "odunc"]],
};

// KN26: on iki degisiklik istegi. Her istek bir kavrama dokunur; kavramin hangi modulde kac
// dosyada gectigi yapiya gore degisir. yuzey = degisiklik modulun disa acik yuzeyini
// degistiriyor mu (ayni istek icin iki yapida da ayni). Model.
const DEGISIKLIK = [
  ["ucret tarifesi", true, { ucret: 2, odunc: 1, sube: 1, rapor: 1 }, { ucret: 2 }],
  ["gecikme esigi", false, { ucret: 1, bildirim: 1, odunc: 1 }, { ucret: 1 }],
  ["uye alani", true, { uyelik: 2, odunc: 1, rapor: 1, sube: 1 }, { uyelik: 2 }],
  ["odunc suresi", false, { odunc: 2, ucret: 1, bildirim: 1 }, { odunc: 2 }],
  ["rezervasyon kurali", true, { odunc: 2, sube: 1 }, { odunc: 2 }],
  ["katalog alani", true, { katalog: 2, sube: 1, rapor: 1 }, { katalog: 2 }],
  ["bildirim metni", false, { bildirim: 2 }, { bildirim: 2 }],
  ["sube takvimi", false, { sube: 2, odunc: 1 }, { sube: 2 }],
  ["rapor sutunu", false, { rapor: 2, ucret: 1 }, { rapor: 2 }],
  ["para birimi", true, { ortak: 1, ucret: 2, rapor: 1, sube: 1 }, { ortak: 2 }],
  ["kimlik alani", true, { uyelik: 2, ortak: 1, odunc: 1 }, { uyelik: 2 }],
  ["indirim kurali", false, { ucret: 2, odunc: 1, rapor: 1 }, { ucret: 2 }],
];

// Yayilma: yuzeyi degistiren bir degisiklik, dokunulan module bagimli modulleri de
// dokundurur; her dolayli modulde bir cagri yeri duzeltilir. Derinlik, dogrudan dokunulan
// modulden en uzak dolayli module kadar olan adim sayisidir.
const olc = (yapi, yuzey, yerlesim) => {
  const dogrudan = Object.keys(yerlesim);
  let dosya = Object.values(yerlesim).reduce((s, n) => s + n, 0);
  const gorulen = new Map(dogrudan.map((m) => [m, 0]));
  if (yuzey) {
    let sira = [...dogrudan], derinlik = 0;
    while (sira.length) {
      derinlik += 1;
      const sonraki = [];
      for (const m of sira)
        for (const [a, b] of BAGIMLILIK[yapi])
          if (b === m && !gorulen.has(a)) { gorulen.set(a, derinlik); sonraki.push(a); dosya += 1; }
      sira = sonraki;
    }
  }
  return { dosya, modul: gorulen.size, derinlik: Math.max(...gorulen.values()) };
};

mkdirSync("model", { recursive: true });
writeFileSync("model/model.mjs",
  `export const MODUL = ${JSON.stringify(MODUL)};\n` +
  `export const BAGIMLILIK = ${JSON.stringify(BAGIMLILIK)};\n` +
  `export const DEGISIKLIK = ${JSON.stringify(DEGISIKLIK)};\n` +
  `export const olc = ${olc};\n`);

console.log(`${MODUL.length} modul; bagimlilik A ${BAGIMLILIK.A.length}, B ${BAGIMLILIK.B.length}`);
console.log(`\n${"degisiklik".padEnd(20)}${"yuzey".padEnd(7)}` +
  `${"A dosya".padStart(8)}${"A modul".padStart(8)}${"A der".padStart(6)}` +
  `${"B dosya".padStart(9)}${"B modul".padStart(8)}${"B der".padStart(6)}`);
const olcum = DEGISIKLIK.map(([ad, yuzey, a, b]) =>
  [ad, yuzey, olc("A", yuzey, a), olc("B", yuzey, b)]);
for (const [ad, yuzey, a, b] of olcum)
  console.log(`${ad.padEnd(20)}${(yuzey ? "evet" : "hayir").padEnd(7)}` +
    `${String(a.dosya).padStart(8)}${String(a.modul).padStart(8)}${String(a.derinlik).padStart(6)}` +
    `${String(b.dosya).padStart(9)}${String(b.modul).padStart(8)}${String(b.derinlik).padStart(6)}`);

const ort = (yapi, alan) =>
  (olcum.reduce((s, o) => s + o[yapi][alan], 0) / olcum.length).toFixed(2);
console.log(`\ndegisiklik basina ortalama — A: dosya ${ort(2, "dosya")}, modul ${ort(2, "modul")}, ` +
  `derinlik ${ort(2, "derinlik")}`);
console.log(`degisiklik basina ortalama — B: dosya ${ort(3, "dosya")}, modul ${ort(3, "modul")}, ` +
  `derinlik ${ort(3, "derinlik")}`);
const enKotu = olcum.slice().sort((a, b) => b[3].modul - a[3].modul)[0];
console.log(`iki yapinin da en pahali degisikligi: ${enKotu[0]} ` +
  `(A ${enKotu[2].modul} modul, B ${enKotu[3].modul} modul)`);
```

```
8 modul; bagimlilik A 15, B 9

degisiklik          yuzey   A dosya A modul A der  B dosya B modul B der
ucret tarifesi      evet          6       5     1        2       1     0
gecikme esigi       hayir         3       3     0        1       1     0
uye alani           evet          7       6     1        2       1     0
odunc suresi        hayir         4       3     0        2       1     0
rezervasyon kurali  evet          5       4     1        4       3     1
katalog alani       evet          4       3     0        2       1     0
bildirim metni      hayir         2       1     0        2       1     0
sube takvimi        hayir         3       2     0        2       1     0
rapor sutunu        hayir         3       2     0        2       1     0
para birimi         evet          9       8     2        9       8     1
kimlik alani        evet          9       8     1        2       1     0
indirim kurali      hayir         4       3     0        2       1     0

degisiklik basina ortalama — A: dosya 4.92, modul 4.00, derinlik 0.50
degisiklik basina ortalama — B: dosya 2.67, modul 1.75, derinlik 0.17
iki yapinin da en pahali degisikligi: para birimi (A 8 modul, B 8 modul)
```

Üç ölçüt de aynı yönü gösteriyor ama farklı büyüklükte ayrışıyor. Dosyada oran 1,8; modülde 2,3;
derinlikte 3. En zayıf ayrım dosyada, çünkü doğrudan dokunulan dosya sayısının büyük bölümü işin
kendisinden gelir — bir tarife değişikliği hangi yapıda olursa olsun tarifenin yazıldığı iki dosyayı
ister. **Yapı farkı dosyada değil, dosyaların hangi modüllere dağıldığında görünüyor.**

Farkın tamamı yüzeyi değiştiren altı değişiklikten geliyor. Yüzeyi değiştirmeyen altı istekte
yayılma yok, derinlik sıfır ve dağınık yapıda bile iki ile dört dosya arasında kalınıyor. Yapının
bedeli her değişiklikte değil, yalnız dışa açık yüzeye dokunan değişiklikte ödeniyor; ölçüm bu iki
kümeyi ayırmazsa ortalama, farkı olduğundan küçük gösterir.

Bir satır iki yapıda da aynı: para birimi değişikliği ikisinde de sekiz modüle dokunuyor. Derli
yapıda kavram tek modülde toplanmış, ama o modül ortak modül ve ona herkes bağlı. **Toplamak,
kavram zaten herkesin bağlı olduğu yerdeyse bir şey kazandırmaz.** Modüler yapının kazancı seçici:
kavramı bir kenara toplayabildiği yerde büyük, merkeze toplamak zorunda kaldığı yerde sıfır.

## Ölçütler Bozulmayı Gösteriyor mu

Bir ölçütün asıl sınavı tek bir ölçümde değil, zaman içinde verdiği eğridedir. Aşağıdaki blok derli
yapının altı çeyrekte bozulmasını **modelliyor** — her çeyrekte bir kavram fazladan bir modüle
sızıyor, iki çeyrekte ayrıca yeni bir bağımlılık kenarı açılıyor — ve üç ölçütün bu bozulmayı
gösterip göstermediğini sınıyor. Sonra bir eşik kuralı yazıp altıncı çeyrekteki gerçek maliyet
kaydında koşturuyor.

```js
// bozulma.mjs — olcutlerin zaman icinde bozulmayi gosterip gostermedigini sinar ve esik
// kuralini bilinen maliyet kaydinda kosturur
import { BAGIMLILIK, DEGISIKLIK, olc } from "./model/model.mjs";

// KN27: B yapisi alti ceyrekte bozuluyor. Her ceyrekte bir kavram fazladan bir module siziyor
// [kavram, modul]; iki ceyrekte ayrica yeni bir bagimlilik kenari aciliyor. Model.
const SIZINTI = [
  ["ucret tarifesi", "sube", null],
  ["uye alani", "odunc", null],
  ["odunc suresi", "sube", ["rapor", "ucret"]],
  ["ucret tarifesi", "rapor", null],
  ["katalog alani", "rapor", ["bildirim", "uyelik"]],
  ["uye alani", "rapor", null],
];

const yerlesim = DEGISIKLIK.map(([ad, yuzey, , b]) => [ad, yuzey, { ...b }]);
const olcumler = [];
const cek = () => {
  const o = yerlesim.map(([ad, yuzey, y]) => [ad, olc("B", yuzey, y)]);
  const ort = (alan) => o.reduce((s, [, v]) => s + v[alan], 0) / o.length;
  return { o, dosya: ort("dosya"), modul: ort("modul"), derinlik: ort("derinlik"),
    ihlal: o.filter(([, v]) => v.modul > 2).length };
};
olcumler.push(cek());
for (const [kavram, modul, kenar] of SIZINTI) {
  const y = yerlesim.find(([ad]) => ad === kavram)[2];
  y[modul] = (y[modul] || 0) + 1;
  if (kenar) BAGIMLILIK.B.push(kenar);
  olcumler.push(cek());
}

console.log(`${"ceyrek".padEnd(8)}${"dosya/degisiklik".padStart(17)}${"modul/degisiklik".padStart(17)}` +
  `${"derinlik".padStart(10)}${"esigi asan degisiklik".padStart(23)}  (Q0 = bozulmadan once)`);
olcumler.forEach((m, i) =>
  console.log(`${`Q${i}`.padEnd(8)}${m.dosya.toFixed(2).padStart(17)}` +
    `${m.modul.toFixed(2).padStart(17)}${m.derinlik.toFixed(2).padStart(10)}` +
    `${String(m.ihlal).padStart(23)}`));

const ilkHareket = (alan) => olcumler.findIndex((m, i) => i > 0 && m[alan] > olcumler[0][alan]);
const artan = (alan) => olcumler.every((m, i) => i === 0 || m[alan] >= olcumler[i - 1][alan]);
for (const alan of ["dosya", "modul", "derinlik", "ihlal"])
  console.log(`${alan.padEnd(9)} ilk hareket Q${ilkHareket(alan)}, ` +
    `bastan sona artis ${(olcumler.at(-1)[alan] - olcumler[0][alan]).toFixed(2)}, ` +
    `hic geri gitmiyor mu: ${artan(alan) ? "evet" : "hayir"}`);

// KN28: alti ceyrek sonunda on iki degisikligin gercek maliyeti ekip kaydindan okunuyor;
// dordu pahali gecmis. Kayit bir gozlemdir, olcutten cikmaz. Model.
const PAHALI = ["ucret tarifesi", "uye alani", "rezervasyon kurali", "katalog alani"];
// Kural: bir degisiklik en fazla iki module dokunmali.
const ESIK = 2;
const son = olcumler.at(-1).o;
let yak = 0, kac = 0, yanlis = 0, sessiz = 0;
const ayrik = [];
for (const [ad, v] of son) {
  const oter = v.modul > ESIK, pahali = PAHALI.includes(ad);
  if (oter && pahali) yak += 1; else if (oter) yanlis += 1;
  else if (pahali) kac += 1; else sessiz += 1;
  if (oter !== pahali) ayrik.push(`  ${oter ? "yanlis alarm" : "kacan"}: ${ad} ` +
    `(${v.modul} modul, kayitta ${pahali ? "pahali" : "ucuz"})`);
}
console.log(`\nesik ${ESIK} modul, ${son.length} degisiklik, ${PAHALI.length} pahali: ` +
  `yakalanan ${yak}, kacan ${kac}, yanlis alarm ${yanlis}, dogru sessizlik ${sessiz}`);
for (const s of ayrik) console.log(s);

// KN29: cevrilemeyen kisim. Olcut genisligi sayar, zorlugu sayamaz; bir kavramin dogru
// modulde olup olmadigi da bir yargidir. Yerine ceyrekte bir yerlesim gozden gecirmesi
// konur: 12 degisiklik x 1 kisi-saat.
const SAAT = 1;
console.log(`\ncevrilemeyen: degisikligin zorlugu ve kavramin dogru modulde olmasi (yargi); ` +
  `yanlis alarm ${yanlis}, kacan ${kac} tam olarak bu kapsamda`);
console.log(`yerine konan: ceyrekte bir yerlesim gozden gecirmesi, ` +
  `${son.length * SAAT} kisi-saat/ceyrek, alti ceyrekte ${son.length * SAAT * 6}`);
const kayit = DEGISIKLIK.length * 3 + BAGIMLILIK.B.length;
console.log(`olcut maliyeti: ${kayit} kayit (12 degisiklik x 3 alan + ` +
  `${BAGIMLILIK.B.length} bagimlilik kenari); kosum ${olcumler.length * son.length} olcum; ` +
  `degisim maliyeti, borc faizi olarak olculen seyin gozlenen yuzudur`);
```

```
ceyrek   dosya/degisiklik modul/degisiklik  derinlik  esigi asan degisiklik  (Q0 = bozulmadan once)
Q0                   2.67             1.75      0.17                      2
Q1                   2.75             1.83      0.17                      2
Q2                   3.00             2.08      0.25                      3
Q3                   3.17             2.25      0.33                      4
Q4                   3.17             2.25      0.25                      4
Q5                   3.42             2.50      0.33                      4
Q6                   3.42             2.50      0.33                      4
dosya     ilk hareket Q1, bastan sona artis 0.75, hic geri gitmiyor mu: evet
modul     ilk hareket Q1, bastan sona artis 0.75, hic geri gitmiyor mu: evet
derinlik  ilk hareket Q2, bastan sona artis 0.17, hic geri gitmiyor mu: hayir
ihlal     ilk hareket Q2, bastan sona artis 2.00, hic geri gitmiyor mu: evet

esik 2 modul, 12 degisiklik, 4 pahali: yakalanan 3, kacan 1, yanlis alarm 1, dogru sessizlik 7
  kacan: katalog alani (2 modul, kayitta pahali)
  yanlis alarm: para birimi (8 modul, kayitta ucuz)

cevrilemeyen: degisikligin zorlugu ve kavramin dogru modulde olmasi (yargi); yanlis alarm 1, kacan 1 tam olarak bu kapsamda
yerine konan: ceyrekte bir yerlesim gozden gecirmesi, 12 kisi-saat/ceyrek, alti ceyrekte 72
olcut maliyeti: 47 kayit (12 degisiklik x 3 alan + 11 bagimlilik kenari); kosum 84 olcum; degisim maliyeti, borc faizi olarak olculen seyin gozlenen yuzudur
```

Dosya ve modül ölçütleri ilk çeyrekte hareket ediyor ve altı çeyrek boyunca hiç geri gitmiyor.
Derinlik ölçütü ikisini de yapmıyor: ikinci çeyrekte hareket ediyor, dördüncü çeyrekte geri gidiyor.
Yapı yalnız kötüleşirken ölçüt bir çeyrek iyileşmiş görünüyor. Nedeni ölçütün tanımında: sızıntı,
bir kavramı daha önce dolaylı dokunulan modüle doğrudan yazıyor, o modül artık yayılma değil
başlangıç sayılıyor ve derinlik düşüyor. **Bozulmanın kendisi ölçütün girdisini değiştiriyorsa
ölçüt tek yönlü olmaz** — ve bu, ölçütü kullanışsız kılmaz, yalnız tek başına okunamaz kılar.

Eşiği aşan değişiklik sayısı basamak basamak ilerliyor: iki, üç, dört, sonra üç çeyrek sabit. Kaba
sayım geç hareket ediyor ve son üç çeyrekteki bozulmayı hiç göstermiyor; ortalama ise aynı üç
çeyrekte 2,25'ten 2,50'ye çıkıyor. İkisi birbirinin yerine geçmiyor: ortalama erken uyarı verir,
eşik sayımı karar noktası olur.

Kuralın kendisi altıncı çeyrekte on iki değişikliğin dördü pahalı geçmişken üç yakalama, bir kaçan,
bir yanlış alarm ve yedi doğru sessizlik üretiyor. Kaçan, iki modüle dokunduğu halde pahalı geçen
katalog alanı değişikliği; yanlış alarm, sekiz modüle dokunduğu halde ucuz geçen para birimi
değişikliği — sekiz yerde aynı sabitin adı düzeltilmiş. **İki hata da tek kaynaktan geliyor: ölçüt
genişliği sayıyor, zorluğu değil.** Çevrilemeyen kısım tam olarak budur; değişikliğin zorluğu ve
kavramın doğru modülde olup olmadığı bir yargıdır. Yerine çeyrekte bir yerleşim gözden geçirmesi
konuyor: on iki değişiklik için 12 kişi-saat, altı çeyrekte 72.

Ölçütün kendi maliyeti küçük görünüyor — 47 kayıt ve 84 ölçüm. Ama kayıtların hepsi elle tutuluyor:
her değişiklik isteğinin hangi kavrama dokunduğu, yüzeyi değiştirip değiştirmediği ve hangi modülde
kaç dosyada geçtiği. Bu kayıt bırakılırsa ölçüt susmaz, yanlış konuşur; bozulmayı gösteren eğri,
kaydın eskime eğrisi olur.

## Özet

- Aynı on iki değişiklik iki yapıda koşturulduğunda dağınık yapı değişiklik başına 4,92 dosya, 4,00
  modül ve 0,50 derinlik; derli yapı 2,67 dosya, 1,75 modül ve 0,17 derinlik istiyor.
- Ayrım en zayıf dosyada (1,8 kat), en keskin derinlikte (3 kat); farkın tamamı yüzeyi değiştiren
  altı değişiklikten geliyor, ötekilerde iki yapı ayrışmıyor.
- Ortak modüle dokunan değişiklik iki yapıda da sekiz modüle yayılıyor: toplamak, kavram zaten
  herkesin bağlı olduğu yerdeyse kazandırmıyor.
- Altı çeyreklik bozulmada dosya ve modül ölçütleri ilk çeyrekte hareket edip hiç geri gitmiyor;
  derinlik dördüncü çeyrekte geri gidiyor, çünkü sızıntı dolaylı dokunuşu doğrudana çeviriyor.
- Eşik kuralı 3 yakalanan, 1 kaçan, 1 yanlış alarm, 7 doğru sessizlik veriyor; iki hata da ölçütün
  genişliği sayıp zorluğu saymamasından geliyor.
- Çevrilemeyen kısmın yerine çeyrekte 12 kişi-saatlik yerleşim gözden geçirmesi konuyor; ölçütün
  koşumu 84 ölçüm, bakımı 47 elle tutulan kayıt.

## Sonraki Adım

Bu konu nitelikleri ölçüye bağladı. Ağaçta otuz yaprak sayıldı ve hangisinin denetime çevrilebildiği
ayrıldı; gerilim matrisi hangi kararın hangi niteliği bastırdığını gösterdi; güven sınırları ve
denetimsiz geçişler sayıldı; ölçek biriminin üç adayı kopyalanan, paylaşılan ve kopyalanamayan
üzerinden karşılaştırıldı; değişim maliyeti iki yapıda doğrudan ölçüldü. Artık hangi kararın hangi
niteliği koruduğu yazılabiliyor.

Ama bu ölçülerin hepsi **bir kez** alındı. Eşikler bir günün eşiği, grafik bir günün grafiği,
yerleşim bir günün yerleşimi. Altı ay sonra hâlâ geçerli olup olmadığını söyleyen bir şey yok — bu
dersin bozulma tablosu bile elle kurulmuş bir modeldi, kendiliğinden koşan bir düzen değil.
Ölçümü tekrarlayan, sapmayı bildiren ve her ölçünün kime ait olduğunu belirleyen bir mekanizma
gerekiyor; onsuz bu konudaki bütün sayılar, alındıkları günün fotoğrafı olarak kalır.
