---
title: "Gereğinden Karmaşık Bir Sistemin Verdiği Sinyaller"
description: "Kodun veya mimarinin gereksiz karmaşıklaştığını ele veren somut kırmızı çizgiler — ve sadeleştirmeye nereden başlanacağı."
url: https://sade.dev/tr/journal/gereginden-karmasik-sistem-sinyalleri/
lang: tr
author: "Muhammet Şafak"
published: 2026-07-25
updated: 2026-09-06
section: Journal
tags: ["architecture","simplicity","decisions","opinion"]
summary: "Karmaşıklık tek bir kararla gelmez; tek tek savunulabilir adımlarla birikir, bu yüzden sadeleştirme bir hisle değil adı konmuş sinyallerle başlar. Sekiz somut sinyal, ardından dört adımlık bir çıkarma: ölü kod, tek implementasyonlu interface, erken dolaylılık ve en son net sınırlar. Hedef en az kod değil, en az gereksiz kod — özsel karmaşıklık silinmez, yalnızca daha kötü bir yere taşınır."
---

# Gereğinden Karmaşık Bir Sistemin Verdiği Sinyaller

> Karmaşıklık tek bir kararla gelmez; tek tek savunulabilir adımlarla birikir, bu yüzden sadeleştirme bir hisle değil adı konmuş sinyallerle başlar. Sekiz somut sinyal, ardından dört adımlık bir çıkarma: ölü kod, tek implementasyonlu interface, erken dolaylılık ve en son net sınırlar. Hedef en az kod değil, en az gereksiz kod — özsel karmaşıklık silinmez, yalnızca daha kötü bir yere taşınır.

Ekibe yeni katılan bir mühendis ilk haftasının sonunda sordu: "Tek bir alan eklemek neden iki gün sürüyor?" Soru masumdu, teşhis netti. Kimse o sistemi bir gün oturup "karmaşıklaştıralım" diye kararlaştırmamıştı. Karmaşıklık öylece birikmişti.

Sorun da burada: karmaşıklık tek bir kararla gelmez, fark edilmeden birikir. Onu geri almak için önce onu **görebilmek** gerekir.

## Karmaşıklık nasıl birikir?

Hiçbir karmaşık sistem, karmaşık olmaya karar vermez. Her adım tek başına makul görünür: "şimdilik bir interface açalım", "bu duruma bir flag koyalım", "araya bir katman daha". Her biri küçük, her biri savunulabilir.

Toplamları savunulabilir değil. Karmaşıklık bir olay değil, bir birikim — ve birikim, adı konmadığı sürece görünmez. Bu yüzden sadeleştirme bir his ile başlayamaz; somut sinyallerle başlar.

## Somut sinyaller

Bir sistemin gereğinden karmaşık olduğunu söyleyen, tartışmaya kapalı kırmızı çizgiler:

- **Tek bir özelliği anlamak için çok sayıda dosya açıyorsunuz.** Bir isteğin nereye gittiğini görmek altı dosya ve dört dolaylılık gerektiriyorsa, problem sizde değil, yapıdadır.
- **Tek satırlık bir değişiklik bir düzine dosyaya dokunuyor.** Bir alan eklemek için migration, model, DTO, mapper, interface, factory, test fixture... Değişimin maliyeti, değişimin büyüklüğüyle orantılı değil.
- **Tek implementasyonlu interface'ler.** "İhtimale karşı" açılmış, asla ikinci implementasyonu gelmemiş soyutlamalar. Bu, [spekülatif genelliğin](/tr/journal/ileride-lazim-olur-kodunun-faturasi) kod tabanında bıraktığı tortudur.
- **Onboarding haftalar sürüyor.** Olgun ve sade bir sistemde yeni mühendis ilk günlerde üretkendir. Haftalar sürüyorsa, kod kendini anlatmıyordur.
- **Kimse sistemi tahtaya çizemiyor.** "Şu kutu şuraya bağlı" diye anlatılamayan bir mimari, anlaşılmıyor demektir.
- **Test kurulumu testin kendisinden uzun.** Bir davranışı test etmek için kurulması gereken on mock, o davranışın çok fazla şeye bağlı olduğunun itirafıdır.
- **"Oraya dokunma, kırılır."** Bir kod bölgesi dokunulmaz ilan edilmişse, o bölge zaten kırıktır — sadece henüz patlamamıştır.
- **Kimsenin kullanmadığı config, flag ve seçenekler.** Açılıp unutulmuş her seçenek, kodu her okuyanın hesaba katması gereken bir daldır.

Bir sistemde bu sinyallerden ikisi-üçü varsa, tartışma "karmaşık mı" değil, "nereden başlayacağız"dır.

## Sadeleştirmeye nereden başlanır?

Sadeleştirme bir yeniden yazım değildir; çoğu zaman bir **çıkarma** işlemidir. Sırayla:

1. **Ölü kodu sil.** Kullanılmayan flag, çağrılmayan method, ulaşılmayan branch. En düşük riskli, en yüksek getirili adım — silinen kodun bug'ı olmaz.
2. **Tek implementasyonlu interface'leri çökert.** Soyutlama gerçek bir ikinci kullanım kazanana kadar somut sınıfı doğrudan kullanın. Dikiş gerçekten gerektiğinde — [ihtiyaç kanıtlandığında](/tr/journal/ileride-lazim-olur-kodunun-faturasi) — birkaç saatlik bir refactor'la geri gelir.
3. **Erken dolaylılığı satır içine al.** Tek yerden çağrılan, sadece argümanı bir başka fonksiyona geçiren katmanları kaldırın.
4. **Sınırları netleştir.** Geriye kalan karmaşıklığı [modüler monolitteki](/tr/journal/projelere-neden-moduler-monolit-ile-basliyorum) gibi net sınırların arkasına toplayın — böylece bir dahaki birikim erken görünür.

Her adımdan sonra durun ve ölçün. Sadeleştirme de aşırıya kaçabilir; amaç "en az kod" değil, "en az gereksiz kod".

## Karmaşıklık her zaman kötü değil

Önemli bir ayrım: karmaşıklığın iki türü var. Fred Brooks'un kavramlarıyla — **özsel (essential)** ve **tesadüfi (accidental)**.

Özsel karmaşıklık domain'in kendisinden gelir. Vergi hesabı karmaşıktır, çünkü vergi mevzuatı karmaşıktır; bunu silemezsiniz, sadece dürüstçe modelleyebilirsiniz. Tesadüfi karmaşıklık ise sizin eklediğinizdir: gereksiz katman, erken soyutlama, unutulmuş flag.

Sadeleştirmenin hedefi tesadüfi olanı temizlemektir — özsel olanı değil. Bir sistemi "çok basit" yapıp domain'in gerçek karmaşıklığını görmezden gelmek de bir hatadır; o karmaşıklık silinmez, sadece yanlış yere — genelde çağıran kodun içine — taşınır.

İyi mimari, domain ne kadar karmaşıksa o kadar karmaşıktır; daha fazlası değil.

---

Karmaşıklık fark edilmeden birikir; bu yüzden onu fark edilir kılan sinyalleri ezbere bilmek bir mühendislik becerisidir. Sinyali adlandıramıyorsanız, sadeleştirmeye de başlayamazsınız.

Bir sistemi basit tutmak, onu basit kurmaktan daha çok emek ister — ve o emeğe değer.

## Sık sorulanlar

**Gereğinden karmaşık bir sistemle gerçekten zor bir domain nasıl ayırt edilir?**

Baktığınız karmaşıklığın türüne göre. Özsel karmaşıklık domain'den gelir — vergi hesabı karmaşıktır çünkü vergi mevzuatı karmaşıktır — ve yalnızca dürüstçe modellenebilir. Tesadüfi karmaşıklık ise sizin eklediğinizdir: fazladan katman, erken soyutlama, unutulmuş flag. Temizlemeye değer olan yalnızca ikincisidir.

**Sadeleştirmeye nereden başlanır?**

Sırayla: ölü kodu silin, tek implementasyonlu interface'leri çökertin, tek yerden çağrılıp yalnızca argümanı ileten dolaylılığı satır içine alın, sonra geriye kalanı net sınırların arkasına toplayın. Her adımdan sonra durup ölçün — sadeleştirme de aşırıya kaçabilir.

**Tek implementasyonlu bir interface her zaman hata mıdır?**

O, ihtimale karşı açılmış bir soyutlamanın ikinci implementasyonu hiç gelmeyince geride bıraktığı tortudur. Soyutlama gerçek bir ikinci kullanım kazanana kadar somut sınıfı doğrudan kullanın; dikiş gerçekten gerektiğinde birkaç saatlik bir refactor'la geri gelir. Bu, onu yıllarca taşımaktan ucuzdur.


## Kaynaklar

- [No Silver Bullet — Essence and Accidents of Software Engineering (TR86-020): essence, the difficulties inherent in the nature of software, versus accidents, those that attend its production but are not inherent](https://www.cs.unc.edu/techreports/86-020.pdf) — Frederick P. Brooks Jr., University of North Carolina
- [Yagni: the cost of build, delay, carry and repair for a presumptive feature](https://martinfowler.com/bliki/Yagni.html) — Martin Fowler
