C# ile Rule (Kural) Nasıl Yapılır?
Modern yazılım mimarilerinde, iş mantığını (business logic) kodun geri kalanından ayırmak, sürdürülebilir bir uygulama geliştirmenin temelidir. C# projelerinizde Rule (kural) nasıl yapılır sorusu, özellikle karmaşık doğrulama süreçlerinde veya dinamik karar mekanizmalarında karşımıza çıkar. Bu rehberde, kurallarınızı merkezi bir yapıda yönetmenizi sağlayacak "Specification" ve "Rule Engine" (kural motoru) desenlerini adım adım inceleyeceğiz.
Bu makale, temiz kod (clean code) prensiplerini benimseyen ve uygulama katmanındaki "if-else" karmaşasından kurtulmak isteyen C# geliştiricileri için hazırlanmıştır. 2026 yılı standartlarına uygun olarak, modern .NET yapısını kullanarak kuralları nasıl modüler hale getireceğinizi öğreneceksiniz.
Gereksinimler ve Ön Hazırlık
Bu eğitimdeki örnekleri uygulayabilmek için sisteminizde .NET 9 veya .NET 10 SDK'nın yüklü olması önerilir. Geliştirme ortamı olarak Visual Studio 2026 veya VS Code kullanabilirsiniz.
- .NET SDK: 9.0 veya üzeri sürüm.
- IDE: Visual Studio 2026, JetBrains Rider veya VS Code.
- Bilgi Seviyesi: C# temel sözdizimi, Interface (Arayüz) mantığı ve Dependency Injection (Bağımlılık Enjeksiyonu) kavramlarına aşinalık.
Adım 1: Temel Kural Arayüzünü Tanımlama
Bir kuralın neyi temsil ettiğini belirlemek için ilk adım, standart bir arayüz oluşturmaktır. Bu arayüz, tüm kurallarınızın aynı sözleşmeye (contract) uymasını sağlar. Böylece kural motorunuz, hangi kuralın çalıştığını bilmeden onu tetikleyebilir.
public interface IRule
{
bool IsSatisfied(T entity);
string ErrorMessage { get; }
}
Bu arayüz, T tipindeki herhangi bir nesne üzerinde doğrulama yapmamızı sağlar. IsSatisfied metodu kuralın geçip geçmediğini dönerken, ErrorMessage hata durumunda kullanıcıya neyi düzeltmesi gerektiğini söyler.
Adım 2: Spesifik Bir Kural Sınıfı Oluşturma
Şimdi, bir kullanıcı kaydı için "Şifre Uzunluğu" kuralını oluşturalım. Bu adım, iş mantığını sınıflara nasıl böleceğimizi gösterir.
public class PasswordLengthRule : IRule
{
public string ErrorMessage => "Şifre en az 8 karakter olmalıdır.";
public bool IsSatisfied(User user)
{
return user.Password != null && user.Password.Length >= 8;
}
}
Bu sınıf, sadece şifre uzunluğunu kontrol eder. Kuralın tek bir sorumluluğu vardır (Single Responsibility Principle). Bu sayede test edilmesi ve bakımı oldukça kolaydır.
Adım 3: Kural Motoru (Rule Engine) Tasarımı
Birçok kuralınız olduğunda bunları tek tek çağırmak yerine bir motor kullanmak en mantıklı yoldur. Kural motoru, kurallar listesini alır ve hepsini sırayla kontrol eder.
public class RuleEngine
{
private readonly List _rules = new();
public void AddRule(IRule rule) => _rules.Add(rule);
public List Validate(T entity)
{
var errors = new List();
foreach (var rule in _rules)
{
if (!rule.IsSatisfied(entity))
{
errors.Add(rule.ErrorMessage);
}
}
return errors;
}
}
Bu motor, belirlenen tüm kuralları çalıştırır ve başarısız olanların hata mesajlarını bir liste halinde döndürür. Bu yapı, if-else bloklarını kodunuzun merkezinden uzaklaştırır.
Adım 4: Kuralların Uygulanması ve Test Edilmesi
Artık oluşturduğumuz yapıyı bir senaryoda kullanalım. Bir kullanıcı nesnesini doğrulamak için motorumuzu devreye alıyoruz.
var engine = new RuleEngine();
engine.AddRule(new PasswordLengthRule());
engine.AddRule(new EmailFormatRule()); // Varsayımsal başka bir kural
var user = new User { Password = "123", Email = "gecersiz-email" };
var errors = engine.Validate(user);
if (errors.Any())
{
Console.WriteLine("Doğrulama Hataları:");
errors.ForEach(e => Console.WriteLine($"- {e}"));
}
Bu örnekte, Validate metodu çağrıldığında tüm kurallar çalışır ve kullanıcıya hatalar raporlanır. Bu yöntem, özellikle web API projelerinde model doğrulama süreçleri için oldukça güçlüdür.
Kural Yönetim Yöntemlerinin Karşılaştırılması
| Yöntem | Avantaj | Dezavantaj |
|---|---|---|
| If-Else Blokları | Hızlı ve basit | Kod karmaşası (Spagetti) |
| Specification Deseni | Modüler ve test edilebilir | Daha fazla dosya yönetimi |
| Rule Engine Kütüphaneleri | Gelişmiş özellikler | Dış bağımlılık (Third-party) |
Adım 5: Güvenlik ve Performans İpuçları
Kuralları uygularken dikkat etmeniz gereken en önemli husus, doğrulama mantığının dışarıdan manipüle edilememesidir. Özellikle veritabanı sorgusu içeren kurallarda "SQL Injection" riskine karşı mutlaka parametreli sorgular veya ORM (Entity Framework Core) kullanın.
Kritik Güvenlik Uyarısı: Kullanıcıdan alınan verilerle kurallar oluştururken, asla ham veriyi doğrudan sorgu içine gömmeyin. Her zaman veriyi temizleyin (sanitize) ve doğrulama mantığınızı sunucu tarafında (server-side) mutlaka tekrar çalıştırın.
Performans için, çok sık çalışan kurallarda ağır veritabanı sorgularından kaçının. Mümkünse kuralları async hale getirerek I/O işlemlerini optimize edin.
public interface IAsyncRule
{
Task IsSatisfiedAsync(T entity);
string ErrorMessage { get; }
}
Sıkça Sorulan Sorular
Kurallarımı veritabanından dinamik olarak yükleyebilir miyim?
Evet, kuralları bir veritabanı tablosunda saklayıp, çalışma zamanında (runtime) yansıma (reflection) kullanarak veya bir kural motoru kütüphanesi ile yükleyebilirsiniz.
Çok sayıda kural olduğunda performans kaybı yaşanır mı?
Kural sayısı binleri bulmadığı sürece performans farkı ihmal edilebilir düzeydedir. Ancak, her kuralda veritabanı sorgusu yapmamaya dikkat etmelisiniz.
Hangi durumlarda Rule Engine kullanmalıyım?
Eğer uygulamanızdaki iş kuralları sık değişiyorsa veya aynı doğrulama mantığını farklı yerlerde (örneğin hem web hem mobil API) kullanıyorsanız bu desen hayat kurtarıcıdır.
Kural motoru yerine FluentValidation kullanmalı mıyım?
FluentValidation, .NET dünyasında standart haline gelmiş harika bir kütüphanedir. Eğer karmaşık bir kural motoru yazmak yerine hızlıca çözüme ulaşmak istiyorsanız, FluentValidation kullanmanız şiddetle tavsiye edilir.
Hata mesajlarını nasıl yerelleştirebilirim?
ErrorMessage özelliğini doğrudan string olarak vermek yerine, bir IStringLocalizer kullanarak kaynak dosyalarından (resource files) çekebilirsiniz.
Gelişmiş Senaryo: Kuralları Zincirleme (Rule Chaining) ve Önceliklendirme
Gerçek dünya senaryolarında kurallar genellikle birbirinden bağımsız çalışmaz. Bir kuralın çalışması, kendisinden önce
Sonuç
C# ile kural yapısı oluşturmak, uygulamanızın kalitesini ve sürdürülebilirliğini doğrudan etkileyen bir süreçtir. Bu rehberde öğrendiğiniz arayüz tabanlı yaklaşım sayesinde, kodunuzu daha temiz, test edilebilir ve genişletilebilir hale getirdiniz. Bir sonraki adım olarak, projenize FluentValidation kütüphanesini entegre ederek, yazdığınız bu manuel kuralları nasıl daha profesyonel bir seviyeye taşıyabileceğinizi araştırmanızı öneririm.
Sorumluluk Reddi: Bu rehberdeki kod örnekleri eğitim amaçlıdır. Üretim ortamındaki uygulamalarınızda güvenlik açıklarına karşı her zaman güncel kütüphaneleri kullanın ve kodunuzu güvenlik taramalarından geçirin.


Yorumlar (0)
Yorum Yaz