TB
← Tüm yazılar

Domain olaylari

Domain-driven design bağlamında domain olaylarinin tasarımı, uygulamasi, persistence stratejileri ve sistemler arasi yayilim modellerini ele aliyoruz.

Domain event, domainde anlamli bir seyin gerceklestigini bildiren, zamana bağlı kayittir. OrderPlaced, PaymentCaptured, InventoryReserved gibi olaylar is dilinin dogal ifadesidir. Domain eventler yalnizca mesajlasma altyapisi icin degil; aggregate icindeki tutarlılık, audit ve sistemler arasi entegrasyon icin güçlü bir modelleme aracidir.

Domain event vs integration event

Domain event: Bounded context icinde anlamli; genellikle past tense isim. Integration event: Dis sistemlere yayilan mesaj; schema ve surumleme gerektirir. Domain event integration evente cevrilir; birebir ayni olmak zorunda degildir.

// Domain event
public sealed record OrderPlaced(
    OrderId OrderId,
    CustomerId CustomerId,
    Money Total,
    DateTimeOffset OccurredAt);

// Integration event (public contract)
public sealed record OrderPlacedIntegrationV1(
    string OrderId,
    decimal TotalAmount,
    string Currency,
    string OccurredAtUtc);

Aggregate ve event uretimi

Aggregate is kuralini uygular ve domain event biriktirir:

public class Order
{
    private readonly List<IDomainEvent> _events = new();

    public static Order Place(CustomerId customer, IReadOnlyList<Line> lines)
    {
        var order = new Order { ... };
        order.Raise(new OrderPlaced(...));
        return order;
    }

    private void Raise(IDomainEvent e) => _events.Add(e);
    public IReadOnlyList<IDomainEvent> DomainEvents => _events;
}

Eventler aggregate disina cikmadan once transaction icinde islenir veya outbox ile yayinlanir.

Event tasarım ilkeleri

  • Past tense: Olan seyi anlatir, emir degil.
  • Immutable: Record veya readonly property.
  • Minimal: Gereksiz veri tasimaz; tuketici ihtiyacina gore zenginlestirilebilir.
  • Surumlenebilir: Breaking change yeni tip veya schema version.

Dispatched pipeline

SaveChanges sonrasi domain eventler dispatch edilir:

  1. Handler ayni transaction icinde (senkron side effect).
  2. Outbox tablosuna yazilir; background worker yayinlar.
  3. Event store append-only loga eklenir.

Ayni transaction icinde cok handler dikkatli kullanılmalı; coupling artar.

Outbox pattern

Veritabanı yazimi ile mesaj yayini atomik olmali. Outbox tablosu ayni transactionda dolar; worker mesaji broker'a gonderir ve isaretler. Bu en az bir kez teslimat sağlar; tuketici idempotent olmali.

Eventual consistency

Domain eventler genellikle eventual consistency getirir. UI aninda guncellenmeyebilir; kullanıcıya geri bildirim tasarlanmali. Saga ve process manager uzun is akislarini koordine eder.

Event sourcing iliskisi

Event sourcing domain eventleri kalıcı durum olarak kullanır. Domain event kullanmak event sourcing zorunlu degildir. Event sourcing ek karmasiklik getirir; ihtiyaç olmadan secilmemeli.

CQRS ve read model

Domain eventler read model projeksiyonunu gunceller. Write model aggregate korur; read model sorgu icin optimize edilir. Gecikme kabul edilebilir raporlama senaryolarinda güçlü kalıptir.

Test stratejisi

Aggregate unit testinde event varligi assert edilir:

var order = Order.Place(customerId, lines);
order.DomainEvents.Should().ContainSingle(e => e is OrderPlaced);

Handler testleri fake repository ile yan etkiyi dogrular.

Yaygın hatalar

  • Anemic event: sadece CRUD bildirimi, is anlami yok.
  • Büyük event: tüm aggregate grafigini tasimak.
  • Sync broker çağrısı transaction icinde: tutarlılık riski.
  • Event isimlendirme present tense: PlaceOrder command ile karistirma.

Surumleme ve schema

Integration eventler schema registry ile yönetilir. Geriye uyumlu ekleme (optional alan) tercih edilir. Breaking change yeni topic veya sürüm numarasi gerektirir.

Güvenlik ve PII

Eventler log ve kuyrukta dolasir. PII maskeleme veya tokenization dusunulmeli. Hassas alanlar ayri encrypted channel veya minimal payload ile tasınır.

Özet

Domain eventler is olaylarini kodda açık modeller. Aggregate icinde uretilir, outbox ile guvenle yayilir, integration event ile sınır otesine gecer. Past tense, immutable tasarım ve idempotent tüketim ile olgun event-driven mimari insa edilir.

Event catalog

Organizasyon olceginde event catalog tüm domain ve integration eventleri listeler. Sahip ekip, schema, SLA ve tuketici listesi tutulur. Kesif ve onboarding kolaylasir.

Debugging

Correlation ID event metadata icinde tasınır. Distributed trace ile uctan uca akis izlenir. Dead letter queue ve replay araci operasyonel zorunluluktur.

Moduler monolit icinde event

Ayni process icinde in-memory event bus moduller arasi coupling azaltir. Ileride broker cikarmak icin adapter yazilir; domain event degismez.

Ordering ve causality

Ayni aggregate icinde event sırası garanti edilir. Farklı aggregate arasinda global sıra genellikle gerekmez. Partition key aggregate ID olmali.

Idempotency key

Tuketici idempotency store tutar. Ayni event iki kez geldiginde yan etki tekrarlanmaz. Event ID veya business key kullanılır.

Temporal query

Event stream uzerinden belirli zamandaki durum sorgulanabilir. Audit ve debug icin degerlidir. Event sourcing olmadan da kisa sureli event log tutulabilir.