---
title: 'Paketleme ve Şablonlama'
source: 'https://academia.sh/tr/kurslar/orkestrasyon/paketleme-ve-sablonlama'
course: 'Konteyner Orkestrasyonu'
language: tr
updated: '2026-08-17T18:09:09+00:00'
license: 'CC BY-SA 4.0'
---

# Paketleme ve Şablonlama

Aynı uygulama beş ortama önce elle, sonra tek şablonla kurulur; yazılan satır, ortam başına değişen değer ve kopyala-yapıştır sürüklenmesi sayılır. Şablonun kendi bedeli de ölçülür: değişken sayısı, koşullu dal sayısı ve şablonu okuyarak kaç satırın kesin bilinebildiği.

Bir önceki ders güvenlik bağlamını politikaya çevirdi: ayrıcalıklı çalışma, salt okunur kök ve
yetenek kısıtı artık kümenin bildirim kabul ederken dayattığı kurallar. Dayatma çalışıyor, ama
dayatılan şeyi yazan taraf değişmedi. Aynı uygulamanın beş ortama kurulması için aynı nesne kümesi
hâlâ beş kez yazılıyor ve beş kopya arasında yalnız birkaç değer değişiyor.

**Dağıtım paketi**, bir uygulamanın küme üzerinde çalışması için gereken nesnelerin tümüdür: sürüm
nesnesi, servis nesnesi, yapılandırma nesnesi, giriş kuralı, kota. **Şablon**, o paketin ortamdan
bağımsız kısmını bir kez yazıp değişen kısmı dışarı çıkaran metindir. Devredilen karar şudur: her
ortamın nesne kümesinin son hâlini insan yazmayı bırakır, bir üretici yazar. Bu dersin ölçtüğü şey
o devrin bedeli — hem kazandırdığı satır hem de üreticinin kendi getirdiği yük.

Ölçüm yine **bölgesel ölçüm ağı** üzerindedir: su sayacı okumalarını toplayan, doğrulayan ve saha
iş emri açan **kurgu** yazılım. Gerçek küme koşturulmaz; ölçülen şey `node` ile kurulmuş bir
**modeldir** — metin üzerinde çalışan bir şablon motoru ve elle düzenlemenin adım adım taklidi.

**OI31.** Dağıtım paketi beş nesneden oluşur ve on altı satırla temsil edilir.
**OI32.** Beş ortam vardır: geliştirme, sınama, ön-üretim, üretim-batı, üretim-doğu.
**OI33.** Elle yolda taban paket bir kez yazılır, dört kez kopyalanır; kopyalar sonra düzeltilir.
**OI34.** Üç değişiklik turu koşulur; her turda kimin atladığı ya da yanlış yazdığı **önceden
yazılıdır**, rastgelelik yoktur.
**OI35.** Şablon motoru üç işi bilir — değer yerleştirme, koşullu blok, döngü — ve nesne şemasını
**bilmez**.
**OI36.** Şema ders içinde tanımlanır ve yalnız üretilmiş çıktıya uygulanır.

## Beş Ortam, Tek Nesne Kümesi

```js
// veri.mjs — taban nesne kumesi, ortam basina degisen degerler, sablon ve sablon motoru.
export const TABAN = `nesne surum-nesnesi okuma-toplayici
  kopya 3
  imge-etiketi 4.2.0
  istek-cpu 200
  sinir-cpu 500
nesne servis-nesnesi okuma-toplayici
  kapi 8080
nesne yapilandirma-nesnesi toplayici-ayar
  kutuk-duzeyi ozet
  toplu-boyut 500
  dogrulayici-adres dogrulayici.olcum-agi:8080
nesne giris-kurali toplayici-giris
  konak toplayici.on.ic
nesne kota olcum-agi
  cpu-toplam 4000
  bellek-toplam 8192`;                               // on-uretim ortami icin elle yazildi

export const ALAN = ["kopya", "kutuk-duzeyi", "toplu-boyut", "konak", "cpu-toplam",
  "bellek-toplam", "sinir-cpu"];
const HAM = {                                        // ortam: [yedi deger] + acik dallar
  "gelistirme":  [1, "ayrinti", 50, "toplayici.gelistirme.ic", 1000, 2048, 300, []],
  "sinama":      [2, "ozet", 200, "toplayici.sinama.ic", 2000, 4096, 400, ["giris"]],
  "on-uretim":   [3, "ozet", 500, "toplayici.on.ic", 4000, 8192, 500, ["giris"]],
  "uretim-bati": [6, "uyari", 1000, "toplayici.bati.ic", 12000, 24576, 800, ["giris"]],
  "uretim-dogu": [6, "uyari", 1000, "toplayici.dogu.ic", 12000, 24576, 800, ["giris", "yedek"]] };
export const ORTAM = Object.keys(HAM);
export const DEGER = Object.fromEntries(ORTAM.map((o) => [o, Object.fromEntries(
  [...ALAN.map((a, i) => [a, HAM[o][i]]), ...HAM[o][7].map((x) => [x, true])])]));

export const SABLON = `nesne surum-nesnesi okuma-toplayici
  kopya {{kopya}}
  imge-etiketi 4.2.0
  istek-cpu 200
  sinir-cpu {{sinir-cpu}}
nesne servis-nesnesi okuma-toplayici
  kapi 8080
nesne yapilandirma-nesnesi toplayici-ayar
  kutuk-duzeyi {{kutuk-duzeyi}}
  toplu-boyut {{toplu-boyut}}
  dogrulayici-adres dogrulayici.olcum-agi:8080
{{#eger giris}}nesne giris-kurali toplayici-giris
  konak {{konak}}
{{/eger}}{{#eger yedek}}nesne surum-nesnesi okuma-toplayici-yedek
  kopya {{yedek-kopya}}
  imge-etiketi 4.2.0
{{/eger}}nesne kota olcum-agi
  cpu-toplam {{cpu-toplam}}
  bellek-toplam {{bellek-toplam}}
{{#her ek-etiket}}  etiket {{.}}
{{/her}}`;

export const uret = (s, d) => s                      // yerlestirme, kosullu blok, dongu
  .replace(/\{\{#eger ([\w-]+)\}\}([\s\S]*?)\{\{\/eger\}\}/g, (_, a, g) => (d[a] ? g : ""))
  .replace(/\{\{#her ([\w-]+)\}\}([\s\S]*?)\{\{\/her\}\}/g, (_, a, g) =>
    (d[a] ?? []).map((x) => g.replaceAll("{{.}}", x)).join(""))
  .replace(/\{\{([\w-]+)\}\}/g, (_, a) => String(d[a] ?? `<eksik:${a}>`))
  .split("\n").filter((s) => s.trim() !== "").join("\n");
export const satir = (m) => m.split("\n").filter((s) => s.trim() !== "").length;
```

Taban paket ön-üretim ortamı için yazılmıştır ve on altı satırdır. Beş ortam arasında değişen değer
yedi tanedir; geri kalan dokuz satır beş ortamda da birebir aynıdır. Şablon bu ayrımı metne
taşır: yedi değer `{{...}}` ile dışarı çıkar, iki nesne koşullu bloğa girer.

Ayrım burada iki türlü değişkenlik olduğunu gösterir. Birincisi **değer değişkenliğidir** —
kopya sayısı, kütük düzeyi, kota tavanı; nesne kümesi aynı kalır, içindeki sayı değişir. İkincisi
**yapı değişkenliğidir** — geliştirme ortamında giriş kuralı hiç yoktur, üretim-doğuda fazladan
bir sürüm nesnesi vardır; değişen şey değer değil, nesnenin varlığıdır. Değer değişkenliği düz bir
listeyle kapatılır; yapı değişkenliği koşullu dal ister ve dersin sonunda görüleceği gibi bedelin
büyük kısmı oradan gelir.

## Yazılan Satır ve Kopyala-Yapıştır Sürüklenmesi

```js
// olc.mjs — ayni uygulama bes ortama elle ve sablonla kurulur; satir, dokunma, surukleme sayilir.
import { TABAN, SABLON, uret, satir, ALAN, ORTAM, DEGER } from "./veri.mjs";

const ortak = ["imge-etiketi", "istek-cpu", "kapi", "dogrulayici-adres", "hazir-olma-denetimi"];
let yazilan = satir(TABAN), kopyalanan = 0, duzenlenen = 0;
const elle = {};
for (const o of ORTAM) {                             // taban bir kez yazilir, dort kez kopyalanir
  let m = TABAN;
  if (o !== "on-uretim") {
    kopyalanan += satir(TABAN);
    for (const a of ALAN) {
      const y = m.replace(new RegExp(`(  ${a}) .*`), `$1 ${DEGER[o][a]}`);
      if (y !== m) duzenlenen++;
      m = y;
    }
    if (!DEGER[o].giris) { m = m.replace(/nesne giris-kurali.*\n  konak .*\n/, ""); duzenlenen += 2; }
    if (DEGER[o].yedek) { m += "\nnesne surum-nesnesi okuma-toplayici-yedek\n  kopya 6"; duzenlenen += 2; }
  }
  elle[o] = m;
}

const tur = [                            // uc tur; atlama ve yanlis yazma onceden yazilidir
  { f: (m) => m.replace(/(  sinir-cpu .*)/, "$1\n  hazir-olma-denetimi /saglik"), atla: "uretim-dogu" },
  { f: (m) => m.replaceAll(/(  imge-etiketi) .*/g, "$1 4.3.0"), atla: "sinama" },
  { f: (m) => m.replace(/(  istek-cpu) .*/, "$1 250"),
    yanlis: { "on-uretim": (m) => m.replace(/(  istek-cpu) .*/, "$1 300") } }];
let sablon = SABLON, sDuzenlenen = 0;
for (const t of tur) {
  for (const o of ORTAM) {
    if (t.atla === o) continue;
    elle[o] = (t.yanlis?.[o] ?? t.f)(elle[o]);
    duzenlenen++;
  }
  sablon = t.f(sablon);                              // sablon yolunda ayni tur tek dokunus
  sDuzenlenen++;
}
const uretilen = Object.fromEntries(ORTAM.map((o) => [o, uret(sablon, DEGER[o])]));

const ayrisma = (kume) => {                          // ortak alanlarda cogunluktan sapan kopyalar
  const sapan = {};
  let alan = 0;
  for (const a of ortak) {
    const d = ORTAM.map((o) => (kume[o].match(new RegExp(`  ${a} (.*)`)) ?? [, "-"])[1]);
    const cok = d.map((v) => [v, d.filter((x) => x === v).length]).sort((x, y) => y[1] - x[1])[0][0];
    ORTAM.forEach((o, i) => { if (d[i] !== cok) { alan++; (sapan[o] ??= []).push(a); } });
  }
  return { kopya: Object.keys(sapan).length, alan, sapan };
};
const e = ayrisma(elle), s = ayrisma(uretilen);
console.log(`elle yol   : yazilan ${yazilan}  kopyalanan ${kopyalanan}  elle duzenlenen ${duzenlenen}` +
  `  depodaki satir ${ORTAM.map((o) => satir(elle[o])).reduce((a, b) => a + b)}`);
console.log(`sablon yolu: yazilan ${satir(SABLON)}  deger satiri ${ORTAM.length}` +
  `  elle duzenlenen ${sDuzenlenen}  depodaki satir ${satir(SABLON) + ORTAM.length}`);
console.log(`ortam basina degisen deger ${ALAN.length}   ortak kalmasi gereken alan ${ortak.length}`);
console.log(`suruklenme (elle)  : ${e.kopya}/5 kopya ayrismis, ${e.alan} alan`);
for (const [o, a] of Object.entries(e.sapan)) console.log(`    ${o.padEnd(12)} ${a.join(", ")}`);
console.log(`suruklenme (sablon): ${s.kopya}/5 kopya ayrismis, ${s.alan} alan`);
```

```
elle yol   : yazilan 16  kopyalanan 64  elle duzenlenen 44  depodaki satir 84
sablon yolu: yazilan 21  deger satiri 5  elle duzenlenen 3  depodaki satir 26
ortam basina degisen deger 7   ortak kalmasi gereken alan 5
suruklenme (elle)  : 3/5 kopya ayrismis, 3 alan
    sinama       imge-etiketi
    on-uretim    istek-cpu
    uretim-dogu  hazir-olma-denetimi
suruklenme (sablon): 0/5 kopya ayrismis, 0 alan
```

Elle yolda depoda seksen dört satır durur ve bunların altmış dördü kopyadır. Asıl sayı kopya değil,
**elle düzenlenen kırk dört satırdır**: otuz biri ilk kuruluşta, on üçü üç değişiklik turunda.
Şablon yolunda aynı iş yirmi bir satırlık bir şablon, beş satırlık değer listesi ve üç turda üç
dokunuşla biter. Depodaki satır oranı üçe bir; değişiklik turlarındaki dokunuş oranı on üçe üç.

Sürüklenme bu oranın nedenini gösterir. Beş kopyanın ortak kalması gereken beş alanı vardır ve üç
tur sonunda **üç kopya üç alanda ayrışmıştır**: sınama eski görüntü etiketinde kalmış, ön-üretim
kaynak isteğine 250 yerine 300 yazmış, üretim-doğu hazır olma denetimini hiç almamış. Üçünün de
tek nedeni aynıdır — ortak değerin beş ayrı yerde durması. Ayrışmanın ölçülebilir yanı da burada:
kopyalar ayrışsa bile hiçbiri hata vermez, çünkü her biri kendi başına geçerli bir pakettir.
Şablon yolunda aynı üç tur sıfır ayrışma bırakır; ortak değer tek yerde durduğu için atlanacak bir
kopya yoktur.

## Şablonun Kendi Bedeli

```js
// bedel.mjs — sablonun kendi bedeli: degisken, kosullu dal, okunabilirlik, sema kusuru.
import { SABLON, uret, ORTAM, DEGER } from "./veri.mjs";

const degisken = new Set([...SABLON.matchAll(/\{\{([\w-]+)\}\}/g)].map((m) => m[1]));
const dal = [...SABLON.matchAll(/\{\{#(?:eger|her) ([\w-]+)\}\}/g)].map((m) => m[1]);
const bicim = new Set(ORTAM.map((o) => dal.map((a) => (DEGER[o][a] ? 1 : 0)).join("")));
const im = SABLON.replace(/\{\{#(?:eger|her) [\w-]+\}\}([\s\S]*?)\{\{\/(?:eger|her)\}\}/g,
  (_, g) => g.split("\n").map((s) => (s.trim() ? "@" + s : s)).join("\n"));
const sS = im.split("\n").filter((s) => s.trim()), kosullu = sS.filter((s) => s.startsWith("@")).length;
console.log(`sablon ${sS.length} satir  degisken ${degisken.size}  kosullu dal ${dal.length}` +
  `  uretilebilir bicim ${2 ** dal.length}  bes ortamda kullanilan ${bicim.size}`);
console.log(`sablonu okuyarak kesin bilinen satir ${sS.length - kosullu}/${sS.length};` +
  ` ${kosullu} satir icin uretim gerekir`);

const SEMA = { kopya: "sayi", "imge-etiketi": "metin", "istek-cpu": "sayi", "sinir-cpu": "sayi",
  kapi: "sayi", "kutuk-duzeyi": "metin", "toplu-boyut": "sayi", "dogrulayici-adres": "metin",
  konak: "metin", "cpu-toplam": "sayi", "bellek-toplam": "sayi", etiket: "metin" };
const denetle = (m) => m.split("\n").filter((s) => s.startsWith("  ")).flatMap((s) => {
  const [a, d] = s.trim().split(/ (.+)/);            // sema motorun disindadir, ciktiya uygulanir
  if (!(a in SEMA)) return [`bilinmeyen alan ${a}`];
  if (d?.startsWith("<eksik:")) return [`${a} = ${d}`];
  return SEMA[a] === "sayi" && !/^\d+$/.test(d ?? "") ? [`${a} sayi degil`] : [];
});
let kusur = 0, olu = 0;
for (const o of ORTAM) {
  const c = uret(SABLON, DEGER[o]), h = denetle(c);
  kusur += h.length;
  if (h.length) console.log(`  ${o.padEnd(12)} uretildi, sema kusuru: ${h.join("; ")}`);
  if (!c.includes(String(DEGER[o].konak))) olu++;
}
console.log(`motorun yakaladigi ${0}/${kusur}   uretim sonrasi sema denetimi ${kusur}/${kusur}` +
  `   olu deger ${olu}   hic uretilmemis bicim ${2 ** dal.length - bicim.size}`);
```

```
sablon 20 satir  degisken 8  kosullu dal 3  uretilebilir bicim 8  bes ortamda kullanilan 3
sablonu okuyarak kesin bilinen satir 14/20; 6 satir icin uretim gerekir
  uretim-dogu  uretildi, sema kusuru: kopya = <eksik:yedek-kopya>
motorun yakaladigi 0/1   uretim sonrasi sema denetimi 1/1   olu deger 1   hic uretilmemis bicim 5
```

Şablonun bedeli üç sayıda toplanır. Birincisi **değişken sayısıdır**: sekiz değişken, yedisi değer
listesinde tanımlı, biri hiçbir yerde tanımlı değil. İkincisi **koşullu dal sayısıdır**: üç dal,
sekiz üretilebilir biçim, beş ortamda yalnız üçü kullanılıyor — kalan beş biçim şablonda duruyor
ama hiç üretilmiyor, dolayısıyla hiç sınanmıyor.

Üçüncüsü okunabilirliktir ve şu sayıya bağlanır: **yirmi satırlık şablonun on dördü okunarak kesin
bilinir, altısı için üretim gerekir**. Bu altı satır koşullu blokların içindedir; bir ortamın
çıktısında olup olmadıklarına şablona bakarak karar verilemez, değer listesiyle birlikte
üretilmeleri gerekir. Elle yazılan paket bu yükü taşımaz — orada yazılan şey çıktının kendisidir.
Şablon yolunda insan artık çıktıyı değil, **çıktıyı üreten programı** okur.

Sonuncu satır devrin asıl bedelini gösterir. Şablon motoru üç iş bilir ve nesne şemasını bilmez;
`yedek-kopya` değişkeni hiçbir değer listesinde tanımlı olmadığı için üretim-doğu çıktısına
`<eksik:yedek-kopya>` yazar ve **hata vermez**. Motor bu kusurun sıfırını yakalar; üretim sonrası
şema denetimi birini de yakalar. Aynı sessizlik ters yönde de görünür: geliştirme ortamı için
tanımlanmış `konak` değeri hiçbir çıktıda kullanılmaz, çünkü o ortam giriş kuralı dalına girmez —
**ölü değer**, hiçbir yerde uyarı üretmeden değer listesinde durur.

## Devrin Bilançosu

| Ölçü | Elle | Şablonla |
|---|---|---|
| ilk kuruluşta elle düzenlenen satır | 31 | 21 (şablon) + 5 (değer) |
| üç değişiklik turunda elle dokunuş | 13 | 3 |
| depodaki satır | 84 | 26 |
| ortak alanda ayrışan kopya | 3/5 | 0/5 |
| okunarak kesin bilinen satır | 84/84 | 14/20 |
| hiç üretilmemiş biçim | yok | 5 |
| şema kusurunu yakalayan | insan | motor 0, sonradan şema denetimi 1 |

Devredilen karar tek cümleyle yazılır: **her ortamın nesne kümesinin son hâline insan değil bir
üretici karar verir.** Bunun için gereken bilgi kalemleri de sayılıdır — ortam başına yedi değer,
ortam başına açık dal listesi, ve hangi alanın ortak kalması gerektiği. İlk ikisi değer
listesindedir; **üçüncüsü hiçbir yerde yazılı değildir**. Şablon "imge etiketi bütün ortamlarda
aynı olmalı" bilgisini taşımaz; o alan şablonda sabit yazıldığı için ortak kalır. Aynı alan yarın
bir dalın içine taşınırsa ortaklık sessizce biter ve bunu haber verecek bir denetim yoktur.

Bilginin maliyeti de bu tablodan okunur. Yedi değer ortam başına bir kez yazılır ve ortam
eklendikçe doğrusal büyür; dal listesi ortam başına bir satırdır ama şablonun dal sayısını
büyüttüğü anda üretilebilir biçim sayısı ikinin kuvvetiyle artar. Bugünkü üç dal sekiz biçim
demek; dördüncü bir dal eklendiğinde beş ortam yine aynı beş çıktıyı üretir, sınanmayan biçim
sayısı ise beşten on bire çıkar. Şablonun büyümesi değer listesinin büyümesiyle aynı hızda
gitmez.

Kazanç da bedel de aynı yerden çıkar: çıktı artık okunmuyor. Elle yolda seksen dört satırın
seksen dördü okunabilirdi ve kopyalar yine de ayrıştı; şablon yolunda ayrışma sıfır, ama okunan
metin çıktı değil üretici oldu ve üreticinin altı satırı ancak koşturularak biliniyor. Şablon
sürüklenmeyi ortadan kaldırmadı, **sürüklenmenin yerini değiştirdi**: beş kopya arasındaki farktan,
bir üreticinin hiç üretilmemiş beş biçimine taşıdı.

## Özet

- Beş ortam elle kurulduğunda 16 satır yazıldı, 64 satır kopyalandı, 44 satır elle düzenlendi;
  şablonla aynı iş 21 satır şablon, 5 satır değer ve 3 dokunuşla bitti.
- Üç değişiklik turu sonunda elle yolda 5 kopyanın 3'ü, ortak kalması gereken 5 alanın 3'ünde
  ayrıştı; şablon yolunda ayrışma 0 kaldı.
- Şablonun bedeli 8 değişken ve 3 koşullu daldır: 8 üretilebilir biçimin yalnız 3'ü kullanılıyor,
  5'i hiç üretilmiyor ve hiç sınanmıyor.
- Şablonun 20 satırının 14'ü okunarak kesin bilinir, 6'sı için üretim gerekir; insan artık çıktıyı
  değil, çıktıyı üreten programı okur.
- Motor şemayı bilmediği için tanımsız değişkeni `<eksik:...>` diye çıktıya yazdı ve 1 kusurun
  0'ını yakaladı; aynı sessizlik ters yönde 1 ölü değer bıraktı.

## Sonraki Adım

Şablon, var olan nesne türlerinden yeni birleşimler üretir; **yeni bir tür** üretemez. Bölgesel
ölçüm ağının okuma toplama düzeni beş nesnenin hiçbirine tam oturmuyor — sürüm nesnesi, kotası ve
zamanlanmış işi bir arada, tek bir kavram olarak anılması gerekiyor. Bir sonraki ders kümenin
tanıdığı kaynak türlerini genişletir: kurgu bir tür tanımlanır, alanları bir şemaya bağlanır ve
geçersiz bildirimlerin kaç tanesinin kabul anında yakalandığı, kaçının ancak koşumda patladığı
sayılır. Şema büyüdükçe yakalanan hata ile yazım yükünün birlikte nasıl arttığı, ve eski
bildirimlerin yeni şemada kaç alanda kırıldığı da orada ölçülür.
