S.O.L.I.D. Prensipleri

Evren Vural
HardwareAndro
Published in
3 min readJul 19, 2020

S.O.L.I.D Prensipleri, Robert Martin (Uncle Bob) tarafından bizlere sunulmuş Nesne Yönelimli Programlamanın temellerini oluşturan yazılımsal tasarım kurallarıdır.

Bu kuralların genel amacı; yazdığımız kodu daha okunabilir, geliştirmeye açık hale getirmektir. 5 Maddeden oluşur.

Single-Responsibility Principle

Open-Closed Principle

Liskov Substitution Principle

Interface Segregation Principle

Dependency Inversion Principle

1. Single-Responsibility Principle

Her Entity’nin (sınıf, modül, fonksiyon, vb.) tek bir görevi olmalıdır. Entity’lere birden fazla sorumluluk verilmemelidir.

Örnek

Bir oyundaki Player sınıfını ele alalım. Hareket etmek, ateş etmek bir karakterin işlevleriyken database’e kayıt etme işlemi başka bir sorumluluktur. Bu sorumluluk Player’a verilmemelidir.

Bu Prensibe Neden Uymalıyız?

Bu kuralın genel amacı; yazılımınızın mimarisini gelecekte ekleyeceğiniz yeniliklere ya da değişikliklere karşı korumaktır.

Daha somut olarak açıklamak gerekirse oyunumuzdaki player karakterinde yapacağımız bir değişiklik başka bir sorumluluk olan database işlemlerini etkilememelidir.

Sorumluluklar birbirlerinden ayrılmalıdır ki yönetimleri kolay olsun.

2. Open-Closed Principle

Entity’ler genişletilmeye açık (Open), değişime kapalı (Closed) olmalıdır.

Örnek

Az önceki Player sınıfımıza zıplama özelliği kazandıralım.

Görüldüğü gibi hiçbir mevcut özelliği değiştirmeden sınıfımızı genişletebildik.

Bu Prensibe Neden Uymalıyız?

Bu prensipteki asıl amaç kargaşanın önüne geçmektir. Bir binanın zeminini düzgün tasarlamazsanız ve çatıya gelindiğinde zeminde değişiklik yapmanız gerekirse o bina ne kadar sağlam olabilir?

Bu prensibi uygularken sınıfımızı bir kutu gibi düşünebiliriz. Değerli eşyalarınızı sakladığınız bir kutuya bir kalem eklemek istediğinizde kutuda yer olması gerekir. Bu yeri de düzen ile sağlarız. Kalemi eklemek için başka bir değerli eşyanızın yerini değiştirmemelisiniz. Kutuyu en başta iyi düzenlerseniz o kalemi sadece doğru yere koyarsınız.

Yazılımdaki en büyük maliyet sonradan yapılan değişimlerdir.

3. Liskov Substitution Principle

Bu kural, Nesne Yönelimli Programlama ile doğrudan ilişkilidir. Üst sınıftan türetilen bir alt sınıfın, üst sınıfta bulunan tüm özellikleri karşılayabilmesini prensip olarak alır.

Örnek

Ana sınıfımız kuş olsun ve kuş sınıfına uçabilme fonksiyonunu ekleyelim. Kuş sınıfından Güvercin sınıfını türettiğimizde hiçbir sıkıntı yok ancak Devekuşu sınıfını türettiğimizde devekuşuna yapamayacağı bir özelliği eklemiş oluruz.

Liskov Substitution Prensipleri bu durumun olmamasını gerektiğini söyler. Bu sorunu araya bir sınıf daha koyarak ya da interface (Swift dilinde Protocol olarak geçer.) ile Pigeon sınıfına uçma yeteneği kazandırarak çözebiliriz.

Araya bir sınıf daha eklendi.
Uçabilme yeteneği interface yardımıyla sınıfa eklendi.

Bu Prensibe Neden Uymalıyız?

Sınıflarımızda oluşacak herhangi bir mantık hatasının önüne geçmek ve boş fonksiyon ekleyip kodun kalitesini, okunurluğunu düşürmemek için bu prensip bizlere sunulmuştur.

4. Interface Segregation Principle

Interface’leri bir sınıf gibi kapsayıcı değil, sınıflara kazandırılan bir yetenek gibi daha spesifik oluşturmamız gerektiğini söyleyen prensiptir.

Örnek

Karakter seçebildiğimiz bir olimpiyat oyunu düşünelim. Karakterlerimizin her birinin kendine göre iyi olup kötü olduğu özellikler olacaktır.

IAtgleticAbilities interface’imizi SwimmerAthlete sınıfına eklediğimizde yüzücümüze ihtiyacı olmayan zıplama yeteneğini de eklemiş olduk. Peki bu durumu nasıl çözebiliriz?

Interface’leri parçalayarak tam olarak istediğimiz yapıyı sağlamış olduk.

Bu Prensibe Neden Uymalıyız?

Interface Segregation’a göre gereksiz hiçbir yetenek sınıflara eklenmemelidir. Çünkü bu durum kod karmaşıklığını arttırıp kodun okunurluğunu düşünür. Bu durumun önüne geçmek amacıyla bu kural, interface’leri parçalamamız gerektiğini söyler.

5. Dependency Inversion Principle

Sınıflar arası bağımlılıkların en aza indirgenmesi gerektiğini söyleyen prensiptir. Özellikle alt sınıflarda olan bir değişikliğin üst sınıfları etkilememesi gerektiğini dile getirir.

Örnek

Uygulamamızın mesaj ve mail yolu ile bildirim gönderdiğini düşünelim. Bunun için mesaj ve mail olmak üzere iki ayrı sınıfa bir de bildirim işlemlerini yönetecek bir sınıfa ihtiyacımız var.

Sınıflarımızı tam olarak böyle oluşturduğumuzda, üst sınıf olan Notification sınıfını alt sınıflara bağımlı hale getirmiş oluruz. Gelecek zamanda alt sınıflarda yapılacak bir değişiklik direkt olarak Notification sınıfını etkileyecektir. Bu durum kodumuzun karışmasına ve yönetiminin zorlaşmasına olanak sağlayacaktır. Peki nasıl çözebiliriz?

Abstraction, yani soyutlama burada devreye girer. Bir üst sınıf olan Notification’ı bir özellik olarak alt sınıflarımıza eklersek alt sınıflarda olacak bir değişiklikten üst sınıfımızın haberi olmayacaktır.

Bu Prensibe Neden Uymalıyız?

Dependency Inversion Prensibi kodda oluşacak karışıklığın önüne geçmek için ileri sürülmüş bir prensiptir. Sınıflar arası bağımlılıklar en aza indirgenir ki olası değişikliklerde sadece etkilenmesi gereken alanlar etkilensin. Bu prensip ile kodumuz gelişmeye ve büyümeye açık hale gelir.

Zaman ayırıp okuduğunuz için teşekkür ederim.

--

--