---
title: 'Alan Odaklı Tasarımın Gerekçesi'
source: 'https://academia.sh/tr/kurslar/alan-odakli-tasarim/alan-odakli-tasarimin-gerekcesi'
course: 'Alan Odaklı Tasarım'
language: tr
updated: '2026-08-17T18:10:41+00:00'
license: 'CC BY-SA 4.0'
---

# Alan Odaklı Tasarımın Gerekçesi

Modelin alanla hizasının bir ölçü hâline getirilmesi: alan uzmanının tek cümlesindeki on iki adın iki modelde kaçının birebir bulunduğunun sayılması, alan dilinde yazılmış üç değişiklik isteğinin her modelde kaç satıra indiğinin ölçülmesi ve iki modelin aynı ücreti verdiğinin gösterilmesiyle hizanın doğruluktan ayrı bir nitelik olduğunun ortaya konması.

Tasarım Kalıpları kursu, bir kalıbın ancak bir ölçüyü iyileştirdiği ölçüde kalıp olduğunu
göstererek kapandı. Otuz dersin hepsi çözümün **biçimi** üzerineydi: kural nereye yazılır,
nesne nasıl yaratılır, sınır nereye çizilir. Hiçbiri kuralın **ne olduğunu** sormadı.
Gönderi, tarife, bölge, rota ve indirim sözcüklerinin ne anlama geldiği, hangilerinin bir
arada değiştiği, aynı sözcüğün iki takımda iki farklı şeyi adlandırıp adlandırmadığı o
kursun dışında kaldı.

Bu ders o soruyu alır. **Alan odaklı tasarım** (domain-driven design), bir kod tabanının
yapısını alanın kendi ayrımlarından türetmeyi öneren bir yaklaşımdır; buradaki alan,
yazılımın hakkında olduğu iş dünyasıdır. Yaklaşımın iddiası bir estetik iddia değildir,
dolayısıyla bir ölçüsü olmalıdır. Kurs boyunca ölçülen şey **modelin alanla hizasıdır**:
alanı konuşan insanın kullandığı ayrımların kodda birebir karşılığı var mı, yok mu.

## Alan Uzmanının Cümlesi

Ölçünün dayanağı, alanı işi gereği bilen kişinin — **alan uzmanının** (domain expert) —
kuralı söylerken kullandığı sözcüklerdir. Gönderi ücretlendirme kitaplığında bu kişi
ücretlendirme uzmanıdır ve kuralı tek cümlede söylüyor:

> Bir gönderinin ücreti, ağırlık kademesinin taban ücretiyle bölge katsayısının
> çarpımıdır; hacim ağırlıktan büyükse hacim esas alınır, indirim oranlarının toplamı
> tavanı aşamaz, net ücret asgari ücretin altına inemez.

Cümlede on iki ad geçiyor: gönderi, ağırlık, hacim, kademe, taban ücret, bölge, katsayı,
posta kodu, indirim, oran, tavan, asgari ücret. Bu on iki ad ölçünün sabit listesidir.

## Aynı Kuralın İki Modeli

Kitaplığın iki sürümü var. İkisi de aynı kuralı uyguluyor; ayrım yalnız adlardadır.

```sh
mkdir -p teknik alan
```

```js
// teknik/hesap.mjs — ayni kural, teknik adlarla
const T1 = [[1, 3900], [5, 6400], [Infinity, 11800]];
const T2 = { "34": 1, "06": 1.35, "65": 1.8 };
const LIM = 0.4;
const MIN = 3990;
const DIV = 5000;

export function process(d) {
  const v = Math.max(d.w, d.vol / DIV);
  const base = T1.find(([u]) => v <= u)[1];
  const f = T2[d.z.slice(0, 2)] ?? 1.8;
  const r = Math.min(d.ds.reduce((t, x) => t + x.r, 0), LIM);
  return Math.max(Math.round(base * f * (1 - r)), MIN);
}
```

Dosya kısa, dallanması az ve doğru çalışıyor. Temiz Kod kursunun ölçüleriyle bakıldığında
kusuru yalnız adlandırmadır. Alan odaklı tasarımın söylediği şey bunun bir adlandırma
kusuru olmadığıdır: `T1` ile `T2` arasındaki ayrımın alanda bir karşılığı vardır ve o ayrım
kodda kayıptır.

```js
// alan/ucret.mjs — ayni kural, alan adlariyla
const KADEMELER = [[1, 3900], [5, 6400], [Infinity, 11800]];
const BOLGE_KATSAYISI = { "34": 1, "06": 1.35, "65": 1.8 };
const INDIRIM_TAVANI = 0.4;
const ASGARI_UCRET = 3990;
const HACIM_BOLENI = 5000;

const ucretliAgirlik = (gonderi) => Math.max(gonderi.agirlik, gonderi.hacim / HACIM_BOLENI);
const tabanUcret = (agirlik) => KADEMELER.find(([ustAgirlik]) => agirlik <= ustAgirlik)[1];
const bolgeKatsayisi = (postaKodu) => BOLGE_KATSAYISI[postaKodu.slice(0, 2)] ?? 1.8;
const indirimOrani = (indirimler) =>
  Math.min(indirimler.reduce((t, i) => t + i.oran, 0), INDIRIM_TAVANI);

export function netUcret(gonderi) {
  const ham = tabanUcret(ucretliAgirlik(gonderi)) * bolgeKatsayisi(gonderi.postaKodu);
  return Math.max(Math.round(ham * (1 - indirimOrani(gonderi.indirimler))), ASGARI_UCRET);
}
```

## Hizanın Ölçülmesi

İki ölçü alınır. Birincisi **ad hizası**: uzmanın cümlesindeki on iki addan kaçı kaynakta
bir tanımlayıcının içinde birebir bulunuyor. İkincisi **aday satır sayısı**: alan dilinde
gelen bir değişiklik isteğinin sözcükleri kaç satırda birlikte geçiyor. İkinci ölçü, isteği
alan kişinin dosyada kaç satıra bakması gerektiğini verir.

```js
// hiza-olc.mjs — uzman cumlesinin adlari kodda var mi, istek kac satirda gorunuyor
import { readFileSync } from "node:fs";
import { process as teknikUcret } from "./teknik/hesap.mjs";
import { netUcret } from "./alan/ucret.mjs";

const ADLAR = ["gonderi", "agirlik", "hacim", "kademe", "tabanucret", "bolge",
  "katsayi", "postakodu", "indirim", "oran", "tavan", "asgariucret"];
const ISTEKLER = {
  "indirim tavani inecek": ["indirim", "tavan"],
  "asgari ucret cikacak": ["asgari", "ucret"],
  "hacim boleni degisecek": ["hacim", "bolen"],
};
const MODEL = { teknik: "teknik/hesap.mjs", alan: "alan/ucret.mjs" };

for (const [model, dosya] of Object.entries(MODEL)) {
  const metin = readFileSync(dosya, "utf8");
  const ham = metin.match(/[A-Za-z_][A-Za-z0-9_]*/g) ?? [];
  const kimlik = ham.map((s) => s.toLowerCase().replaceAll("_", ""));
  const bulunan = ADLAR.filter((ad) => kimlik.some((k) => k.includes(ad)));
  const satir = metin.split("\n").filter((s) => s.trim() !== "" && !s.startsWith("//"));
  console.log(`${model}: alan adi ${bulunan.length}/${ADLAR.length}, satir ${satir.length}`);
  console.log(`  eksik ad: ${ADLAR.filter((a) => !bulunan.includes(a)).join(" ") || "yok"}`);
  for (const [istek, sozcuk] of Object.entries(ISTEKLER)) {
    const aday = satir.filter((s) => sozcuk.every((w) => s.toLowerCase().includes(w)));
    console.log(`  "${istek}" -> aday satir ${aday.length}/${satir.length}`);
  }
}

const GONDERILER = [
  { agirlik: 0.6, hacim: 2000, postaKodu: "34710", indirimler: [] },
  { agirlik: 3, hacim: 24000, postaKodu: "06800", indirimler: [{ ad: "sozlesme", oran: 0.15 }] },
  { agirlik: 12, hacim: 40000, postaKodu: "65100", indirimler: [{ ad: "hacim", oran: 0.5 }] },
  { agirlik: 0.4, hacim: 9000, postaKodu: "81600", indirimler: [{ ad: "kampanya", oran: 0.1 }] },
];
const cevir = (g) => ({ w: g.agirlik, vol: g.hacim, z: g.postaKodu,
  ds: g.indirimler.map((i) => ({ r: i.oran })) });

let ayrilan = 0;
for (const g of GONDERILER) if (teknikUcret(cevir(g)) !== netUcret(g)) ayrilan += 1;
console.log(`ayrilan sonuc = ${ayrilan} / ${GONDERILER.length}`);
```

```sh
node hiza-olc.mjs
```

```
teknik: alan adi 0/12, satir 12
  eksik ad: gonderi agirlik hacim kademe tabanucret bolge katsayi postakodu indirim oran tavan asgariucret
  "indirim tavani inecek" -> aday satir 0/12
  "asgari ucret cikacak" -> aday satir 0/12
  "hacim boleni degisecek" -> aday satir 0/12
alan: alan adi 12/12, satir 14
  eksik ad: yok
  "indirim tavani inecek" -> aday satir 2/14
  "asgari ucret cikacak" -> aday satir 2/14
  "hacim boleni degisecek" -> aday satir 2/14
ayrilan sonuc = 0 / 4
```

İlk sayı hizanın kendisidir: uzmanın on iki adından teknik sürümde 0'ı, alan sürümünde
12'si kodda bulunuyor. İkinci grup bunun bedelini veriyor. Üç değişiklik isteğinin üçünde
de teknik sürümde aday satır 0 çıkıyor; aday yoksa isteği alan kişinin on iki satırın
tamamını okuması, her adın neyi tuttuğunu çıkarması ve ancak sonra doğru satırı bulması
gerekir. Alan sürümünde aynı üç istek 14 satırın 2'sine iniyor.

## Hiza Doğruluk Değildir

Çıktının son satırı ölçünün ne olmadığını söylüyor: dört gönderinin dördünde iki sürüm
aynı ücreti veriyor. Teknik sürüm yanlış değildir, yavaş da değildir. Hizasızlığın bedeli
çalışma zamanında değil, **değişiklik zamanında** ödenir.

Bedelin ödendiği yer ölçüm betiğinde de görünüyor: `cevir` işlevi. İki sürümü aynı
gönderilerle çağırabilmek için `agirlik` alanının `w`, `hacim` alanının `vol`, `postaKodu`
alanının `z` olduğunu bilen bir eşleme yazmak gerekti. Bu eşleme kodda dört satırdır ama
kodda olmayan bir yerde de tutulur: isteği alan kişinin kafasında. Alan odaklı tasarımın
temel önerisi bu eşlemeyi ortadan kaldırmaktır — çeviri yapılmasın diye alanla kodun aynı
sözcükleri kullanması.

Ayrım bir adlandırma alışkanlığından fazlasıdır çünkü kayıp yalnız adlarda değil
**ayrımlarda**dır. Teknik sürümde `LIM` ile `MIN` iki sayıdır; alanda biri bir oran tavanı,
öteki bir para tutarıdır ve ikisi ayrı kararlarla, ayrı sıklıkta değişir. Tasarım İlkeleri
kursundaki politika–ayrıntı ayrımı bu iki sayının aynı dosyada durmasını değişim sıklığıyla
sorgulamıştı; alan odaklı tasarım aynı soruyu bir adım önce sorar: bu ikisi alanda aynı tür
şey mi?

## Karmaşıklık Nerede

Yaklaşımın bir sınırı vardır ve kendi gerekçesinden çıkar. Alanla hizalanmanın kazancı,
alanın kendisinin karmaşık olmasına bağlıdır. Kitaplığın ücretlendirme tarafında kademe,
bölge, hacim, tavan ve asgari tutar gibi birbirinden bağımsız ayrımlar var; uzmanın cümlesi
uzundur ve sık değişir. Bu yüzden on iki adı taşımak kazanç üretir.

Karmaşıklığın alanda değil teknik tarafta olduğu işlerde hesap tersine döner. Aldığı
baytları başka bir yere yazan bir bileşende alan sözlüğü iki sözcükten oluşur; oraya bir
alan katmanı kurmak, ölçülecek bir ad hizası olmadığı için bedelini karşılamaz. Ayrım
ölçütü kod tabanının boyutu da değildir — uzmanın kuralı söylemek için kaç ayrı ada ihtiyaç
duyduğudur.

İkinci sınır, alan uzmanına erişimin kendisidir. Ad hizası ölçüsünün girdisi uzmanın
cümlesidir; o cümle alınamıyorsa ölçünün sabit listesi de yoktur. Bu durumda kodda görünen
adlar alanın değil, kodu yazan kişinin varsayımlarının adları olur.

## Özet

- Alan odaklı tasarım, kod tabanının yapısını alanın kendi ayrımlarından türetmeyi önerir;
  kurs boyunca ölçülen nitelik modelin alanla hizasıdır.
- Ölçünün girdisi alan uzmanının kuralı söylediği cümledir; ücretlendirme kuralının cümlesi
  on iki ad taşıyor.
- Teknik adlarla yazılmış sürümde bu adların 0'ı, alan adlarıyla yazılmış sürümde 12'si
  kaynakta birebir bulundu.
- Alan dilinde gelen üç değişiklik isteği teknik sürümde 0 aday satıra, alan sürümünde
  14 satırın 2'sine indi; aday yoksa dosyanın tamamı okunmak zorundadır.
- Dört gönderinin dördünde iki sürüm aynı ücreti verdi: hiza bir doğruluk niteliği değil,
  değişiklik zamanında ödenen bir maliyet kalemidir.
- Kazanç alanın karmaşıklığına bağlıdır; uzmanın kuralı iki adla söylediği işlerde ölçülecek
  bir hiza yoktur.

## Sonraki Adım

Bu derste hiza tek dosyada ölçüldü ve uzmanın on iki adı bir kez yazıldı. Gerçek bir kod
tabanında aynı kavram birden çok yerde adlandırılır: veritabanı sütunu bir ad kullanır,
uygulama katmanı ikincisini, dışa açılan arayüz üçüncüsünü. O zaman soru adların alandan
gelip gelmediği değil, **kaç tanesinin** aynı şeyi adlandırdığı olur. Sonraki ders kavram
başına eş ad sayısını ve iki ad arasında çeviri yapan nokta sayısını sayar, iki eş adın aynı
kurala ayrı ayrı tabi tutulmasının ürettiği tutarsızlığı ölçer ve tek sözlüğün bu sayıları
nereye indirdiğini gösterir.
