Skip to main content
Bir aggregate, birlikte tutarlı kalması gereken entity ve value object’lerin oluşturduğu sınırdır. Sınırın tepesinde tek bir aggregate root durur; dışarıdan tüm erişim ve değişiklik bu root üzerinden geçer. Bu sayede iş kuralları (invariant) tek bir yerde garanti altına alınır.
Temel kural: Çocuk entity’ler dışarıya doğrudan açılmaz. User.Sessions koleksiyonuna yeni oturum eklemek için user.StartSession(...) çağrılır — user.Sessions.Add(...) değil. Repository yalnızca root için vardır.

User aggregate’i — derinlemesine

User, back-office (personel) kullanıcısını temsil eden en zengin aggregate’tir. Tüm desenleri tek örnekte gösterir.

Value object alanları

FullName, Phone, Email birer value object’tir (nullable — kullanıcı telefon veya e-posta ile kaydolabilir). Totp ise TotpConfigurationInfo VO’sudur. Setter’lar private’tır; değişim yalnızca davranış metotları üzerinden olur.

Çocuk entity’ler

internal ctor — factory zorunluluğu

Constructor internal’dır. Bu, User’ın yalnızca aynı assembly içindeki factory (UserFactory) veya domain service (UserRegistrationService) tarafından oluşturulabilmesini garanti eder. Böylece uniqueness gibi kurallar atlanamaz.
protected User() parametresiz ctor EF Core’un materializasyonu için gereklidir; internal ctor ise iş kurallarını barındırır. Oluşturma anında UserCreatedDomainEvent kuyruğa eklenir — kayıt persist edildikten sonra dispatch edilir.

UserStatus — durum makinesi

Durum, davranışı kapılayan hesaplanan property’lerle okunur:

Davranış metotları

Aggregate’in tüm yetenekleri açık niyetli (intention-revealing) metotlardır. Birkaç örnek:
RefreshSession, mevcut token’ı eşleştirip yeni token’a döndürür (rotation).
VerifyOtp/VerifyChallenge doğru kodda ilgili kanalı doğrular ve UserPhoneNumberVerifiedDomainEvent / UserEmailVerifiedDomainEvent yayar.
TotpConfigurationInfo immutable bir VO’dur; her geçiş yeni bir örnek döndürür.
InvalidateTokens(), TokenVersion’ı artırarak mevcut tüm JWT’leri geçersiz kılar.
ActivateOnExternalLogin(), başarılı dış login’de Draft/Pending kullanıcıyı Active’e geçirir; Banned/Suspended’e dokunmaz, Active ise idempotent çıkar.
Davranış metotlarında tekrar eden iki desen dikkat çeker: idempotency (aynı işlem tekrar çağrılırsa sessizce geçer) ve guard + DomainException (kural ihlalinde anlamlı hata). Yeni metot yazarken her ikisini de göz önünde bulundurun.

Citizen aggregate — User’a paralel

Citizen, vatandaş portalının kullanıcısıdır ve User ile neredeyse birebir aynı yapıya sahiptir (FullName/Phone/Email, OTP/TOTP/oturum, dış IdP, CitizenStatus). Ama ayrı bir aggregate’tir — farklı tablolar, farklı Keycloak realm’i ve farklı iş kuralları taşır. Ek olarak CitizenProfileImageInfo (profil fotoğrafı) içerir.
İki aggregate’i kasıtlı olarak ayrı tutmak, personel ve vatandaş kimlik akışlarının bağımsız evrilmesini sağlar. Ortak ihtiyaçlar value object düzeyinde (FullName, Phone…) paylaşılır.

Diğer aggregate’ler — özet

Kurum/tenant. Branch (şube) ve StaffMember (personel) çocuk entity’leri; StaffPermission izin kayıtları. AddBranch(...) gibi root metotları ile yönetilir.
RBAC rol–izin eşlemesi. Hangi rolün hangi PermissionCode’a sahip olduğunu tutar.
Bağış başvurusu bir state machine’dir: OnBasvuru → Incelemede → ... Her geçiş BagisBasvuruStatusHistory kaydı ve domain event üretir (IncelemeyeAl, Onayla, Reddet, IptalEt). BagisBasvuruPlan başvuru şablonudur.
Etkinlik başvurusu; bağış ile paralel state machine. Plan kontenjanı dolunca EtkinlikBasvuruPlanKontenjanDolduDomainEvent yayılır, iptalde kontenjan geri verilir.
Destek talebi. Çocuklar: SupportTicketComment, SupportTicketAttachment, SupportTicketStatusHistory. Atama ve durum değişiminde event yayar.
AdminNotification: SSE ile yayınlanan admin bildirimi. LegalDocument: yasal metin + LegalDocumentVersion. Center: merkez lokasyonu. SiteSettings: tekil site ayarı. District: int kimlikli sabit ilçe referans verisi.

Tüm aggregate tablosu

Sonraki adımlar

Value Object'ler

Aggregate alanlarında kullanılan VO kataloğu.

Domain Event'ler

AddDomainEvent ile yayılan olayların dispatch akışı.

Factory ve Servisler

internal ctor’lu aggregate’ler nasıl oluşturulur.

SharedKernel

Entity, Enumeration ve guard altyapısı.