---
title: 'Mantıksal Bayrak Parametreleri'
source: 'https://academia.sh/tr/kurslar/temiz-kod/mantiksal-bayrak-parametreleri'
course: 'Temiz Kod'
language: tr
updated: '2026-08-17T18:10:37+00:00'
license: 'CC BY-SA 4.0'
---

# Mantıksal Bayrak Parametreleri

Doğruluk değeri taşıyan parametrelerin bedelinin sınamayla ölçülmesi: iki bayraklı tek fonksiyonun ve bölünmüş iki fonksiyonun dallarını kapsayan sınama sayılarının node --test ile karşılaştırılması, bayrağın gövdede açtığı dallanma sayısı ve çağrı yerindeki opak argümanlar.

Önceki derste imzadan boş değerler ayıklandı. Benzer bir sorun başka bir kılıkta geri
geliyor. Ücretlendirme kitaplığı iade gönderilerini de hesaplıyor ve iki hesap büyük
ölçüde ortak: aynı kademe seçimi, aynı ağırlık, farklı çarpan ve farklı asgari ücret.
Farkı taşımak için imzaya bir doğruluk değeri eklemek akla yakın görünür.

Bir mantıksal bayrak (boolean flag) parametresi, fonksiyonun **iki farklı iş** yaptığını
imzada ilan eder. Bedeli iki yerde ortaya çıkar: gövdede açtığı dallanmalarda ve çağrı
yerinde hiçbir şey söylemeyen argümanda. İkisi de sayılabilir.

## İki Bayraklı Sürüm

Fonksiyon iki bayrak alıyor: gönderinin iade olup olmadığı ve sigortalı olup olmadığı.

```sh
mkdir -p bayrakli bolunmus
```

```js
// bayrakli/ucret.mjs — iade ve sigorta kararlari iki bayrakla tasiniyor
export function ucretHesapla(gonderi, tarife, iade, sigortali) {
  const kademe = tarife.agirlikKademeleri.find((k) => gonderi.agirlikKg <= k.ustSinirKg);
  const temel = kademe.kiloBasiUcret * gonderi.agirlikKg;
  const ucret = iade ? temel * 0.6 : temel;
  const sigorta = sigortali && iade === false ? gonderi.beyanDegeri * 0.01 : 0;
  const asgari = iade ? tarife.asgariIadeUcreti : tarife.asgariUcret;
  return Math.max(ucret + sigorta, asgari);
}
```

Bayrak imzada bir kez geçer, gövdede üç yerde daha karşımıza çıkar: ücret çarpanında,
sigortanın bastırılmasında ve asgari ücret seçiminde.

```sh
tail -n +2 bayrakli/ucret.mjs | grep -c iade
```

```
4
```

Sayı, bayrağın tek bir anahtar olmadığını gösteriyor. `iade` bir açma kapama düğmesi
değil, fonksiyonun gövdesini baştan sona ikiye bölen bir ayrımdır. İkinci bayrak birinciye
bağımlı: sigorta yalnız iade olmayan gönderilerde uygulanıyor, yani `iade === false`
koşulu sigortanın da içine giriyor.

## Bölünmüş Sürüm

İkinci sürümde iki bayrak da kayboluyor. `iade` bayrağı iki ayrı fonksiyona bölünüyor;
`sigortali` bayrağı ise zaten veride bulunan bir bilgiyi tekrar ediyordu — beyan değeri
sıfır olan bir gönderinin sigorta ücreti de sıfırdır.

```js
// bolunmus/ucret.mjs — iki ayri islem, iki ayri fonksiyon
function temelUcret(gonderi, tarife) {
  const kademe = tarife.agirlikKademeleri.find((k) => gonderi.agirlikKg <= k.ustSinirKg);
  return kademe.kiloBasiUcret * gonderi.agirlikKg;
}

export function gonderiUcreti(gonderi, tarife) {
  const sigorta = gonderi.beyanDegeri * 0.01;
  return Math.max(temelUcret(gonderi, tarife) + sigorta, tarife.asgariUcret);
}

export function iadeUcreti(gonderi, tarife) {
  return Math.max(temelUcret(gonderi, tarife) * 0.6, tarife.asgariIadeUcreti);
}
```

"İade gönderisine sigorta uygulanmaz" kuralı artık bir koşul değil, `iadeUcreti`
fonksiyonunun kendisidir. Kuralı bozmak için fonksiyonu değiştirmek gerekir; bayraklı
sürümde bir çağrıda yanlış birleşim geçirmek yetiyordu.

## Sınamayla Ölçüm

İki sürüm de aynı tarifeyle ve aynı iki gönderiyle sınanıyor. Ölçüt sabit: her dalın en az
bir sınamayla geçilmesi. Bayraklı sürümde iki bayrağın dört birleşimi var ve her birleşim
asgari ücretin devrede olduğu ve olmadığı durumda ayrı ayrı sınanmalı.

```js
// tarife.mjs — iki sinamanin paylastigi tarife ve gonderiler
export const TARIFE = {
  agirlikKademeleri: [{ ustSinirKg: 1, kiloBasiUcret: 38 }, { ustSinirKg: 5, kiloBasiUcret: 26 },
    { ustSinirKg: 10, kiloBasiUcret: 21 }, { ustSinirKg: 30, kiloBasiUcret: 17 }],
  asgariUcret: 52,
  asgariIadeUcreti: 40,
};
export const BUYUK = { agirlikKg: 4, beyanDegeri: 2000 };
export const KUCUK = { agirlikKg: 0.5, beyanDegeri: 0 };
```

```js
// test-bayrakli.mjs — iki bayragin dort birlesimi, her birinde asgari ucret siniri
import { test } from "node:test";
import assert from "node:assert/strict";
import { ucretHesapla } from "./bayrakli/ucret.mjs";
import { TARIFE, BUYUK, KUCUK } from "./tarife.mjs";

test("gonderi, sigortasiz, asgari uzeri", () => {
  assert.equal(ucretHesapla(BUYUK, TARIFE, false, false), 104);
});
test("gonderi, sigortasiz, asgari altinda", () => {
  assert.equal(ucretHesapla(KUCUK, TARIFE, false, false), 52);
});
test("gonderi, sigortali, asgari uzeri", () => {
  assert.equal(ucretHesapla(BUYUK, TARIFE, false, true), 124);
});
test("gonderi, sigortali, asgari altinda", () => {
  assert.equal(ucretHesapla(KUCUK, TARIFE, false, true), 52);
});
test("iade, sigortasiz, asgari uzeri", () => {
  assert.equal(ucretHesapla(BUYUK, TARIFE, true, false), 62.4);
});
test("iade, sigortasiz, asgari altinda", () => {
  assert.equal(ucretHesapla(KUCUK, TARIFE, true, false), 40);
});
test("iade, sigortali, sigorta bastirilir", () => {
  assert.equal(ucretHesapla(BUYUK, TARIFE, true, true), 62.4);
});
test("iade, sigortali, asgari altinda", () => {
  assert.equal(ucretHesapla(KUCUK, TARIFE, true, true), 40);
});
```

Bölünmüş sürümde birleşim yok; her fonksiyonun tek bir sınırı var.

```js
// test-bolunmus.mjs — iki fonksiyon, her birinde asgari ucret siniri
import { test } from "node:test";
import assert from "node:assert/strict";
import { gonderiUcreti, iadeUcreti } from "./bolunmus/ucret.mjs";
import { TARIFE, BUYUK, KUCUK } from "./tarife.mjs";

test("gonderi ucreti, asgari uzeri", () => {
  assert.equal(gonderiUcreti(BUYUK, TARIFE), 124);
});
test("gonderi ucreti, asgari altinda", () => {
  assert.equal(gonderiUcreti(KUCUK, TARIFE), 52);
});
test("iade ucreti, asgari uzeri", () => {
  assert.equal(iadeUcreti(BUYUK, TARIFE), 62.4);
});
test("iade ucreti, asgari altinda", () => {
  assert.equal(iadeUcreti(KUCUK, TARIFE), 40);
});
```

Sayım, çalıştırıcının kendi özetinden okunur. Süre alanları çalıştırmadan çalıştırmaya
değiştiği için yalnız sayaç satırları alınıyor.

```sh
for t in test-bayrakli.mjs test-bolunmus.mjs; do
  echo "== $t"
  node --test "$t" 2>&1 | grep -E '(tests|pass|fail) [0-9]+$'
done
```

```
== test-bayrakli.mjs
ℹ tests 8
ℹ pass 8
ℹ fail 0
== test-bolunmus.mjs
ℹ tests 4
ℹ pass 4
ℹ fail 0
```

Sekiz sınamaya karşı dört sınama. İki sürüm aynı dört sonucu (104, 124, 62,4 ve 40 ile
asgari ücret sınırları) üretiyor; fark, bayrakların birleşimlerinin ayrıca sınanmak
zorunda olmasından geliyor.

İkinci ölçüm çağrı yerinde. İlk derste tanımlanan opak argüman ölçütü doğruluk değerleri
için doğrudan geçerlidir: çıplak bir `true` çağrı satırında hangi parametreyi doldurduğunu
söylemez.

```sh
for t in test-bayrakli.mjs test-bolunmus.mjs; do
  echo "$t: $(grep -o 'true\|false' $t | wc -l | tr -d ' ') opak dogruluk argumani"
done
```

```
test-bayrakli.mjs: 16 opak dogruluk argumani
test-bolunmus.mjs: 0 opak dogruluk argumani
```

`ucretHesapla(BUYUK, TARIFE, true, false)` satırını okuyan kişi ikinci `false` değerinin
sigortayı mı yoksa başka bir seçeneği mi kapattığını bilemez; imzayı açmak zorundadır.
`iadeUcreti(BUYUK, TARIFE)` satırında sorulacak bir soru kalmaz.

## Bayrak Sayısı Arttığında

İki bayrak dört birleşim üretti. Üçüncü bir bayrak eklendiğinde birleşim sayısı sekize
çıkar; sınama sayısı da aynı oranda artar. Bölünmüş tasarımda üçüncü bir iş üçüncü bir
fonksiyondur ve toplam iki değil bir artar. Bayraklı imza çarpar, bölünmüş imza toplar.

Bu, önceki derste ölçülen dallanma davranışının aynısıdır: aynı gövdede duran bağımsız
kararlar çarpılır. Bayrak parametresi bu çarpımı fonksiyonun **dışına** taşır; artık
birleşimleri üreten şey gövdedeki koşullar değil, çağıran tarafın geçirdiği değerlerdir.

## Bayrağın Meşru Olduğu Yer

Her doğruluk değeri parametresi kusur değildir. Ayırt edici soru şudur: bayrak
fonksiyonun **ne yaptığını** mı yoksa **nasıl yaptığını** mı değiştiriyor?

`iade` bayrağı ne yapıldığını değiştiriyordu — iki ayrı iş vardı ve ikisi tek imzaya
sıkıştırılmıştı. Buna karşılık bir biçimlendirme fonksiyonuna geçirilen "kuruş kısmını
göster" bayrağı aynı işin bir ayrıntısını belirler; iş tektir. Böyle bir parametre yine de
çağrı yerinde opaktır ve adlandırılmış bir alan olarak geçirildiğinde
(`{ kurusGoster: true }`) opaklık ortadan kalkar.

İkinci ölçüt, bayrağın veriyle çakışıp çakışmadığıdır. `sigortali` bayrağı bunun örneğiydi:
beyan değeri zaten sigortanın uygulanıp uygulanmayacağını söylüyordu. Aynı bilgiyi iki
yerde tutmak, ikisinin ayrı düşmesine izin verir — sigortalı işaretlenmiş ama beyan değeri
sıfır olan bir gönderi tutarsızdır ve bayraklı imza bu tutarsızlığı kabul eder.

## Özet

- Mantıksal bayrak parametresi fonksiyonun iki iş yaptığını ilan eder; bedeli gövdedeki
  dallanmalarda ve çağrı yerindeki opak argümanda ortaya çıkar.
- `iade` bayrağı imzada bir kez geçiyor, dosyada dört satırda görünüyordu: ücret çarpanı,
  sigortanın bastırılması ve asgari ücret seçimi ayrı ayrı ona bağlıydı.
- İki bayrağın dallarını kapsamak sekiz sınama gerektirdi; aynı davranışı iki ayrı
  fonksiyon olarak sınamak dört sınamayla tamamlandı.
- Çağrı yerlerinde on altı opak doğruluk argümanı sıfıra indi; bölünmüş imzalar çağrı
  satırında soru bırakmıyor.
- Bayrak sayısı arttıkça birleşimler çarpılır, ayrı fonksiyonlar toplanır; bayrak yalnız
  işin ne olduğunu değil nasıl yapıldığını belirlediğinde ve veriyle çakışmadığında
  savunulabilir.

## Sonraki Adım

İmza kararları bir fonksiyonun dışarıya ne söylediğini belirliyor. Aynı soru modül
düzeyinde de sorulabilir: bir modül dışarıya kaç ad açıyor? `bolunmus/ucret.mjs`
dosyasında `temelUcret` dışa aktarılmadı, iki ücret fonksiyonu aktarıldı. Bu karar
keyfî değil; dışa açılan her ad, o modülün değiştirilemez yüzeyine eklenen bir maddedir.
Sonraki ders bu yüzeyi ölçer: bir modülün dışa açtığı adların kaçı gerçekten kullanılıyor
ve açılan her ad modülün değişme özgürlüğünü ne kadar daraltıyor.
