Solid Prensipleri -2

Samet Avcı
5 min readAug 17, 2022

--

3- Liskov Substitution Principle (LSP)

Bu prensipteki amaç şu şekilde açıklanıyor.

“Subtypes must be substitutable for their base types.”

Kodumuzdaki alt seviye sınıflardan üretilmiş objeler ile üst seviye sınıflardan üretilen objeler birbirleri ile yer değiştirildiğinde hiçbir özelliği değiştirilmeden kullanılabilmelidir.

Bu prensibin bize sağladığı avantajlara bakacak olursak;

  • Sürdürülebilir bir arayüz yapısı oluşturmamızı sağlar.
  • Beklenmedik hatalarla karşılaşma olasılığını azaltır.

Bu prensibin faydalarını daha net anlamak için koda dökmek gerekir. Kodda bilim ve sanat alanında iki farklı alandan lise öğrencilerimiz olsun ve bu öğrencilerin isimlerini, sınıflarını, fizik ve resim puanlarını yazan bir kod bloğumuz olsun.

Bu kodda Student Interface’i ile istediğimiz verileri alabileceğimiz methotları tanımladık. Ardından HighSchool adında bir struct oluşturduk. Ve bu struct’ı StudentArt ve StudentScience adındaki iki yeni structta kullandık. Bu yeni structlar öğrencilerin bölümünü temsil etmektedir.

Bu seneryomuzda sanat bölümünde okuyan öğrencimiz Fizik dersi görmüyor fakat biz HighSchool’da fizik puanı adında bir field ekledik, aynı şekilde bilim bölümünde okuyan öğrencide resim dersi görmüyor aynı şekilde resim puanı adında da bir field ekledik. Bu durumda bize çıktı olarak fizik öğrencilerinde resim dersi sanat öğrencilerinde fizik dersi default olarak 0 gelir.

Bu durum büyük projelerde yanlış verilere, gereksiz verilere neden olur. Böyle bir yapıyı projenin farklı yerinde kullanmak çok ciddi sıkıntılara yol açar. Aynı şekilde proje büyüdükçe bu sorunları çözmek çok daha zor hale gelecektir. Şimdi Liskov prensibine uygun hale getirelim.

Bu yeni yapımızda HighSchoolStudent struct’ımız tüm lise öğrencilerde olan sınıf numarasını ve isim field’ını alıyor. Fizik öğrencilerimizde ekstra olarak fizik puanı ve sanat öğrencilerimiz resim puanı alıyor. Yukarıdaki fazla ve yanlış bilgi ihtimalini çözdük, aynı zamanda yeni bölümler rahatlıkla ekleyebiliriz. Oluşturduğumuz öğrencileri HighSchoolStudent yerinede kullanabiliriz. Şuan her şey çok daha temiz görünüyor.

4- Interface Segregation Principle (ISP)

Solid’in 4.prensibi Interface segregation prensibine bakacak olursak bu prensip bize nesnenin ihityacı olmayan interface bağımlılıklarına maruz kalmamsı için interfaceleri ayırmamızı söyler.

“Clients should not be forced to depend upon interfaces that they do not use.”

Yani kısaca bir obje interface’deki ihtiyacı olmayan herhangi bir methoda maruz kalmamalıdır. Bu sorunu çözmek için ise interface’i parçalara ayırmak gerekmektedir. Örnekle açıklayacak olursak;

Bu örnekte bir cars interface’imiz var. Bu interface Run, OpenSunRoof ve EnterPitStop olmak üzere 3 tane methoda sahip. Şimdi bu interface’i kullandığımız struct’lara bakacak olursak, Formula aracımızda SunRoof yok, Spor arabamızda ise EnterPitStop özelliği yok. Fakat biz interface’imizden dolayı bu methodlarıda yazmak zorundayız. Buda prensibimize aykırı bir durum aynı zamanda kodun okunabilirliğini düşürmektedir. Şimdi prensibimize uygun şekilde refactör edilmiş haline bakalım;

Şimdi bu örneğimizde 3 farklı interface’imiz var ve oluşturduğumuz structlarda ilgili özellikleri olan interface ile bağımlılık oluşturduk. Bu durumda ihtiyaç olmayan methodu yazmak durumunda kalmamış olduk.

5- Dependency Inversion Principle (DIP)

Bu prensipte bize yine bağımlılıkları azaltmamız gerektiğinden bahsetmektedir.

High-level modules should not depend on low-level modules. Both should depend on abstractions.

Üst seviye modüller düşük seviyeli modüllere bağımlı olmamalıdır. Iki modülde soyutlamalara bağımlı olmalıdır. Bunu kod ile açıklamak gerekirse;

Buradaki kodu incelediğimizde Add, Get ve delete işlemleri yapabilen bir storage yapımız var. Bu yapı ile Yeni yönetici ekleme, gösterme ve silme işlemi yapabilmekteyiz. Bu durumda üst modülümüz Yönetici olmaktadır. Burada yönetici yapımız Storage’daki herhangi bir değişiklikten etkilenebilir. Bu durum prensibimize aykırıdır.

Bu sorunu çözmek için araya soyut bir interface ekliyoruz ve bağlantıyı yeni eklediğimiz interface üzerinden sağlıyoruz. Şimdi prensibe uygun olan kod bloğumuza bakalım.

Buradaki kodu incelediğimizde yukarıdaki koda ek olarak manager ve storage yapılarının arasına userStorage ile bağlantıyı sağlayıp bağımlılıklarını ortadan kaldıran bir katman bulunmaktadır.

NewManager fonksiyonunu incelersek yeni oluşturulacak managera storage olarak userStorage declare ediliyor ve bu userStorage storage yapısına declare ediliyor. Böylelikle araya bir katman daha eklenmiş oluyor.

Bir sonraki yazıda görüşmek üzere …

Kaynaklar

--

--

Samet Avcı

Software developer in building next-generation web applications backend with Golang.I am eager to learn and use new generation software technologies.