SOLİD  PRENSİPLERİ

SOLİD PRENSİPLERİ

8 Mayıs 2020 0 Yazar: Ertan Eryılmaz

Geliştirme yaparken Java, C# gibi Object Oriented Programming (Nesneye Yönelimli Programlama) mimarisine sahip dilleri tercih eden şirketlerin iş ilanlarında sıkça aranılan özellik olan ve mülakatlarda mutlaka “SOLİD prensipleri nelerdir?” sorusu karşımıza çıkar.

Yazılımcılar büyük ölçekli projeler geliştirmeye başladığından beri birçok temel sorun ile karşılaşmıştır. Sorunların her birine farklı yaklaşımlar getirerek çözümler ortaya konulmuş ve bunların bir kısmı yazılım camiasından kabul görerek günümüzde aktif olarak kullanılan Design Patterns ve Prensipleri oluşturmuştur. Biz bugün bu kabul gören prensiplerden biri olan Solid prensibini inceleyeceğiz.

1. Single Responsibility Principle

2. Open/Closed Principle

3. Liskov ‘s Substitution Principle

4. Interface Segregation Principle

5. Dependency Inversion Principle

1. Single Responsibility Principle (SRP)

“Her sınıfın veya metodun tek bir sorumluluğu olmalı”

Prensibin ana hedefini ben şu sözle özdeşleştiriyorum, “Bir tek şeyi yap ve onu en iyi yap.” Prensibimizin ana hedefi her sınıfın ve metodun tek bir sorumluluğu olması ve o sorumluluğu yerine getirmesi gerektiğini ve bir sınıf veya metod değişmesi için bir tek sebebi olması gerektiğini söyler.

Projelerde en önemli ama aslında en fazla ihmal edilen konulardan birisi sorumluluk ayrımıdır. Bu konuya dikkat edilmeyen projelere sonradan dâhil olduğumuzda veya kendimiz o an işimizi çözmesi için prensibe uygun olmayan bir şekilde kod yazdığımız zaman, bir süre sonra ortaya her değişikliğin birçok yeri etkilediği, okunması zor ve geliştirme maliyeti fazla olan “Makarna kod” diye tabir ettiğimiz bir çöp proje çıkar.

Bir arabayı gözünüzün önüne getirin nasıl her parçanın bir görevi ve bir sorumluluğu var ise ve bir tek o sorumluluğu yerine getiriyorsa Single Responsibility’de bize anlatılmak istenen budur.

2. Open / Closed Principle (OCP)

“Sınıflar değişikliğe kapalı ancak gelişime açık olmalıdır.”

Biliyorum biraz kafamız karıştı, hem yeni bir geliştirme olacak hem bu geliştirme değişikliğe sebebiyet vermeyecek, üstelik aynı şey bir sonraki geliştirmeler içinde geçerli olacak.

Sınıflarımız veya metotlarımızı oluştururken ileride olabilecek yeni istekler ve gelişmeleri de öngörerek tasarlamamız gerekir. Projemizde oluşabilecek yeni istek ve ihtiyaçlar sonucunda yapacağımız geliştirmeler, projemizdeki diğer sistemleri etkilememeli ve herhangi bir değişikliğe sebebiyet vermemelidir.

3. Liskov’s Substitution Principle (LSP)

“T cinsinden parametre alan tüm programlar (fonksiyonlar) P olacak şekilde, S tipinde o1 nesnesi ve T tipinde o2 nesnesi olsun. Eğer o1 ile o2 nesneleri yer değiştirdiğinde P’nin davranışı değişmiyorsa S tipi T tipinin alt tipidir!”

4. İnterface Segregation Principle

“Ara yüzlerin ayrılması prensibi”

Bana göre prensipler arasında en kolay anlaşılabilir olanı ISP, temel amacı ara yüz implementation sonucunda oluşacak gereksiz kodları önlemek ve kodumuzun daha amaca yönelik hale gelmesini sağlamaktır.

Biraz daha açıklamak gerekirse, ara yüzler içinde sadece metotların imzaları bulunur. Bir ara yüz bir sınıfa implemente edildiği zaman, ara yüz’ün barındırdığı metotları barındırmak veya oluşturmak zorundadır. Zaten bu durumun aksi olduğundan hata alırız.

İşte bu durumda prensibimiz devreye girer ve derki “eğer class içerisinde gerçekten ihtiyaç duyulmayan ve kullanılmayan metotlar ara yüz aracılığı ile implemente edilmiş ise bu kodlar dummy kod olur, bu yüzden ara yüzler ayrılmalı ve classlar açısından işlevsel olmayan metotlar barındırması engellenmelidir.”

5. Dependency Inversion Principle

“Katmanlı mimarilerde üst seviye modüller alt seviyedeki modüllere doğruda bağımlı olmamalıdır.”

Prensibin Türkçeye çevrilmiş hali bağımlılıkların tersine çevrilmesi şeklindedir. Pek anlaşılır gelmediğinin farkındayım biz bunun yerine açıklamada belirtilen ifadeyi biraz daha açarak “üst seviyeli katmanlar kesinlikle alt seviyedeki katmanlara bağlı olmamalı, bağımlılıklar sadece abstract (soyut) kavramlara olmalıdır” şeklinde ifade edebiliriz.

Burada amaç üst seviyedeki modüllerin alt seviyelere bağımlı olmasından dolayı çıkabilecek sorunları ortadan kaldırmaktır. Yani alt seviyede yapılan herhangi bir değişikliğin üst seviyede kod değişikliğine veya onun bağlılıklarının etkilenmesine engel olmaktır amaç.

Daha kaba bir anlatım ile üst seviyedeki modül alt seviyedeki işin nasıl yürüdüğünü bilmemeli ve ilgilenmemelidir. Ben üst seviyedeki modül olarak diyorum ki; alt taraftan x verisinin nasıl geldiği ile ilgilenmem, bana gelen x verisi ile ilgili işlemimi yapar, gerekli yerlere gönderirim. Ama x verisi bir veri tabanından mı geldi, bir API den mi geldi yoksa bir text dosyasından okunarak mı geldi burası beni ilgilendirmez. Zaten bu gibi isteklerinde beni etkilememesi gerekmektedir.