irdaweb Bilgi Teknolojileri
Telefon numaramız +90 541 209 02 05
E-posta adresimiz [email protected]
Konu 06 · Yazılım & Mimari

Doğru sınırları çizelim, geri kalan kendiliğinden gelir.

Yazılım mimarisi, kararı geri almanın pahalı olduğu kararların toplamıdır — modül sınırları, bağımlılık yönü, eşzamanlılık modeli. Doğru sınır, ekibin altı ay sonraki hızını da belirler. Bu sayfa monolit ile mikroservis ikileminden hexagonal yaklaşıma, olay-güdümlü sistemlerden test stratejisine kadar — kararlarınızı sadeleştirmek için hazırlandı.

01 — Topoloji

Üç topoloji, üç farklı olgunluk dengesi.

Mikroservis bir hedef değil, belirli bir ölçeğe ulaşmış ekiplerin ödediği bedeldir. Çoğu ürün için doğru başlangıç tek dağıtım birimidir; modüler bir monolit, çoğu kez mikroservise geçmeden de aynı bağımsızlığı verir. Sıralama olgunlukla ilerler — sınırlar oturmadan dağıtık sisteme geçmek, basit bir sorunu ağ üzerinde dağıtık bir soruna dönüştürür.

Topoloji · 01 Monolit

Tek süreç, tek dağıtım

Tüm kod tek bir uygulamada koşar; refactor ucuz, transaction'lar basit, dağıtım tek adımdadır. Sınırlar kod düzeyinde gevşekse büyüdükçe modüller birbirine yapışır — "big ball of mud" tehlikesi tek riskidir.

Topoloji · 02 Modüler monolit

Sınırlı modüller, tek dağıtım

Aynı uygulamada koşar ama modüller iyi tanımlı arayüzlerle ayrılır; çapraz çağrılar yalnızca açık API'lerden geçer. Mikroservisin ekip bağımsızlığını, monolitin operasyonel sadeliği ile birleştirir — çoğu ekip için doğru hedef.

Topoloji · 03 Mikroservis

Bağımsız dağıtılan servisler

Her servis ayrı süreç, ayrı veritabanı, ayrı dağıtım. Ekipler bağımsız çalışır; ölçek seçici olur. Bedeli yüksektir: dağıtık izleme, observability, sözleşmeler, eventual consistency — hepsi yeni problem olarak gelir.

Dağıtık monolit anti-örüntüsü. Mikroservislere bölündüğü hâlde servisler birbirine senkron, sıkı bağlıdır; biri durduğunda diğerleri çöker. Tek dağıtım kolaylığını kaybetmiş, mikroservisin bağımsızlığını ise kazanmamış bir kurulumdur. Çözüm yeni servis eklemek değil, sınırları yeniden çizmektir.
02 — Sınırlar

İş kuralı dış dünyaya bağımlı olmamalı.

Hexagonal mimari (ports & adapters) tek bir kural koyar: bağımlılık oku içeri dönüktür. Veritabanı, HTTP, kuyruk, e-posta sağlayıcısı — hepsi adapter'dır; iş kuralları onları tanımayı değil, onların kendine uymasını ister. Bu ters çevirme sayesinde Postgres'i SQLite ile değiştirmek, REST'i gRPC'ye çevirmek ya da bir kuyruğu başkasıyla değiştirmek çekirdeği etkilemez.

Aynı fikir farklı isimlerle de anılır: Clean Architecture, Onion Architecture. Sözcükler değişir, kural aynı kalır — dış katman içe bağlanır, iç katman dışı bilmez.

ports & adapters
# çekirdek, arayüzü tanımlar (port)

interface OrderRepository {
  find(id): Order
  save(order: Order): void
}

# servis, somut teknolojiyi değil arayüzü bilir

class PlaceOrder {
  constructor(private orders: OrderRepository) {}
}

# adapter, dış dünyayı arayüze uydurur

class PostgresOrders implements OrderRepository { … }
class InMemoryOrders implements OrderRepository { … }

# bağımlılık yönü
   adapter  →  port  →  çekirdek   ✓ doğru
   çekirdek →  Postgres'i import eder   ✗ sızıntı
DDD
Sınırı iş diline göre çizin
Domain-driven design'ın bounded context kavramı, "sipariş" kelimesinin satışta ve lojistikte farklı şeyler olabileceğini söyler. Her bağlamın kendi modeli olur; sınırı doğru yere çizmek modüllerin de servislerin de doğal hattını verir.
SoC
İş kuralı & altyapı ayrımı
İndirim hesaplama kuralı veritabanını, e-postayı ya da HTTP'yi bilmemeli. Bu ayrım kuralın yalnız bir bilgisayarda değil bir kuyrukta ya da batch job içinde de aynı şekilde çalışabilmesini sağlar — ve test ucuzlar.
ACL
Yabancı modeli içeri sızdırmayın
Eski sistem ya da üçüncü taraf API ile konuşurken anti-corruption layer, dış modeli kendi diline çevirir. Çekirdek kendi sözcüklerini konuşur; sağlayıcı değiştiğinde yalnız bu katman değişir.
03 — Olaylar

Senkron çağrı yerine olay yayınlamak.

Senkron bir HTTP çağrısı çağrılan tarafın o an çalışmasını şart koşar; biri yavaşsa zincir yavaşlar, biri düşerse zincir kırılır. Olay-güdümlü yaklaşımda gönderici "şu oldu" bilgisini yayınlar ve gerisine karışmaz. Dinleyenler işlerini kendi hızında yapar — ama tutarlılık artık eventual'dir.

Üç ayrım önemli: command "yap" der ve bir tarafa gider; event "oldu" der ve herkese duyurulur; query sorudur, durumu değiştirmez. Bu üç kavramı karıştırmak en yaygın mesajlaşma hatasıdır.

Outbox

İki yazma, tek atom

Hem veritabanına yazıp hem kuyruğa olay göndermek atomik değildir; biri başarısız olursa sistem tutarsız kalır. Outbox örüntüsü, olayı önce aynı transaction'da bir tabloya yazar; ayrı bir süreç onu kuyruğa taşır.

Saga

Dağıtık iş akışı

Servisler arası bir akış (sipariş + ödeme + stok), uzun süreli bir transaction yerine adım adım ilerler; herhangi bir adımda hata olursa daha önceki adımlar telafi edici aksiyonlarla geri alınır.

Idempotent

Aynı mesaj, aynı sonuç

Çoğu kuyruk "en az bir kere" teslim eder; aynı olay iki kez gelebilir. Tüketicinin mesaj kimliğine göre idempotent davranması — aynı mesajı bir kere işlemiş olması — sistemi tutarlı tutar.

domain event
# olay, geçmiş zamandadır — bir komut değil

{
  "type": "OrderPlaced",
  "id":   "7f3c…",
  "at":   "2026-05-21T22:46:19+03:00",
  "data": { orderId: "42", total: 198.00 }
}

# sözleşme kural koyar:
   alan eklemek güvenli     # geriye uyumlu
   alan silmek  kırıcı            # tüketici varsayar
   anlam değişikliği en tehlikeli # sessizce yanlış işler
04 — Test stratejisi

Test, mimarinin aynasıdır.

Hangi katmanda ne kadar test yazdığınız, kodunuzun nasıl tutulduğunu söyler. Çok fazla uçtan uca test yavaş ve kırılgan bir sürüm hattı doğurur; tek başına birim testi ise üretimdeki entegrasyon hatalarını yakalayamaz. Klasik piramidi ile daha yeni test trofesi yaklaşımının vurguları farklıdır — ama amaç aynıdır: güvene en hızlı yoldan ulaşmak.

Birim
Tek fonksiyon
Saf iş kuralları için hızlı ve ucuzdur — çekirdek mantığı yer kaplamadan kapsar. Çok fazla mock'a dayandığında "testi geçti ama üretim çöktü" durumu doğar; kuralı test edin, uygulamayı değil.
Entegrasyon
Modül + bağımlılık
Gerçek bir veritabanı, gerçek bir HTTP istemcisi ile koşan testler. Yavaşlığı kabul edilebilirdir; modüller arasındaki sözleşmeyi en gerçekçi ölçen seviye burasıdır.
Sözleşme
Servisler arası
Tüketici, beklediği API şeklini yazar; üretici bu şekle uyduğunu doğrular. Mikroservislerde uçtan uca testin pahalı yerine alınan en hızlı koruma — Pact gibi araçlar standartlaşmıştır.
Uçtan uca
Tarayıcıdan veritabanına
Birkaç kritik kullanıcı yolculuğu için yeterlidir. Genelde piramidin tepesinde küçük tutulur; trofesi yaklaşımı entegrasyon testini büyütüp uçtan ucayu yine ince tutar.
Kod sahipliği, testin altyapısıdır. Bir modülün net bir sahibi yoksa testin de bir bekçisi yoktur — kırılır, susturulur, unutulur. CODEOWNERS dosyası ile her klasöre net bir gözden geçirici atamak, devir-teslimde "buranın ne yaptığını kimse bilmiyor" çukurunu kapatır. Sahiplik tek bir kişide değil, küçük bir takımda olsun; tek-kişi bağımlılığı operasyonel bir risktir.
05 — Sık karıştırılanlar

Benzer görünen ama ayrı işler yapan kavramlar.

Monolit vs. Modüler monolit

İkisi de tek bir uygulama olarak dağıtılır. Monolit'te modül sınırı çoğunlukla yalnızca klasör adıdır; çapraz çağrılar serbestçe artar. Modüler monolit'te modüller iyi tanımlı API'ler üzerinden konuşur — büyüdüğünde mikroservise geçmek refactor olur, yeniden yazma değil.

Mikroservis vs. Dağıtık monolit

Mikroservis bağımsız dağıtım, ayrı veritabanı ve gevşek bağlantı demektir. Dağıtık monolit servislere bölünmüş ama hâlâ birbirine sıkı bağlı (paylaşılan veritabanı, senkron zincir, ortak sürüm) bir kurulumdur — mikroservisin bedeli ödenmiştir, faydası alınmamıştır.

Hexagonal vs. Clean Architecture

Aynı fikrin iki adıdır: bağımlılık oku içeri dönüktür; çekirdek altyapıyı bilmez, altyapı çekirdeğe uyar. Hexagonal port/adapter sözcüklerini kullanır, Clean halkalı katmanlardan söz eder. Sözcük farkı dışında pratikleri büyük ölçüde örtüşür.

Command vs. Event

Command bir niyet bildirir ("siparişi kapat"); tek bir alıcıya gider, başarısız olabilir. Event olmuş bir gerçeği bildirir ("sipariş kapandı"); birden çok dinleyiciye gider, geri alınamaz. İkisinin de adı geçmiş zaman/emir kipi olarak doğru yazılmalı — "OrderClose" değil "CloseOrder" (komut) ya da "OrderClosed" (olay).

Test piramidi vs. Test trofesi

Piramit tabanda çok birim, tepede az uçtan uca öngörür — birim testin ucuzluğunu öne çıkarır. Trofe entegrasyon testlerini büyütür: gerçek bağımlılıklarla koşan testler, mock ağırlıklı birimden daha gerçekçi güven verir. Modern web uygulamalarında trofe yaklaşımı yaygınlaştı.

Birinci el kaynaklar

Mimari sınırlar, dağıtık sistemler ve test stratejisi üzerine temel kaynaklar.

Sıradaki adım

Mimari kararlarınıza birlikte bakalım.

Mevcut topolojinizi, modül sınırlarınızı ve test stratejinizi masaya yatıralım — sürdürülebilir hızı destekleyen bir yapıyı birlikte planlayalım.