Software Architecture

Alan Olaylarını Ustalaşma: DDD'de Adlandırma, Yükler ve Çözümleme

Alan Odaklı Tasarım (DDD), stratejik netliğiyle sıkça övülür, ancak taktiksel uygulama özensizse başarısız olabilir. En kritik, ancak sıklıkla yanlış ele alınan bileşenlerden biri Alan Olayı'dır. Doğru uygulandığında, alan olayları farklı sınırlı bağlamların sıkı bir bağımlılık olmadan değişikliklere tepki vermesini sağlar. Kötü yapıldığında ise gizli bağımlılıklar ve kırılgan sistemler oluşturur.

Bu yazıda, etkili alan olayı tasarımının üç temelini inceleyeceğiz: adlandırma kuralları, yük yapısı ve çözümleme stratejileri.

Olayları Adlandırma Sanatı

Adlar sizin API'nizdir. DDD'de olay adları ne olduğunun ve ne zaman gerçekleştiğini açıkça iletmelidir. Yaygın bir hata, emir kipi fiiller veya belirsiz isimler kullanmaktır.

En İyi Uygulamalar:

  • Geçmiş Zaman Kullanın: Olaylar, zaten gerçekleşmiş şeyleri tanımlar. SiparişVerildi, SiparişVer değil.
  • Spesifik Olun: ÖdemeBaşarısızOldu, ÖdemeHatası'dan daha iyidir. Spesifiklik, aboneler için yorumlamayı azaltır.
  • Toplu Kökü Dahil Edin: Bağlam açık değilse, toplu adını öne ekleyin veya gömün. FaturaOluşturuldu vs. FaturaOnaylandı.

VarlıkGüncellendi gibi genel adlardan kaçının. Bu, tüketicilerin değişikliğin önemini anlamak için yüke bakmak zorunda kalmasına neden olur ve bu da kapsülleme ilkesini ihlal eder.

Yük Yapısı: Minimum Viable Veri

Yaygın bir anti-desen, varlığın tüm durumunu olay yüküne dökmektir. Bu iki soruna yol açar:

  1. Bilgi Sızıntısı: Aboneler, ihtiyaç duymadıkları verileri alır ve toplunun iç detayları ifşa edilir.
  2. Kırılganlık: Varlığın yapısını değiştirirseniz, tek bir alana önem verenler dahil olmak üzere her tüketiciyi bozarsınız.

"Minimum Viable Yük" Kuralı

Abonenin harekete geçmesi için gerekli olan verileri dahil edin. Abone daha fazlasına ihtiyaç duyuyorsa, kendi deposunu sorgulamalı veya ayrı bir API çağrısı yapmalıdır.

// ❌ Kötü: Her şeyi döküyor
public class OrderCreatedEvent {
    public Order Order { get; set; } // 50 alan içerir, çoğu alakasız
}

// ✅ İyi: Sadece gerekli olanlar
public class OrderCreatedEvent {
    public Guid OrderId { get; }
    public Guid CustomerId { get; }
    public DateTime CreatedAtUtc { get; }
    public decimal TotalAmount { get; }
    public Currency Code { get; }
}

OrderCreatedEvent'in, aşağı akış sistemlerinin (ör. Envanter, Faturalama) tepki vermesi için gerekli olan alanları içerdiğine dikkat edin. Nakliye Servisi daha sonra adresi aramak için yalnızca OrderId ve CustomerId gerekebilir. TotalAmount'a ihtiyacı yoktur.

Çözümleme: Asıl Amaç

Alan olaylarının birincil amacı gevşek bağlamadır. Yayıncınız abone olanları biliyorsa, çözümlememişsinizdir. Sadece bir dolaylı katman eklemişsinizdir.

Gerçek Çözümleme Stratejileri:

  1. Soyutlama Üzerinden Yayınlayın: Toplu kökü doğrudan servislere çağrı yapmamalıdır. Bunun yerine, olayları açığa çıkarır ve bir arabulucu veya olay busu bunları yayınlar.
    public class Order {
        private readonly List _events = new List();
    
        public void Place() {
            if (Status != Status.Pending) throw new DomainException("Order not pending");
            Status = Status.Placed;
            _events.Add(new OrderPlacedEvent(OrderId, CustomerId, TotalAmount, DateTime.UtcNow));
        }
    
        public List GetUncommittedEvents() => _events;
    }
  2. Entegrasyon Olaylarını Alan Olaylarından Ayrı Tutun:
    • Alan Olayları: Aynı sınırlı bağlam içinde veya iç tutarlılık için kullanılır. Senkron veya asenkron olabilirler ancak alan mantığıyla sıkı sıkıya bağlıdırlar.
    • Entegrasyon Olayları: Sınırlı bağlamlar arasında iletişim kurmak için kullanılır. Bunlar olaylı tutarlılık mesajları olmalıdır. Kararlı, sürümlenmiş ve bir aracı üzerinden (Kafka, RabbitMQ vb.) taşınmalıdır.

    İç alan olaylarınızı doğrudan bir mesaj aracısına yayınlamayın. Önce bunları entegrasyon olaylarına eşleyin. Bu, dış sözleşmeleri bozmadan iç alanınızı yeniden yapılandırmanıza olanak tanır.

Sürümleme ve Geriye Dönük Uyumluluğun Ele Alınması

Olaylar uzun ömürlü mesajlardır. Bir kez yayınlandıktan sonra, kontrol etmediğiniz sistemler tarafından tüketilebilirler. Olay şemalarını herkese açık API'ler gibi ele alın.

  • Alanları Asla Kaldırmayın: Bunun yerine yeni alanlar ekleyin. Tüketiciler bilinmeyen alanları yok sayabilir.
  • Olaylarınızı Sürümlendirin: Kırıcı bir değişiklik gerekliyse, yeni bir olay sürümü oluşturun (ör. OrderPlacedV2) ve bir geçiş dönemi boyunca ikisini paralel çalıştırın.
  • Şema Kayıtlarını Kullanın: Confluent Schema Registry gibi araçlar, dağıtım öncesinde uyumluluk kontrolleri uygular.

Sonuç

Alan olayları, DDD'de ölçeklenebilir ve çözümlenmiş sistemler inşa etmek için güçlü bir araçtır. Ancak güçleri sorumlulukla birlikte gelir. Net adlandırma kurallarına uymak, yükleri minimal ve odaklı tutmak ve alan olaylarını entegrasyon olaylarından kesin olarak ayırmak, değişikliğe dayanıklı ve evrilmeye kolay sistemler inşa etmenizi sağlar.

Unutmayın: Abonelerinizin olayın nasıl üretildiğini bilmesi gerekiyorsa, uygulama detaylarını sızdırmışsınız demektir. Sadece ne olduğunun ve ne yapmaları gerektiğinin bilmesi gerekiyorsa, iyi bir olay tasarlamışsınız demektir.

İyi kodlamalar!

Share: