Domain-Driven Design (DDD) Türkçe Rehber: Alan Odaklı Tasarım
Domain-Driven Design (DDD), yazılım geliştirmede iş alanını (domain) merkeze koyan bir yaklaşımdır. Eric Evans'ın 2003'teki kitabı ile popülerleşen DDD, karmaşık iş mantığına sahip projelerde vazgeçilmez bir tasarım felsefesidir.
DDD Neden Önemli?
Çoğu yazılım projesi, teknik karmaşıklık nedeniyle değil, iş alanının yanlış modellenmesi nedeniyle başarısız olur. DDD, bu sorunu çözmek için geliştiricileri ve iş uzmanlarını ortak bir dil etrafında birleştirir.
Temel Kavramlar
1. Ubiquitous Language (Ortak Dil)
Teknik ekip ile iş birimi arasında herkesin anladığı tek bir dil oluşturmak. Örneğin:
- ❌ "User tablosundaki row'u update et" → Teknik jargon
- ✅ "Müşterinin adres bilgisini güncelle" → Ortak dil
Bu dil, kodda, dokümantasyonda ve toplantılarda tutarlı olmalıdır.
2. Bounded Context (Sınırlı Bağlam)
Büyük bir sistemi, her biri kendi modeliyle yönetilen alt alanlara ayırmak. Aynı kavram farklı bağlamlarda farklı anlama gelebilir:
Satış Bağlamı: Müşteri = Sipariş veren kişi
Destek Bağlamı: Müşteri = Ticket açan kişi
Muhasebe Bağlamı: Müşteri = Fatura kesilen kişi
Her bağlam kendi modelini yönetir. Bağlamlar arası iletişim tanımlı arayüzlerle olur.
3. Entity (Varlık)
Kimliği (ID) olan ve yaşam döngüsü boyunca değişebilen nesneler:
Müşteri { id: "M001", ad: "Ali", adres: "..." }
İki müşteri aynı ada sahip olsa bile, farklı varlıklardır çünkü farklı ID'lere sahiptirler.
4. Value Object (Değer Nesnesi)
Kimliği olmayan, değeriyle tanımlanan nesneler:
Para { miktar: 100, birim: "TL" }
Adres { şehir: "İstanbul", ilçe: "Kadıköy", sokak: "..." }
İki Para(100, "TL") nesnesi aynıdır — kimliğe gerek yoktur.
5. Aggregate (Küme)
Birlikte değişmesi gereken entity ve value object'lerin grubu. Her aggregate'in bir Aggregate Root (kök varlık) vardır:
Sipariş Aggregate:
├── Sipariş (Root Entity)
├── SiparişKalemi (Entity)
├── TeslimatAdresi (Value Object)
└── Ödeme (Value Object)
Dışarıdan sadece Aggregate Root üzerinden erişilir.
6. Repository (Depo)
Aggregate'lerin kalıcı depolanmasını yöneten arayüz:
interface SiparişRepository {
bul(id: SiparişId): Sipariş
kaydet(sipariş: Sipariş): void
sil(id: SiparişId): void
}
7. Domain Event (Alan Olayı)
İş alanında gerçekleşen önemli olaylar:
SiparişOluşturuldu { siparişId, müşteriId, tutarı, tarih }
ÖdemeAlındı { siparişId, ödemeYöntemi, tarih }
SiparişKargoyaVerildi { siparişId, takipNo, tarih }
Event Sourcing ile birlikte kullanıldığında çok güçlü bir kombinasyon oluşturur.
Stratejik DDD
Context Mapping
Bounded Context'ler arası ilişkileri tanımlayan harita:
- Shared Kernel — İki bağlam ortak bir modeli paylaşır
- Customer-Supplier — Bir bağlam diğerine servis sunar
- Anti-Corruption Layer — Dış sistemi kendi modeline çevirir
- Conformist — Bir bağlam diğerini olduğu gibi kabul eder
BilgeOne Örneği
BilgeOne platformundaki bounded context'ler:
┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│ Restoran │ │ Finans │ │ CRM │
│ Bağlamı │──│ Bağlamı │──│ Bağlamı │
│ (Menü,Masa) │ │ (Fatura,Gelir)│ │ (Müşteri) │
└─────────────┘ └─────────────┘ └─────────────┘
Her sektör modülü kendi bounded context'idir. Finans ve CRM gibi ortak modüller, tüm sektörlerle entegre çalışır.
DDD Ne Zaman Kullanılmalı?
✅ Kullanın
- Karmaşık iş mantığı olan projeler
- Uzun ömürlü, büyüyen sistemler
- İş uzmanlarıyla yakın çalışılan projeler
❌ Kullanmayın
- Basit CRUD uygulamaları
- Kısa ömürlü prototipler
- Teknik karmaşıklık ağırlıklı projeler (ör. oyun motoru)
DDD Öğrenme Kaynakları
- Eric Evans — "Domain-Driven Design" (mavi kitap)
- Vaughn Vernon — "Implementing Domain-Driven Design" (kırmızı kitap)
- Yazılım Mimarisi 3.0 — Türkçe kapsamlı rehber
- LabLudus — İnteraktif DDD görevleri
Sonuç
DDD, yazılımı teknik bir problem değil, iş problemi olarak görmemizi sağlar. Doğru uygulandığında, hem iş biriminin hem de teknik ekibin aynı dili konuşmasını, bu sayede daha doğru ve sürdürülebilir sistemler kurulmasını sağlar.