---
title: 'Servis Yönelimli Mimari'
source: 'https://academia.sh/tr/kurslar/servis-mimarileri/servis-yonelimli-mimari'
course: 'Servis Mimarileri'
language: tr
updated: '2026-08-17T18:06:53+00:00'
license: 'CC BY-SA 4.0'
---

# Servis Yönelimli Mimari

Kurumsal servis düşüncesinin ölçüsü: birimlerin ortak bir sözleşme ve kanonik veri modeli üzerinden konuşması, ortak katmana bağlı birim sayısının sayılması, kanonik bir alan adının değişmesinin kaç birimi dokunulur kıldığı ve sahibi güncellenip tüketicisi güncellenmediğinde doğan sessiz yanlış davranış.

Önceki ders sınırı ithal grafiğinde kurdu, ama `depo.mjs` bütün alanların ortak veri yapısını
tutmayı sürdürdü. Sınır kodda vardı, veride yoktu. Bu ders o ortaklığı büyütür: alanlar
kendi durumlarını taşıyan ayrı birimlere dönüşür, aralarında ortak bir yol üzerinden konuşur
ve konuşmanın biçimini **kurumsal ortak bir model** belirler.

Bu düzenin adı **servis yönelimli mimari** (service-oriented architecture). Biçemin tanımı Mimari Biçemler kursunda
yapıldı; burada ölçülen şey tanım değil, ortak katmanın koda getirdiği bağlaşımdır.

**MS4.** Birimler ayrı süreç değildir; hepsi aynı süreçte, bir ileti yolu üzerinden konuşur.
Ölçülen şey sözleşme bağlaşımıdır, ağ değil. Süreçlere bölme sonraki derste yapılır.

## Ortak Katman

Ortak katman iki şey tanımlar: her iletinin taşıyacağı zarf ve kanonik üye kaydının alanları.

```js
// ortak/sozlesme.mjs — kurumsal ortak model: ileti zarfi ve kanonik uye alanlari
export const ZARF = ["kaynak", "islem", "govde"];
export const UYE_ALANLARI = ["uyeNo", "ad", "acikOdunc", "sinir", "borc"];
export function dogrula(ileti) {
  for (const a of ZARF) if (a in ileti === false) throw new Error(`zarf alani eksik: ${a}`);
  return ileti;
}
```

```js
// yol.mjs — kurumsal servis yolu; her ileti ortak sozlesmeye gore dogrulanir
import { dogrula } from "./ortak/sozlesme.mjs";
const birimler = new Map();
export const sayac = { ileti: 0 };
export function tanit(islem, islev) { birimler.set(islem, islev); }
export function gonder(ileti) {
  sayac.ileti += 1;
  return birimler.get(dogrula(ileti).islem)(ileti.govde);
}
```

Her birim kendi durumunu taşır ve yaptığı işi yola tanıtır. Doğrudan ithal yoktur; birimler
birbirinin adını değil, **işlem adını** bilir.

```js
// katalog.mjs — kitap birimi
import { tanit } from "./yol.mjs";
const kitaplar = { 1: { kitapNo: 1, baslik: "Korluk", durum: "rafta" },
                   2: { kitapNo: 2, baslik: "Kum Kitabi", durum: "rafta" } };
tanit("kitap.durum", ({ kitapNo }) => kitaplar[kitapNo].durum);
tanit("kitap.oduncIsaretle", ({ kitapNo }) => { kitaplar[kitapNo].durum = "odunc"; });
```

```js
// uyelik.mjs — kanonik uye kaydini tutan birim
import { tanit } from "./yol.mjs";
import { UYE_ALANLARI } from "./ortak/sozlesme.mjs";
const uyeler = {
  4: { uyeNo: 4, ad: "Emre", acikOdunc: 1, sinir: 3, borc: 0 },
  5: { uyeNo: 5, ad: "Selin", acikOdunc: 3, sinir: 3, borc: 0 },
};
export const eksikAlan = (u) => UYE_ALANLARI.filter((a) => a in u === false);
tanit("uye.getir", ({ uyeNo }) => uyeler[uyeNo]);
tanit("uye.oduncEkle", ({ uyeNo }) => { uyeler[uyeNo].acikOdunc += 1; });
tanit("uye.borcEkle", ({ uyeNo, tutar }) => { uyeler[uyeNo].borc += tutar; });
```

```js
// ucretlendirme.mjs — gecikme ucreti birimi
import { tanit } from "./yol.mjs";
tanit("ucret.hesapla", ({ gecikmeGun }) => (gecikmeGun > 0 ? gecikmeGun * 2 : 0));
```

```js
// bildirim.mjs — bildirim birimi; kanonik kayittan ad alanini okur
import { tanit, gonder } from "./yol.mjs";
tanit("bildirim.gonder", ({ uyeNo, metin }) => {
  const uye = gonder({ kaynak: "bildirim", islem: "uye.getir", govde: { uyeNo } });
  console.log(`  bildirim -> ${uye.ad}: ${metin}`);
});
```

Ödünç birimi iş akışını yürütür. Dikkat edilecek yer sınır denetimidir: kanonik kaydı
alıyor ve kuralı **kendisi** uyguluyor.

```js
// odunc.mjs — is akisi; kanonik uye kaydini okuyup kurali kendisi uygular
import { gonder, sayac } from "./yol.mjs";
export function oduncVer(kitapNo, uyeNo, gecikmeGun = 0) {
  const z = (islem, govde) => gonder({ kaynak: "odunc", islem, govde });
  const uye = z("uye.getir", { uyeNo });
  if (uye.acikOdunc >= uye.sinir) throw new Error("odunc siniri asildi");
  if (z("kitap.durum", { kitapNo }) !== "rafta") throw new Error("kitap rafta degil");
  z("kitap.oduncIsaretle", { kitapNo });
  z("uye.oduncEkle", { uyeNo });
  const tutar = z("ucret.hesapla", { gecikmeGun });
  if (tutar > 0) z("uye.borcEkle", { uyeNo, tutar });
  z("bildirim.gonder", { uyeNo, metin: `kitap ${kitapNo} odunc verildi` });
  return { tutar, ileti: sayac.ileti };
}
```

```js
// uygulama.mjs — butun birimleri yukler ve is akisini kosturur
import "./katalog.mjs"; import "./uyelik.mjs"; import "./ucretlendirme.mjs";
import "./bildirim.mjs";
import { oduncVer } from "./odunc.mjs";
for (const [kitapNo, uyeNo, gun] of [[1, 4, 3], [2, 5, 0]]) {
  try {
    const s = oduncVer(kitapNo, uyeNo, gun);
    console.log(`odunc verildi: kitap ${kitapNo} -> uye ${uyeNo}, ucret ${s.tutar}, ileti ${s.ileti}`);
  } catch (h) { console.log(`basarisiz (uye ${uyeNo}):`, h.message); }
}
```

```sh
node uygulama.mjs
```

```
  bildirim -> Emre: kitap 1 odunc verildi
odunc verildi: kitap 1 -> uye 4, ucret 6, ileti 8
basarisiz (uye 5): odunc siniri asildi
```

Birinci ölçü ileti sayısıdır: bir ödünç iş akışı **8 ileti** üretti. Birinci derste aynı iş
akışı 6 yerel çağrıyla yürüyordu. Fark iki yerden geliyor. Bildirim birimi artık üyenin adını
almak için ayrı bir ileti gönderiyor; ödünç birimi de `uygunMu` gibi bir davranış çağırmak
yerine kanonik kaydı çekip kuralı kendisi uyguluyor. Ortak model konuşmayı **davranıştan
veriye** kaydırdı.

## Ortak Modele Bağlı Birim

Bağlaşımın ölçüsü, kanonik alan adlarına kaç birimden atıf yapıldığıdır.

```js
// bagalasim.mjs — ortak modeldeki alan adlarina hangi birimden atif var
import { readdirSync, readFileSync } from "node:fs";
import { UYE_ALANLARI } from "./ortak/sozlesme.mjs";
const disarida = ["bagalasim.mjs", "uygulama.mjs", "yol.mjs"];
const birimler = readdirSync(".").filter((a) => a.endsWith(".mjs") && disarida.includes(a) === false);
let bagli = 0;
for (const b of birimler.sort()) {
  const metin = readFileSync(b, "utf8");
  const bulunan = UYE_ALANLARI.filter((a) => new RegExp(`\\b${a}\\b`).test(metin));
  if (bulunan.length > 0) bagli += 1;
  console.log(`${b.padEnd(20)} kanonik alan atfi: ${bulunan.join(", ") || "(yok)"}`);
}
console.log(`birim: ${birimler.length}   ortak modele bagli birim: ${bagli}`);
```

```sh
node bagalasim.mjs
```

```
bildirim.mjs         kanonik alan atfi: uyeNo, ad
katalog.mjs          kanonik alan atfi: (yok)
odunc.mjs            kanonik alan atfi: uyeNo, acikOdunc, sinir
ucretlendirme.mjs    kanonik alan atfi: (yok)
uyelik.mjs           kanonik alan atfi: uyeNo, ad, acikOdunc, sinir, borc
birim: 5   ortak modele bagli birim: 3
```

Beş birimin üçü kanonik üye kaydının alan adlarını biliyor. Önceki derste bu sayı birdi:
`acik` alanını yalnız üyelik alanı tanıyordu, ödünç ona `uygunMu` diye soruyordu. Ortak
model, kaydın iç yapısını üç birime yaydı.

Buradaki ayrım şudur: `bildirim.mjs` ile `odunc.mjs` üye kaydına **sahip değil**, ama onun
biçimine bağlı. Veri sahipliği üyelik biriminde, veri bilgisi üç yerde.

## Ortak Katmanın Değişmesi

Kanonik modelin bir alanı yeniden adlandırılsın. Değişikliği ortak katmanda ve alanın
sahibinde yapmak yeterli görünür.

```sh
# degistir.sh — kanonik alan adi degisir; yalniz ortak katman ve alanin sahibi guncellenir
sed -i.y 's/acikOdunc/acikOduncSayisi/g' ortak/sozlesme.mjs uyelik.mjs
rm -f ortak/sozlesme.mjs.y uyelik.mjs.y
echo "dokunulan dosya: 2"
node uygulama.mjs
```

```
dokunulan dosya: 2
  bildirim -> Emre: kitap 1 odunc verildi
odunc verildi: kitap 1 -> uye 4, ucret 6, ileti 8
  bildirim -> Selin: kitap 2 odunc verildi
odunc verildi: kitap 2 -> uye 5, ucret 0, ileti 15
```

İkinci istek geçti. Üye 5 sınırındaydı ve bir önceki koşumda reddedilmişti; şimdi ödünç
aldı. Hiçbir hata basılmadı, hiçbir yerde bir uyarı çıkmadı.

Sebep ödünç birimindeki tek satırdır: `uye.acikOdunc` artık `undefined` döndürüyor ve
`undefined >= 3` karşılaştırması `false` veriyor, yani sınır denetimi her zaman geçiyor.
Ortak modeldeki bir ad değişikliği, tüketicide **hata değil yanlış davranış** üretti.

Düzeltme, aynı değişikliğin tüketici birime de taşınmasıdır.

```sh
# duzelt.sh — ayni degisiklik tuketici birime de tasinir
sed -i.y 's/acikOdunc/acikOduncSayisi/g' odunc.mjs
rm -f odunc.mjs.y
echo "dokunulan dosya: 3 (ortak/sozlesme.mjs, uyelik.mjs, odunc.mjs)"
node uygulama.mjs
```

```
dokunulan dosya: 3 (ortak/sozlesme.mjs, uyelik.mjs, odunc.mjs)
  bildirim -> Emre: kitap 1 odunc verildi
odunc verildi: kitap 1 -> uye 4, ucret 6, ileti 8
basarisiz (uye 5): odunc siniri asildi
```

Ölçü şudur: ortak katmandaki bir alan adı değişikliği **3 dosyaya** dokundu ve bu üç dosya
birlikte yayına çıkmak zorunda. Birimler ayrı ayrı tanıtılmış olsa da, kanonik model onları
tek bir sürüm adımına bağlıyor. Yerinde düzenlemede `-i` seçeneği GNU ve BSD sürümlerinde
farklı davrandığı için yedek uzantısı verilip yedek silinmiştir.

## Üç Sütun

| | Servis yönelimli mimari |
|---|---|
| Ucuzlattığı | Birimler birbirini ithal etmiyor; yeni bir birim eklemek yalnız bir işlem adı tanıtmakla oluyor, mevcut birimlerin hiçbiri değişmiyor |
| Pahalılaştırdığı | Ortak modele bağlı birim 1'den 3'e çıktı; kanonik bir alan adı değişikliği 3 dosyayı birlikte yayına zorluyor; iş akışı 6 çağrı yerine 8 ileti üretiyor |
| Doğan arıza kipi | Ortak modelin sahibi güncellenip tüketicisi güncellenmediğinde hata alınmıyor; sınır denetimi sessizce devre dışı kalıyor |

Üçüncü sütun bu dersin asıl kazancıdır. Ortak katman bir bağlaşım noktasıdır ve o noktadan
gelen kusurlar çoğunlukla çökme değil, **sessiz yanlış davranış** biçiminde görünür. Ödünç
birimi çalıştı, cevap döndürdü, kayıt yazdı; yalnız uygulamadığı bir kural vardı.

## Özet

- Servis yönelimli düzende birimler birbirini ithal etmiyor, ortak bir yol üzerinden işlem
  adıyla konuşuyor; yeni birim eklemek mevcut birimleri değiştirmiyor.
- Ortak kanonik model konuşmayı davranıştan veriye kaydırdı: iş akışı 6 yerel çağrı yerine
  8 ileti üretti, çünkü tüketiciler kaydı çekip kuralı kendileri uyguluyor.
- Kanonik alan adlarını bilen birim sayısı 1'den 3'e çıktı; veri sahipliği tek birimde
  kalırken veri bilgisi üçe yayıldı.
- Ortak katmandaki bir alan adı değişikliği 3 dosyaya dokundu ve üçünü tek bir sürüm adımına
  bağladı.
- Sahibi güncellenip tüketicisi güncellenmediğinde sistem hata vermedi; sınırındaki üyeye
  ödünç verildi. Ortak model kusurları sessiz yanlış davranış olarak üretiyor.

## Sonraki Adım

Bu düzende birimler ayrıldı, ama ayrılmanın bedeli hâlâ ödenmedi: hepsi aynı süreçte
koşuyor, `gonder` bir işlev çağrısı, ileti bir nesne. Bir birim çökerse hepsi çöker, bir
birim yeniden yayına çıkarsa hepsi çıkar. Sonraki ders aynı iş akışını **gerçekten ayrı
süreçlere** böler: her birim kendi bağlantı noktasında dinler, iletiler ağ üzerinden gider.
Ölçülecek şeyler süreç sayısı, uç sayısı, istek başına ağ atlaması, zincir gecikmesi, bir
değişikliğin dokunduğu dağıtım birimi ve sistemi ayağa kaldırma adımıdır.
