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

# Alan Olayları

Anlamlı iş olaylarının açık modeli: aynı altmış olgudan üretilen iki kütükte alan uzmanının üç sorusunun kaçının tek süzmeyle doğru yanıtlandığının ölçülmesi, yanıt için kaç olayın alanlarının karşılaştırılmak zorunda kaldığının sayılması, olay adlarının alan sözlüğünde bulunma oranının ve kütük uzunluğunun karşılaştırılması.

Buraya kadarki bütün ölçüler modelin durumu üzerineydi: hangi ad hangi kavramı gösteriyor,
hangi değişmez hangi sınırın içinde, nesne hangi yolla kuruluyor. Alanda bir de olup bitenler
var — bir gönderi fiyatlandı, sözleşme indirimi kaldırıldı, tarife değiştiği için tutar
yeniden hesaplandı. Bu olguların kodda kendi adları olabilir ya da hepsi "kayıt güncellendi"
diye geçebilir.

Alanda olup biten, geçmiş zamanda anlatılan ve alan dilinde bir adı olan olguya **alan olayı**
(domain event) denir. Olayın yayımlanması, dinleyicilere ulaştırılması ve işlemle birlikte
kesinleşmesi Veri Erişim Katmanı ve İş Mantığı kursundaki Alan Olayları dersinde kurulmuş ve
ölçülmüştü. Bu ders o tarafa girmez. Tek soruyu sorar: olayın **adı** nereden geliyor?

## Ölçünün Kurulumu

Ölçü için bir günün ücretlendirme geçmişi altmış olgu olarak yazılır. Her olgunun bir türü,
bir gönderi numarası ve öncesi–sonrası görüntüsü vardır. İki kütük de bu tek kaynaktan
üretilir; aradaki fark yalnız neyin saklandığıdır.

```sh
mkdir -p genel alan
```

```js
// olgular.mjs — bir gunun ucretlendirme gecmisi: 60 olgu, iki kutugun de kaynagi
const OLGU = ["gonderi-fiyatlandi", "sozlesme-indirimi-kaldirildi", "hacim-indirimi-eklendi",
  "tartim-duzeltmesi-uygulandi", "tarife-degistigi-icin-yeniden-fiyatlandi",
  "asgari-ucret-uygulandi"];
export const ASGARI_UCRET = 3990;

export const OLGULAR = [];
for (let i = 0; i < 60; i += 1) {
  const olgu = OLGU[i % 6];
  const gonderiNo = `G-5${101 + (i % 20)}`;
  const t = 4200 + (i % 5) * 900;
  let oncesi;
  let sonrasi;
  if (olgu === "gonderi-fiyatlandi") {
    oncesi = { tutar: 0, tarife: null, indirimler: [] };
    sonrasi = { tutar: t, tarife: "standart", indirimler: [] };
  } else if (olgu === "sozlesme-indirimi-kaldirildi") {
    oncesi = { tutar: t, tarife: "standart", indirimler: ["sozlesme", "hacim"] };
    sonrasi = { tutar: t + 600, tarife: "standart", indirimler: ["hacim"] };
  } else if (olgu === "hacim-indirimi-eklendi") {
    oncesi = { tutar: t, tarife: "standart", indirimler: ["sozlesme"] };
    sonrasi = { tutar: t - 400, tarife: "standart", indirimler: ["sozlesme", "hacim"] };
  } else if (olgu === "tartim-duzeltmesi-uygulandi") {
    oncesi = { tutar: t, tarife: "standart", indirimler: ["hacim"] };
    sonrasi = { tutar: i % 4 === 3 ? ASGARI_UCRET : t + 250, tarife: "standart",
      indirimler: ["hacim"] };
  } else if (olgu === "tarife-degistigi-icin-yeniden-fiyatlandi") {
    oncesi = { tutar: t, tarife: "standart", indirimler: ["hacim"] };
    sonrasi = { tutar: t - 700, tarife: "bolgesel", indirimler: ["hacim"] };
  } else {
    oncesi = { tutar: t, tarife: "bolgesel", indirimler: ["hacim"] };
    sonrasi = { tutar: ASGARI_UCRET, tarife: "bolgesel", indirimler: ["hacim"] };
  }
  OLGULAR.push({ sira: i + 1, olgu, gonderiNo, oncesi, sonrasi });
}
```

Birinci kütük olayın adını iki genel addan birine indirir ve olup biteni önce–sonra
görüntüsüyle anlatır. Bu, kalıcılık tarafından bakıldığında en doğal seçimdir: her yazma bir
güncellemedir.

```js
// genel/kutuk.mjs — her olgu ayni iki addan birini alir, yuk oncesi/sonrasi goruntusudur
import { OLGULAR } from "../olgular.mjs";

export const KUTUK = OLGULAR.map((o) => ({
  tur: o.oncesi.tarife === null ? "GonderiOlusturuldu" : "GonderiGuncellendi",
  gonderiNo: o.gonderiNo,
  oncesi: o.oncesi,
  sonrasi: o.sonrasi,
}));
```

İkinci kütük olayın adını alan dilinden alır. Görüntüye ihtiyaç kalmaz: ad neyin olduğunu
söyler, yük yalnız o adın gerektirdiği kadardır.

```js
// alan/kutuk.mjs — olayin adi alan dilinden gelir, yuk o adin gerektirdigi kadardir
import { OLGULAR } from "../olgular.mjs";

const AD = {
  "gonderi-fiyatlandi": "GonderiFiyatlandi",
  "sozlesme-indirimi-kaldirildi": "SozlesmeIndirimiKaldirildi",
  "hacim-indirimi-eklendi": "HacimIndirimiEklendi",
  "tartim-duzeltmesi-uygulandi": "TartimDuzeltmesiUygulandi",
  "tarife-degistigi-icin-yeniden-fiyatlandi": "TarifeDegistigiIcinYenidenFiyatlandi",
  "asgari-ucret-uygulandi": "AsgariUcretUygulandi",
};

export const KUTUK = OLGULAR.map((o) => ({
  tur: AD[o.olgu],
  gonderiNo: o.gonderiNo,
  tutar: o.sonrasi.tutar,
}));
```

## Ölçüm

Alan uzmanı kütüğe üç soru soruyor: kaç gönderi sözleşme indirimini sonradan kaybetti, tarife
değiştiği için kaç kez yeniden fiyatlama yapıldı, kaç kez asgari ücret devreye girdi. Her soru
iki kütükte de tek bir süzmeyle yanıtlanmaya çalışılır ve yanıt gerçek sayıyla karşılaştırılır.

```js
// olay-olc.mjs — uzmanin uc sorusu iki kutukte kac dogru yanit ve kac karsilastirma istiyor
import { OLGULAR, ASGARI_UCRET } from "./olgular.mjs";
import { KUTUK as GENEL } from "./genel/kutuk.mjs";
import { KUTUK as ALAN } from "./alan/kutuk.mjs";

const gercek = (olgu) => OLGULAR.filter((o) => o.olgu === olgu).length;
const ind = (g) => g?.indirimler ?? [];

const SORULAR = [
  ["sozlesme indirimini kaybeden gonderi", "sozlesme-indirimi-kaldirildi",
    (k) => k.filter((e) => ind(e.oncesi).includes("sozlesme")
      && !ind(e.sonrasi).includes("sozlesme")).length,
    (k) => k.filter((e) => e.tur === "SozlesmeIndirimiKaldirildi").length],
  ["tarife degistigi icin yeniden fiyatlama", "tarife-degistigi-icin-yeniden-fiyatlandi",
    (k) => k.filter((e) => e.oncesi.tarife !== e.sonrasi.tarife).length,
    (k) => k.filter((e) => e.tur === "TarifeDegistigiIcinYenidenFiyatlandi").length],
  ["asgari ucretin devreye girmesi", "asgari-ucret-uygulandi",
    (k) => k.filter((e) => e.sonrasi.tutar === ASGARI_UCRET).length,
    (k) => k.filter((e) => e.tur === "AsgariUcretUygulandi").length],
];

let genelDogru = 0;
let alanDogru = 0;
for (const [soru, olgu, genelYanit, alanYanit] of SORULAR) {
  const d = gercek(olgu);
  const g = genelYanit(GENEL);
  const a = alanYanit(ALAN);
  if (g === d) genelDogru += 1;
  if (a === d) alanDogru += 1;
  console.log(`${soru}`);
  console.log(`  gercek ${d}  genel kutuk ${g} ${g === d ? "dogru" : "YANLIS"}  ` +
    `alan kutugu ${a} ${a === d ? "dogru" : "YANLIS"}`);
}
console.log(`tek suzmeyle dogru yanit: genel ${genelDogru}/3, alan ${alanDogru}/3`);

const goruntulu = (k) => k.filter((e) => "oncesi" in e).length;
console.log(`3 soru icin alan karsilastirilan olay: genel ${goruntulu(GENEL) * 3}, ` +
  `alan ${goruntulu(ALAN) * 3}`);

// SOZLUK: alan uzmaninin cumlelerinde gecen sozcukler
const SOZLUK = ["gonderi", "tarife", "bolge", "agirlik", "hacim", "indirim", "sozlesme",
  "tartim", "duzeltme", "asgari", "ucret", "fiyatlandi", "eklendi", "kaldirildi",
  "uygulandi", "yeniden", "degis", "icin"];
const parcala = (t) => t.replace(/([a-z])([A-Z])/g, "$1 $2").toLowerCase().split(" ");
for (const [ad, k] of Object.entries({ genel: GENEL, alan: ALAN })) {
  const turler = [...new Set(k.map((e) => e.tur))];
  const alanli = turler.filter((t) =>
    parcala(t).every((p) => SOZLUK.some((s) => p.startsWith(s))));
  console.log(`${ad}: olay turu ${turler.length}, adinin tamami alan sozlugunde olan ` +
    `${alanli.length}/${turler.length}`);
  console.log(`  ${turler.join(" ")}`);
}
console.log(`kutuk uzunlugu: genel ${JSON.stringify(GENEL).length}, ` +
  `alan ${JSON.stringify(ALAN).length}`);
```

```sh
node olay-olc.mjs
```

```
sozlesme indirimini kaybeden gonderi
  gercek 10  genel kutuk 10 dogru  alan kutugu 10 dogru
tarife degistigi icin yeniden fiyatlama
  gercek 10  genel kutuk 20 YANLIS  alan kutugu 10 dogru
asgari ucretin devreye girmesi
  gercek 10  genel kutuk 15 YANLIS  alan kutugu 10 dogru
tek suzmeyle dogru yanit: genel 1/3, alan 3/3
3 soru icin alan karsilastirilan olay: genel 180, alan 0
genel: olay turu 2, adinin tamami alan sozlugunde olan 0/2
  GonderiOlusturuldu GonderiGuncellendi
alan: olay turu 6, adinin tamami alan sozlugunde olan 6/6
  GonderiFiyatlandi SozlesmeIndirimiKaldirildi HacimIndirimiEklendi TartimDuzeltmesiUygulandi TarifeDegistigiIcinYenidenFiyatlandi AsgariUcretUygulandi
kutuk uzunlugu: genel 11121, alan 4141
```

Üç sorunun yalnız birinde genel kütük doğru sayıyı veriyor. İkinci soruda yirmi diyor, oysa
tarife değişikliği yüzünden yapılan yeniden fiyatlama on kez olmuş; fark, ilk fiyatlamanın da
tarife alanını boştan doluya çevirmesinden geliyor. Üçüncü soruda on beş diyor, oysa asgari
ücret on kez devreye girmiş; beş olayda tutar tartım düzeltmesi sonucu asgari ücretle eşitlenmiş
ama kural uygulanmamış.

Bu iki yanlış, sorgunun düzeltilmesiyle giderilebilir: ilk fiyatlamayı dışarıda bırakan bir
koşul, asgari ücret eşitliğini başka bir alanla doğrulayan bir koşul yazılabilir. Ölçünün
gösterdiği şey bu düzeltmelerin **nereye** yazıldığıdır. Her düzeltme, kütükte bulunmayan bir
alan bilgisini sorgunun içine gömer ve kütükten sınanamaz. Alan kütüğünde aynı üç soru tür
adına bakan tek bir süzmeyle yanıtlanıyor, üçü de doğru çıkıyor.

İkinci satır bedeli işlem cinsinden veriyor: üç soruyu yanıtlamak için genel kütükte yüz seksen
olayın alanları karşılaştırılıyor, alan kütüğünde hiçbiri. Üçüncü ölçü adların kaynağını
gösteriyor: genel kütükteki iki türün adı alan sözlüğünde yok — "oluşturuldu" ve "güncellendi"
uzmanın kullandığı sözcükler değil, kalıcılık işlemlerinin adları. Alan kütüğündeki altı türün
altısı alan sözlüğünden geliyor.

Son satır bir yan kazançtır: adın taşıdığı bilgi, görüntünün taşıdığı bilgiden kısadır. Kütük
uzunluğu 11121 karakterden 4141 karaktere iniyor.

## Olayın Adı Ne Söyler

Alan olayının adı üç şeyi birlikte taşır: neyin olduğu, hangi kavramda olduğu ve olmuş bitmiş
olduğu. `SozlesmeIndirimiKaldirildi` adı bunların üçünü de veriyor. Ad geçmiş zamandadır çünkü
olay bir istek değildir; olmasını istemek başka bir kavramdır ve başka bir adı vardır.

Adın alan diline ait olmasının ölçülebilir sonucu, uzmanın kütüğü doğrulayabilmesidir. Alan
kütüğündeki altı tür adı uzmanın önüne konduğunda uzman eksik olanı söyleyebilir: "iade
ücretinin hesaplanması da bir olgudur, listede yok." Genel kütükteki iki ad önüne konduğunda
söyleyecek bir şeyi olmaz, çünkü o adlar onun dilinde değildir.

Olayın yükü de aynı ölçütten geçer. `TarifeDegistigiIcinYenidenFiyatlandi` olayının yükünde
yeni tutarın bulunması alanla ilgilidir; kaydın veritabanı satır kimliğinin bulunması değildir.
Kütüğe yük eklendiğinde sorulan soru, o alanın uzmanın cümlesinde geçip geçmediğidir.

## Ne Zaman Genel Ad Yeterlidir

Alan olaylarının bedeli tür sayısıdır. Altı tür, altı ad, altı süzme koşulu ve zaman içinde
altı ayrı sürüm demektir; genel kütükte iki ad vardır ve yeni bir olgu türü hiçbir şey
eklemez.

Bu bedelin karşılıksız kaldığı durum, kütüğe alan sorusu sorulmadığı durumdur. Yalnız
"bu kayda en son ne zaman dokunuldu" sorusu için tutulan bir iz kaydında önce–sonra görüntüsü
yeterlidir ve tür ayrımı kazanç üretmez. Ayrım ölçütü kütüğün boyutu da değildir — kütüğe
sorulan alan sorusunun sayısıdır.

İkinci durum, olgunun alanda bir adı olmamasıdır. Uzmanın "bu bir şey değil, kaydın
düzeltilmesi" dediği değişiklikler için alan olayı adı uydurmak, sözlüğe alanda karşılığı
olmayan bir kavram eklemek olur; ikinci dersin ölçüsü bunu ad başına kavram sayısı olarak
sayar.

## Özet

- Alan olayı, alanda olup biten ve alan dilinde bir adı olan olgudur; bu ders yalnız adın
  nereden geldiğini ölçtü, yayım ve ulaştırma tarafına girmedi.
- Aynı altmış olgudan üretilen iki kütükte uzmanın üç sorusundan genel kütük 1'ini, alan
  kütüğü 3'ünü tek süzmeyle doğru yanıtladı.
- Genel kütüğün iki yanlış yanıtı düzeltilebilir, ama her düzeltme kütükte bulunmayan bir alan
  bilgisini sorgunun içine gömer ve kütükten sınanamaz hâle getirir.
- Üç soruyu yanıtlamak genel kütükte 180 olayın alanlarının karşılaştırılmasını gerektirdi,
  alan kütüğünde 0.
- Genel kütükteki 2 tür adının 0'ı, alan kütüğündeki 6 tür adının 6'sı alan sözlüğünden
  geliyor; kütük uzunluğu 11121'den 4141 karaktere indi.
- Bedel tür sayısıdır; kütüğe alan sorusu sorulmuyorsa ya da olgunun alanda bir adı yoksa
  genel ad yeterlidir.

## Sonraki Adım

Bu konudaki dersler kimliği, değeri, sınırı, davranışın yerini, yaratımı ve olayı tek tek
ölçtü. Hepsinin ortak varsayımı, alan nesnesinin bir davranışı olduğuydu. Yaygın bir düzen bu
varsayımı kaldırır: alan sınıfları yalnız alan taşır, bütün kurallar servislere yazılır ve
sınıflar bir veri biçiminden fazlası olmaz. Sonraki ders bu düzeni alan modeli bağlamında
ölçer: aynı kuralın kaç serviste tekrarlandığını, yeni bir kural eklendiğinde dokunulan dosya
sayısını ve uzmanın cümlesindeki fiillerin kaçının alan nesnesinde bir yöntem olarak
bulunduğunu sayar.
