Skip to main content
Yazılım Geliştirme

SOLID Prensipleri Detaylı Rehber: Temiz ve Sürdürülebilir Kod Yazmanın Temelleri

Mart 29, 2026 5 dk okuma 3 views Raw
SOLID prensipleri ve yazılım mimarisi
İçindekiler

SOLID Prensipleri Nedir ve Neden Önemlidir?

SOLID, Robert C. Martin (Uncle Bob) tarafından popülerleştirilen beş nesne yönelimli tasarım prensibinin baş harflerinden oluşan bir kısaltmadır. Bu prensipler, yazılımın daha anlaşılır, esnek ve bakımı kolay olmasını sağlamak için tasarlanmıştır. SOLID prensiplerini doğru uygulamak, teknik borcu azaltır, test edilebilirliği artırır ve ekip içi işbirliğini kolaylaştırır.

Yazılım projelerinin büyük çoğunluğu, ilk geliştirme sürecinden çok bakım ve geliştirme aşamasında zaman harcar. SOLID prensipleri, bu uzun vadeli bakım sürecini kolaylaştırmak için var olan en temel mimari rehberdir.

S — Single Responsibility Principle (Tek Sorumluluk Prensibi)

Tek Sorumluluk Prensibi, bir sınıfın yalnızca bir nedenden dolayı değişmesi gerektiğini belirtir. Başka bir deyişle, her sınıf tek bir işlevsellik alanından sorumlu olmalıdır.

Gerçek Dünya Örneği

Bir UserService sınıfı düşünün. Bu sınıf hem kullanıcı kaydı yapıyor, hem e-posta gönderiyor, hem de raporlama yapıyorsa, üç farklı değişim nedeni vardır. E-posta şablonu değiştiğinde, kullanıcı doğrulama kuralları değiştiğinde veya raporlama formatı değiştiğinde bu sınıf değiştirilmelidir.

Anti-Pattern: God Class

Tek Sorumluluk Prensibinin en yaygın ihlali "God Class" olarak adlandırılan devasa sınıflardır. Bu sınıflar yüzlerce metot içerir, onlarca farklı sorumluluk taşır ve zamanla bakımı imkansız hale gelir.

Refactoring İpuçları

  • Sınıfınızın ne yaptığını tek bir cümleyle açıklayamıyorsanız, muhtemelen birden fazla sorumluluğu vardır
  • "ve" kelimesini kullanmadan sınıfın amacını ifade etmeye çalışın
  • Her sorumluluğu ayrı bir sınıfa taşıyın ve bağımlılık enjeksiyonu ile birleştirin
  • Değişim nedenlerini analiz edin: farklı nedenlerle değişen kod blokları ayrılmalıdır

O — Open/Closed Principle (Açık/Kapalı Prensibi)

Açık/Kapalı Prensibi, yazılım varlıklarının (sınıflar, modüller, fonksiyonlar) genişlemeye açık ancak değişikliğe kapalı olması gerektiğini belirtir. Yeni davranış eklemek için mevcut kodu değiştirmek yerine, mevcut yapıyı genişletmeliyiz.

Strateji Deseni ile Uygulama

Bir ödeme sistemi düşünün. Kredi kartı, banka havalesi ve dijital cüzdan gibi farklı ödeme yöntemlerini desteklemeniz gerekiyor. Her yeni ödeme yöntemi eklendiğinde mevcut kodu değiştirmek yerine, bir IPaymentStrategy arayüzü tanımlayıp her ödeme yöntemi için ayrı bir uygulama oluşturabilirsiniz.

Anti-Pattern: Switch/If-Else Zincirleri

Uzun switch-case veya if-else zincirleri genellikle Açık/Kapalı Prensibinin ihlal edildiğine işaret eder. Her yeni durum eklendiğinde mevcut kodun değiştirilmesi gerekir, bu da hata riskini artırır.

Mevcut kodu değiştirmeden yeni özellik ekleyebiliyorsanız, Açık/Kapalı Prensibini doğru uyguluyorsunuz demektir.

L — Liskov Substitution Principle (Liskov Yerine Koyma Prensibi)

Barbara Liskov tarafından tanımlanan bu prensip, alt sınıfların üst sınıfların yerine sorunsuzca kullanılabilmesi gerektiğini belirtir. Bir üst sınıf referansı kullanan herhangi bir kod, alt sınıf nesnesiyle de doğru çalışmalıdır.

Klasik Örnek: Dikdörtgen ve Kare

Kare, matematiksel olarak bir dikdörtgenin özel halidir. Ancak yazılımda Square sınıfını Rectangle sınıfından türetmek Liskov prensibini ihlal eder. Dikdörtgende genişlik ve yükseklik bağımsız olarak değiştirilebilirken, karede bu davranış beklenmedik sonuçlar doğurur.

Kurallar

  1. Ön koşullar: Alt sınıf, üst sınıfın ön koşullarını güçlendiremez
  2. Son koşullar: Alt sınıf, üst sınıfın son koşullarını zayıflatamaz
  3. Değişmezler: Üst sınıfın değişmezleri alt sınıfta da korunmalıdır
  4. İstisna uyumluluğu: Alt sınıf, üst sınıfın fırlatmadığı istisnaları fırlatmamalıdır

Refactoring İpuçları

  • "is-a" ilişkisi yerine davranışsal uyumu değerlendirin
  • Alt sınıf, üst sınıfın tüm metotlarını anlamlı şekilde uygulayamıyorsa, kalıtım yerine bileşimi tercih edin
  • Üst sınıf metotlarını boş bırakmak veya istisna fırlatmak Liskov ihlalinin belirtisidir

I — Interface Segregation Principle (Arayüz Ayrımı Prensibi)

Arayüz Ayrımı Prensibi, istemcilerin kullanmadıkları metotlara bağımlı olmaya zorlanmaması gerektiğini belirtir. Büyük ve kapsamlı arayüzler yerine, küçük ve odaklanmış arayüzler tercih edilmelidir.

Şişirilmiş Arayüz Örneği

Bir IWorker arayüzü düşünün: Work(), Eat(), Sleep() metotları içeriyor. Robot bir çalışan bu arayüzü uygulamak zorunda kaldığında, Eat() ve Sleep() metotları anlamsız kalır. Çözüm, arayüzü IWorkable, IFeedable ve ISleepable olarak bölmektir.

Anti-Pattern: Fat Interface

Onlarca metot içeren arayüzler, uygulayan sınıfların kullanmadıkları metotları boş uygulamasına veya NotImplementedException fırlatmasına neden olur. Bu durum hem Liskov hem de Arayüz Ayrımı prensiplerini ihlal eder.

YaklaşımAvantajDezavantaj
Tek büyük arayüzBasit başlangıçGereksiz bağımlılıklar, test zorluğu
Küçük arayüzlerEsneklik, test kolaylığıDaha fazla dosya ve arayüz yönetimi
Rol tabanlı arayüzlerNet sorumluluk alanlarıTasarım karmaşıklığı

D — Dependency Inversion Principle (Bağımlılık Tersine Çevirme Prensibi)

Bağımlılık Tersine Çevirme Prensibi iki temel kurala dayanır: Üst seviye modüller alt seviye modüllere bağımlı olmamalıdır; her ikisi de soyutlamalara bağımlı olmalıdır. Soyutlamalar detaylara bağımlı olmamalıdır; detaylar soyutlamalara bağımlı olmalıdır.

Bağımlılık Enjeksiyonu ile Uygulama

Dependency Injection (DI), Bağımlılık Tersine Çevirme Prensibini uygulamanın en yaygın yoludur. Constructor injection, property injection ve method injection olmak üzere üç ana yöntemi vardır. Constructor injection en çok tercih edilen yöntemdir çünkü bağımlılıkları açık ve değişmez kılar.

IoC Container Kullanımı

ASP.NET Core'un yerleşik DI container'ı, Autofac, Ninject veya Unity gibi IoC container'lar bağımlılık yönetimini otomatikleştirir. Servis yaşam döngüsü (Transient, Scoped, Singleton) seçimi kritik bir karardır ve yanlış seçim bellek sızıntılarına veya paylaşılan durum sorunlarına yol açabilir.

Anti-Pattern: Service Locator

Service Locator deseni her ne kadar bağımlılıkları çözümlemek için kullanılsa da, bağımlılıkları gizlediği ve test edilebilirliği azalttığı için anti-pattern olarak kabul edilir. Constructor injection ile bağımlılıkları açıkça bildirmek her zaman tercih edilmelidir.

SOLID Prensiplerini Birlikte Uygulamak

SOLID prensipleri birbirinden bağımsız değildir; birbirini tamamlar ve güçlendirir. Tek Sorumluluk Prensibi doğal olarak küçük arayüzlere (ISP) yol açar. Açık/Kapalı Prensibi, soyutlamalara bağımlılık (DIP) ile en iyi şekilde uygulanır. Liskov Prensibi, arayüz tasarımını (ISP) doğrudan etkiler.

Adım Adım Refactoring Yaklaşımı

  1. Mevcut kodu analiz edin ve SOLID ihlallerini tespit edin
  2. Önce testler yazın (varsa mevcut testleri güçlendirin)
  3. Tek seferde yalnızca bir prensibi düzeltin
  4. Her adımda testlerin geçtiğinden emin olun
  5. Küçük adımlarla ilerleyin; büyük refactoring'ler risklidir

SOLID prensipleri dogma değildir. Pragmatik olun: basit CRUD işlemleri için karmaşık soyutlamalar oluşturmak, prensiplerin amacına aykırıdır. Karmaşıklığı yönetmek için kullanın, karmaşıklık yaratmak için değil.

Sonuç

SOLID prensipleri, yazılım geliştirmenin temel taşlarıdır ve her seviyedeki geliştiricinin bilmesi gereken kavramlardır. Bu prensipleri anlamak ve uygulamak, daha temiz, daha test edilebilir ve daha sürdürülebilir kod yazmanızı sağlar. Unutmayın, mükemmel tasarım yoktur; önemli olan sürekli iyileştirme ve pragmatik karar alma yeteneğidir. SOLID prensiplerini rehber olarak kullanarak yazılım projelerinizin kalitesini ve uzun vadeli başarısını önemli ölçüde artırabilirsiniz.

Bu yazıyı paylaş