Katmanli mimari, yazılım sistemlerini sorumluluk alanlarina gore yatay dilimlere ayiran en yaygın yapisal yaklasimlardan biridir. Sunum, uygulama, domain ve altyapi katmanları gibi isimlendirmeler degisse de temel fikir aynidir: ust katman alt katmana bağımlıdır, tersi degil. Bu kural basit görünür ancak buyuyen kod tabanlarinda sik sik ihlal edilir. Pratikte başarı, katman sinirlarini kod review, bağımlılık kurallari ve modül yapisi ile korumaktan gecer.
Katmanli mimarinin temel ilkeleri
Her katman belirli bir soyutluk seviyesini temsil eder. Sunum katmanı HTTP, CLI veya mesaj formatlarini isler; uygulama katmanı use case orkestrasyonunu yapar; domain katmanı is kurallarini barindirir; altyapi katmanı veritabanı, dosya sistemi ve dis servis adaptasyonlarini sağlar. Katmanlar arasi iletişim genelde arayüzler uzerinden gerçekleşir; somut sınıf referanslari yalnizca kompozisyon noktalarinda kullanılır.
- Tek yonlu bağımlılık: Ust katman alt katmanı bilir, alt katman ust katmanı bilmez.
- Arayüz ile gevsekleme: Altyapi detaylari domain'e sizdirilmaz.
- Ince adaptasyon: Controller veya endpoint yalnizca DTO dönüşümü ve delegasyon yapar.
- Test edilebilirlik: Domain katmanı dis bağımlılık olmadan birim test edilebilir.
Klasik uc katman ve n katman modelleri
Geleneksel uc katman modeli Presentation, Business Logic ve Data Access olarak adlandirilir. Modern .NET ve Java ekosistemlerinde bu model genelde dört veya bes katmana genisler: API, Application, Domain, Infrastructure ve bazen Contracts. Ek katmanlar organizasyonel netlik sağlar ancak her yeni katman gecikme ve mapping maliyeti getirir. Pragmatik kural: katman sayisi ekip buyuklugu ve domain karmasikligi ile orantili olmalidir.
src/
Api/ # HTTP endpoints, auth filters
Application/ # Commands, queries, handlers
Domain/ # Entities, value objects, domain services
Infrastructure/ # EF Core, email, message bus adapters
Katmanlar arasi veri akisi
Tipik bir yazma akisi su sekildedir: istemci JSON gonderir, API katmanı DTO'yu Command'a cevirir, Application handler domain nesnelerini oluşturur veya yukler, domain kurallari uygulanir, Infrastructure kalıcı depolamayi gerceklestirir. Okuma akisinda projection ve read model kullanımı performansi artirir; domain entity'lerinin gereksiz yuklenmesi onlenir.
Bağımlılık yönetimi ve mimari testler
Katman ihlallerini erken yakalamak icin mimari testler kullanılır. NetArchTest, ArchUnit veya custom Roslyn analyzer ile 'Domain katmanı Infrastructure'i referans alamaz' gibi kurallar CI pipeline'inda calistirilir. Bu testler ilk basta katı gelebilir ancak refactor donemlerinde hayat kurtarir.
[Fact]
public void Domain_should_not_reference_Infrastructure()
{
var result = Types.InAssembly(DomainAssembly)
.Should().NotHaveDependencyOn("Infrastructure");
result.ShouldBeSuccessful();
}
DTO, entity ve mapping stratejisi
Katmanli mimaride her katmanin kendi veri sozlesmesi vardir. API DTO'lari, Application command/query nesneleri ve Domain entity'leri birbirinden ayrilmalidir. AutoMapper gibi araclar mapping yukunu azaltir ancak profil yönetimi ve debug zorlugu değerlendirilmelidir. Küçük projelerde manual mapping daha okunabilir olabilir.
- API katmanı: request/response DTO, validation attribute'lari
- Application katmanı: command, query, handler, application service arayuzleri
- Domain katmanı: aggregate root, value object, domain event
- Infrastructure katmanı: persistence model, external API client
Transaction ve tutarlılık sınırları
Bir use case genelde tek bir transaction sınırı olmalidir. Handler basinda transaction acilir, domain kurallari uygulanir, SaveChanges cagrilir ve commit edilir. Birden fazla aggregate guncelleniyorsa eventual consistency veya outbox pattern dusunulmelidir. Katmanli mimari tek basina distributed transaction cozmez; saga veya compensation mekanizmalari ayri tasarlanmalidir.
Unit of Work deseni
Infrastructure katmaninda IUnitOfWork arayüzü Application'a sunulur. Handler birden fazla repository çağrısı yapar ancak commit tek noktada gerçekleşir. Bu desen testlerde mock unit of work ile kolayca simule edilir.
Cross-cutting concern'lerin yeri
Loglama, yetkilendirme, metrik ve cache gibi konular her katmana dagitilmamali; pipeline, middleware veya decorator ile merkezilestirilmelidir. ASP.NET Core'da authorization filter API katmaninda, validation MediatR pipeline'inda, audit Infrastructure interceptor'unda konumlandirilabilir.
- Loglama: Structured log, correlation ID ile tüm katmanlarda.
- Yetkilendirme: Policy bazli, API veya application girisinde.
- Cache: Read-heavy query handler'larda veya decorator ile.
- Exception handling: Merkezi middleware, Problem Details formati.
Katmanli mimari vs hexagonal mimari
Hexagonal (ports and adapters) mimari katmanları dairesel olarak dusunur: domain merkezde, adaptasyonlar disarda. Katmanli mimari yatay dilimler sunar. Pratikte ikisi birbirini dislamaz; Clean Architecture ve DDD projelerinde genelde birlesik bir model kullanılır. Önemli olan terminoloji degil, bağımlılık yonunun korunmasidir.
Ölçeklendirme ve modulerlesme
Tek monolit icinde katmanli yapı yeterli olabilir. Ekip ve kod tabani buyudukce modül sınırları eklenir: her modül kendi Application ve Domain alt katmanlarina sahiptir, ortak Infrastructure paylasilir veya modül bazli ayristirilir. Bu geçiş moduler monolite doğru atilan ilk adimdir.
Anti-pattern'ler
Anemic domain model: entity'ler sadece getter/setter tasir, is mantigi service siniflarina kacar. Smart UI: controller icinde SQL ve is kurallari bir arada. Leaky abstraction: repository arayüzü IQueryable dondurur ve ust katman EF Core detaylarina baglanir. God service: tek application service yuzlerce satir ve onlarca bağımlılık tasir.
Test piramidi ve katman kapsami
Domain katmanı en yüksek birim test yogunluguna sahip olmalidir. Application handler testleri mock repository ile yazilir. API entegrasyon testleri az sayida kritik akislari kapsar. End-to-end testler maliyetli oldugundan sinirli tutulur.
Domain.Tests/ # Pure unit tests, no mocks for domain logic
Application.Tests/ # Handler tests with mocked ports
Api.IntegrationTests/ # WebApplicationFactory, Testcontainers
Performans dusunceleri
Katman sayisi basina ek mapping ve allocation maliyeti vardir. Read-heavy senaryolarda dogrudan read model veya Dapper kullanımı Application katmaninda kabul edilebilir bir istisnadır; ancak bu istisna dokumante edilmeli ve sinirli kalmalidir. Profiling olmadan katman birlestirme yapmak erken optimizasyondur.
Ekip organizasyonu ile hizalama
Katmanlar ekip sorumluluklariyla hizalanabilir: frontend/API ekibi sunum, backend ekibi application ve domain, platform ekibi infrastructure. Code ownership CODEOWNERS dosyasi ile katman bazinda tanimlanir. PR review'da katman ihlali otomatik olarak reddedilir.
Geçiş ve evrim stratejisi
Legacy sistemlerde katmanli yapiya geçiş big bang degil strangler fig pattern ile yapilir. Yeni özellikler yeni katmanlarda geliştirilir, eski kod zamanla izole edilir. Facade arayuzleri geçiş doneminde tutarlılık sağlar.
Karar cercevesi
Katmanli mimari su durumlarda güçlü bir secimdir: orta ve büyük ölçekli kurumsal uygulamalar, cok gelistiricili ekipler, uzun omurlu bakım gereksinimi ve test edilebilirlik onceligi. Küçük prototiplerde veya tek geliştirici projelerinde tam katman ayrimi gereksiz yük olabilir. Pragmatizm, katman sayisini ihtiyaca gore azaltmak ve mimari testlerle sınırları korumak anlamina gelir.
Gozlemlenebilirlik ve operasyon
Her katman kendi metriklerini uretmelidir: API latency, handler süreleri, repository sorgu sayisi. Distributed trace ile istek katmanlar arasi takip edilir. Hata ayiklama sirasinda hangi katmanda sorun olduğu hizla tespit edilir. Log mesajlarinda katman ve use case adi standart alan olarak bulunur.
Versiyonlama ve geriye uyumluluk
API katmanı versiyonlanirken Application ve Domain geriye uyumlu kalmaya çalışır. Breaking API degisiklikleri yeni versiyonda sunulur. Internal katmanlarda refactoring serbesttir cunku dis sözleşme API ile sinirlidir.
Özet
Katmanli mimari pratikleri ozetle su ilkelerle hatirlanabilir: bağımlılık yonunu koru, arayuzlerle gevsek bagla, DTO ve entity'leri ayir, transaction sinirini use case bazinda tanımla, cross-cutting concern'leri merkezilestir, mimari testlerle ihlali erken yakala, anti-pattern'lerden kaçın ve olcekleme ihtiyacina gore modulerles. Bu disiplin, kod tabaninin yillar icinde anlasilir ve değiştirilebilir kalmasini sağlar.