---
title: 'Derleyici Tabanlı Yaklaşımlar'
source: 'https://academia.sh/tr/kurslar/bilesen-tabanli-gelistirme/derleyici-tabanli-yaklasimlar'
course: 'Bileşen Tabanlı Arayüz Geliştirme'
language: tr
updated: '2026-08-17T18:09:13+00:00'
license: 'CC BY-SA 4.0'
---

# Derleyici Tabanlı Yaklaşımlar

Bağımlılıkların derleme zamanında çözülmesi; şablonu güncelleme koduna çeviren küçük bir dönüştürücü, üretilen kodun okunması, çözümlemenin sağlamlık sınırı ve derleme adımının bedeli.

Önceki iki aile de defterini çalışma zamanında tutuyordu: biri ağacı karşılaştırarak,
diğeri abonelikleri kaydederek. İkisinin de indirilen kodda bir karşılığı vardı.

Oysa hangi ifadenin hangi değere bağlı olduğu, çoğu durumda kaynak metne bakarak
anlaşılabilir. Bir şablonda bir metin düğümünün hangi değişkeni okuduğu yazılıdır. Bunu
kod çalışmadan önce çıkarabilen bir araç, çalışma zamanına yalnızca "şu değer değişirse şu
yeri yaz" biçiminde doğrudan kod bırakabilir.

## Bağımlılık Kaynak Metinde Yazılıdır

Bilgisayarlar Nasıl Çalışır kursundaki Derleme Aşamaları dersinde kurulan zincir burada
küçük ölçekte tekrarlanır: sözcüksel çözümleme, ağaç kurma, çözümleme ve kod üretimi. Girdi
bir şablon, çıktı çalıştırılabilir güncelleme kodudur.

Ayrım şuradadır: önceki iki ailede çerçeve, uygulamanın **verisini** yorumlar; bu ailede
araç, uygulamanın **kaynak metnini** yorumlar. Yorumlama bir kez, derleme sırasında yapılır
ve sonucu bir daha değişmez.

Aşağıdaki dönüştürücü bunu en yalın biçimde kurar. Şablonu durağan parçalara ve ifade
yuvalarına böler, her ifadenin okuduğu durum alanlarını bulur ve alan başına yalnızca o
alandan etkilenen yuvaları yazan bir işlev üretir.

```js
// derleyici.mjs — sablonu derleme zamaninda cozup guncelleme kodu ureten donusturucu
const DURUM_ALANLARI = ["ad", "deger", "damga", "esikAsildi"];

const SABLON = `<tr class="satir {esikAsildi ? 'uyari' : 'olagan'}">
  <th scope="row">{ad}</th>
  <td class="deger">{deger.toFixed(1)} °C</td>
  <td class="damga">{esikAsildi ? damga : '—'}</td>
</tr>`;

// 1) Ayristirma: sablon, duragan parcalara ve ifade yuvalarina bolunur.
function ayristir(sablon) {
  const duragan = [];
  const ifadeler = [];
  let son = 0;
  for (const eslesme of sablon.matchAll(/\{([^{}]*)\}/g)) {
    duragan.push(sablon.slice(son, eslesme.index));
    ifadeler.push(eslesme[1].trim());
    son = eslesme.index + eslesme[0].length;
  }
  duragan.push(sablon.slice(son));
  return { duragan, ifadeler };
}

// Dizgi degismezlerini ayirmadan hicbir cozumleme dogru olamaz.
const dizgisiz = (ifade) => ifade.replace(/'[^']*'|"[^"]*"/g, (d) => " ".repeat(d.length));

// 2) Cozumleme: her ifadenin okudugu durum alanlari bulunur.
function cozumle(ifade) {
  const g = dizgisiz(ifade);
  const dinamik = /\[[^\]]*\]/.test(g);                    // durum[degisken] gibi erisim
  const adlar = DURUM_ALANLARI.filter((a) => new RegExp(`(?<![.\\w$])${a}\\b`).test(g));
  return { adlar, dinamik };
}

// 3) Kod uretimi: ifadedeki durum adlari `d.` ile nitelenir.
function nitele(ifade) {
  const g = dizgisiz(ifade);
  let sonuc = "";
  let son = 0;
  const eslesmeler = [];
  for (const a of DURUM_ALANLARI)
    for (const e of g.matchAll(new RegExp(`(?<![.\\w$])${a}\\b`, "g"))) eslesmeler.push({ konum: e.index, uzunluk: a.length });
  eslesmeler.sort((x, y) => x.konum - y.konum);
  for (const e of eslesmeler) {
    sonuc += ifade.slice(son, e.konum) + "d." + ifade.slice(e.konum, e.konum + e.uzunluk);
    son = e.konum + e.uzunluk;
  }
  return sonuc + ifade.slice(son);
}

function derle(sablon) {
  const { duragan, ifadeler } = ayristir(sablon);
  const cozum = ifadeler.map(cozumle);
  const govdeler = ifadeler.map((ifade, i) => `y[${i}] = String(${nitele(ifade)});`);
  const etkilenen = {};
  for (const alan of DURUM_ALANLARI)
    etkilenen[alan] = cozum.map((c, i) => (c.dinamik || c.adlar.includes(alan) ? i : -1)).filter((i) => i >= 0);

  const kaynak = [
    `const DURAGAN = ${JSON.stringify(duragan)};`,
    `const yuvaYaz = [`,
    ...govdeler.map((g, i) => `  (d, y) => { ${g} },   // yuva ${i}`),
    `];`,
    `const kur = (d) => { const y = []; for (const f of yuvaYaz) f(d, y); return y; };`,
    ...DURUM_ALANLARI.map((a) =>
      `const ${a}Degisti = (d, y) => { ${etkilenen[a].map((i) => `yuvaYaz[${i}](d, y);`).join(" ")} return ${etkilenen[a].length}; };`),
    `const metin = (y) => DURAGAN.reduce((m, s, i) => m + s + (y[i] ?? ""), "");`,
  ].join("\n");

  // Uretilen kodu calistirilabilir hale getir.
  const yuvaYaz = govdeler.map((g) => new Function("d", "y", g));
  const modul = {
    kur: (d) => { const y = []; for (const f of yuvaYaz) f(d, y); return y; },
    metin: (y) => duragan.reduce((m, s, i) => m + s + (y[i] ?? ""), ""),
  };
  for (const a of DURUM_ALANLARI)
    modul[`${a}Degisti`] = (d, y) => { for (const i of etkilenen[a]) yuvaYaz[i](d, y); return etkilenen[a].length; };
  return { kaynak, duragan, ifadeler, cozum, etkilenen, modul };
}

const derlenmis = derle(SABLON);
console.log("--- üretilen kod ---");
console.log(derlenmis.kaynak);

console.log("\n--- ifade / bağımlılık tablosu ---");
derlenmis.ifadeler.forEach((ifade, i) =>
  console.log(`  yuva ${i}: ${ifade.padEnd(32)} → ${JSON.stringify(derlenmis.cozum[i].adlar)}`));
console.log("  alan → etkilenen yuvalar:", JSON.stringify(derlenmis.etkilenen));

const m = derlenmis.modul;
const durum = { ad: "sensör-120", deger: 42.5, damga: "06:00", esikAsildi: true };
const yuvalar = m.kur(durum);
console.log("\nilk çizim:");
console.log(m.metin(yuvalar));

durum.deger = 43.1;
console.log(`\ndeğer değişti → yeniden değerlendirilen ifade: ${m.degerDegisti(durum, yuvalar)}`);
console.log(m.metin(yuvalar));

durum.esikAsildi = false;
console.log(`\neşik durumu değişti → yeniden değerlendirilen ifade: ${m.esikAsildiDegisti(durum, yuvalar)}`);
console.log(m.metin(yuvalar));

console.log("\ndeğişen alan     derlenmiş  çözümleme yapmayan çalışma zamanı");
for (const alan of DURUM_ALANLARI)
  console.log(`${alan.padEnd(16)} ${String(derlenmis.etkilenen[alan].length).padStart(9)} ${String(derlenmis.ifadeler.length).padStart(34)}`);

// 4) Cozumlemenin siniri: dinamik erisim butun alanlara bagimlilik uretir.
const belirsiz = derle(`<td>{deger[ad]}</td>`);
console.log("\ndinamik erişimli şablon:");
console.log("  ifade:", belirsiz.ifadeler[0], "| dinamik:", belirsiz.cozum[0].dinamik);
console.log("  alan → etkilenen yuvalar:", JSON.stringify(belirsiz.etkilenen));
```

```
--- üretilen kod ---
const DURAGAN = ["<tr class=\"satir ","\">\n  <th scope=\"row\">","</th>\n  <td class=\"deger\">"," °C</td>\n  <td class=\"damga\">","</td>\n</tr>"];
const yuvaYaz = [
  (d, y) => { y[0] = String(d.esikAsildi ? 'uyari' : 'olagan'); },   // yuva 0
  (d, y) => { y[1] = String(d.ad); },   // yuva 1
  (d, y) => { y[2] = String(d.deger.toFixed(1)); },   // yuva 2
  (d, y) => { y[3] = String(d.esikAsildi ? d.damga : '—'); },   // yuva 3
];
const kur = (d) => { const y = []; for (const f of yuvaYaz) f(d, y); return y; };
const adDegisti = (d, y) => { yuvaYaz[1](d, y); return 1; };
const degerDegisti = (d, y) => { yuvaYaz[2](d, y); return 1; };
const damgaDegisti = (d, y) => { yuvaYaz[3](d, y); return 1; };
const esikAsildiDegisti = (d, y) => { yuvaYaz[0](d, y); yuvaYaz[3](d, y); return 2; };
const metin = (y) => DURAGAN.reduce((m, s, i) => m + s + (y[i] ?? ""), "");

--- ifade / bağımlılık tablosu ---
  yuva 0: esikAsildi ? 'uyari' : 'olagan'  → ["esikAsildi"]
  yuva 1: ad                               → ["ad"]
  yuva 2: deger.toFixed(1)                 → ["deger"]
  yuva 3: esikAsildi ? damga : '—'         → ["damga","esikAsildi"]
  alan → etkilenen yuvalar: {"ad":[1],"deger":[2],"damga":[3],"esikAsildi":[0,3]}

ilk çizim:
<tr class="satir uyari">
  <th scope="row">sensör-120</th>
  <td class="deger">42.5 °C</td>
  <td class="damga">06:00</td>
</tr>

değer değişti → yeniden değerlendirilen ifade: 1
<tr class="satir uyari">
  <th scope="row">sensör-120</th>
  <td class="deger">43.1 °C</td>
  <td class="damga">06:00</td>
</tr>

eşik durumu değişti → yeniden değerlendirilen ifade: 2
<tr class="satir olagan">
  <th scope="row">sensör-120</th>
  <td class="deger">43.1 °C</td>
  <td class="damga">—</td>
</tr>

değişen alan     derlenmiş  çözümleme yapmayan çalışma zamanı
ad                       1                                  4
deger                    1                                  4
damga                    1                                  4
esikAsildi               2                                  4

dinamik erişimli şablon:
  ifade: deger[ad] | dinamik: true
  alan → etkilenen yuvalar: {"ad":[0],"deger":[0],"damga":[0],"esikAsildi":[0]}
```

## Üretilen Kodun Okunması

Çıktının ilk bölümü, çalışma zamanına inen şeyin ne olduğunu gösteriyor: dört yuva yazma
işlevi, alan başına bir güncelleme işlevi ve bir metin birleştirici. Fark alma algoritması
yok, abone kümesi yok, ağaç temsili yok. Kod, hangi yerin hangi değişiklikte yazılacağını
**doğrudan** söylüyor.

`esikAsildiDegisti` iki yuvayı birden yazıyor, çünkü eşik durumu hem satırın sınıf adında
hem de damga hücresinde okunuyor. Bu bilgi bağımlılık tablosundan geliyor ve çalışma
zamanında hiçbir hesaba dayanmıyor.

`damgaDegisti` yalnızca üçüncü yuvayı yazıyor. Damga değiştiğinde satırın sınıf adı yeniden
hesaplanmıyor — çünkü sınıf adı damgayı okumuyor. Çözümleme yapmayan bir çalışma zamanı
hangi alan değişirse değişsin dört ifadeyi de yeniden değerlendirirdi; tablo bu farkı
gösteriyor.

Durağan parçaların da ayrılmış olması ikinci bir kazançtır. `<th scope="row">` metni bir
kez üretilir ve bir daha hiçbir güncellemede dokunulmaz. Sanal ağaç ailesinde bu düğüm her
karşılaştırmada gezilir; burada karşılaştırma diye bir adım yoktur.

## Çözümlemenin Sağlamlık Sınırı

Son bölüm yaklaşımın kırılma noktasını gösteriyor. `deger[ad]` ifadesinde okunan alan
kaynak metinden belli değildir; hangi anahtarın kullanılacağı çalışma zamanında belli olur.
Çözümleyici bu durumda **muhafazakâr** davranmak zorundadır: ifadeyi bütün alanlara bağımlı
sayar, böylece hangi alan değişirse değişsin yuva yeniden yazılır.

Bu, derleyici tabanlı yaklaşımın genel kuralıdır. Çıkarım **sağlam** olmalıdır: bir
bağımlılığı kaçırmak, güncellenmeyen bir görünüm demektir ve bu bir başarım sorunu değil,
doğruluk sorunudur. Fazladan bağımlılık eklemek yalnızca gereksiz iş üretir. Belirsizlik
karşısında araç her zaman fazlayı seçer.

Sonuç, dilin bir alt kümesine yönelmedir. Şablon dilleri, ifade sözdizimini bilerek kısıtlar:
sınırlı ifade biçimleri, sınırlı erişim yolları, açıkça bildirilen durum. Kısıt bir eksiklik
değil, çıkarımın çalışabilmesinin koşuludur. Aynı fikir Düzen Sistemleri kursundaki ön
işlemcilerde de vardır — girdi dili ne kadar dar olursa, araç o kadar çok şey söyleyebilir.

Çözümleme aynı zamanda **kullanılmayan** yolları da görür. Bir durum alanı hiçbir ifadede
okunmuyorsa, o alan için üretilen güncelleme işlevi boş kalır; kullanılmayan bileşenler ve
dallar paketten tümüyle çıkarılabilir. Derleme Aşamaları dersindeki ölü kod eleme, burada
uygulama düzeyine taşınır.

## Derleme Adımının Bedeli

Kazançların karşılığı, çalıştırılan kodun yazılan kod olmamasıdır.

Hata ayıklama bunun ilk sonucudur. Kesme noktası konan satır ile çalışan satır ayrıdır;
aradaki bağı kaynak haritası kurar. Tarayıcı ve Web Platformu kursundaki Kaynak Hata Ayıklama
dersinde tanıtılan kaynak haritası bu ailede isteğe bağlı bir kolaylık değil, zorunlu bir
parçadır. Eşleme eksik ya da bozuksa, hata iletisi anlaşılmaz bir konumu gösterir.

İkinci bedel araç zinciri bağımlılığıdır. Kod tarayıcıda doğrudan çalışmaz; bir derleme
adımından geçmek zorundadır. Geliştirme sırasında bu adımın hızlı olması gerekir, yoksa her
değişiklikte beklenir. Sürüm yükseltmelerinde de derleyici ile yazılan kaynak metin arasında
uyum gözetilir: aracın sürümü, uygulamanın kaynak metninin bir parçası hâline gelir.

Üçüncü bedel öngörülebilirliktir. Üretilen kod okunabilir olsa bile, yazılan kodun ne
üreteceği her zaman apaçık değildir. Bir ifadeyi bir yardımcı işleve taşımak, çözümleyicinin
bağımlılığı görmesini engelleyip muhafazakâr moda düşürebilir; sonuç, hiçbir hata vermeden
artan bir iş miktarıdır. Bu ailede başarım sorunlarının tanısı, üretilen kodun okunmasını
gerektirir.

## Ailenin Profili

Güncelleme birimi, derleme zamanında belirlenmiş tek bir yazma işlemidir. Çalışma zamanı
kodu, uygulamanın karmaşıklığıyla değil, kullanılan özelliklerle orantılıdır; genel amaçlı
bir güncelleme düzeneği taşınmaz.

Karşılığında bir derleme adımı, bir kaynak haritası zinciri ve girdi dili üzerinde bir
kısıt gelir. Çözümleme sağlam kalmak zorunda olduğu için dinamik yapılar muhafazakâr
bağımlılık üretir; dilin ifade gücü ile çıkarımın keskinliği arasında doğrudan bir ödünleşim
vardır.

Bu aile ile önceki iki aile arasındaki sınır kesin değildir. Bağımlılığı çalışma zamanında
izleyen çerçeveler de şablonlarını derler; sanal ağaç tutan çerçeveler de derleme zamanında
değişmez alt ağaçları işaretleyip karşılaştırmadan çıkarabilir. Ayrım, kararın **nerede**
verildiğinin ağırlığıdır.

## Özet

- Bu ailede hangi ifadenin hangi değere bağlı olduğu, kod çalışmadan önce kaynak metinden
  çıkarılır ve sonuç doğrudan güncelleme kodu olarak üretilir.
- Üretilen kodda fark alma algoritması, abone kümesi ve ağaç temsili yoktur; alan başına
  hangi yuvaların yazılacağı sabittir.
- Durağan parçalar bir kez üretilir ve hiçbir güncellemede gezilmez.
- Çıkarım sağlam olmak zorundadır: dinamik erişim gibi belirsiz durumlarda araç muhafazakâr
  davranıp bütün alanlara bağımlılık üretir.
- Kısıtlı bir girdi dili, keskin çıkarımın koşuludur; kullanılmayan yolların paketten
  çıkarılması da aynı çözümlemeden gelir.
- Bedel, çalıştırılan kodun yazılan kod olmamasıdır: kaynak haritası zorunlu bir parçaya,
  aracın sürümü kaynak metnin bir bağımlılığına dönüşür.

## Sonraki Adım

Üç aile de aynı soruya yanıt veriyordu: durum değiştiğinde belgenin neresi yazılacak. Bir
uygulamanın bileşen katmanının üstünde ise başka sorular var — adresin hangi görünüme
karşılık geldiği, formun doğrulama kurallarını nereden aldığı, bir servisin bileşene nasıl
ulaştığı. Şimdiye kadar ele alınan ailelerde bu soruların yanıtı çerçevenin dışındadır ve
her ekip kendi birleşimini kurar. Bir başka yaklaşım, bu yanıtları çerçevenin kendisiyle
birlikte vermektir. Sonraki ders, yönlendirmeyi, form modelini ve bağımlılık çözümünü tek
bir sözleşmede toplayan çerçeveleri ele alır ve bütünleşikliğin karar yüzeyini nasıl
küçülttüğünü, buna karşılık neyi bağladığını sayarak gösterir.
