Domain‑Driven Design (DDD): Karmaşık Yazılım Sistemleri İçin Pratik ve Teorik Rehber
1. GİRİŞ
Domain‑Driven Design (DDD), karmaşık iş problemlerini yazılım modellerine doğrudan yansıtmak için Eric Evans tarafından popülerleştirilen bir yaklaşımdır. DDD, teknik tasarım ve iş uzmanlığı arasındaki kopukluğu gidererek sürdürülebilir, anlaşılır ve evrilebilir sistemler inşa etmeyi amaçlar. Özellikle microservices, event‑driven mimariler ve domain‑intensive uygulamalarda DDD'in önemi artmıştır.
Neden bugün önemli?
- Karmaşık iş kuralları ve çok sayıda paydaş bulunan sistemlerde model doğruluğu sürdürülebilirlik ve bakım maliyetini doğrudan etkiler.
- Mikroservis ve bounded context odaklı mimariler, DDD prensipleriyle hizalandığında hizmet sınırları netleşir ve bağımsız takımlar daha verimli çalışır.
- AI, veri‑driven karar süreçleri ve real‑time sistemlerin yaygınlaşması domain uzmanlığı ve net modelleme ihtiyacını büyütmektedir.
Kimler için önemli?
- Yazılım mimarları ve teknik liderler
- Backend geliştiriciler ve sistem tasarımcıları
- Ürün sahipleri, domain uzmanları ve analistler
Hangi problemleri çözüyor?
- Domain karmaşıklığını yönetilebilir modüllere bölme
- İş kuralları ile teknolojik kararlar arasındaki uyuşmazlığı azaltma
- Ekipler arası iletişimi ve model tutarlılığını iyileştirme
2. KAVRAMSAL TEMELLER
2.1 Temel tanımlar
- Domain
- Problemin çözülmeye çalışıldığı iş alanı veya konu grubu (ör. ödeme, sipariş, envanter).
- Model
- Domain içindeki varlıkları, ilişkileri ve iş kurallarını temsil eden soyutlama; kod ve terimler aracılığıyla ifade edilir.
- Ubiquitous Language
- Geliştiriciler ve domain uzmanları arasında paylaşılan ortak dil; tüm kod, test ve tasarım dokümanlarında aynı terimler kullanılır.
- Bounded Context
- Modelin anlamının tutarlı olduğu sınırlı kapsam. Farklı bounded context'ler aynı terimi farklı anlamlarda kullanabilir; bu sınırlar açıkça tanımlanmalıdır.
- Aggregate
- Bir işlemle tutarlı kalması gereken bir grup nesne; root entity aracılığıyla dış dünya ile etkileşime girer.
- Entity ve Value Object
- Entity kimliğe (ID) sahip, yaşam döngüsü olan obje; Value Object kimliksiz, eşitlik ve immutable özellikleri taşır.
- Repository
- Aggregate'ların saklanması ve getirilmesi için soyutlama katmanı.
- Domain Service & Application Service
- Domain Service: entity/vo dışında kalan domain davranışı; Application Service: use case orchestration ve transaction boundary yönetimi.
2.2 Stratejik vs Taktiksel DDD
Stratejik DDD, bounded context, context map ve ekip organizasyonu gibi yüksek‑seviye kararlarla ilgilenir. Taktiksel DDD ise aggregate, entity, value object, repository gibi modelleme araçlarını kapsar. Her iki seviyenin birlikte düşünülmesi başarılı DDD uygulamaları için şarttır.
3. NASIL ÇALIŞIR? — TEKNİK MİMARİ VE AKIŞ
3.1 Bounded Context ve Context Map
Büyük bir sistem, mantıksal olarak farklı domain bölümlerine ayrılmalıdır. Her bounded context içinde terimler ve modeller tutarlı olmalıdır. Context Map, bounded context'ler arasındaki ilişkileri (conformist, anti‑corruption layer, shared kernel, partnership) belgeleyen bir haritadır. Örneğin bir e‑ticaret sisteminde "Catalog" ve "Ordering" farklı bağlamlarda farklı iş kurallarına sahip olabilir.
3.2 Ubiquitous Language'in uygulamaya yansıması
Terminoloji kod seviyesinde sınıf, metod ve test isimlerine yansıtılmalıdır. Ubiquitous Language, ekip içi iletişimi basitleştirir ve yanlış anlamaları azaltır. Domain uzmanları ile birlikte terminoloji oturana kadar iteratif workshop'lar yapılmalı ve terimler dokümante edilmelidir.
3.3 Aggregate tasarımı
Aggregate sınırları seçilirken birkaç kural uygulanır:
- Aggregate, transactional consistency garantisi sağlamak için yeterince küçük olmalı; aşırı geniş aggregate'ler performans ve concurrency problemlere yol açar.
- Aggregate root tek entry point olmalı; dış dünya aggregate içindeki nesneleri doğrudan değiştirmemeli.
- İş kuralları aggregate içinde kapsanmalı; yalnızca aggregate'in kendi invariants'ı kontrol etmelidir.
3.4 Persistence ve Repository pattern
Repository, aggregate'ların bulunması ve saklanması için domain seviyesinde soyutlama sağlar. Uygulama katmanı repository ile konuşur, veri tabanı teknolojisi (RDB, NoSQL, event store) repository implementasyonu tarafından soyutlanır. Bu ayrım domain modelinin veri erişim detaylarından korunmasını sağlar.
3.5 Transaction boundary ve eventual consistency
Tek bir aggregate için eşzamanlı transaction mümkünken, farklı bounded context'ler arasında cross‑aggregate transaction maliyetli ve karmaşıktır. Bu yüzden event‑driven asenkron entegrasyon (publish/subscribe, eventual consistency, sagas/compensating transactions) tercih edilir. Saga pattern, uzun süreli iş akışlarını koordine etmek için yaygın bir yaklaşımdır.
3.6 Anti‑Corruption Layer (ACL)
Farklı bounded context'ler arasında bir bağdaştırıcı katmanı (anti‑corruption layer) uygulamak, dışarıdan gelen model ve terimleri iç modelle uyumlu hale getirir. Bu, bir bağlamın diğerinin modelini doğrudan kirletmesini önler ve bağlamlar arasındaki bağımlılığı azaltır.
4. GERÇEK DÜNYA KULLANIMLARI
4.1 Netflix ve domain decomposition
Netflix gibi ölçekli platformlarda domain decomposition (bounded context temelli service boundary'ler) ekiplerin bağımsız çalışmasına olanak tanır. Her ekip kendi bounded context'ini yönetir ve API/contract'lar üzerinden etkileşir. Bu sayede deploy cadence ve domain ownership netleşir.
4.2 Amazon — katalog, sipariş ve fulfillment ayrımı
Büyük e‑ticaret platformlarında katalog yönetimi, sipariş işleme ve fulfillment farklı ekipler ve bounded context'ler olarak ele alınır. Event‑driven entegrasyonlar (order created event → fulfillment) ve anti‑corruption layer'lar ile bağlamlar birbirine bağlanır.
4.3 Finans sektöründe DDD
Bankacılık ve ödeme sistemlerinde domain kuralları kompleks ve regülasyon odaklıdır. DDD, hesap, işlem ve uyumluluk bounded context'lerini açıkça ayırarak audit, risk yönetimi ve kanıtlanabilir süreç akışı sağlar.
4.4 Startup ve ürün odaklı kullanım
Küçük ekipler için DDD'in tüm detaylarını baştan uygulamak aşırı olabilir. Ancak ubiquitous language, açık context boundary ve aggregate düşüncesi ilk iterasyonlardan itibaren büyük fayda sağlar. Mühendislik borcu ve domain karmaşıklığı arttıkça DDD uygulaması kademeli olarak genişletilir.
5. AVANTAJLAR VE SINIRLAMALAR
Avantajlar
- Domain uzmanlığı ile yazılım modeli arasındaki uyum artar.
- Ekip sınırları ve servislere dayalı decomposition netleşir.
- Bakım, test ve evrim süreçleri kolaylaşır: model doğruysa değişimler yerinde yapılır.
Sınırlamalar
- Öğrenme eğrisi: DDD kavramları ve prensipleri ekip içinde benimsenmelidir.
- Başlangıç maliyeti: Proje karmaşıklığı düşükse DDD overhead getirebilir.
- Operasyonel gereksinimler: Event‑driven entegrasyon ve distributed transaction yönetimi ek altyapı gerektirir.
6. ALTERNATİFLER VE KARŞILAŞTIRMA
| Yaklaşım | Avantaj | Dezavantaj |
|---|---|---|
| Basit CRUD / monolit | Hızlı geliştirme, az başlangıç karmaşıklığı | Büyüdükçe bakım zorluğu, model bulanıklığı |
| Modüler monolit + iyi sınırlar | Daha az dağıtık operasyon, net modüller | Servis bağımsızlığı sınırlı olabilir |
| DDD + mikroservis | Domain odaklı decomposition, ekip bağımsızlığı | Dağıtık koordinasyon, event yönetimi ve operasyonel maliyet |
7. EN İYİ PRATİKLER
Production kullanımı
- Ubiquitous Language'i baştan kurun: terimler kod, test ve dokümantasyonda tutarlı olsun.
- Bounded Context'leri açıkça tanımlayın ve context map oluşturun.
- Aggregate sınırlarını iş kurallarına göre belirleyin; küçük tutun ve performans/test gereksinimlerini ölçün.
- Transactional Outbox ve event bus ile asenkron entegrasyonları güvenilir hale getirin.
Performans ve ölçeklenebilirlik
- Read ve write store'ları ayrı tutarak okuma yükünü optimize edin (CQRS pattern uygulanabilir).
- Eventual consistency etkilerini UX ile örtüşecek biçimde tasarlayın; read‑after‑write gerekiyorsa fallback stratejileri sağlayın.
- Monitoring ve observability: aggregate latency, event publish success, projection lag gibi metrikleri takip edin.
Güvenlik ve veri yönetimi
- Domain verilerindeki PII'yı minimize edin; event'lerde tokenization veya encryption kullanın.
- Access control'ü bounded context seviyesinde uygulayın; cross‑context erişimleri ACL veya API gateway ile yönetin.
8. SIK YAPILAN HATALAR
- Terimlerin ekip içinde farklı anlamlarda kullanılması — Ubiquitous Language yokluğu ciddi teknik borç yaratır.
- Aggregate'leri aşırı büyütmek — concurrency ve performans sorunlarına neden olur.
- Bounded context'leri belirsiz bırakmak — servis boundary'leri zamanla çakışır ve entegrasyon karmaşası artar.
- Eventual consistency'i göz ardı etmek — kullanıcı arayüzü veya iş akışlarında beklenmeyen davranışlar oluşur.
9. GELECEK TRENDLER
- Domain‑aware AI araçları: Model önerileri, domain terimlerinin otomatik çıkarımı ve code generation ile DDD pratiği desteklenecek.
- Event Mesh ve federated context discovery: Çoklu bulut/multi‑cluster ortamlar için domain‑aware event routing çözümleri yaygınlaşacak.
- Serverless & DDD kombinasyonları: Bounded context'lerin hızlı ve maliyet‑etkin olarak bağımsız deploy edilmesi artacak.
EK BÖLÜMLER
Sık Sorulan Sorular (FAQ)
- 1. DDD her projeye uygulanmalı mı?
Hayır. Basit projeler için DDD overhead getirebilir. Ancak domain karmaşıklığı ve takım boyutu arttıkça DDD faydaları öne çıkar.
- 2. Ubiquitous Language nasıl oluşturulur?
Domain uzmanlarıyla workshop'lar düzenleyin, terimleri kod, test ve dokümantasyona yansıtın ve sürekli olarak gözden geçirin.
- 3. Aggregate sınırını nasıl belirlerim?
Transactional consistency, performance ve ownership kriterlerini göz önünde bulundurun. Eğer bir grup entity birlikte tutarlı kalmalıysa aynı aggregate içinde olmalıdır.
- 4. DDD ile mikroservis farkı nedir?
DDD bir modelleme yaklaşımıdır; microservice bir dağıtık mimari stilidir. DDD bounded context'ler mikroservis sınırları için rehberlik eder ancak birebir eşleştirme her zaman gerekli değildir.
- 5. Anti‑Corruption Layer ne zaman kullanılmalı?
Harici sistemler veya farklı bounded context'lerden gelen modeller iç domain'i kirletebiliyorsa ACL katmanı ile çeviri ve adaptasyon yapın.
- 6. DDD öğrenme yol haritası nedir?
Temel DDD kavramlarından başlayın (ubiquitous language, bounded context), ardından taktiksal desenleri (aggregate, VO, repository) uygulayın ve zamanla stratejik DDD pratiklerini (context mapping, team structure) benimseyin.
- 7. DDD ile event sourcing birlikte mı kullanılmalı?
Birbirini tamamlayıcı yaklaşımlardır; event sourcing replay, audit ve timeline avantajı sunar. Ancak işletimsel maliyeti göz önünde bulundurarak karar verin.
- 8. DDD uygularken hangi metrikleri izlemeliyim?
Event throughput, aggregate command latency, projection lag, cross‑context error rate ve domain‑specific SLA metriklerini izleyin.
Anahtar Kavramlar
- Bounded Context
- Model anlamının tutarlı olduğu sınır; hizmet veya modül seviyesinde düşünülür.
- Ubiquitous Language
- Domain uzmanı ve geliştirici arasında paylaşılan ortak dil.
- Aggregate
- Transactional consistency için birlikte ele alınan nesne kümesi.
- Anti‑Corruption Layer
- Dış modellerin iç modele çevrilmesini sağlayan adaptör katmanı.
- Repository
- Aggregate'ların erişim ve saklama soyutlaması.
Öğrenme Yol Haritası
- 0–1 ay: DDD temelleri, Ubiquitous Language ve bounded context kavramlarını öğrenin; küçük bir domain modelleyin.
- 1–3 ay: Taktiksel desenleri (aggregate, VO, repository) uygulayın; test driven development ile domain logic'i doğrulayın.
- 3–6 ay: Stratejik DDD: context mapping, team ownership ve anti‑corruption layer uygulamalarını geliştirin.
- 6–12 ay: Event‑driven entegrasyon, CQRS/ES kombinasyonları, multi‑team coordination ve governance pratikleri üzerinde deneyim kazanın.