Not içeriği yükleniyor...
// Markdown dosyası okunuyor
// İçerik işleniyor
// Syntax highlighting hazırlanıyor
// Markdown dosyası okunuyor
// İçerik işleniyor
// Syntax highlighting hazırlanıyor
Aggregate pattern, consistency boundaries ve transaction management. Domain boundaries belirleme ve aggregate root tasarım prensipleri.
Özellik | Açıklama |
---|---|
Kök (Root) | Her Aggregate’in bir Aggregate Root’u vardır (genellikle ana Entity) |
Tek giriş noktası | Aggregate içindeki diğer nesnelere dışarıdan doğrudan erişilmez, Root üzerinden erişilir |
Tutarlılık sınırı (Consistency Boundary) | Bir Aggregate kendi içinde tutarlı olmak zorundadır |
İş kuralları burada çalışır | Tüm domain mantığı Aggregate içinde kapsüllenmelidir |
Order
AggregateBurada:bashpublic sealed class Order : Entity { public Order (Guid id, string orderNumber, DateTime createdDate, OrderStatusEnum status) : base(id) { OrderNumber = orderNumber; CreatedDate = createdDate; Status = status; OrderLines = new List<OrderLine>(); } public string OrderNumber { get; private set; } public DateTime CreatedDate { get; private set; } public OrderStatusEnum Status { get; private set; } public ICollection<OrderLine> OrderLines { get; private set; } }
Order
= Aggregate RootOrderLine
= Aggregate’in parçası ama root değilOrder
üzerinden yapılır (AddItem, RemoveItem), doğrudan OrderLine
’a dışarıdan müdahale edilmez.bashpublic sealed class OrderLine : Entity { public OrderLine(Guid id, Guid orderId, Guid productId, int quantity, Money price) : base(id) { ProductId = productId; Quantity = quantity; Price = price; } public Guid OrderId { get; private set; } public Guid ProductId { get; private set; } public Product Product { get; private set; } public int Quantity { get; private set; } public Money Price { get; private set; } }
Order
olduğuna göre genel kuralımız neydi ?bashpublic sealed class Order : Entity { public Order(Guid id, string orderNumber, DateTime createdDate, OrderStatusEnum status) : base(id) { OrderNumber = orderNumber; CreatedDate = createdDate; Status = status; OrderLines = new List<OrderLine>(); } public string OrderNumber { get; private set; } public DateTime CreatedDate { get; private set; } public OrderStatusEnum Status { get; private set; } public ICollection<OrderLine> OrderLines { get; private set; } public void CreateOrderLine(List<CreateOrderDto> createOrder) { if (createOrder == null || !createOrder.Any()) { throw new ArgumentException("Order oluştururken sipariş kalemi olması gerekir. .", nameof(createOrder)); }; foreach (var item in createOrder) { if (item.Quantity <= 0) { throw new ArgumentException("Sipariş kalemi miktarı 0'dan büyük olmalıdır.", nameof(item.Quantity)); } if(item.Price.Amount <= 0) { throw new ArgumentException("Sipariş kalemi fiyatı 0'dan büyük olmalıdır.", nameof(item.Price)); } if (item.ProductId == Guid.Empty) { throw new ArgumentException("Sipariş kalemi ürün kimliği boş olamaz.", nameof(item.ProductId)); } var existingItem = OrderLines.FirstOrDefault(i => i.ProductId == productId); if (existingItem is not null) { existingItem.IncreaseQuantity(quantity); } var orderLine = new OrderLine(Guid.NewGuid(), Id, item.ProductId, item.Quantity, item.Price); OrderLines.Add(orderLine); } } public void RemoveOrderLine(Guid orderLineId) { var orderLine = OrderLines.FirstOrDefault(x => x.Id == orderLineId); if (orderLine == null) { throw new ArgumentException("Sipariş kalemi bulunamadı.", nameof(orderLineId)); } OrderLines.Remove(orderLine); } }
OrderItem
, bir ürünün sipariş üzerindeki temsilidir.OrderItem
’ın sadece kendi miktarını güncellemesi, onun sorumluluğudur.{
item.IncreaseQuantity(2);
}
OrderItem
'a aittir çünkü “kaç adet sipariş edildiği” bilgisi ona özgüdür.Order
) dışındaki entity'lere doğrudan dış dünyadan erişim olmamalıdır. O yüzden OrderItem
'da bu metot olabilir ama sadece Order
içinden çağrılmalıdır.
Yanlış:
Doğru:bash{ order.Items.First().IncreaseQuantity(1); // ❌ dış dünya doğrudan alt entity'yi değiştiriyor }
Yanibash{ order.AddItem(productId, name, price, quantity); // ✅ Order kontrolü yapar, içerde çağırır }
Order
Aggregate Root şöyle der:
bashpublic void AddItem(...) { var existing = _items.FirstOrDefault(...); if (existing != null) existing.IncreaseQuantity(...); else _items.Add(new OrderItem(...)); }
Order
Root Tüm Mantığı Yönetebilir mi?IncreaseQuantity
metodunu OrderItem
'dan alıp Order
içine taşıyabilirsin. Ama bu, Order
'u şişirir ve OrderItem
'ın kendi sorumluluğunu kaybettirir.
DDD'nin favori tercihi: davranışı ait olduğu yerde bırakmaktır.Soru | Cevap |
---|---|
IncreaseQuantity OrderItem içinde olabilir mi? | Evet, kesinlikle. Çünkü bu davranış ona aittir. |
Ama dış dünyadan doğrudan çağrılır mı? | Hayır. Sadece Order içinden erişilmeli. |
Başka bir yere taşımalı mıyız? | Gerek yok, davranış ait olduğu yerdedir. |