DiyanetCleanArchitecture.Domain.SharedKernel projesi, tüm domain modelinin üzerine inşa edildiği temel yapı taşlarını içerir. Burada somut iş kuralı yoktur; yalnızca soyut taban sınıflar, arayüzler ve yardımcılar bulunur.
EntityBase<TId>
Tüm entity’lerin tabanı. Kimlik, audit izi ve soft-delete alanlarını tek yerde toplar. Setter’larprotected’tır — değer yalnızca aggregate davranışı veya interceptor üzerinden değişir.
IsDeleted()—DeletedAtdolu ise kayıt mantıksal olarak silinmiştir. Global query filter (DeletedAt == null) bu kayıtları sorgulardan otomatik dışlar.IsTransient()— henüz kalıcı kimliği olmayan (DB’ye yazılmamış) nesneyi belirtir.Equals/GetHashCodekimlik üzerinden çalışır; iki transient entity asla eşit kabul edilmez.
EntityBase (generic olmayan taban) domain event kuyruğunu tutar:
Entity : EntityBase<Guid>
Pratikte aggregate ve çocuk entity’lerin neredeyse tamamıGuid kimliklidir, bu yüzden hazır bir kısayol vardır:
Entity için IsTransient, CreatedAt set edilene kadar nesneyi geçici sayar — böylece henüz persist edilmemiş (event’i daha dispatch edilmemiş) nesneler eşitlik kıyaslamasında doğru davranır.IAggregateRoot
Boş bir marker arayüzüdür. Tutarlılık sınırının kökünü işaretler;IRepository<T> yalnızca IAggregateRoot türlerini kabul eder.
ValueObject
Kimliği olmayan, değerine göre eşitlenen nesnelerin tabanı. Türetilen sınıf yalnızcaGetAtomicValues() ile eşitliğe katkıda bulunan alanları sıralar; Equals, GetHashCode ve operatörler taban tarafından sağlanır.
DomainEvent
Tüm domain event’lerin tabanı. Her event Version 7 (zaman sıralı) GUID kimliği ve UTC zaman damgası alır.INotification ile birlikte kullanıldığında MediatR pipeline’ına girer.
DomainEvent’ten türer hem INotification’ı uygular:
Enumeration
C#enum’larının yetersiz kaldığı yerlerde kullanılan, davranış ve veri taşıyabilen tip-güvenli sabit küme deseni. Id ve Name taşır; lookup metodları ile değer/isim dönüşümü yapılır.
GuidFactory
Kimlik üretimini tek noktada toplar. Hep Version 7 (zaman sıralı) GUID üretir — bu, B-tree index’lerde daha iyi yerellik (locality) sağlar.this.Id = GuidFactory.New();
DomainException
Domain kuralı ihlallerinde fırlatılan istisna tipi. API katmanındaProblemDetails ile HTTP 400’e map edilir.
Check — guard yardımcısı
Argüman doğrulamasını okunabilir tek satırlara indirir; ihlaldeDomainException (gerekirse iç ArgumentException ile) fırlatır.
Audit, soft-delete ve tenant arayüzleri
Bu arayüzlerEntityBase<TId> tarafından otomatik uygulanır; değerleri EF Core’daki tek AuditInterceptor doldurur (detay Veri Katmanı).
Repository ve UnitOfWork arayüzleri
Domain, persistence’tan habersizdir; yalnızca arayüzleri tanımlar. Implementasyonlar Infrastructure katmanındadır (EFRepository, CachedRepository).
IRepositoryBase<T> ve IReadRepositoryBase<T>, Ardalis.Specification kütüphanesinden gelir; specification tabanlı sorgulama sağlar (FirstOrDefaultAsync(new UserByEmailSpecification(email), ct) gibi). Yazma akışında SaveChanges doğrudan değil, UnitOfWork.SaveEntitiesAsync üzerinden yapılır — bu metod kaydetme sonrası domain event’leri dispatch eder.
Sonraki adımlar
Aggregate'ler
Bu yapı taşlarının
User aggregate’inde nasıl bir araya geldiği.Value Object'ler
ValueObject üzerine kurulu hazır VO kataloğu.Domain Event'ler
DomainEvent + INotification’ın dispatch akışı.Veri Katmanı
AuditInterceptor, soft-delete filter ve SaveEntitiesAsync detayları.