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

# Kullanım Senaryoları

Uygulama katmanının sorumluluğunun kullanım senaryosuyla tanımlanması: aynı senaryonun kararları uygulama katmanında taşıyan ve kararları toplama köküne indiren iki sürümünde karar noktalarının sayılması, alan uzmanının beş cümlesinin kodda kaç yere yazıldığının ölçülmesi ve iki sürümün davranış eşitliğinin sınanması.

Bağlamlar konusu modelin **nerede** geçerli olduğunu kurdu: sınır bir adın anlamının değiştiği
yerden geçiyor, bağlamlar arası ilişkiler yön ve türle adlandırılıyor, dış modelin sızması bir
katmanla durduruluyor, alt alan ayrımı hangi parçaya ne kadar emek verileceğini söylüyor. Açıkta
kalan soru bir bağlamın **içindedir**: o bağlamdaki model bir uygulamanın içine nasıl yerleşir?
Bir istek nereden girer, hangi sırayla hangi nesneye iner, işlemin sınırını kim çizer, sonuç
kime döner?

Bu konu o düzeni kurar ve ilk ders **kullanım senaryosunu** uygulama katmanının birimi olarak
alır: alan modelini çağıran, işlemi başlatıp bitiren, ama iş kuralını kendisi taşımayan ince
bir kabuk. Buraya kadarki örneklerde kurallar doğrudan çağrılmıştı; şimdi çağıranın ne olduğu
sorulacak. Bu bölümün through-line'ı teslimat operasyonu bağlamıdır: `gonderi` burada rotası ve
durum damgaları olan fiziksel pakettir, `rota` aktarma noktalarının sırasıdır, `teslimat` o
paketin operasyon boyunca izlenen durumudur. Ele alınacak senaryo tek bir cümledir: bir aktarma
noktasına varış kaydet.

## Senaryonun Adımı ile Kararı

**Kullanım senaryosu** (use case) uygulamanın dışarıya açtığı tek bir işlemdir ve iki farklı
şeyi bir arada barındırabilir: adımların **sırası** ile o adımların içindeki **kararlar**.
Sıra teknik bir düzenlemedir — deponun çağrılması, işlem sınırının açılması, sonucun yazılması,
dışarıya dönen sözleşmenin üretilmesi. Karar ise alanın kendi cümlesidir.

Uygulama sınırının tek yerde tanımlanması Tasarım Kalıpları kursundaki servis katmanı
kalıbında, katmanların sorumlulukları ve aralarındaki bağımlılık yönü ise Veri Erişim Katmanı
ve İş Mantığı kursunda kurulmuş ve ölçülmüştü. Burada yeni olan şey katmanın tanımı değil, tek
bir soru: senaryonun içindeki kararlar hangi dosyada duruyor?

Alan uzmanının varış kaydı hakkında söylediği beş cümle şunlardır: kapanmış bir teslimata
varış işlenmez; varış ancak rotada bulunan bir noktaya işlenir; aynı nokta iki kez geçilmiş
sayılmaz; varış rota sırasına uygun olmalıdır; rotanın son noktasına varan gönderi dağıtıma
çıkar. Bu beş cümlenin kodda kaç yere yazıldığı, bu dersin hiza ölçüsüdür.

İki sürüm de aynı kalıcılık düzenini kullanır.

```js
// depo.mjs — teslimat kayitlarini tutan bellek ici depo; iki duzen de bunu kullanir
const TABLO = new Map();

export const teslimatDeposu = {
  bul: (id) => structuredClone(TABLO.get(id) ?? null),
  yaz: (kayit) => { TABLO.set(kayit.id, structuredClone(kayit)); },
};

export function tohum(id) {
  TABLO.set(id, { id, durum: "kabul-edildi", rota: ["34", "06", "35"], gecilen: [] });
}
```

## Kararlar Uygulama Katmanında

İlk sürümde teslimat kaydı davranışsız bir veri yığınıdır; beş cümlenin hepsi senaryonun
gövdesine yazılmıştır.

```sh
mkdir -p kararlar-yukarida/uygulama
```

```js
// kararlar-yukarida/uygulama/varis-kaydet.mjs — kullanim senaryosu hem sirayi hem kararlari tasiyor
import { teslimatDeposu } from "../../depo.mjs";

export function varisKaydet(id, nokta) {
  const t = teslimatDeposu.bul(id);
  if (t === null) throw new RangeError(`teslimat yok: ${id}`);
  if (t.durum === "teslim-edildi") throw new Error("kapali teslimata varis islenemez");
  if (!t.rota.includes(nokta)) throw new Error(`nokta rotada yok: ${nokta}`);
  if (t.gecilen.includes(nokta)) throw new Error(`nokta zaten gecildi: ${nokta}`);
  const sira = t.rota.indexOf(nokta);
  if (sira !== t.gecilen.length) throw new Error("rota sirasi bozuk");
  t.gecilen.push(nokta);
  t.durum = sira === t.rota.length - 1 ? "dagitimda" : "aktarmada";
  teslimatDeposu.yaz(t);
  return { kimlik: t.id, durum: t.durum, gecilen: t.gecilen.length };
}
```

Uygulamanın ikinci istemcisi aktarma merkezinin gün sonunda gönderdiği okuma listesini toplu
işler. Kararlar senaryonun gövdesinde durduğu için ikinci istemci onları yeniden yazar.

```js
// kararlar-yukarida/uygulama/toplu-varis.mjs — ikinci istemci ayni kararlari yeniden yaziyor
import { teslimatDeposu } from "../../depo.mjs";

export function topluVaris(girdiler) {
  return girdiler.map(({ id, nokta }) => {
    try {
      const t = teslimatDeposu.bul(id);
      if (t === null) throw new RangeError(`teslimat yok: ${id}`);
      if (t.durum === "teslim-edildi") throw new Error("kapali teslimata varis islenemez");
      if (!t.rota.includes(nokta)) throw new Error(`nokta rotada yok: ${nokta}`);
      if (t.gecilen.includes(nokta)) throw new Error(`nokta zaten gecildi: ${nokta}`);
      const sira = t.rota.indexOf(nokta);
      if (sira !== t.gecilen.length) throw new Error("rota sirasi bozuk");
      t.gecilen.push(nokta);
      t.durum = sira === t.rota.length - 1 ? "dagitimda" : "aktarmada";
      teslimatDeposu.yaz(t);
      return { kimlik: t.id, durum: t.durum, gecilen: t.gecilen.length };
    } catch (hata) { return { kimlik: id, hata: hata.message }; }
  });
}
```

Toplu betik tekil senaryonun gövdesini bir eşlemenin içine almış hâlidir. Tekrarlanan şey
satır değil, alanın beş cümlesidir.

## Kararlar Alan Modelinde

İkinci sürümde beş cümle **toplama kökünün** içine taşınır. Teslimat bir varlık nesnesidir:
kimliği vardır, durumu zamanla değişir ve geçilen noktalar dizisi onun değişmezini taşır.

```sh
mkdir -p kararlar-alanda/alan kararlar-alanda/uygulama
```

```js
// kararlar-alanda/alan/teslimat.mjs — ayni bes karar, toplama kokunun icinde
export class Teslimat {
  #id; #rota; #gecilen; #durum;

  constructor(kayit) {
    this.#id = kayit.id; this.#rota = [...kayit.rota];
    this.#gecilen = [...kayit.gecilen]; this.#durum = kayit.durum;
  }

  varisKaydet(nokta) {
    if (this.#durum === "teslim-edildi") throw new Error("kapali teslimata varis islenemez");
    if (!this.#rota.includes(nokta)) throw new Error(`nokta rotada yok: ${nokta}`);
    if (this.#gecilen.includes(nokta)) throw new Error(`nokta zaten gecildi: ${nokta}`);
    const sira = this.#rota.indexOf(nokta);
    if (sira !== this.#gecilen.length) throw new Error("rota sirasi bozuk");
    this.#gecilen.push(nokta);
    this.#durum = sira === this.#rota.length - 1 ? "dagitimda" : "aktarmada";
  }

  kayda() { return { id: this.#id, durum: this.#durum, rota: [...this.#rota], gecilen: [...this.#gecilen] }; }
  ozet() { return { kimlik: this.#id, durum: this.#durum, gecilen: this.#gecilen.length }; }
}
```

Senaryoda dört adım kalır: kaydı oku, toplamaya söyle, sonucu yaz, sözleşmeyi döndür.

```js
// kararlar-alanda/uygulama/varis-kaydet.mjs — kullanim senaryosu yalniz sirayi tasiyor
import { teslimatDeposu } from "../../depo.mjs";
import { Teslimat } from "../alan/teslimat.mjs";

export function varisKaydet(id, nokta) {
  const kayit = teslimatDeposu.bul(id);
  if (kayit === null) throw new RangeError(`teslimat yok: ${id}`);
  const teslimat = new Teslimat(kayit);
  teslimat.varisKaydet(nokta);
  teslimatDeposu.yaz(teslimat.kayda());
  return teslimat.ozet();
}
```

```js
// kararlar-alanda/uygulama/toplu-varis.mjs — ikinci istemci yalniz dongu ekliyor
import { varisKaydet } from "./varis-kaydet.mjs";

export function topluVaris(girdiler) {
  return girdiler.map(({ id, nokta }) => {
    try { return varisKaydet(id, nokta); }
    catch (hata) { return { kimlik: id, hata: hata.message }; }
  });
}
```

İkinci istemcinin tekilden gerçek farkı ortaya çıktı: bir döngü ve hata biçimi. Beş cümleye
dair hiçbir şey bilmiyor.

## Ölçüm

Ölçüm üç sayı çıkarır. Birincisi dosya başına karar noktası: dallanma belirteçlerinin
(`if`, üçlü işleç, `catch`) sayısı. İkincisi kural başına yazım yeri: beş cümlenin her birinin
kaç dosyada göründüğü. Üçüncüsü koşumdan gelir: iki sürüm aynı işlem dizisinde aynı sonucu
veriyor mu?

```js
// karar-say.mjs — karar noktasi, kuralin yazildigi dosya sayisi ve iki duzenin davranis esitligi
import { readFileSync } from "node:fs";
import { teslimatDeposu, tohum } from "./depo.mjs";
import { topluVaris as yukariToplu } from "./kararlar-yukarida/uygulama/toplu-varis.mjs";
import { topluVaris as alanToplu } from "./kararlar-alanda/uygulama/toplu-varis.mjs";

const DAL = /\bif \(|\bcatch \(| \? /g;
const KURAL = {
  "kapali-teslimat": /=== "teslim-edildi"/,
  "nokta-rotada": /rota\.includes\(nokta\)/,
  "nokta-tekrari": /gecilen\.includes\(nokta\)/,
  "rota-sirasi": /sira !== /,
  "son-nokta": /"dagitimda"/,
};
const YUKARIDA = ["kararlar-yukarida/uygulama/varis-kaydet.mjs", "kararlar-yukarida/uygulama/toplu-varis.mjs"];
const ALANDA = ["kararlar-alanda/uygulama/varis-kaydet.mjs", "kararlar-alanda/uygulama/toplu-varis.mjs",
  "kararlar-alanda/alan/teslimat.mjs"];

function tara(ad, dosyalar) {
  console.log(ad);
  const metinler = dosyalar.map((d) => [d, readFileSync(d, "utf8")]);
  let uygulamaKarari = 0, alanKarari = 0;
  for (const [d, m] of metinler) {
    const karar = (m.match(DAL) ?? []).length;
    if (d.includes("/uygulama/")) uygulamaKarari += karar; else alanKarari += karar;
    console.log(`  ${d.padEnd(46)} karar noktasi = ${karar}`);
  }
  console.log(`  uygulama katmani karari = ${uygulamaKarari}, alan modulu karari = ${alanKarari}`);
  let yer = 0;
  for (const [k, kalip] of Object.entries(KURAL)) {
    const nerede = metinler.filter(([, m]) => kalip.test(m)).map(([d]) => d.split("/").at(-1));
    yer += nerede.length;
    console.log(`  kural ${k.padEnd(16)} ${nerede.length} yerde (${nerede.join(", ")})`);
  }
  console.log(`  bes kuralin toplam yazim yeri = ${yer}`);
}

tara("kararlar uygulama katmaninda", YUKARIDA);
tara("kararlar alan modelinde", ALANDA);

const ISLEMLER = (id) => [
  { id, nokta: "34" }, { id, nokta: "34" }, { id, nokta: "35" }, { id, nokta: "99" },
  { id, nokta: "06" }, { id, nokta: "35" }, { id: "T-YOK", nokta: "34" },
];
tohum("T-A"); tohum("T-B");
const a = yukariToplu(ISLEMLER("T-A"));
const b = alanToplu(ISLEMLER("T-B"));
const sadeles = (r, id) => JSON.stringify(r).replaceAll(id, "T");
let ayrilan = 0;
for (let i = 0; i < a.length; i += 1) {
  const x = sadeles(a[i], "T-A"), y = sadeles(b[i], "T-B");
  if (x !== y) ayrilan += 1;
  console.log(`${String(i).padStart(2)} ${x}`);
}
console.log(`ayrilan sonuc = ${ayrilan} / ${a.length}`);
console.log(`son kayit = ${JSON.stringify(teslimatDeposu.bul("T-B"))}`);
```

```sh
node karar-say.mjs
```

```
kararlar uygulama katmaninda
  kararlar-yukarida/uygulama/varis-kaydet.mjs    karar noktasi = 6
  kararlar-yukarida/uygulama/toplu-varis.mjs     karar noktasi = 7
  uygulama katmani karari = 13, alan modulu karari = 0
  kural kapali-teslimat  2 yerde (varis-kaydet.mjs, toplu-varis.mjs)
  kural nokta-rotada     2 yerde (varis-kaydet.mjs, toplu-varis.mjs)
  kural nokta-tekrari    2 yerde (varis-kaydet.mjs, toplu-varis.mjs)
  kural rota-sirasi      2 yerde (varis-kaydet.mjs, toplu-varis.mjs)
  kural son-nokta        2 yerde (varis-kaydet.mjs, toplu-varis.mjs)
  bes kuralin toplam yazim yeri = 10
kararlar alan modelinde
  kararlar-alanda/uygulama/varis-kaydet.mjs      karar noktasi = 1
  kararlar-alanda/uygulama/toplu-varis.mjs       karar noktasi = 1
  kararlar-alanda/alan/teslimat.mjs              karar noktasi = 5
  uygulama katmani karari = 2, alan modulu karari = 5
  kural kapali-teslimat  1 yerde (teslimat.mjs)
  kural nokta-rotada     1 yerde (teslimat.mjs)
  kural nokta-tekrari    1 yerde (teslimat.mjs)
  kural rota-sirasi      1 yerde (teslimat.mjs)
  kural son-nokta        1 yerde (teslimat.mjs)
  bes kuralin toplam yazim yeri = 5
 0 {"kimlik":"T","durum":"aktarmada","gecilen":1}
 1 {"kimlik":"T","hata":"nokta zaten gecildi: 34"}
 2 {"kimlik":"T","hata":"rota sirasi bozuk"}
 3 {"kimlik":"T","hata":"nokta rotada yok: 99"}
 4 {"kimlik":"T","durum":"aktarmada","gecilen":2}
 5 {"kimlik":"T","durum":"dagitimda","gecilen":3}
 6 {"kimlik":"T-YOK","hata":"teslimat yok: T-YOK"}
ayrilan sonuc = 0 / 7
son kayit = {"id":"T-B","durum":"dagitimda","rota":["34","06","35"],"gecilen":["34","06","35"]}
```

## Sayıların Okunması

Uygulama katmanının karar noktası 13'ten 2'ye indi; alan modülünde 5 karar noktası oluştu.
Toplam 13'ten 7'ye düşmesinin nedeni tekrarın kalkmasıdır, kararların yok olması değil.
Kalan 2 karar noktası dallanmanın kendisidir: her iki senaryoda kaydın bulunamaması durumu.

Beş cümlenin toplam yazım yeri 10'dan 5'e indi; oran 2,0'dan 1,0'a düştü. Bu oran dersin hiza
ölçüsüdür: alan uzmanının bir cümlesi kodda birden fazla yerde yaşıyorsa iki yerin birbirinden
sapması bir sürüm meselesidir, tasarım meselesi değildir. Oranın büyüme biçimi de bellidir.
Senaryoyu kendi içinde yürüten `n` istemci varken yazım yeri `5n`, kararlar toplama kökünde
iken sabit 5'tir; altıncı bir cümle geldiğinde ilk düzende `n` dosya, ikincisinde 1 dosya
düzenlenir.

Son yedi satır davranışın korunduğunu gösteriyor. Aynı işlem dizisi iki sürümde de aynı
sonucu üretti: üç geçerli varış, üç kural ihlali, bir bulunamayan kimlik. Ayrılan sonuç 0.
Son kayıt üç noktanın da geçildiğini ve durumun dağıtıma döndüğünü doğruluyor.

## Uygulama Katmanında Kalan Kararlar

Ölçüyü "karar noktası sıfıra insin" biçiminde okumak yanlış olur. Uygulama katmanının kendine
ait, alan modeline ait olmayan kararları vardır ve bunlar aşağı indirilirse alan modeli
bilmemesi gereken şeyleri bilmeye başlar.

Kaydın bulunamaması bunlardan biridir: bu bir alan kuralı değil, bir arama sonucudur; teslimat
nesnesi henüz kurulmamışken verilir. İşlem sınırının nerede açılıp kapandığı, çağıranın bu
işlemi yapmaya yetkili olup olmadığı, birden çok toplamanın hangi sırada okunacağı, dışarıya
dönen sözleşmenin hangi alanları taşıdığı da uygulama katmanının kararlarıdır. Bunların ortak
özelliği alan uzmanının cümlesinde geçmemeleridir: uzman "kapanmış teslimata varış işlenmez"
der, "işlemi burada aç" demez.

Ayrım pratikte tek soruyla yapılır: bu karar alanın sözlüğünden mi geliyor, uygulamanın
gerçekleştirim düzeninden mi? Birinci durumda toplama köküne iner, ikinci durumda senaryoda
kalır.

## Özet

- Kullanım senaryosu adım sırası ile kararı bir arada barındırabilir; sıra uygulamanın,
  karar alanın sözlüğüne ait olduğunda toplama kökünün işidir.
- Kararlar senaryoda iken uygulama katmanının karar noktası 13, alan modülünün 0'dı; kararlar
  toplama köküne indirildiğinde sayılar 2 ve 5 oldu.
- Alan uzmanının beş cümlesinin toplam yazım yeri 10'dan 5'e, cümle başına yer oranı 2,0'dan
  1,0'a indi; ilk düzende bu sayı istemci sayısıyla `5n` olarak büyür.
- Yedi işlemin yedisinde iki sürüm aynı sonucu üretti; taşıma davranışı değiştirmedi, kararın
  hangi dosyada durduğunu değiştirdi.
- Arama sonucu, işlem sınırı, yetki ve dışarıya dönen sözleşme uygulama katmanının kararlarıdır;
  ölçütü alan uzmanının cümlesinde geçip geçmemeleridir.

## Sonraki Adım

Kararlar toplama köküne indi, ama senaryonun dört adımından biri hâlâ bir dış dünya adını
taşıyor: `teslimatDeposu`. Bu ad tek bir örnekte kalmayacak. Varış kaydı taşıyıcının kendi
nokta kodunu ister, bir varış numarası üretilmesini ister, aktarma merkezine duyuru
gönderilmesini ister.
Bu adların her biri alan modülüne doğrudan bir bağ olarak girerse alan modeli dışarıyı bilmeye
başlar; ithal kapanışı büyür ve modelin sınanması dış dünyanın hazır olmasına bağlanır. Sonraki
ders alanın dışa açıldığı her yeri açık bir bağlantı noktası olarak adlandırır, bağdaştırıcıları
dışarıda tutar, alan modülünden dış dünyaya giden doğrudan bağ sayısını ve bağdaştırıcı
değiştiğinde düzenlenen dosya sayısını iki düzende karşılaştırır.
