Clean Architecture (temiz mimari), Robert C. Martin'in (Uncle Bob) 2012'de tanımladığı ve 2017'de aynı adlı kitabında genişlettiği bir yazılım mimarisi yaklaşımıdır. Amacı, uygulamanın iş kurallarını veritabanından, kullanıcı arayüzünden ve kullanılan çerçevelerden bağımsız tutmaktır.
Bağımlılık kuralı
Clean Architecture'ın vazgeçilmez tek kuralı şudur: kaynak koddaki bağımlılıklar yalnız içe doğru gösterir. İç halkadaki kod dış halkadaki hiçbir şeyin adını bilmez. Bir sınıf, fonksiyon ya da veri yapısı dış katmanda tanımlanmışsa iç katman ona başvuramaz.
İç katmanın dış dünyayla konuşması gerektiğinde, örneğin bir kaydı veritabanına yazarken, bağımlılığın tersine çevrilmesi ilkesi (Dependency Inversion) devreye girer: iç katman bir arayüz tanımlar, dış katman o arayüzü uygular. Çalışma anında akış dışarı doğru ilerler ama kaynak koddaki bağımlılık içeriyi gösterir.
- Entities (varlıklar)
- Kurum genelindeki iş kuralları
- En az değişen katman
- Use Cases (kullanım senaryoları)
- Uygulamaya özgü iş kuralları
- Varlıklar arasındaki akışı yönetir
- Interface Adapters (arayüz adaptörleri)
- Controller, presenter, gateway
- Veriyi iç katmanların ve dış araçların biçimi arasında çevirir
- Frameworks and Drivers (çerçeveler ve sürücüler)
- Veritabanı, web çerçevesi, arayüz
- Ayrıntılar bu halkada kalır
Kaynak: Robert C. Martin, "The Clean Architecture" (2012) ve Clean Architecture (Prentice Hall, 2017). Martin halkaların şematik olduğunu, dört tane olmak zorunda olmadığını; değişmeyenin bağımlılık yönü olduğunu vurgular.
Avantajları
- Bağımlılıklar kontrol altında: İş mantığı veri erişiminden ve dış servislerden bağımsız olduğu için bir katmandaki değişiklik diğerlerine sızmaz.
- Test edilebilirlik: Kullanım senaryoları veritabanı ya da web sunucusu olmadan, dış bağımlılıklar mock ya da stub ile taklit edilerek birim testiyle sınanır. Bir sipariş oluşturma senaryosu veritabanına hiç dokunmadan test edilebilir.
- Değişime dayanıklılık: İlişkisel bir veritabanından NoSQL'e geçmek ya da bir üçüncü taraf servisi değiştirmek yalnız dış katmandaki kodu etkiler; iş kuralları yerinde kalır.
- Bakım kolaylığı: Her katmanın sorumluluğu belli olduğu için yeni özellik eklemek ya da hata düzeltmek ilgili katmanda kalır. Ekibe yeni katılan geliştirici kodda daha kolay yol bulur.
- Yeniden kullanım: Çerçeveye bağlı olmayan iş kuralları başka bir uygulamada ya da serviste yeniden kullanılabilir.
Dezavantajları
- Öğrenme eğrisi: Katmanlar ve bağımlılık yönetimi, bu yapıyla ilk kez çalışan geliştiricilere başta karmaşık gelebilir.
- Başlangıç maliyeti: Katmanları ayırmak, arayüzleri tanımlamak ve veriyi katmanlar arasında taşımak projenin başında ek zaman ister. Uzun ömürlü projelerde bu yatırım geri döner.
- Küçük projelerde fazlalık: İş kuralı basit, birkaç ekranlık bir uygulamada bu kadar katman gereğinden ağır kalabilir (overengineering).
Ardalis Clean Architecture
.NET topluluğunda yaygın kullanılan başlangıç şablonlarından biri, Steve Smith'in (ardalis) GitHub'da yayımladığı Clean Architecture şablonudur. Martin'in ilkelerini ASP.NET Core'a uyarlar ve çözümü Core, UseCases, Infrastructure ve Web projelerine böler. Varlık tabanı, alan olayları ve repository arayüzü gibi ortak temel sınıflar ayrı bir SharedKernel paketinde durur. Şablon dotnet new komutuyla kurulur ve çalışmaya hazır bir iskelet verir: ilkeler aynıdır, kararların bir kısmı önceden verilmiştir.
Projelerimizdeki katman yapısı
ASP.NET Core projelerimizde Clean Architecture'ı yedi projeye ayırarak uyguluyoruz. Adlar ekibimizin uzlaşısıdır; kural yine aynıdır: bağımlılıklar Core'a doğru akar.
Core
Varlıklar, değer nesneleri, alan servisleri ve iş kuralları. Diğer katmanlara ve altyapı paketlerine bağımlı değildir; projenin en kararlı parçasıdır.
Application
Kullanım senaryoları, uygulama servisleri ve veri transfer nesneleri (DTO). Kullanıcıdan gelen talebi iş kurallarıyla işler; veritabanına ve dış servislere doğrudan değil, iç katmanda tanımlı arayüzler üzerinden ulaşır.
Infrastructure
Veri erişimi (repository uygulamaları ve migration'lar), harici API istemcileri ve üçüncü taraf kütüphanelerle entegrasyon. İç katmanların tanımladığı arayüzleri uygular.
DependencyInversion
Bağımlılık enjeksiyonu (DI) ve IoC kayıtlarının toplandığı katman: hangi arayüzün hangi sınıfla çalışacağı ve servislerin yaşam döngüsü burada belirlenir. Bir veri kaynağını ya da dış servisi değiştirmek çoğu zaman yalnız bu kayıtları değiştirmek demektir.
SharedKernel
Alana ait olmayan ama birden fazla katmanın kullandığı ortak yapı taşları: hata türleri, olaylar ve yardımcı sınıflar. Projeler arasında yeniden kullanılacak biçimde bağımsız tutulur.
UI
API uç noktaları ya da MVC katmanı. İsteği karşılar ve Application katmanına iletir; iş kuralı taşımaz. Bu yüzden arayüzde yapılan bir değişiklik iş mantığını etkilemez.
Tests
Birim ve entegrasyon testleri. İş kuralları dış bağımlılık olmadan birim testleriyle, veri erişimi ve servis entegrasyonları entegrasyon testleriyle doğrulanır.
Bu yapının bize kazandırdıkları
- Okunabilirlik: Her katmanın sorumluluğu belli olduğu için kodda neyin nerede durduğu tahmin edilebilir.
- Merkezi bağımlılık yönetimi: Yeni bir servisi ya da dış kaynağı eklemek DependencyInversion katmanındaki kayıtla sınırlı kalır.
- Yeniden kullanım: SharedKernel'deki ortak parçaları farklı projelerde tekrar kullanıyoruz.
- Güvenli değişiklik: Core ve Application bağımsız test edildiği için iş kurallarındaki bir değişiklik veri erişimini ya da arayüzü bozmadan doğrulanır.
- Mikro servise hazırlık: Sınırları net çizilmiş bir uygulama, ileride modüllerine ayrılması gerektiğinde en kolay bölünen uygulamadır.


