SOLID Prensipleri: Yazılım Geliştirmenin Beş Temel Taşı
18 Şubat 2025
Bir bina inşa ederken temeli ne kadar sağlam olursa, yapı o kadar dayanıklı olur. Yazılım dünyasında da sağlam bir temel oluşturmanın en iyi yollarından biri SOLID prensiplerini takip etmektir. SOLID, Robert C. Martin (namıdiğer Uncle Bob) tarafından ortaya atılan ve bakımı kolay, genişletilebilir ve sürdürülebilir yazılım geliştirmeyi sağlayan beş temel prensibi ifade eder.
Bu yazıda, SOLID prensiplerini hem teknik hem de günlük hayattan örneklerle ele alacağız.
1) Single Responsibility Principle (SRP) - Tek Sorumluluk Prensibi
"Bir sınıfın sadece tek bir amacı olmalıdır."
Bir sınıf yalnızca bir sorumluluğa sahip olmalı ve bu sorumlulukla ilgili değişiklikler nedeniyle güncellenmelidir. Eğer bir sınıf birden fazla amaca hizmet ediyorsa, bir değişiklik diğer özellikleri de etkileyebilir ve kodun bakımı zorlaşır.
Gerçek Hayat Örneği
Bir restoran düşünelim. Şef yemekleri yapmaktan, garson sipariş almaktan, muhasebeci ise finansları yönetmekten sorumludur. Eğer şefe sipariş alma ve finans yönetme görevlerini de yüklersek, bu hem restoranın işleyişini zorlaştırır hem de şefin yemek yapma kalitesini düşürür.
-Yanlış Kullanım (SRP'ye Uymayan Kod)
public class Report
{
public void GenerateReport() { /* Rapor oluşturma kodu */ }
public void SaveToDatabase() { /* Veriyi veritabanına kaydetme kodu */ }
public void SendEmail() { /* E-posta gönderme kodu */ }
}
Bu sınıf hem rapor oluşturuyor, hem veritabanına kaydediyor hem de e-posta gönderiyor. 3 farklı sorumluluğu var!
-Doğru Kullanım (SRP'yi Uygulayan Kod)
public class ReportGenerator { public void GenerateReport() { /* Rapor oluşturma kodu */ } }
public class ReportSaver {public void SaveToDatabase() { /* Veriyi veritabanına kaydetme kodu */ } }
public class EmailSender { public void SendEmail() { /* E-posta gönderme kodu */ } }
Her sınıf yalnızca tek bir sorumluluğa sahiptir. Böylece, rapor oluşturma, kaydetme ve e-posta işlemleri birbirinden bağımsız hale gelir.
2) Open/Closed Principle (OCP) - Açık/Kapalı Prensibi
"Bir sınıf genişletilebilir olmalı, ancak değiştirilemez olmalıdır."
Kodumuz, yeni özellikler eklenmeye açık olmalı, ancak mevcut kod değişikliğe kapalı olmalıdır. Böylece eski kodu değiştirmeden, yeni özellikler ekleyebiliriz.
Gerçek Hayat Örneği
Telefonlarımızın işletim sistemi güncellenebilir, ancak cihazın iç yapısını değiştirmemiz gerekmez. Yani, iOS veya Android'e yeni özellikler eklenebilir, ancak temel sistem aynı kalır.
-Yanlış Kullanım (OCP'ye Uymayan Kod)
public class PaymentProcessor
{
public void ProcessPayment(string paymentType)
{
if (paymentType == "CreditCard") { /*Kredi kartı işlemleri */}
else if (paymentType == "PayPal") { /*PayPal işlemleri*/ }
}
}
Yeni bir ödeme yöntemi eklemek istediğimizde mevcut kodu değiştirmek zorunda kalırız!
-Doğru Kullanım (OCP'yi Uygulayan Kod)
public interface IPaymentMethod { void ProcessPayment(); }
public class CreditCardPayment : IPaymentMethod { public void ProcessPayment() { /* Kredi kartı işlemleri */ } }
public class PayPalPayment : IPaymentMethod { public void ProcessPayment() { /* PayPal işlemleri */ } }
public class PaymentProcessor
{
public void ProcessPayment(IPaymentMethod paymentMethod)
{ paymentMethod.ProcessPayment(); }
}
Artık yeni bir ödeme yöntemi eklemek için IPaymentMethod arayüzünü kullanarak yeni bir sınıf eklememiz yeterli! Mevcut kod değişmeden kalıyor.
3) Liskov Substitution Principle (LSP) - Liskov Yerine Koyma Prensibi
"Türetilmiş sınıflar, temel sınıfın yerine kullanılabilmelidir."
Bir alt sınıf, üst sınıfın yerine kullanılabilir olmalıdır.
-Yanlış Kullanım (LSP'ye Uymayan Kod)
public class Bird { public virtual void Fly() { /* Uçma kodu */ } }
public class Penguin : Bird
{
public override void Fly() { throw new Exception("Penguenler uçamaz!"); }
}
Bird sınıfı "uçma" özelliği barındırıyor, ancak Penguin uçamaz! Bu, LSP'yi ihlal eder.
-Doğru Kullanım (LSP'yi Uygulayan Kod)
public abstract class Bird { }
public class FlyingBird : Bird { public void Fly() { /* Uçma kodu */ } }
public class Penguin : Bird { /* Penguenler uçamaz, ama sorun da çıkmaz */ }
Şimdi Penguin, Fly() metodunu devralmıyor ve hata oluşmuyor.
4) Interface Segregation Principle (ISP) - Arayüz Ayrımı Prensibi
"Sınıflar ihtiyacı olmayan metotları içeren arayüzleri kullanmamalıdır."
5) Dependency Inversion Principle (DIP) - Bağımlılığı Tersine Çevirme Prensibi
"Sınıflar, soyutlamalara bağımlı olmalı, somut sınıflara değil."
Sonuç olarak SOLID prensipleri daha kaliteli, verimli, okunabilir ve taşınabilir kod yazmamızı sağlar.
Yorumlar
gerçekten verimli bir yazı olmuş tebrik ederim