C#'ta Şartlı if Yeniden Düzenleme: Derek Comartin ile Şartlı Dağınıklıktan Kaçınma
C#'ta if deyimi, if else deyimi ve switch deyimi gibi koşullu ifadeler temel araçlardır. Ama bu yapılar aşırı bir şekilde kullanıldığında — özellikle enum'larla bağlandığında — ne olur? Derek Comartin, 'Enums Kötü Değil. Her Yerde Koşullu İfadeler' videosunda, yaygın koşullu mantığı daha temiz, daha sürdürülebilir desenlerle değiştiren detaylı bir yeniden yapılandırmayı ele alıyor.
Bu makalede Derek'in gerekçeli adımlarını zaman damgalarını referans alarak inceleyeceğiz. Ayrıca onun fikirlerinin C#'taki yaygın koşullu desenlere — üçlü operatör, else ifadesi ve switch-case yapıları gibi — nasıl uygulandığını, bu yapıların büyük kod tabanlarında nasıl sorunlara yol açabileceğini ve daha iyi bir tasarım için nasıl yeniden yapılandırılabileceğini ele alacağız.
Koşullu If Patlaması: Gerçek Sorun
Derek, ürün tipini kontrol eden bir if ifadesi göstererek başlar:
if (productType == ProductType.Template || productType == ProductType.Ebook)if (productType == ProductType.Template || productType == ProductType.Ebook)İlk bakışta, yukarıdaki koşullu if basit görünüyor. Ama Derek, bu tür bir ifadenin, verilen bir durumu değerlendirip ancak durum doğruysa bir kod bloğu çalıştırdığı için tekrarlandığında problemli hale geldiği konusunda uyarıyor.
Bu bloğu başka bir metot veya sınıfta tekrar görmek mümkün:
if (offeringType == ProductType.Template || offeringType == ProductType.Ebook)if (offeringType == ProductType.Template || offeringType == ProductType.Ebook)Derek, bu desenin büyük bir sistemde hızla yayıldığını açıklar. Aynı if else mantığı birçok hizmette görünür, yeni bir enum değeri eklerken tutarsızlıklara ve hatalara neden olur. Örneğin, yeni bir ürün türü olan Video'yu eklediğinizde ne olur? Bu koşullu ifadenin bulunduğu her bloğu güncellemeniz gerektiğini hatırlamanız gerekecek.
Tekrar Karmaşıklığı Artırır
Bir sonraki örnekte, Derek iç içe geçmiş koşullu ifadelere derinlemesine girer. Bir yöntem içinde, bir if else ifadesi aynı enum'u kontrol eder ve bu sonuç başka bir yönteme iletilir, bu metod da benzer bir kontrol içerir.
İfade Şablon veya E-Kitap için kontrol yapar ve bir şey döndürür — aksi takdirde, null döner. Derek, bu tekrarın kodu sadece uzatmadığını, aynı zamanda bakım tehlikesi yarattığını belirtir. Aynı mantık birçok dosyaya kopyalanmıştır ve bu kontrol akışında kaosa yol açar.
Sisteminiz her yeniden enum eklediğinizde bir varsayılan durum eklemenizi gerektiriyorsa, bir şeylerin yanlış olduğunu bilirsiniz.
Koşullu İfadeler Hakkında Düşünme Şeklimizi Değiştirme
Sürekli if else ile türleri kontrol etmek yerine, Derek daha iyi bir soru sormayı önerir:
Ürünün indirilebilir özellikleri var mı?
Bu, amaca daha iyi bir ifadedir. Kodunuzu daha okunabilir hale getirir ve tamamen enum'a olan bağımlılığı azaltır. İki koşullu bir if ifadesi yazmak yerine:
if (product.Type == ProductType.Template || product.Type == ProductType.Ebook)if (product.Type == ProductType.Template || product.Type == ProductType.Ebook)Bu mantığı bir modelde kapsüllenebilir ve şu şekilde yazabilirsiniz:
if (product.HasDownloadableResource())if (product.HasDownloadableResource())Bu, yalnızca indirilebilir bir kaynak mevcut olduğunda true döndürür — karmaşık koşullu ifadelere olan ihtiyaçı azaltır.
If İfadelerinden Kapsüllenmiş Davranışa
Temel sorunu çözmek için Derek, bir IndirilebilirKaynak türü tanıtır. Bu tür, bir indirme URL'si ve varsayılan bir dosya adı içerir. If ifadelerine dayanmak yerine, alan modelinizin birinci sınıf bir parçası haline gelir.
Artık bunu tekrar etmek yerine:
if (product.Type == ProductType.Template)
{
// Generate file name
}
else if (product.Type == ProductType.Ebook)
{
// Generate file name
}if (product.Type == ProductType.Template)
{
// Generate file name
}
else if (product.Type == ProductType.Ebook)
{
// Generate file name
}Bunu yazabilirsiniz:
var downloadable = product.GetDownloadableResource();
if (downloadable != null)
{
Console.WriteLine(downloadable.FileName);
}var downloadable = product.GetDownloadableResource();
if (downloadable != null)
{
Console.WriteLine(downloadable.FileName);
}Bu, mantığı büyük ölçüde basitleştirir ve else durum dallarına ya da hatta bir switch ifadesine olan ihtiyaçı ortadan kaldırır.
Derleme Zamanından Çalışma Zamanına: Stratejik Bir Değişim
Derek, mantığı derleme zamanından çalışma zamanına kaydıran önemli bir tasarım seçimi açıklayarak daha da öteye gider. Bu, bir ürün için bir İndirilebilirKaynak mevcut olup olmadığını görmek için sistemi çalışma zamanında sorgulamak anlamına gelir. Eğer varsa, üzerine harekete geç. Eğer yoksa, atla.
Bu hamle, statik if else mantığını çalışma zamanlı sorgulara dönüştürür. Bir veritabanı çağrısı eklenebilir, ancak iç içe if else mantığını azaltır ve davranışı merkezileştirir. Bu, ölçeklendikçe sürdürülebilirliği artırır.
İndirilebilir Ürünler için Kalıtım Kullanımı
Derek'in incelediği diğer bir yol kalıtımdır. Soyut bir temel sınıf olarak Ürün oluşturabilir ve ardından E-Kitap, Şablon veya ÇevrimdışıKurs gibi türetilmiş türler tanımlayabilirsiniz.
Her biri, gibi yöntemleri geçersiz kılar:
public virtual string GetDownloadUrl() { ... }public virtual string GetDownloadUrl() { ... }Bu yaklaşım, her ürünün kendi mantığını ele almasına olanak tanır. Bu, bir switch ifadesinden veya birden çok koşullu ifadenin önüne geçerken, Derek yine de dikkatli olunmazsa içsel koşullu ifadeler yazabileceğinizi belirtir.
Kalıtımsız Daha İyi Kapsülleme
Kalıtım fazla sert geliyorsa, Derek Şemalı Ürün gibi açık türler kullanmayı önerir, bu kendi özellikleri ve yöntemleri içerir — bir hiyerarşiye bağlı olmaksızın.
Programınızda bu şu şekilde görünebilir:
var downloader = new DownloadableProduct(product);
Console.WriteLine(downloader.GetDefaultFileName());var downloader = new DownloadableProduct(product);
Console.WriteLine(downloader.GetDefaultFileName());Davranışı belirlemek için bir if else veya switch ifadesine gerek yoktur — her nesne ne yapacağını bilir.
Hafif Çözüm: Enum Üzerinde Uzantı Yöntemleri
Enum'lardan vazgeçmeye hazır değilseniz, Derek hafif bir çözüm önerir — uzantı yöntemi oluşturun:
public static bool IsDownloadable(this ProductType type)
{
return type == ProductType.Template || type == ProductType.Ebook;
}public static bool IsDownloadable(this ProductType type)
{
return type == ProductType.Template || type == ProductType.Ebook;
}Artık şu şekilde yazmak yerine:
if (product.Type == ProductType.Template || product.Type == ProductType.Ebook)if (product.Type == ProductType.Template || product.Type == ProductType.Ebook)Bunu basitleştirebilirsiniz:
if (product.Type.IsDownloadable())if (product.Type.IsDownloadable())Bu, mantığınızı merkezileştirir ve kıvrık parantezleri ve kod bloğunu tekrar tekrar yazma ihtiyaçını ortadan kaldırır.
Üçlü Operatörler ve Switch Aşırı Kullanımından Kaçının
Derek ayrıca üçlü operatör gibi kısa yol ifadelerini aşırı kullanmaktan kaçınmanızı öneriyor:
string filename = product.Type == ProductType.Template ? "template.pdf" : "default.pdf";string filename = product.Type == ProductType.Template ? "template.pdf" : "default.pdf";Geçerli bir sözdizimi olsa da, mantık karmaşık hale geldiğinde hataya açık ve okunması zor olabilir. Özellikle koşul yanlış olarak değerlendirilirse, yanlış değer ince bir şekilde atanabilir.
Benzer şekilde, bir break ifadesi ve varsayılan durumla birlikte switch de bu tuzağa düşer. Objelere davranışlar sormak, switch-case mantığını kullanmaktan daha iyidir.
Sonuç: Daha Az Koşullu Karmaşıklıkla Akıllı Kontrol
Sonuç olarak, Derek'in videosu aslında enumlara bir saldırı değil—onları çevreleyen koşullu if yapılarını nasıl kullandığımızın bir eleştirisidir. Kod tabanınıza if else ve switch ifadelerini yayarak, sistemi test etmeyi, bakımını ve evrimini zorlaştırırsınız.
Enkapsülasyon, çalışma zamanı arama, kalıtım veya basit uzatma yöntemlerinden hangisini seçerseniz seçin, hedef aynı kalır: koşulluları azaltın ve mantığı ait olduğu yere taşıyın.
Unutmayın:
Koşullar kötü değildir.
Koşullu karmaşıklık kötüdür.
Temiz kod, sınıflar arasında dağıtılmış çok sayıda if else ifadesine dayanmaz.
- Bağlamınızı değerlendirin ve buna göre yeniden yapılandırın.
Derek'in dediği gibi, "Bağlamınıza bağlı" Ancak bir şey kesindir: bir ürün her zaman sadece bir ürün değildir—bazen, tasarımınızı yeniden düşünmek için bir işarettir.

