Alan Odaklı Tasarımda Record'lar
Değişmezliği zorunlu kılmak ve kodun açıklığını artırmak için değer nesnelerini, DTO'ları ve alan olaylarını record olarak modelleyin.
Alan Odaklı Tasarımda Record'lar, CoddyKit'te ücretsiz bir C# Academy dersidir. Bu, 4 dersinin 4. dersidir. Aşağıdan dersin tamamını ücretsiz okuyabilir, sonra tarayıcıda yerleşik kod editörü ve 7/24 yapay zeka koçu ile uygulamalı olarak pratik yapabilirsin. Bu, C# Academy öğrenme yolunun bir parçasıdır ve ilerlemeniz web ve CoddyKit uygulaması arasında senkronize olur. C# Academy kursu toplamda 4 dersten oluşur.
DDD ve Değer Nesneleri
Etki Alanı Odaklı Tasarımda (DDD), bir Değer Nesnesi kimliğiyle değil, özellikleriyle tanımlanır. Money(100, "USD") değerlerinden ikisi birbirinin yerine kullanılabilir. Kayıt türleri, değer nesneleri için mükemmel C# gösterimleridir.
Değer Nesnelerini Kayıt Türü Olarak Modelleme
Etki alanı değer nesnelerini kayıt türleri olarak modelleyin. Yapısal eşitlikleri, değişmezlikleri ve özlü söz dizimleri DDD ilkeleriyle mükemmel biçimde örtüşür.
// Value objects — defined by their values, not identity
public record Money(decimal Amount, string Currency);
public record Email(string Value);
public record PhoneNumber(string CountryCode, string Number);
public record Address(string Street, string City, string Country, string PostalCode);
// Two Money objects with same values are equal:
var price = new Money(99.99m, "USD");
var same = new Money(99.99m, "USD");
Console.WriteLine(price == same); // TrueDeğer Nesnesi Kurucularında Doğrulama
Değişmezleri doğrulamak için kısa bir kurucu ekleyin. Değer nesneleri yalnızca geçerli bir durumda oluşturulabilmelidir — geçersiz durum, oluşturma sırasında hata vermelidir.
public record Email(string Value)
{
// Compact constructor for validation
public Email : this(Value)
{
if (string.IsNullOrWhiteSpace(Value) || !Value.Contains('@'))
throw new ArgumentException("Invalid email address", nameof(Value));
Value = Value.Trim().ToLowerInvariant();
}
}
// Usage:
var email = new Email(" Alice@Example.COM "); // normalized to alice@example.com
new Email("not-an-email"); // throws ArgumentExceptionVarlıklar ve Değer Nesneleri
Varlıkların kimliği vardır (zaman içinde ID ile izlenir); Değer Nesnelerinin kimliği yoktur ve değerleri eşleştiğinde birbirlerinin yerine kullanılabilirler. Bunları C#'ta farklı şekilde modelleyin.
// ENTITY: has identity, mutable state
public class Customer
{
public Guid Id { get; } = Guid.NewGuid();
public string Name { get; set; } = "";
public Email Email { get; set; } = default!; // value object
}
// VALUE OBJECT: no identity, immutable
public record Email(string Value);
public record Money(decimal Amount, string Currency);
// Two customers with same name are DIFFERENT entities
// Two Money(100, "USD") are the SAME valueEtki Alanı Yöntemleri İçeren Zengin Değer Nesneleri
Değer nesneleri, etki alanı mantığını yöntemler olarak içerebilir. İşlemler mevcut nesneyi değiştirmek yerine yeni değer nesneleri döndürür.
public record Money(decimal Amount, string Currency)
{
public Money Add(Money other)
{
if (Currency != other.Currency)
throw new DomainException("Cannot add different currencies");
return this with { Amount = Amount + other.Amount };
}
public Money Subtract(Money other) =>
Amount >= other.Amount
? this with { Amount = Amount - other.Amount }
: throw new DomainException("Insufficient funds");
public Money ApplyDiscount(decimal percent) =>
this with { Amount = Amount * (1 - percent / 100) };
public static Money Zero(string currency) => new(0, currency);
}Kayıt Türü Olarak Etki Alanı Olayları
Etki alanı olayları, etki alanında gerçekleşen şeyleri açıklar. Kayıt türleri bu iş için idealdir: değişmezdir, açıklayıcıdır ve yapısal eşitlik kullanmaları sınamayı kolaylaştırır.
// Domain events as records
public abstract record DomainEvent(DateTime OccurredAt);
public record OrderPlaced(
Guid OrderId,
Guid CustomerId,
Money Total,
DateTime OccurredAt) : DomainEvent(OccurredAt);
public record OrderShipped(
Guid OrderId,
string TrackingNumber,
DateTime OccurredAt) : DomainEvent(OccurredAt);
public record PaymentReceived(
Guid OrderId,
Money Amount,
DateTime OccurredAt) : DomainEvent(OccurredAt);Kayıt Türü Olarak DTO'lar ve API Sözleşmeleri
İstek ve yanıt DTO'ları doğal olarak değer nesneleridir — kimlik taşımaz, veri taşırlar. Kayıt türleri onları özlü ve değişmez hâle getirir.
// Request DTOs
public record CreateOrderCommand(
Guid CustomerId,
IReadOnlyList<OrderLineDto> Lines);
public record OrderLineDto(Guid ProductId, int Quantity);
// Response DTOs
public record OrderCreatedResponse(
Guid OrderId,
string Status,
decimal Total,
DateTime CreatedAt);
// These can be compared in tests by value:
var expected = new OrderCreatedResponse(id, "Pending", 99m, now);
Assert.Equal(expected, actual);Değer Nesnelerini EF Core'da Saklama
Değer nesnelerini EF Core'da kalıcı hâle getirmek için sahip olunan varlıkları kullanın. Her değer nesnesinin özellikleri, ayrı bir PK olmadan sahibinin tablosunda (veya ayrı bir tabloda) saklanır.
public class Order
{
public int Id { get; set; }
public Money Total { get; set; } = new(0, "USD");
public Address ShipTo { get; set; } = default!;
}
// EF Core config:
modelBuilder.Entity<Order>(e =>
{
e.OwnsOne(o => o.Total, money =>
{
money.Property(m => m.Amount).HasColumnType("decimal(18,2)");
money.Property(m => m.Currency).HasMaxLength(3);
});
e.OwnsOne(o => o.ShipTo);
});Değer Nesneleriyle Toplama Kökü
Tümünü bir araya getirelim: değer nesneleri ve etki alanı olayları için kayıt türlerini kullanan bir Order toplama kökü; tüm iş kuralları yöntemlerde uygulanır.
public class Order
{
private readonly List<DomainEvent> _events = new();
public IReadOnlyList<DomainEvent> DomainEvents => _events;
public Guid Id { get; } = Guid.NewGuid();
public Address ShipTo { get; private set; } = default!; // value obj
public Money Total { get; private set; } = Money.Zero("USD");
public void PlaceOrder(Address shipTo, IEnumerable<OrderLine> lines)
{
ShipTo = shipTo;
Total = lines.Aggregate(Money.Zero("USD"),
(acc, l) => acc.Add(l.Price));
_events.Add(new OrderPlaced(Id, CustomerId, Total, DateTime.UtcNow));
}
}Gerçek Dünya: Tür Güvenli Kimlikler
İlkel ID değerlerini sarmalamak ve farklı varlıkların ID değerlerinin yanlışlıkla birbirine karıştırılmasını önlemek için kayıt türlerini kullanın — bu, DDD'de "Güçlü Türlendirilmiş Kimlikler" adı verilen yaygın bir tekniktir.
// Strongly typed IDs — can't confuse CustomerId with OrderId
public record CustomerId(Guid Value)
{
public static CustomerId New() => new(Guid.NewGuid());
public static implicit operator Guid(CustomerId id) => id.Value;
}
public record OrderId(Guid Value)
{
public static OrderId New() => new(Guid.NewGuid());
}
// Type safety:
void ShipOrder(OrderId orderId, CustomerId customerId) { }
ShipOrder(OrderId.New(), CustomerId.New()); // OK
ShipOrder(CustomerId.New(), OrderId.New()); // COMPILE ERROR!Hızlı Kontrol
Bir DDD Değer Nesnesini ne tanımlar ve kayıt türleri neden doğal bir seçimdir?
Özet: Etki Alanı Odaklı Tasarımda Kayıt Türleri
Önemli çıkarımlar:
- Değer Nesneleri: değerleriyle tanımlanır, kimlikleri yoktur — kayıt türlerini kullanın
- Varlıklar: kimlikleri (ID) ve değişebilir durumları vardır — sınıfları kullanın
- Değişmezleri kısa kurucularda doğrulayın — geçersiz durum temsil edilemez
- Kayıt türü olarak etki alanı olayları: değişmez, karşılaştırılabilir ve kendi kendini açıklayıcıdır
- Değer nesnelerini kalıcı hâle getirmek için EF Core sahip olunan varlıkları
- Kayıt türleriyle oluşturulan güçlü türde ID değerleri, varlık ID'lerinin karıştırılmasını önler
Sıkça Sorulan Sorular
“Alan Odaklı Tasarımda Record'lar” dersi ücretsiz mi?
Evet — “Alan Odaklı Tasarımda Record'lar” dersin tüm metni burada web'de ücretsiz olarak okunabilir. Etkileşimli olarak pratik yapmak (yerleşik kod editörü ve 7/24 yapay zeka koçu) ve C# Academy kursunun geri kalanını açmak için CoddyKit PRO'ya yükselt. C# Academy kursu toplamda 4 dersten oluşur.
“Alan Odaklı Tasarımda Record'lar” dersinde ne öğreneceğim?
Değişmezliği zorunlu kılmak ve kodun açıklığını artırmak için değer nesnelerini, DTO'ları ve alan olaylarını record olarak modelleyin. C# Academy ile uygulamalı kodu tarayıcıda doğrudan çalıştırarak pratik yaparsın ve 7/24 yapay zeka koçu dersi çalışırken sorularını yanıtlar.
C# Academy öğrenmeye başlamak için deneyim gerekli mi?
Önceden deneyim gerekmez. CoddyKit'te C# Academy, başlangıçtan ileri seviyeye kadar yapılandırıldığı için buradan başlayabilir veya başından başlayıp kendi hızında ilerleme yapabilirsin. Bu, 4 dersinin 4. dersidir.
“Alan Odaklı Tasarımda Record'lar” dersi ne kadar sürer?
Çoğu CoddyKit dersi yaklaşık 5–10 dakika sürer. Her biri kısa ve etkileşimli olduğu için sabit ilerleme yaparsın ve web ile uygulama arasında tam olarak bıraktığın yerden devam edebilirsin.
Bu C# Academy dersinde kod yazıp çalıştırabilir miyim?
Evet. Her C# Academy dersi yerleşik bir kod editörü içerir, bu sayede tarayıcıda gerçek kod yazıp çalıştırabilir ve anlık yapay zeka geri bildirimi alırsın — yerel kurulum gerekli değildir.
Bu kursun tüm dersleri
- Record Türleri: Temeller ve Sözdizimi
- init ve with ile Değişmezlik
- Değer Eşitliği ve Yapıdan Çıkarma
- Alan Odaklı Tasarımda Record'lar