Blog

Medium

DDD Event Storming: Trendyol Tech DDD Days Notları ve Gerçek Dünya ...

🎙️ReferansBu yazıda paylaşılan bilgiler, 6 Haz 2023 tarihli Trendyol Tech DDD Days — Event Storming yayını sırasında alınan notlar ve sunum içeriği baz alınarak hazırlanmıştır.GirişModern yazılım geliştirme süreçlerinde iş süreçlerini doğru anlamak ve bu süreçleri kodun içine doğru modellemek kritik bir başarı faktörüdür. Bu noktada Domain-Driven Design (DDD) ve onun güçlü bir keşif ve modelleme aracı olan Event Storming devreye giriyor.Geçtiğimiz günlerde Trendyol Tech DDD Days kapsamında gerçekleştirilen Event Storming Workshop’unda bu yaklaşımın pratikte nasıl uygulandığına dair bir çok deneyim paylaşıldı. Bu yazı, o yayında konuşulanlardan derlenmiş bir rehber niteliğinde olarak hazırlanmıştır.Event Storming Nedir?Event Storming, Alberto Brandolini tarafından ortaya atılan bir keşif ve modelleme tekniğidir. Amaç, iş süreçlerinde yaşanan tüm önemli olayları (eventleri) ekipçe beyin fırtınası yaparak ortaya çıkarmak ve bu olaylar etrafında domain modelini şekillendirmektir.DDD’nin Stratejik Tasarım aşamasında kullanılan bu teknik, hem teknik ekiplerin hem de iş birimlerinin ortak bir dilde buluşmasını sağlar.Workshop’tan Öne Çıkan Notlar1️⃣ Doğru Ekip ve Doğru Araçlarla BaşlamakEvent Storming’in etkili olabilmesi için:Business expertler (domain uzmanları)Geliştiriciler (developers)Tasarımcılar (UX/UI)Product Manager’largibi farklı rollerin aynı masa etrafında toplanması gerekir.Trendyol ekibi de workshop’ta hem teknik hem de iş birimlerinden kişilerle bu oturumu gerçekleştirdi. Ortak dilin oturması, iş süreçlerinin detaylarının anlaşılması bu çeşitlilik sayesinde sağlandı.2️⃣ Fiziksel mi, Dijital mi?Pandemi sonrası birçok ekip Miro, Lucidchart gibi araçlarla dijital event storming yapmaya başladı. Trendyol ekibi de bu yayında dijital bir ortamda simülasyon gerçekleştirdi.Avantaj: Sürekli yaşayan bir doküman oluşturma şansı.Dezavantaj: Paralel tartışmalar yapmak zor, fasilitasyon daha kritik hale geliyor.3️⃣ Sürecin Adımları📍 Event’lerin Belirlenmesiİlk adım, domain içindeki önemli olayların (event) sıralanmasıdır. Örneğin:VasProductCreated (Ek hizmet ürünü yaratıldı)PriceRangeUpdated (Fiyat aralığı güncellendi)ServiceAddedToCart (Hizmet sepete eklendi)📍 Eventlerin Zamana Göre SıralanmasıTüm eventler, süreç akışına göre dizilir. Bu sayede eksik kalan adımlar ve tutarsızlıklar hemen görünür hale gelir.📍 Komutlar ve AktörlerHer event’i tetikleyen bir komut (command) ve bu komutu çalıştıran bir aktör (actor) belirlenir.Command: CreateVasProductActor: SellerAdmin📍 Constraint’ler ve KurallarHer event’in hangi koşullarda çalışacağı (business rule) belirlenir.Örneğin:“Sadece onaylı satıcılar ürün yaratabilir.”“Sepete ekleme işlemi sadece stok varsa yapılır.”📍 Aggregateler ve Entity’lerHer event’in etkilediği aggregate veya entity ortaya çıkarılır.VasProduct bir aggregate olarak tanımlanabilir.PriceRange bir value object olabilir.4️⃣ Bağlam Sınırlarının (Bounded Context) BelirlenmesiTüm bu analiz sonunda, domain’in hangi alt parçalara (bounded context) bölüneceği belirlenir.Trendyol’daki örnekte:VasProduct ManagementCart ServicePayment Service gibi bağımsız bounded context’ler belirlendi.5️⃣ Integration Pattern’leri SeçmekBounded Context’ler arasındaki iletişim, DDD’nin önemli bir kararıdır.Open Host Service: Bir context, dış dünyaya belirli API’ler sunar.Anti-Corruption Layer: Bir context, dış context’lerin modeliyle kendi modelini izole eder. Trendyol ekibi, bu kararları da modelleme sırasında tartıştı.Event Storming Neden Faydalı?✅ Teknik ve iş birimlerini ortak dilde buluşturur.✅ Eksik, hatalı veya karışık süreçleri erkenden görünür kılar.✅ Yalnızca kod değil, süreç de modellenir.✅ Tüm ekiplerde ortak bir “büyük resim” algısı oluşur.✅ Yeni gelen ekip üyeleri için mükemmel bir onboarding aracıdır.Sonuç ve KapanışEğer ekiplerinizde DDD uygulamaya çalışıyorsanız veya karmaşık süreçleri daha iyi modellemek istiyorsanız, Event Storming iyi bir başlangıç noktası.

trendyoltechsoftware-architecturedomain-driven-designbounded-contexteventstorming
Medium

DDD, CQRS ve Event Sourcing: Karmaşık Sistemlerde Gerçek Dünya Dene...

Not: Bu yazıda paylaşılan bilgiler, Trendyol Tech DDD Days — CQRS & Event Sourcing başlıklı etkinlikten alınan notlara dayanarak hazırlanmıştır.Etkinlikte, Trendyol’dan Melek Bilgin Tamtürk, Sinan Baran ve Onur Destanoğlu’nun aktardığı gerçek proje deneyimlerinden ve sunum içeriklerinden faydalanılmıştır.GirişModern yazılım geliştirme süreçlerinde özellikle karmaşık domain yapıları ve dağıtık sistemlerle çalışırken, geleneksel mimari yaklaşımlar yetersiz kalabiliyor. Bu noktada Domain-Driven Design (DDD), CQRS ve Event Sourcing gibi kavramlar devreye giriyor. Trendyol’un gerçek dünyada bu mimarileri nasıl kullandığına dair edindikleri tecrübeler, avantajları ve karşılaştıkları zorluklar 27 Temmuz 2023 tarihli bu videoda paylaşılmış.DDD (Domain-Driven Design) Nedir?Eric Evans’ın 2003 yılında yayınladığı “Blue Book” ile hayatımıza giren DDD, karmaşık iş problemlerini çözmek için tasarlanan bir mimari yaklaşımdır. Temel amacı, yazılım ekipleri ile alan uzmanlarının (domain experts) aynı dili konuşmasını sağlamak ve doğru modelleme ile teknik çözümü domain bilgisiyle doğrudan beslemektir.DDD’nin SağladıklarıOrtak Dil (Ubiquitous Language): Teknik ve iş birimleri arasında köprü kurar.Bağlam Sınırları (Bounded Context): Her ekibin ve sistemin kendi sınırlarını net çizer.Taktiksel Yordamlar: Aggregate, Value Object, Domain Event gibi güçlü pattern’lerle modellemeyi destekler.CQRS (Command Query Responsibility Segregation)Nedir?2010 yılında Greg Young tarafından popülerleştirilen CQRS, okuma ve yazma işlemlerini tamamen birbirinden ayıran bir mimari yaklaşımdır. Bu sayede:Okuma (Query) ve yazma (Command) tarafları farklı modeller ve veri kaynakları kullanabilir.Okuma tarafı optimize edilirken, yazma tarafı da kendi performans ve tutarlılık gereksinimlerine göre tasarlanabilir.Avantajları✅ Farklı teknoloji stack’leri kullanılabilir.✅ Performans optimizasyonu kolaylaşır.✅ Takım yapısı da bu mimariye göre ayrılabilir: bir ekip sadece okuma tarafını geliştirirken diğeri yazma tarafına odaklanır.Dezavantajları❌ Ekstra karmaşıklık.❌ Okuma ve yazma modellerinin senkronizasyonu ciddi bir sorumluluk haline gelir.❌ Eventual Consistency kabul edilmesi gerekir.Event SourcingNedir?Event Sourcing, sistemdeki her değişikliğin bir event (olay) olarak kaydedilmesi prensibidir. Geleneksel sistemlerde sadece son durumu (current state) tutarken, Event Sourcing geçmişteki tüm değişiklikleri de saklar.FaydalarıDenetlenebilirlik (Auditability): Tüm değişiklikler adım adım izlenebilir.Geriye Dönme (Rewind): Sistemi istenen bir zamana geri almak mümkündür.Gerçek Dünya Uyumlu: Gerçek dünyadaki süreçler de genellikle adım adım değişimlerden oluşur.ZorluklarVeri boyutu hızla büyür.Replay (baştan oynatma) maliyetlidir.Event şemalarının değişimi ciddi planlama gerektirir.Gerçek Dünya Kullanımı: Trendyol ÖrneğiDDD & CQRS UygulamasıTrendyol’da iade yönetim sistemi yeniden tasarlanırken, DDD ve CQRS prensipleri esas alındı. Bu süreçte:Domain model oluşturuldu.İş süreçleri (flows) netleştirildi.CQRS ile okuma ve yazma operasyonları ayrıştırıldı.Farklı veri kaynakları ve indeksleme teknolojileri (Kafka, ElasticSearch, PostgreSQL) kullanıldı.Data akışları event-driven hale getirildi.Neden CQRS?Okuma yükü ile yazma yükü farklı olduğu için.Farklı teknolojilerin güçlü yönlerinden faydalanabilmek adına.Performans kritik olduğu için, okuma tarafında optimize indeksleme yapmak gerektiği için.Event Sourcing’in YeriHer işlem bir event olarak kaydedildi. Bu event’ler:Geçmişe dönük analizler.Veri tutarlılığı kontrolleri.Hukuki kayıt gereklilikleri. için kullanıldı.Gerçek ZorluklarEvent şemalarının evrimi.Toplam veri boyutunun yönetimi.Eventual consistency ile kullanıcı deneyimini dengelemek.Monitoring ve tracing süreçlerini güçlendirmek.Dağıtık Sistemlerde Transaction YönetimiTwo-Phase Commit (2PC)Güçlü tutarlılık (Strong Consistency) sağlar.Tüm katılımcılar koordinatör tarafından yönetilir.Ancak performans ve ölçeklenebilirlik açısından mikroservis ortamlarında tercih edilmez.Saga PatternEventual consistency sağlar.Tek bir global transaction yerine, bağımsız local transaction’lar zinciri oluşturulur.Trendyol’da, özellikle sipariş ve iade süreçlerinde sıklıkla tercih edilen yaklaşımdır.Choreography (event-driven) ve Orchestration (merkezi koordinatörlü) olarak ikiye ayrılır.SonuçTrendyol’daki bu deneyim gösteriyor ki, her bir pattern veya mimari yaklaşımın yeri ve zamanı farklıdır. Ezbere “trend” yaklaşımları uygulamak yerine:Önce domain’i anlamak.İş gereksinimlerine göre uygun mimariyi seçmek.Domain uzmanlarıyla sürekli iş birliği yapmak. başarıya giden en sağlıklı yoldur.Özetle: Teknoloji bir araçtır, amaç doğru modeli ve doğru çözümü bulmaktır.KapanışTrendyol’daki gerçek projelerden yola çıkarak DDD, CQRS ve Event Sourcing gibi kritik kavramlar bu yayında ele alınmış. Bu tür konularla ilgilenen herkesin, sadece teoriyi değil, pratik dünyada nasıl uygulandığını da göz önünde bulundurması öneriliyor.

trendyoltechdomain-driven-designdddcqrsevent-sourcing
Medium
 DDD Tactical Patterns Notları

DDD Tactical Patterns Notları

🎙️ GirişTrendyol Tech kanalında 9 Mayıs 2024 tarihinde paylaşılan Domain Driven Design: Tactical Patterns yayınından çıkarılmış notları içerir.⚠️ Neden Bu Pattern’ler?Domain-Driven Design (DDD), karmaşık iş kurallarını doğru modellemek için önemli bir rehberdir. DDD’nin Tactical kısmında, domain modelinizi doğru şekilde nasıl tasarlayabileceğinizi gösteren bu pattern’ler yer alır. Özellikle Anemic Model ve Rich Model farkını anlamak çok kritik.📊 Anemic Model Nedir?Sadece veri taşır.İş kuralları ve validasyonlar dışarıda (genellikle service’lerde) tutulur.Encapsulation ihlal edilir.Single Responsibility prensibine aykırıdır.Business logic servis katmanına sızar, bu da bakımı ve anlaşılmasını zorlaştırır.✅ Rich Domain Model Nedir?Veri ve davranış bir aradadır.Encapsulation sağlar.Nesne, kendi geçerliliğini (validity) kendi kontrol eder.Servis katmanı, modelin iç detaylarını bilmek zorunda kalmaz.Okunabilirlik, bakım ve genişletilebilirlik artar.💎 Value Object Nedir?Kimlik taşımaz (ID’sizdir).Immutable’dır, oluşturulduktan sonra değişmez.Kendi kendini valide eder.Aynı değerlere sahip iki value object eşittir.Örnek: Para birimi, mesafe, telefon numarası gibi kavramlar.📦 Entity Nedir?Kimlik (ID) taşır.Kimlik üzerinden takip edilir.Değişebilir (mutable) olabilir.Aynı değerlere sahip iki entity, farklı kimliklere sahipse farklıdır.🌐 Aggregate & Aggregate RootBirden fazla entity ve value object’i kapsayan bütün.Aggregate Root, dış dünya ile iletişimi yönetir.Aggregate root dışındaki entity’lere direkt erişilemez.Tek seferde yüklenir ve kaydedilir (atomicity sağlar).Data consistency’yi garanti eder.Versioning (Optimistic Locking) ile aynı anda birden fazla değişikliği engeller.⚒️ Effective Aggregate DesignLarge Cluster Aggregates: Çok fazla entity içerir, conflict riski yüksektir.Multiple Small Aggregates: Fazla parçalanırsa yönetimi zorlaşır.Optimal: Doğru invariant’ları kapsayan, gerektiği kadar kapsamlı aggregate’ler.Aggregates arası iletişim sadece ID üzerinden olmalıdır.Eventually Consistent yapılarla da desteklenebilir.One Aggregate per Transaction prensibi önerilir.📡 Domain EventsAggregate içinde meydana gelen önemli olayları dış dünyaya bildirir.Aggregates arası gevşek bağlı (loose coupling) iletişimi sağlar.Event Handler’lar application seviyesinde konumlanır.Event Payload sadece gerekli bilgiyi taşır, consumer’a özel veri eklenmez.Outbox Pattern ile event’lerin kaybolması engellenir.🏭 FactoryAggregate, entity veya value object üretiminden sorumludur.Karmaşık oluşturma senaryolarını kapsar.External sistemlerle entegrasyonu da yönetebilir.Modelin creation logic’ini ve business logic’ini birbirinden ayırır.🛠️ Domain ServiceBirden fazla entity veya value object ile çalışan servislerdir.State tutmaz.Genellikle entity’ler arası karşılaştırma, toplama ve işlem yapma gibi durumlarda kullanılır.Rich Model yeterliyse, domain service ihtiyacı azalır.Anemic Model riskine dikkat edilmelidir.📑 CQRS (Command Query Responsibility Segregation)Command: Veri değiştirir (insert, update, delete).Query: Veri getirir (read).Read ve write taraflarını ayırarak performans ve scalability sağlar.Eventually Consistent modellerle uyumludur.Command ve Query Handler’lar, tek bir sorumluluğu olan küçük parçalardır.🔗 Event SourcingSon durumu değil, tüm olayları saklar.Projector ile event’lerden read model (son durum) oluşturulur.Tüm değişiklikler geriye dönük izlenebilir.Append-Only yapısı performans avantajı sağlar.Event Store yönetimi, versiyonlama ve schema evrimi gibi ek zorlukları vardır.⚖️ Separation of ConcernsBüyük servisler yerine küçük command’lar ve handler’lar önerilir.Kolay test edilebilir.Error management ve transaction yönetimi event-driven olabilir.Chain of Responsibility veya Pipeline Patterns ile adımlar modülerleştirilebilir.📐 Hexagonal Architecture (Ports & Adapters)Alistair Cockburn tarafından önerilmiştir.Amaç: Uygulamanın çekirdeği ile dış dünyaya olan bağımlılıkları ayırmak.İç Çekirdek (Core): Domain ve Application Logic içerir.Port: Uygulamanın dış dünyayla iletişim kurmak için sunduğu arayüzlerdir.Adapter: Port’ların dış dünyayla (DB, API, UI, vs.) nasıl iletişim kuracağını tanımlar.UI / Rest / CLI | Adapter | Port | Application Service | Domain✅ Bağımsız test edilebilirlik✅ Teknoloji bağımlılığı minimum✅ Net sınırlar ve sorumluluklar🔗 Distributed TransactionsDağıtık sistemlerde birden fazla servis ve veri kaynağına dokunan işlemlerde transaction yönetimi zordur.ACID garantisi vermek zorlaşır.Çözüm Yolları:✅ Two-Phase Commit (2PC)✅ Saga Pattern✅ Outbox Pattern + Eventual Consistency✅ Compensation Transactions (Tersine İşlemler)✅ Two-Phase Commit (2PC)Dağıtık transaction yönetiminde klasik bir yaklaşımdır.Transaction Coordinator tüm katılımcıları yönetir.Aşamalar:Prepare Phase: Tüm katılımcılara “Hazır mısın?” sorulur.Commit Phase: Tüm katılımcılar “Hazırım” derse commit edilir. Bir hata varsa rollback yapılır.Avantajlar✅ ACID garantisi sağlar.Dezavantajlar❌ Performans problemi (bekleme süresi uzun).❌ Tek noktaya bağımlılık (Transaction Coordinator).❌ Mikroservis dünyasında önerilmez.🔄 Saga PatternBüyük bir işlemi, birbirini takip eden local transaction zincirine böler.Her adım kendi local transaction’ını yapar ve bir event fırlatır.Event’i dinleyen bir sonraki servis kendi local transaction’ını başlatır.Örnek AkışOrder Service siparişi oluşturur (local transaction).Order Service, Payment Service’e “Ödeme Al” event’i yollar.Payment Service ödeme alır (local transaction), sonra Shipping Service’e event yollar.Shipping Service kargoyu başlatır (local transaction).Avantajlar✅ Esnek ve scalable.✅ Event-Driven sistemlere uygundur.Dezavantajlar❌ Eventual consistency problemi.❌ Hata yönetimi ve retry mekanizmaları karmaşık olabilir.❌ Observability (distributed tracing) kritik hale gelir.Karşılaştırma🌟 Öneri ÖzetMonolitik veya tek bir veri kaynağına dokunan işlemler: 2PC.Mikroservisler ve asenkron süreçlerde: Saga Pattern (tercihen Choreography).Kullanıcı deneyimi çok kritikse ve hızlı geri bildirim gerekiyorsa: Outbox + Eventual Consistency.🔥 Son Notlar & ÖrneklerHer domain event, sadece bir durumu yansıtmalı.Consumer’a özel veri taşıyan event’lerden kaçınılmalı.Domain event’ler başka bounded context’lere doğrudan gönderilmemeli (anti-pattern).Domain event’ler kaybolmamalı, Outbox Pattern kullanılmalı.Transactional boundary aggregate’lere göre belirlenmeli.Bir işlemde birden fazla aggregate dokunuyorsa, bu genellikle tasarım hatasıdır.

design-patternstrendyoltechdomain-driven-designentitycqrs