Temiz Mimariyle Küçük Uygulama Tasarımı: Katmanlı Örnek
Yazılım Mimarisi ve Tasarım Desenleri
Temiz Mimariyle Küçük Uygulama Tasarımı: Katmanlı Örnek

Giriş
Yazılım mimarisi ve tasarım desenleri seçimleri, bir uygulamanın sürdürülebilirliği, test edilebilirliği ve bakım maliyetini doğrudan etkiler. "Temiz Mimari" yaklaşımı, iş mantığını altyapıdan izole ederek bu hedeflere ulaşmayı amaçlar; ancak küçük uygulamalarda gereksiz karmaşıklık da yaratabilir. Aşağıda hem Temiz Mimari'nin temel fikirlerini hem de küçük projelerde uygulanabilecek sadeleştirilmiş, katmanlı bir örneği bulacaksınız.
Temiz Mimari nedir?
Temiz Mimari, uygulamanın sorumluluklarını açık katmanlara ayırıp, iş mantığını altyapı bağımlılıklarından soyutlamaya odaklanır. Bu sayede test edilebilirlik, değiştirilebilirlik ve uzun vadeli sürdürülebilirlik artar. Bu yaklaşımın temel amaçları ve kavramsal yapısı hakkında örnek bir özet için SSTTEK Academy'nin açıklamalarına bakabilirsiniz: Clean Architecture Nedir? - SSTTEK Academy (kaynak).
Temel ilkeler
- İş mantığı (domain) altyapıdan bağımsız olmalıdır.
- İç katmanlar dış katmanlara bağımlı olmamalıdır; bağımlılık soyutlamalar (interface/port) aracılığıyla tersine çevrilir.
- Katmanlar net sorumluluklara sahip olmalı; her katman yalnızca kendi görevlerinden sorumlu olmalıdır.
Katmanlı Mimari nedir ve farklar
Katmanlı mimari, uygulamayı sorumluluklara göre gruplandıran daha genel bir yaklaşımdır. Tipik katmanlar sunum, iş mantığı ve altyapı şeklindedir. Katmanlı tasarım modülerlik ve esneklik sağlar; ancak Temiz Mimari, özellikle iş mantığını altyapıdan ayırmaya daha güçlü odaklanır. Katmanlı mimarinin avantajlarını incelemek için AppMaster'ın özetine bakabilirsiniz: Katmanlı Mimari | AppMaster (kaynak).
Karşılaştırma (özet)
- Katmanlı mimari: Genel yapı ve sorumluluk ayrımı sağlar.
- Temiz Mimari: İş mantığını altyapıdan soyutlamaya öncelik vererek bağımlılıkların tersine çevrilmesini teşvik eder.
Küçük uygulamalarda tercih ve riskler
Temiz Mimari, orta ve büyük ölçekli projelerde uzun vadeli fayda sağlayabilir; küçük uygulamalarda ise aşırı soyutlama gereksiz karmaşıklık getirebilir. Bu nedenle her projede aynı seviyede soyutlama uygulamak yerine ihtiyaç odaklı, pragmatik bir yaklaşım izlemek uygundur. SSTTEK Academy'de de benzer dikkatlerin gerektiği vurgulanır: küçük projelerde maliyet-fayda dengesi değerlendirilmelidir (kaynak).
Değerlendirme soruları
- Uygulamanın ömrü ve gelecekteki genişleme olasılığı nedir?
- Birden fazla kullanıcı arayüzü (API, web, mobil) olacak mı?
- Test edilebilirlik ve bağımsız geliştirme sizin için ne kadar öncelikli?
- Ekibin deneyimi ve projenin teslim süresi nedir?
Küçük Uygulama için Sadeleştirilmiş Katmanlı Örnek
Aşağıda küçük bir CRUD API (ör. basit bir TODO uygulaması) için hafifletilmiş bir katmanlı yapı gösterilmiştir. Amaç, Temiz Mimari prensiplerinden yararlanmak ancak gereksiz soyutlamalardan kaçınmaktır.
Önerilen katmanlar (hafif)
- Presentation (Sunum): HTTP katmanı, route/controller; request-validasyon ve response dönüşümleri burada yer alır.
- Application (Use Cases): İş akışları ve uygulama servisleri; birim testleri hedeflenir.
- Domain (Entities): Temel iş kuralları, varlık modelleri ve domain-only mantık.
- Infrastructure (Adapters): Veritabanı, dış servisler, ORM ya da sürücüler; domain tarafından tanımlanan arayüzleri uygular.
Basit dosya/folder yapısı (örnek)
src/ domain/ todo.ts (veya todo.js) application/ todosService.ts infrastructure/ todoRepositoryPg.ts presentation/ todosController.ts compositionRoot.ts (bağımlılıkların bağlandığı yer)
Bağımlılık Tersine Çevirme — Pratik yaklaşım
Domain katmanında repository arayüzü tanımlanır; gerçek veritabanı implementasyonu infrastructure katmanında yer alır. Bu sayede application katmanı sadece arayüzlere bağımlıdır, gerçek implementasyonlar composition root'ta enjekte edilir.
// (sadeleştirilmiş, pseudo-önek) // domain/todoRepository.ts interface TodoRepository { findById(id: string): Promise<Todo | null>; save(todo: Todo): Promise<void>; } // application/getTodoUseCase.ts class GetTodoUseCase { constructor(private repo: TodoRepository) {} async execute(id: string) { return await this.repo.findById(id); } } // infrastructure/todoRepositoryPg.ts class TodoRepositoryPg implements TodoRepository { // db bağlantısı burada async findById(id: string) { /* veritabanı sorgusu */ } async save(todo: Todo) { /* kaydetme */ } }
Yukarıdaki yapı küçük projelerde kullanım kolaylığı ve test edilebilirlik dengesi sunar. Gerçek kodda TypeScript/Java/C# gibi dil özelliklerini kullanarak arayüzleri (interface) açık şekilde tanımlamak, testlerde mock/stub kullanımını kolaylaştırır.
Adım adım uygulanabilir rehber
- Domain modelini ve temel iş kurallarını tanımlayın (entity'ler ve validator'ler).
- Her bir iş akışı için kısa use-case/metot listesi oluşturun.
- Domain içinde ihtiyaç duyulan dış bağımlılıkları interface olarak tanımlayın (ör. TodoRepository).
- Infrastructure katmanında bu interface'leri uygulayın.
- Presentation katmanında sadece request/response ve validasyonla ilgilenin; iş mantığını use-case'lere delegre edin.
- Composition root: uygulama başlatılırken hangi implementasyonun kullanılacağını burada bağlayın.
- Basit unit test'lerle use-case'leri doğrulayın; veri erişimi için test double (mock) kullanın.
Test stratejileri ve pratik ipuçları
- Use-case'leri izole test edin: veri erişimi mock olsun.
- Infrastructure implementasyonlarını entegrasyon testleriyle doğrulayın (ör. hafif DB örnek veritabanı ya da in-memory alternatif).
- Composer/DI (bağımlılık bağlama) mantığını tek yerde tutun; böylece testlerde farklı implementasyon bağlama kolay olur.
Hızlı Kontrol Listesi (Checklist)
- Domain mantığı altyapıdan bağımsız mı?
- Interface'ler iş mantığının ihtiyaçlarına göre mi tanımlandı?
- Bağımlılıkların bağlanması tek yerde mi yapılıyor?
- Testler use-case'leri izole ediyor mu?
- Sadeleştirme ile fazla soyutlama önlendi mi?
Ne zaman Temiz Mimari tercih edilmemeli?
Kısa ömürlü prototipler, tek amaçlı küçük script'ler veya tek geliştiricinin hızlıca teslim etmesi gereken basit işler için tam Temiz Mimari uygulamak fazla karmaşıklık getirebilir. Bu durumlarda katmanları hafifletmek, tek proje/monolitik klasör yapısı içinde açık sorumluluklar belirlemek daha pratiktir.
Sonuç ve kaynaklar
Temiz Mimari prensipleri, doğru durumda uygulandığında sürdürülebilirlik ve test edilebilirlik sağlar. Küçük uygulamalarda ise maliyet-fayda dengesini değerlendirmek ve gerekli soyutlamaları pragmatik şekilde seçmek önemlidir. Daha fazla teknik arka plan ve tanımlar için aşağıdaki kaynaklara bakabilirsiniz:
Not: Bu rehber projeye özgü genel öneriler içerir. Mimarinin son halini belirlerken ekip, süre, test gereksinimleri ve bakım beklentilerini dikkate alınız.