Domain Driven Design (DDD)
DDD, yazılımı işin diliyle modelleme yaklaşımıdır. Amaç, kodun business gerçeğini yansıtmasıdır.
Kod şunu anlatmalıdır:
- Bu sistem ne yapıyor?
- Neden var?
- Hangi iş problemini çözüyor?
DDD bir mimari stil değil, bir modelleme yaklaşımıdır. Karmaşıklık yoksa tercih edilmemelidir. Basit CRUD uygulamalarında gereksiz maliyet üretir.
DDD karmaşık domain’leri yönetmek içindir.
Core Kavramlar
1. Ubiquitous Language
Business ve teknik ekip aynı dili konuşmalıdır.
Yanlış:
- Developer: “User table’a record ekledik.”
- Business: “Müşteri kayıt oldu.”
Doğru:
Her iki taraf da “Customer Registration” der ve bu ifade kodda da aynen geçer.
Yanlış isimlendirme:
calculateSomething()
handleStuff()
processData()
Doğru isimlendirme:
placeOrder()
cancelSubscription()
calculateInvoiceTotal()
Kod, işin kendisini anlatmalıdır.
2. Bounded Context
Aynı terim farklı bağlamlarda farklı anlamlara gelebilir. Bu nedenle sistem mantıksal sınırlara bölünür.
Örnek:
| Context | User Anlamı |
|---|---|
| Auth | Kimlik bilgisi |
| Billing | Fatura sahibi |
| Support | Ticket açan kişi |
Her context kendi modelini tanımlar. Model paylaşımı yapılmaz.
Bounded context, karmaşıklığı izole etmek içindir.
3. Entity
Kimliği (ID) olan ve zaman içinde değişebilen nesnedir.
Örnek: Customer
- İsmi değişebilir
- Email değişebilir
- Ama ID aynı kalır
Kimlik sabittir, değerler değişebilir.
4. Value Object
Kimliği yoktur. Değeri temsil eder. Immutable’dır.
Örnek:
- Money
- Address
- EmailAddress
50 TL başka bir 50 TL ile aynıdır. Identity yoktur.
Value object’ler eşitliği değer üzerinden belirler.
5. Aggregate ve Aggregate Root
Aggregate, birlikte tutarlı kalması gereken nesne grubudur.
Aggregate Root, dış dünyanın erişebileceği tek entry point’tir.
Order (Aggregate Root)
├── OrderItem
├── Address
Dış dünya doğrudan OrderItem değiştiremez.
Doğru kullanım:
order.addItem(productId, quantity)
Bu sayede:
- Invariant korunur
- Hesaplamalar merkezi yapılır
- Veri tutarlılığı sağlanır
Repository sadece Aggregate Root için yazılır.
OrderItem için ayrı repository olmaz.
6. Domain Service
Entity’ye ait olmayan ama domain açısından önemli olan iş kurallarıdır.
Örnek:
- Currency conversion
- Fraud check
- Discount calculation
Domain event ile karıştırılmamalıdır.
Domain Event:
- OrderCompleted
- PaymentRejected
Event bir olaydır. Domain Service bir davranıştır.
DDD + Clean Architecture
DDD genellikle Clean Architecture ile birlikte uygulanır.
Katmanlar:
- Interfaces (Controller / API)
- Application Layer
- Domain Layer
- Infrastructure Layer
Domain Layer
- Entities
- Value Objects
- Domain Services
- Domain Events
- Repository interfaces
Domain hiçbir framework bilmez.
Application Layer
- Use cases
- Transaction yönetimi
- DTO dönüşümleri
- Orchestration
Application iş kuralı barındırmaz.
Infrastructure Layer
- ORM
- Database
- Message broker
- External APIs
Infrastructure detaydır.
DDD vs Layered
| Layered | DDD |
|---|---|
| Anemic model | Rich domain model |
| Service merkezli | Domain merkezli |
| DB merkezli tasarım | Domain merkezli tasarım |
| Hızlı başlar | Analiz gerektirir |
Layered architecture’da business logic genelde service’lerde toplanır.
DDD’de logic entity içinde yaşar.
DDD + Microservices
Her microservice ideal olarak bir bounded context temsil eder.
Kurallar:
- Ayrı domain
- Ayrı DB
- Ortak entity yok
- Event ile haberleşme
Shared database anti-pattern’dir.
Ne Zaman DDD Kullanılmaz?
- Basit CRUD sistemlerde
- Admin panel uygulamalarında
- Domain karmaşıklığı yoksa
- Business rule minimumsa
DDD maliyetlidir:
- Analiz süresi artar
- Modelleme süresi artar
- Öğrenme eğrisi yüksektir
Ama karmaşık domain’de büyük avantaj sağlar.