Clean Architecture
Clean Architecture Nedir?
Clean Architecture, iş mantığının (business logic):
- Framework’lerden
- Veritabanından
- UI’dan
- 3rd party servislerden
bağımsız olması gerektiğini savunan bir mimari yaklaşımdır.
Amaç: İş kurallarını dış dünyadan korumak.
Temel Amaçlar
1. Framework Bağımsızlığı
Express → Fastify geçsen bile iş mantığı değişmez.
2. Test Edilebilirlik
DB, HTTP server veya UI olmadan unit test yazabilirsin.
3. UI Bağımsızlığı
Web, mobile, CLI aynı use-case’i kullanabilir.
4. Database Bağımsızlığı
MongoDB’den PostgreSQL’e geçmek mimariyi bozmaz.
5. Dış Servis Bağımsızlığı
Mail sağlayıcısı değişirse domain etkilenmez.
Katmanlar
┌───────────────────────────────┐
│ Entities (Domain) │ ← En iç (En stabil)
└──────────────┬────────────────┘
│
┌──────────────┴────────────────┐
│ Use Cases (App) │
└──────────────┬────────────────┘
│
┌──────────────┴────────────────┐
│ Interface Adapters │
└──────────────┬────────────────┘
│
┌──────────────┴────────────────┐
│ Frameworks & Drivers │ ← En dış (En değişken)
└───────────────────────────────┘
Dependency Rule
Dış katmanlar iç katmanlara bağımlı olabilir. İç katmanlar dış katmanlara bağımlı olamaz.
Bu Clean Architecture’ın en kritik kuralıdır.
1. Entities (Domain Layer)
- Saf iş kuralları
- Framework bağımlılığı yok
- Express, DB, Logger bilmez
Örnek:
- User
- Order
- Product
Bu katman en stabil katmandır.
2. Use Cases (Application Layer)
- “Ne olacak?” sorusunun cevabı
- İş akışlarını tanımlar
- Repository interface bilir
- DB implementasyonu bilmez
Örnek:
- CreateUser
- PayOrder
- ResetPassword
3. Interface Adapters
- Controller
- Presenter
- Gateway
- Repository implementasyonu
Use-case ile dış dünya arasında çevirmen görevi görür.
4. Frameworks & Drivers
- Express
- MongoDB
- Redis
- React
- Mail servisleri
En dış ve en değişken katmandır.
SOLID Principles
Clean Architecture genelde SOLID prensipleri üzerine oturur.
S — Single Responsibility Principle (SRP)
Bir sınıf sadece bir sebepten dolayı değişmelidir.
✔ Test etmek kolay ✔ Kod okunabilir ✔ Değişiklik güvenli
User, Repository, EmailService, Logger ayrı olmalıdır.
O — Open / Closed Principle (OCP)
Sınıflar genişletmeye açık, değiştirmeye kapalı olmalı.
Yeni PaymentMethod eklemek için mevcut kodu değiştirmemeliyiz.
Bu sayede:
- Risk azalır
- Regression azalır
- Kod stabil kalır
L — Liskov Substitution Principle (LSP)
Alt sınıf, üst sınıfın yerine sorunsuz kullanılabilmelidir.
Square, Rectangle’dan extend edip davranışı bozuyorsa LSP ihlali vardır.
Çözüm:
- Composition kullan
- Doğru abstraction tasarla
I — Interface Segregation Principle (ISP)
Kimse kullanmadığı metodlara bağımlı olmamalı.
Büyük interface yerine küçük ve spesifik interface’ler.
✔ Readable ✔ Writable ✔ Aggregatable
D — Dependency Inversion Principle (DIP)
High-level modüller low-level modüllere değil, abstraction’a bağımlı olmalı.
UserService → IUserRepository (interface)
MongoUserRepository → IUserRepository implement eder
Bu sayede:
- DB değişebilir
- Kod değişmez
Clean Architecture Node.js Örnek Yapı
src/
├── domain/
├── application/
├── infrastructure/
└── interfaces/
Bu yapı sayesinde:
- Domain saf kalır
- Use-case bağımsız kalır
- Infrastructure değişebilir
- Controller sadece adaptör olur
Neden Bu Kadar Katman?
Küçük projede overkill olabilir.
Ama:
- Proje büyüdüğünde
- Mikroservis olduğunda
- Takım büyüdüğünde
- 3–5 yıl yaşayacak sistemde
Clean Architecture hayat kurtarır.
Clean Architecture vs Layered Architecture
Layered:
- Controller → Service → Repository
Clean:
- Domain merkezli
- Dependency ters çevrilmiş
- Framework en dışta
Büyük Resim
Client
↓
Controller
↓
Use Case
↓
Repository Interface
↓
Repository Implementation
↓
Database
Ama dependency yönü:
Database → Repository Impl → Use Case → Domain
Domain kimseyi bilmez.