Skip to main content
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’lar protected’tır — değer yalnızca aggregate davranışı veya interceptor üzerinden değişir.
  • IsDeleted()DeletedAt dolu 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/GetHashCode kimlik ü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ızca GetAtomicValues() ile eşitliğe katkıda bulunan alanları sıralar; Equals, GetHashCode ve operatörler taban tarafından sağlanır.
Örnek bir VO yalnızca atomik değerlerini bildirir:

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.
Somut bir event hem 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.
Örnek tanım:
Aggregate’lerde sık görülen desen: DB’de int StatusId saklanır, domain tarafında ise hesaplanan bir property enumeration’a çevirir — public UserStatus Status => UserStatus.FromValue<UserStatus>(StatusId);

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.
Aggregate ctor’larında doğrudan kullanılır: this.Id = GuidFactory.New();

DomainException

Domain kuralı ihlallerinde fırlatılan istisna tipi. API katmanında ProblemDetails ile HTTP 400’e map edilir.

Check — guard yardımcısı

Argüman doğrulamasını okunabilir tek satırlara indirir; ihlalde DomainException (gerekirse iç ArgumentException ile) fırlatır.
Çocuk entity ctor’unda tipik kullanım:

Audit, soft-delete ve tenant arayüzleri

Bu arayüzler EntityBase<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).
IRepository<T> yalnızca IAggregateRoot türlerini kabul eder. Çocuk entity’ler için doğrudan repository yoktur — onlara her zaman aggregate root üzerinden erişilir. Bu, tutarlılık sınırını derleme zamanında zorlar.
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ı.