---
title: 'Bağlaşım Türleri'
source: 'https://academia.sh/tr/kurslar/tasarim-ilkeleri/baglasim-turleri'
course: 'Tasarım İlkeleri'
language: tr
updated: '2026-08-17T18:10:40+00:00'
license: 'CC BY-SA 4.0'
---

# Bağlaşım Türleri

İki modül arasındaki bağın gücünün sayılması: paylaşılan ad sayısı, geçilen parametre sayısı ve ortak değiştirilen durum ölçen bir betiğin yazılması, aynı fatura satırını üreten üç tasarımda ölçümlerin karşılaştırılması ve paylaşılan duruma yapılan tek satırlık bir dokunuşun yalnız bir tasarımı bozduğunun gösterilmesi.

SOLID ilkeleri bir birimin kime bağlanacağını söyledi ama bağın kendisini ölçmedi. "Gevşek
bağlı" ile "sıkı bağlı" arasındaki fark, bir tasarım yorumundan çıkarılmak yerine sayılabilir
olmalıdır. Bu konu iki ölçü kurar; ilki modüller **arasındaki** bağa ait.

**Bağlaşım** (coupling) iki modül arasındaki bağın gücüdür. Gücün kaynağı üç yerdedir: bir
modülün diğerinden aldığı **ad sayısı**, çağrılarda **geçirilen parametre sayısı** ve iki
modülün **ortak değiştirdiği durum**. Bağlaşım türleri bu üç ölçünün birleşiminden çıkar ve
klasik sıralaması en güçlüden en zayıfa doğrudur: içerik, ortak, denetim, damga, veri.

| Tür | İngilizce | Belirtisi |
|---|---|---|
| İçerik bağlaşımı | content coupling | Bir modül diğerinin iç adına erişir |
| Ortak bağlaşım | common coupling | İki modül aynı değiştirilebilir durumu paylaşır |
| Denetim bağlaşımı | control coupling | Çağrıya, çağrılanın hangi dalı seçeceğini söyleyen bayrak geçilir |
| Damga bağlaşımı | stamp coupling | Kullanılmayan alanları da olan bütün bir kayıt geçilir |
| Veri bağlaşımı | data coupling | Yalnız gereken sayı ya da dize geçilir |

Güçlü bağlaşım kötü olduğu için değil, **değişikliği yayan yüzeyi büyüttüğü** için sınırlanır.
Aşağıdaki üç tasarım aynı fatura satırını üretir; fark yalnız bu yüzeyin genişliğindedir.

## Aynı Çıktı, Üç Tasarım

Birinci tasarım paylaşılan bir ayar nesnesi üzerinden çalışır. Hesap modülü sonucu hem
döndürür hem paylaşılan duruma yazar; fatura modülü sonucu oradan ve hesabın iç adından
okur.

```sh
mkdir -p ortak damga veri
```

```js
// ortak/ayar.mjs — butun modullerin okuyup yazdigi paylasilan durum
export const AYAR = { bolge: 100, kdv: 20, _son: 0 };
```

```js
// ortak/hesap.mjs — sonucu doner, ama once paylasilan duruma yazar
import { AYAR } from "./ayar.mjs";

export const _KADEME = [[1, 3900], [5, 6400], [20, 11800]];
const BOLGE = { "34": 100, "06": 115, "65": 140 };

export function hesapla(gonderi) {
  AYAR.bolge = BOLGE[gonderi.adres.slice(0, 2)] ?? 160;
  const taban = _KADEME.find(([ust]) => gonderi.agirlik <= ust)?.[1] ?? 15000;
  AYAR._son = Math.round((taban * AYAR.bolge * (100 + AYAR.kdv)) / 10000);
  return AYAR._son;
}
```

```js
// ortak/fatura.mjs — sonucu paylasilan durumdan ve hesabin ic adindan okur
import { AYAR } from "./ayar.mjs";
import { hesapla, _KADEME } from "./hesap.mjs";

export function satir(gonderi) {
  hesapla(gonderi);
  return `${AYAR._son} kurus (${_KADEME.length} kademe)`;
}
```

İkinci tasarımda paylaşılan durum yoktur. Bunun yerine bütün gönderi kaydı ve hesabın hangi
dalı seçeceğini söyleyen bir bayrak geçirilir.

```js
// damga/hesap.mjs — paylasilan durum yok; butun kayit ve bir bayrak gecirilir
const KADEME = [[1, 3900], [5, 6400], [20, 11800]];
const BOLGE = { "34": 100, "06": 115, "65": 140 };

export const kademeSayisi = () => KADEME.length;

export function hesapla(gonderi, kdvEkle) {
  const bolge = BOLGE[gonderi.adres.slice(0, 2)] ?? 160;
  const taban = KADEME.find(([ust]) => gonderi.agirlik <= ust)?.[1] ?? 15000;
  const ham = (taban * bolge) / 100;
  return Math.round(kdvEkle ? (ham * 120) / 100 : ham);
}
```

```js
// damga/fatura.mjs — hesaba butun gonderiyi ve davranisi secen bayragi verir
import { hesapla, kademeSayisi } from "./hesap.mjs";

export const satir = (gonderi) => `${hesapla(gonderi, true)} kurus (${kademeSayisi()} kademe)`;
```

Üçüncü tasarımda hesap adımları ayrı işlevlere bölünür ve her biri yalnız ihtiyaç duyduğu
sayıyı alır. Bayrak, iki ayrı işlev adına dönüşür.

```js
// veri/hesap.mjs — her adim yalniz ihtiyac duydugu sayilari alir
const KADEME = [[1, 3900], [5, 6400], [20, 11800]];

export const kademeSayisi = () => KADEME.length;
export const taban = (agirlik) => KADEME.find(([ust]) => agirlik <= ust)?.[1] ?? 15000;
export const bolgeli = (kurus, katsayi) => (kurus * katsayi) / 100;
export const kdvli = (kurus) => Math.round((kurus * 120) / 100);
```

```js
// veri/fatura.mjs — hesaba yalniz sayi gecer, bayrak yok
import { taban, bolgeli, kdvli, kademeSayisi } from "./hesap.mjs";

const BOLGE = { "34": 100, "06": 115, "65": 140 };

export function satir(gonderi) {
  const katsayi = BOLGE[gonderi.adres.slice(0, 2)] ?? 160;
  return `${kdvli(bolgeli(taban(gonderi.agirlik), katsayi))} kurus (${kademeSayisi()} kademe)`;
}
```

## Ölçer

Aşağıdaki betik bir dizindeki modülleri okur, her ithal deyimi için bir kenar üretir ve o
kenarın üç ölçüsünü hesaplar: alınan ad sayısı, çağrılarda geçirilen en yüksek parametre
sayısı ve ithal edilmiş bir ada yapılan yazma sayısı. Türü bu ölçülerden türetir; bir kenarda
birden çok tür bulunursa en güçlüsü etiket olur.

```js
// baglasim-olc.mjs — iki modul arasindaki bagin uc olcusu ve turu
import { readdirSync, readFileSync } from "node:fs";
import { join } from "node:path";

const ITHAL = /import\s*\{([^}]*)\}\s*from\s*["']\.\/([^"']+)["']/g;
// Butun kayit olarak gecirilen alan nesneleri. Bir cagrida bunlardan biri argumansa damga.
const KAYITLAR = ["gonderi", "tarife", "musteri"];

function cagriArgumanlari(metin, ad) {
  const cagrilar = [];
  for (const m of metin.matchAll(new RegExp(`\\b${ad}\\s*\\(`, "g"))) {
    let i = m.index + m[0].length;
    let derinlik = 1;
    let parca = "";
    const parcalar = [];
    while (i < metin.length && derinlik > 0) {
      const c = metin[i];
      if ("([{".includes(c)) derinlik += 1;
      else if (")]}".includes(c)) derinlik -= 1;
      if (derinlik === 0) break;
      if (c === "," && derinlik === 1) { parcalar.push(parca.trim()); parca = ""; } else parca += c;
      i += 1;
    }
    if (parca.trim() !== "") parcalar.push(parca.trim());
    cagrilar.push(parcalar);
  }
  return cagrilar;
}

const kok = process.argv[2];
const dosyalar = readdirSync(kok).filter((a) => a.endsWith(".mjs")).sort();
const metinler = new Map(dosyalar.map((d) => [d, readFileSync(join(kok, d), "utf8")]));

// Once tum agacta hangi ithal edilmis adlara yazildigini topla: yazilan ad paylasilan durumdur.
const yazilan = new Set();
for (const [, metin] of metinler) {
  for (const m of metin.matchAll(/\b([A-Za-z_]\w*)\.\w+\s*=[^=]/g)) yazilan.add(m[1]);
}

let toplamAd = 0;
let toplamParam = 0;
let toplamYazma = 0;

for (const d of dosyalar) {
  const metin = metinler.get(d);
  for (const m of metin.matchAll(ITHAL)) {
    const adlar = m[1].split(",").map((s) => s.trim()).filter(Boolean);
    const hedef = m[2];
    let param = 0;
    let yazma = 0;
    const turler = new Set();
    for (const ad of adlar) {
      const cagrilar = cagriArgumanlari(metin, ad);
      const arg = cagrilar.flat();
      param += cagrilar.length === 0 ? 0 : Math.max(...cagrilar.map((c) => c.length));
      yazma += [...metin.matchAll(new RegExp(`\\b${ad}\\.\\w+\\s*=[^=]`, "g"))].length;
      if (ad.startsWith("_")) turler.add("icerik");
      if (yazilan.has(ad)) turler.add("ortak");
      if (arg.some((a) => a === "true" || a === "false")) turler.add("denetim");
      if (arg.some((a) => KAYITLAR.includes(a))) turler.add("damga");
    }
    if (turler.size === 0) turler.add("veri");
    const sira = ["icerik", "ortak", "denetim", "damga", "veri"];
    const enGuclu = sira.find((t) => turler.has(t));
    toplamAd += adlar.length;
    toplamParam += param;
    toplamYazma += yazma;
    console.log(`  ${d} -> ${hedef}`.padEnd(30) +
      `ad=${adlar.length} parametre=${param} yazma=${yazma}  tur=${enGuclu}` +
      (turler.size > 1 ? ` (${[...sira.filter((t) => turler.has(t))].join(", ")})` : ""));
  }
}
console.log(`${kok.padEnd(6)} toplam: ad=${toplamAd} parametre=${toplamParam} yazma=${toplamYazma}`);
```

```sh
node baglasim-olc.mjs ortak
node baglasim-olc.mjs damga
node baglasim-olc.mjs veri
```

```
  fatura.mjs -> ayar.mjs      ad=1 parametre=0 yazma=0  tur=ortak
  fatura.mjs -> hesap.mjs     ad=2 parametre=1 yazma=0  tur=icerik (icerik, damga)
  hesap.mjs -> ayar.mjs       ad=1 parametre=0 yazma=2  tur=ortak
ortak  toplam: ad=4 parametre=1 yazma=2
  fatura.mjs -> hesap.mjs     ad=2 parametre=2 yazma=0  tur=denetim (denetim, damga)
damga  toplam: ad=2 parametre=2 yazma=0
  fatura.mjs -> hesap.mjs     ad=4 parametre=4 yazma=0  tur=veri
veri   toplam: ad=4 parametre=4 yazma=0
```

Üç tasarım da aynı satırı üretiyor, ölçüleri farklı. Birinci tasarımda üç kenar var, ikisi
paylaşılan duruma bakıyor ve iki yazma sayıldı. İkinci tasarımda tek kenar kaldı; ad ve
parametre sayısı düşük ama tür denetim bağlaşımı. Üçüncü tasarımda yazma sıfır, tür veri
bağlaşımı, buna karşılık ad sayısı dörde ve parametre sayısı dörde çıktı.

Son satır ölçünün önemli bir yanını gösteriyor: **tür ile büyüklük ayrı şeylerdir**. Üçüncü
tasarım en zayıf bağlaşım türüne sahip, ama en çok adı paylaşan tasarım da o. Bağlaşımı
azaltmak "daha az ad geçir" demek değildir; geçen şeyin ne olduğunu değiştirmektir.

## Değişikliğin Yayılması

Ölçünün karşılığı, ilgisiz bir yerden gelen bir dokunuşta görülür. Aşağıdaki betik üç
tasarımın satırını yazar, sonra yalnız paylaşılan ayar nesnesinin bir alanına dokunur ve
satırları yeniden yazar.

```js
// uzaktan-dokunus.mjs — ilgisiz bir modulun tek satiri uc tasarimi nasil etkiliyor
import { AYAR } from "./ortak/ayar.mjs";
import { satir as ortakSatir } from "./ortak/fatura.mjs";
import { satir as damgaSatir } from "./damga/fatura.mjs";
import { satir as veriSatir } from "./veri/fatura.mjs";

const G = { agirlik: 3.0, adres: "06500" };
const yaz = (etiket) =>
  console.log(`${etiket.padEnd(8)} ortak=${ortakSatir(G)}  damga=${damgaSatir(G)}  veri=${veriSatir(G)}`);

yaz("once");
AYAR.kdv = 0;
yaz("sonra");
```

```sh
node uzaktan-dokunus.mjs
```

```
once     ortak=8832 kurus (3 kademe)  damga=8832 kurus (3 kademe)  veri=8832 kurus (3 kademe)
sonra    ortak=7360 kurus (3 kademe)  damga=8832 kurus (3 kademe)  veri=8832 kurus (3 kademe)
```

Hesap modülüne, fatura modülüne, kademe tablosuna dokunulmadı. Değişen tek şey paylaşılan
nesnenin bir alanı oldu ve birinci tasarımın çıktısı 8832'den 7360'a düştü. Ortak bağlaşımın
ölçülebilir tanımı budur: bir modülün davranışı, onu hiç ithal etmemiş bir modül tarafından
değiştirilebiliyor.

## Türlerin Somut Belirtileri

Denetim bağlaşımının belirtisi bir bayrak parametresidir. `hesapla(gonderi, true)` çağrısını
okuyan biri `true` ne demek diye sormak zorundadır; cevabı çağrılanın gövdesindedir. Bayrak
kaldırıldığında bilgi çağrının kendisine geçer: `kdvli(...)` ile `bolgeli(...)` ayrı adlardır
ve hangisinin çağrıldığı çağrı yerinde okunur.

Damga bağlaşımının belirtisi, çağrılanın aldığı kaydın alanlarından yalnız bir kısmını
kullanmasıdır. `hesapla(gonderi, true)` gönderinin ağırlık ve adres alanlarını kullanır;
kaydın geri kalanı — değer, teslim adresi, hacim — çağrıya girer ve kullanılmaz. Bu, gönderi
kaydına eklenen her yeni alanın hesap modülünün girdi yüzeyini büyütmesi demektir.

İçerik bağlaşımının belirtisi ad kuralıdır: `_KADEME` adı altçizgiyle başlayarak dışarı
verilmemesi gerektiğini söylüyor, ama fatura modülü onu yine de ithal ediyor. Ölçer bunu
yakaladı; kademe tablosunun biçimi değiştiğinde fatura modülü de değişecek.

## Özet

- Bağlaşım iki modül arasındaki bağın gücüdür ve üç ölçüyle sayılır: paylaşılan ad sayısı,
  geçirilen parametre sayısı ve ortak değiştirilen durum.
- Türler en güçlüden en zayıfa içerik, ortak, denetim, damga ve veri bağlaşımıdır; bir kenarda
  birden çoğu bulunabilir, etiket en güçlüsüdür.
- Aynı fatura satırını üreten üç tasarımda ölçüm sırasıyla içerik, denetim ve veri bağlaşımı
  verdi; yazma sayısı 2, 0 ve 0 bulundu.
- Tür ile büyüklük ayrı ölçülerdir: en zayıf türe sahip tasarım aynı zamanda en çok adı (4)
  ve en çok parametreyi (4) paylaşan tasarımdı.
- Paylaşılan nesnenin tek bir alanına yapılan dokunuş yalnız ortak bağlaşımlı tasarımın
  çıktısını 8832'den 7360'a değiştirdi; diğer ikisi etkilenmedi.

## Sonraki Adım

Bağlaşım ölçüsü modüller arasındaki kenarları saydı ve modülün içine hiç bakmadı. Üçüncü
tasarımın hesap modülü dört ad dışa veriyor; bu dört adın birbirine ait olup olmadığı sorusu
ölçünün dışında kaldı. Aynı dosyada duran işlevler ortak bir veriye mi dokunuyor, yoksa yalnız
aynı dosyada oldukları için mi yan yanalar? Sonraki ders modül içindeki işlevleri
dokundukları veri kümesine göre kümeler, düşük ilgililikli bir modülü bölerek ölçümü
tekrarlar ve bölmenin bağlaşım ölçüsünü nasıl etkilediğini sayar.
