---
title: 'Servis Yönelimli Mimari'
source: 'https://academia.sh/tr/kurslar/mimari-bicemler/servis-yonelimli-mimari'
course: 'Mimari Biçemler'
language: tr
updated: '2026-08-17T18:10:36+00:00'
license: 'CC BY-SA 4.0'
---

# Servis Yönelimli Mimari

İki bağlamın kurum çapında paylaşılan tek bir kayıt biçimi ve tek bir çağrı yolu üzerinden konuşması: kanonik kaydın alan sayısının, her servisin taşıdığı ama okumadığı alan sayısının, dönüştürme noktasının ve sınırdan geçen baytın ölçülmesi, dar sözleşmeyle karşılaştırılması ve ortak biçimde bir alan değiştiğinde düzenlenen dosya sayısının sayılması.

Tek parça düzende iki bağlam aynı dağıtım biriminde durduğu için bir dosyalık değişiklik dört
dosyayı yeniden yayınlatıyordu. İlk çözüm denemesi bağlamları birbirinden koparmak değil,
aralarına paylaşılan bir tümleştirme yüzeyi koymaktır. Her bağlam kendi dağıtım birimine çıkar,
ama ikisi de ortak bir kayıt biçimi ve ortak bir çağrı yolu üzerinden konuşur.

**Servis yönelimli mimari** (service-oriented architecture) bu düzeni kurumun tamamı için
kurar: her yetenek kaba taneli bir **servis** olarak yayınlanır, servisler kendi
gerçekleştirimlerini gizler ve aralarındaki alışveriş kurum çapında geçerli tek bir kayıt
biçimi üzerinden yapılır. Buradaki servis, Tasarım Kalıpları kursundaki Servis Katmanı
dersinde ölçülen uygulama içi katmanla aynı sözcüğü paylaşır ama farklı bir şeydir: orada
servis bir uygulamanın iç sınırıydı, burada kendi başına yayınlanan bir dağıtım birimidir.

## Kanonik Kayıt ve Ortak Çağrı Yolu

Biçemin merkezinde **kanonik veri modeli** (canonical data model) durur: iki bağlamın da
kabul ettiği tek bir gönderi kaydı. Kayıt her iki bağlamın ihtiyacını karşılamak zorunda
olduğu için alanları ikisinin birleşimidir.

```js
// ortak/kanonik.mjs — kurum capinda tek gonderi kaydi: her servis ayni bicimi konusur
export const KANONIK_ALAN = [
  "id", "agirlik", "hacim", "bolge", "deger",
  "sozlesmeNo", "sozlesmeOrani", "tasiyiciKodu", "teslimDurumu", "sonZamanDamgasi",
];

export function kanonikYap(g) {
  const k = {};
  for (const a of KANONIK_ALAN) k[a] = g[a] ?? null;
  return k;
}
```

Çağrılar doğrudan servisten servise gitmez, paylaşılan bir yüzeyden geçer. Bu yüzey servisi
adıyla bulur, gövdeyi kanonik biçimde taşır ve geçişleri sayar. Serileştirme burada gerçek:
gövde metne çevrilir, karşı tarafta yeniden okunur.

```js
// veriyolu/veriyolu.mjs — paylasilan tumlestirme yuzeyi: cagriyi kanonik bicimde tasir ve sayar
import { kanonikYap } from "../ortak/kanonik.mjs";

export function veriyolu(kayit) {
  const servisler = new Map();
  return {
    tanit(ad, servis) { servisler.set(ad, servis); },
    cagir(ad, islem, gonderi) {
      const govde = JSON.stringify(kanonikYap(gonderi));
      kayit.gecis.push(`veriyolu -> ${ad}.${islem}`);
      kayit.donusum += 1;
      kayit.bayt += govde.length;
      const sonuc = servisler.get(ad)[islem](JSON.parse(govde));
      const yanit = JSON.stringify(sonuc);
      kayit.gecis.push(`${ad}.${islem} -> veriyolu`);
      kayit.donusum += 1;
      kayit.bayt += yanit.length;
      return JSON.parse(yanit);
    },
  };
}
```

Her servis kanonik kaydı alır, kendi iç biçimine çevirir, işini yapar ve sonucu döndürür.
`OKUNAN_ALAN` listesi servisin kanonik kayıttan gerçekten kullandığı alanları bildirir; ölçüm
bu listeyi kullanır.

```js
// servis/ucret-servisi.mjs — kaba taneli servis: kanonik kaydi alir, kendi bicimine cevirir
const TARIFE = { kademe: [[1, 3000], [5, 4800], [20, 9600]], bolge: { "34": 100, "06": 115, "35": 125 }, asgari: 2500 };
export const OKUNAN_ALAN = ["id", "agirlik", "bolge", "sozlesmeOrani"];

export const ucretServisi = {
  fiyatla(kanonik) {
    const g = { agirlik: kanonik.agirlik, bolge: kanonik.bolge, oran: kanonik.sozlesmeOrani ?? 0 };
    const kademe = TARIFE.kademe.find(([k]) => g.agirlik <= k) ?? [0, 9600];
    const taban = Math.max(TARIFE.asgari, Math.round((kademe[1] * TARIFE.bolge[g.bolge]) / 100));
    return { id: kanonik.id, net: taban - Math.round(taban * Math.min(g.oran, 0.4)) };
  },
};
```

```js
// servis/operasyon-servisi.mjs — kaba taneli servis: ayni kanonik kayittan rota uretir
const AGAC = { "34": ["34"], "06": ["34", "06"], "35": ["34", "41", "35"] };
export const OKUNAN_ALAN = ["id", "bolge", "teslimDurumu"];

export const operasyonServisi = {
  planla(kanonik) {
    const rota = AGAC[kanonik.bolge] ?? ["34"];
    return {
      id: kanonik.id, rota, gun: rota.length,
      tasiyici: rota.length > 2 ? "MT" : "AN",
      durum: kanonik.teslimDurumu ?? "planlandi",
    };
  },
};
```

## Paylaşılan Biçimin Ölçülmesi

Ölçüm dört soru sorar: bir istek kaç sınırdan geçiyor ve kaç dönüştürme noktası taşıyor, her
servis kanonik kaydın kaç alanını gerçekten okuyor, aynı istek servise özel dar bir sözleşmeyle
kaç bayta iner, ortak biçimde bir alan değiştiğinde kaç dosya düzenlenir.

```js
// soa/olc.mjs — kanonik bicimin alan kullanimi, donusum noktasi, bayt ve ortak alan degisiminin etkisi
import { readFileSync } from "node:fs";
import { KANONIK_ALAN, kanonikYap } from "../ortak/kanonik.mjs";
import { veriyolu } from "../veriyolu/veriyolu.mjs";
import { ucretServisi, OKUNAN_ALAN as UCRET_ALAN } from "../servis/ucret-servisi.mjs";
import { operasyonServisi, OKUNAN_ALAN as OPERASYON_ALAN } from "../servis/operasyon-servisi.mjs";

const GONDERI = { id: "G1", agirlik: 4, hacim: 18, bolge: "35", deger: 12000, sozlesmeNo: "S7", sozlesmeOrani: 0.15 };
const kayit = { gecis: [], donusum: 0, bayt: 0 };
const yol = veriyolu(kayit);
yol.tanit("ucret", ucretServisi);
yol.tanit("operasyon", operasyonServisi);

const fiyat = yol.cagir("ucret", "fiyatla", GONDERI);
const plan = yol.cagir("operasyon", "planla", GONDERI);
console.log(`teklif = ${JSON.stringify({ id: fiyat.id, net: fiyat.net, gun: plan.gun, tasiyici: plan.tasiyici })}`);
console.log(`sinir gecisi = ${kayit.gecis.length}, donusum noktasi = ${kayit.donusum}, sinirdan gecen bayt = ${kayit.bayt}`);

console.log(`kanonik alan = ${KANONIK_ALAN.length}`);
for (const [ad, okunan] of [["ucret", UCRET_ALAN], ["operasyon", OPERASYON_ALAN]]) {
  console.log(`  ${ad.padEnd(9)} okudugu alan = ${okunan.length}, tasidigi ama okumadigi alan = ${KANONIK_ALAN.length - okunan.length}`);
}

const dar = (alanlar) => JSON.stringify(Object.fromEntries(alanlar.map((a) => [a, GONDERI[a] ?? null])));
const kanonikBayt = 2 * JSON.stringify(kanonikYap(GONDERI)).length;
const darBayt = dar(UCRET_ALAN).length + dar(OPERASYON_ALAN).length;
console.log(`iki istek govdesi: kanonik = ${kanonikBayt} bayt, servise ozel dar sozlesme = ${darBayt} bayt`);
for (const n of [2, 4, 8]) {
  console.log(`  servis = ${n}: kanonik donusturucu = ${n}, noktadan noktaya donusturucu = ${n * (n - 1)}`);
}

const DOSYA = ["ortak/kanonik.mjs", "veriyolu/veriyolu.mjs", "servis/ucret-servisi.mjs", "servis/operasyon-servisi.mjs"];
for (const alan of ["bolge", "sozlesmeOrani"]) {
  const gecen = DOSYA.filter((d) => readFileSync(d, "utf8").includes(alan));
  console.log(`"${alan}" alani degisirse duzenlenen dosya = ${gecen.length} (${gecen.join(", ")})`);
}
```

```sh
node soa/olc.mjs
```

```
teklif = {"id":"G1","net":5100,"gun":3,"tasiyici":"MT"}
sinir gecisi = 4, donusum noktasi = 4, sinirdan gecen bayt = 427
kanonik alan = 10
  ucret     okudugu alan = 4, tasidigi ama okumadigi alan = 6
  operasyon okudugu alan = 3, tasidigi ama okumadigi alan = 7
iki istek govdesi: kanonik = 326 bayt, servise ozel dar sozlesme = 101 bayt
  servis = 2: kanonik donusturucu = 2, noktadan noktaya donusturucu = 2
  servis = 4: kanonik donusturucu = 4, noktadan noktaya donusturucu = 12
  servis = 8: kanonik donusturucu = 8, noktadan noktaya donusturucu = 56
"bolge" alani degisirse duzenlenen dosya = 3 (ortak/kanonik.mjs, servis/ucret-servisi.mjs, servis/operasyon-servisi.mjs)
"sozlesmeOrani" alani degisirse duzenlenen dosya = 2 (ortak/kanonik.mjs, servis/ucret-servisi.mjs)
```

## Sayıların Okunması

Tek parça derste teklif isteği 4 sınırdan geçiyordu, dönüştürme noktası 0, sınırdan geçen bayt
0'dı. Aynı çıktıyı üreten servis yönelimli düzende sınır geçişi yine 4 ama dönüştürme noktası
4'e, sınırdan geçen bayt 427'ye çıktı. Bu, biçemin ilk faturasıdır: her sınır artık bir
serileştirme noktasıdır ve gövdenin biçimi bir sözleşmedir.

İkinci sayı kümesi kanonik modelin karakteristik maliyetini gösterir. Kayıt 10 alan taşıyor;
ücret servisi bunların 4'ünü okuyor, 6'sını taşıyıp bırakıyor. Operasyon servisi 3'ünü okuyor,
7'sini taşıyıp bırakıyor. Bu boş alanlar yalnız bayt değildir: her biri servisin bilmek zorunda
olmadığı bir kavramı sözleşmesine sokar. `deger` alanının anlamı değiştiğinde operasyon servisi
o alanı hiç okumasa da sözleşmesi değişmiş olur.

Dar sözleşme karşılaştırması bedeli sayıya çeviriyor: aynı iki istek servise özel biçimlerle
101 bayt, kanonik biçimle 326 bayt. Kanonik modelin karşılığını aldığı yer ise dönüştürücü
sayısıdır. İki servis varken iki düzen eşit; sekiz servise çıkıldığında kanonik düzende 8
dönüştürücü, noktadan noktaya düzende 56 dönüştürücü gerekir. Kanonik modelin gerekçesi budur
ve servis sayısı arttıkça güçlenir.

Son iki satır biçemin gerçek sınırını gösterir. Ortak biçimde `bolge` alanı değişirse 3 dosya
düzenlenir ve bunlardan ikisi ayrı dağıtım birimidir: iki servis birlikte yayınlanmak zorunda
kalır. `sozlesmeOrani` değiştiğinde 2 dosya düzenlenir ve yalnız bir servis etkilenir. Yayın
bağlaşımı tek parça düzende olduğu gibi %100 değil, ama sıfır da değil: paylaşılan sözleşmenin
kapsadığı her alan bir bağlaşım noktasıdır.

## Biçemin Yerleştiği Yer

Sayılar bir kalite niteliği ödünleşimini betimliyor. Kazanılan nitelik uyumluluk ve yeniden
kullanımdır: on alanlık tek bir kayıt biçimi öğrenildiğinde kuruma yeni katılan bir servis
mevcut iki servisle konuşmak için 1 dönüştürücü yazar, iki ayrı biçim öğrenmek zorunda kalmaz.
Bırakılan nitelik bağımsız değişebilirliktir: paylaşılan biçimin her alanı, o alanı okumayan
servisleri de yayına bağlar.

Bu yüzden biçemin uygulandığı yer kurum ölçeğidir. İki servis için kanonik model kazanç
getirmez — dönüştürücü sayısı iki düzende de 2, karşılığında istek gövdesi üç katına çıkar.
Servis sayısı arttıkça ve servisler ayrı ekiplere dağıldıkça denge tersine döner: öğrenilecek
biçim sayısı 1'de kalır, dönüştürücü sayısı doğrusal büyür.

## Özet

- Servis yönelimli mimari her yeteneği kaba taneli bir dağıtım birimi olarak yayınlar ve
  alışverişi kurum çapında tek bir kanonik kayıt biçimi üzerinden yürütür.
- Aynı teklif isteği tek parça düzende 0 dönüştürme noktası ve 0 bayt taşırken bu düzende 4
  dönüştürme noktası ve 427 bayt taşıdı.
- On alanlık kanonik kaydın ücret servisi 4, operasyon servisi 3 alanını okudu; taşınıp
  okunmayan alan sayısı 6 ve 7 oldu.
- İki istek dar sözleşmelerle 101 bayt, kanonik biçimle 326 bayt tuttu; kanonik modelin
  karşılığı dönüştürücü sayısıdır: sekiz servis için 8'e karşı 56.
- Ortak biçimde `bolge` alanı değiştiğinde 3 dosya düzenlendi ve iki servis birlikte yayınlanmak
  zorunda kaldı; yayın bağlaşımı %100'den düştü ama sıfırlanmadı.
- Biçem kurum ölçeğinde kazanır: öğrenilecek biçim sayısı 1'de kalırken dönüştürücü sayısı
  servis sayısıyla doğrusal büyür.

## Sonraki Adım

Paylaşılan sözleşme bağlaşımın kaynağı olduğu ortaya çıktı: on alanın hepsi, o alanı okumayan
servisi bile yayına bağlıyor. Bir sonraki adım ortak biçimi kaldırmaktır. Her servis kendi
sözleşmesini, kendi veri biçimini ve kendi yayın takvimini alır; aralarındaki çağrı ortak bir
yüzeyden değil doğrudan geçer. Bu düzen bağımsız yayını gerçekten sağlar ama karşılığında yeni
bir sayı üretir: bir servis durduğunda kaç isteğin yanıtlanmaya devam ettiği. Sonraki ders iki
servisi ayrı yerel süreç olarak çalıştırır, sınır geçişini ve gövde boyutunu ölçer, sonra bir
süreci durdurup ayakta kalan uç sayısını sayar.
