# SOLID Tasarım Prensipleri: Daha İyi Yazılım Mimarisi Nasıl Oluşturulur?
Yazılım geliştirme dünyasında, karmaşık ve sürekli büyüyen projelerle başa çıkmak için sağlam bir mimariye ihtiyaç vardır. Kontrolsüz büyüyen kod tabanları, bakımı zor, hata ayıklaması zahmetli ve gelecekteki geliştirmelere açık olmayan bir yapıya dönüşebilir. İşte tam bu noktada SOLID tasarım prensipleri devreye giriyor. Bu prensipler, daha esnek, sürdürülebilir ve ölçeklenebilir yazılımlar oluşturmanıza yardımcı olan beş temel ilkeden oluşur. Bu makalede, SOLID prensiplerini adım adım, gerçek dünya örnekleriyle ve performans optimizasyon ipuçlarıyla ele alacağız.
Öğrenme Yol Haritası:
* Yeni Başlayan: Adım adım açıklama, basit kod örneği
* Orta: Gerçek hayat örneği, optimizasyon ipuçları
* İleri Düzey: Performans analizi, edge case’ler
1. Tek Sorumluluk Prensibi (Single Responsibility Principle – SRP): Bir Sınıfın Tek Bir Sorumluluğu Olmalı
Bir sınıfın sadece bir sebepten dolayı değiştirilmesi gerektiği ilkesidir. Eğer bir sınıfın birden fazla sorumluluğu varsa, bu değişikliklerin yönetimi karmaşıklaşır ve beklenmedik hatalara yol açabilir. Bir sınıfın tek bir sorumluluğu olması, kodun daha anlaşılır, daha test edilebilir ve daha sürdürülebilir olmasını sağlar.
Yeni Başlayan:
Örneğin, bir Kullanıcı sınıfının hem kullanıcı verilerini yönetmesi hem de veritabanıyla iletişim kurması doğru değildir. Bunlar ayrı sorumluluklardır. Kullanıcı sınıfı sadece kullanıcı verilerini tutmalı, veritabanı işlemleri ise ayrı bir VeritabaniYonetimi sınıfına bırakılmalıdır.
// Kötü örnek:
public class Kullanici {
public string Ad { get; set; }
public string Soyad { get; set; }
public void VeritabaninaKaydet() { // Veritabanı işlemi burada!
// ... Veritabanı kaydetme işlemleri ...
}
}
// İyi örnek:
public class Kullanici {
public string Ad { get; set; }
public string Soyad { get; set; }
}
public class VeritabaniYonetimi {
public void KullaniciKaydet(Kullanici kullanici) {
// ... Veritabanı kaydetme işlemleri ...
}
}
Orta:
Bir e-ticaret sisteminde, Urun sınıfının hem ürün bilgilerini tutması hem de fiyatlandırma hesaplamaları yapması yanlış bir tasarımdır. Fiyatlandırma, ayrı bir FiyatlandırmaHesaplayici sınıfına atanmalıdır. Bu, farklı fiyatlandırma stratejileri (indirim, kampanya vb.) eklendiğinde daha esnek bir yapı sağlar.
İleri Düzey:
Performans analizi için, VeritabaniYonetimi sınıfındaki veritabanı işlemlerinin performansını izleyebilir ve gerektiğinde optimizasyonlar (örneğin, bağlantı havuzlama, sorguları optimize etme) yapabilirsiniz. Edge case olarak, veritabanı bağlantısının kopması durumunda nasıl davranılacağını düşünmelisiniz. Hata yönetimi ve geri dönüş mekanizmaları eklemelisiniz.
2. Açık-Kapalı Prensibi (Open-Closed Principle – OCP): Sınıflar Genişlemeye Açık, Değişikliğe Kapalı Olmalı
Sınıflar yeni işlevler eklemek için kolayca genişletilebilmeli, ancak mevcut işlevselliği değiştirmek için değiştirilmemelidir. Bu, kodun daha az hata yapmasına ve daha kolay bakım yapılmasına olanak tanır.
Yeni Başlayan:
Örneğin, farklı ödeme yöntemlerini destekleyen bir sistem düşünün. Her yeni ödeme yöntemi için mevcut kodu değiştirmek yerine, bir OdemeYontemi arayüzü tanımlayıp, her ödeme yöntemi için ayrı bir sınıf oluşturabilirsiniz.
Orta:
Bir raporlama sistemi düşünün. Farklı rapor türleri (PDF, Excel, HTML) için ayrı rapor oluşturucular oluşturarak, yeni rapor türleri eklemek için mevcut kodu değiştirmenize gerek kalmaz. Bu, strateji deseni kullanılarak uygulanabilir.
İleri Düzey:
Performans analizi için, her bir ödeme yöntemi sınıfının performansını ayrı ayrı izleyebilirsiniz. Edge case olarak, bir ödeme yöntemi başarısız olduğunda, diğer ödeme yöntemlerinin de etkilenmemesi için hata yönetimi mekanizmaları eklemelisiniz.
3. Liskov Yerine Geçme Prensibi (Liskov Substitution Principle – LSP): Alt Sınıflar Üst Sınıfların Yerine Kullanılabilmeli
Alt sınıflar, üstsınıfların yerine kullanıldığında, programın davranışını değiştirmemelidir. Bu, polimorfizmin doğru bir şekilde kullanılmasını sağlar.
Yeni Başlayan:
Örneğin, bir Kare sınıfı Dikdörtgen sınıfından türetilmişse, Kare nesnelerinin Dikdörtgen nesnelerinin yerine kullanılabilmesi gerekir. Ancak, Kare‘nin kenar uzunlukları her zaman eşit olduğundan, Dikdörtgen‘in genişlik ve yüksekliğini bağımsız olarak ayarlamak mümkün değildir. Bu, LSP’yi ihlal eder.
Orta:
Bir hayvanat bahçesi simülasyonu düşünün. Hayvan sınıfından türetilen Kuş ve Balık sınıfları olsun. Hayvan sınıfında bir HareketEt() metodu varsa, hem Kuş hem de Balık sınıfları bu metodu kendi özel davranışlarıyla (uçmak, yüzmek) uygulayabilir.
İleri Düzey:
Performans analizi için, farklı hayvan sınıflarının hareket etme yöntemlerinin performansını ayrı ayrı ölçebilirsiniz. Edge case olarak, bazı hayvanların hareket edememesi durumunu (örneğin, yaralı bir hayvan) ele almalısınız.
4. Arabirim Ayrımı Prensibi (Interface Segregation Principle – ISP): Çok Büyük Arabirimlerden Kaçının
Büyük ve karmaşık arabirimler yerine, küçük ve özel amaçlı arabirimler kullanılmalıdır. Bu, sınıfların sadece ihtiyaç duydukları metodları uygulamasını sağlar ve gereksiz bağımlılıkları önler.
Yeni Başlayan:
Örneğin, bir Yazdırma arabirimi hem PDF hem de HTML çıktısı üretmeyi zorunlu kılıyorsa, bu büyük bir arabirimdir. Bunun yerine, PdfYazdirma ve HtmlYazdirma gibi ayrı arabirimler kullanmak daha iyidir.
Orta:
Bir oyun geliştirme projesinde, bir Karakter sınıfının hem hareket etmesini hem de saldırı yapmasını sağlayan tek bir arabirim yerine, HareketEdilebilir ve Saldirilabilir gibi ayrı arabirimler kullanarak daha esnek bir tasarım elde edebilirsiniz.
İleri Düzey:
Performans analizi için, her bir arabirimin uygulanmasının performansını ayrı ayrı ölçebilirsiniz. Edge case olarak, bir arabirimin uygulanmasının başarısız olması durumunu ele almalısınız.
5. Bağımlılık Ters Çevirme Prensibi (Dependency Inversion Principle – DIP): Soyutlamalara Bağımlı Olun, Somutlamalara Değil
Yüksek seviyeli modüller, düşük seviyeli modüllere değil, soyutlamalara (arayüzler, soyut sınıflar) bağımlı olmalıdır. Bu, kodun daha esnek ve test edilebilir olmasını sağlar.
Yeni Başlayan:
Örneğin, bir EmailGonder sınıfının doğrudan bir SmtpClient sınıfına bağımlı olması yerine, bir EmailGonderici arabirimi tanımlayıp, EmailGonder sınıfının bu arabirime bağımlı olması daha iyidir. Bu sayede, farklı e-posta sağlayıcılarını kullanmak için kodu değiştirmenize gerek kalmaz.
Orta:
Bir veritabanı işlemleri sınıfının doğrudan bir veritabanı sağlayıcısına (örneğin, MySQL) bağımlı olması yerine, bir VeritabaniIslemci arabirimi tanımlayıp, farklı veritabanı sağlayıcılarını bu arabirim üzerinden kullanabilirsiniz. Bu, veritabanı sağlayıcısını değiştirmeyi kolaylaştırır.
İleri Düzey:
Performans analizi için, farklı veritabanı sağlayıcılarının performansını karşılaştırabilirsiniz. Edge case olarak, veritabanı bağlantısının kopması durumunu ele almalısınız.
Performans Optimizasyonu
SOLID prensiplerini uygulayarak kodun okunabilirliğini, sürdürülebilirliğini ve test edilebilirliğini artırırken, performans optimizasyonunu da göz ardı etmemek önemlidir. Örneğin, gereksiz nesne oluşturma işlemlerini azaltmak, doğru veri yapıları seçmek ve veritabanı sorgularını optimize etmek performansı önemli ölçüde artırabilir. Profilleme araçları kullanarak kodun hangi bölümlerinin performans darboğazı oluşturduğunu tespit edebilirsiniz. [Fatih Soysal’ın blogunda](https://fatihsoysal.com) performans optimizasyonu hakkında daha fazla bilgi bulabilirsiniz.
Sonuç
SOLID tasarım prensipleri, daha iyi yazılım mimarisi oluşturmak için temel bir rehberdir. Bu prensipleri uygulamak, kodun daha esnek, sürdürülebilir, ölçeklenebilir ve daha kolay bakım yapılmasını sağlar. Ancak, her zaman tüm prensipleri tam anlamıyla uygulamak mümkün olmayabilir. Önemli olan, prensiplerin ruhunu kavrayıp, projenizin ihtiyaçlarına göre en uygun şekilde uygulamayı öğrenmektir.
Sıkça Sorulan Sorular:
1. SOLID prensiplerini öğrenmek için ne kadar zaman gerekir? Bu, önceki deneyiminize ve öğrenme hızınıza bağlıdır. Temel prensipleri anlamak için birkaç gün yeterli olabilir, ancak uzmanlık düzeyine ulaşmak zaman ve pratik gerektirir.
2. Tüm SOLID prensiplerini her zaman uygulamak zorunda mıyım? Hayır, her proje için tüm prensipleri uygulamak gerekli olmayabilir. Önemli olan, prensiplerin ruhunu kavrayıp, projenizin ihtiyaçlarına göre en uygun şekilde uygulamayı öğrenmektir.
3. SOLID prensiplerini ihlal etmek ne gibi sorunlara yol açar? SOLID prensiplerini ihlal etmek, kodun daha karmaşık, daha az sürdürülebilir, daha zor test edilebilir ve daha hata yapmaya meyilli olmasına yol açar.
4. SOLID prensiplerini öğrenmek için hangi kaynakları kullanabilirim? Bu makale ve [Fatih Soysal’ın blogu](https://fatihsoysal.com) iyi bir başlangıç noktasıdır. Ayrıca, çeşitli kitaplar ve çevrimiçi kurslar da mevcuttur.
5. SOLID prensiplerinin performans üzerinde etkisi nedir? Doğru uygulandığında SOLID prensipleri performansı olumsuz etkilemez, aksine uzun vadede daha iyi performans ve sürdürülebilirlik sağlar. Ancak, gereksiz soyutlamalar veya aşırı tasarım performansı olumsuz etkileyebilir.
Yazar: Fatih Soysal