SOLID PRENSİPLERİ

Iremgulten
MobvenLab TR
Published in
5 min readJun 2, 2021

Merhaba, bugün ilk medium yazımla karşınızdayım. Öncelikle SOLID Prensiplerinin ne olduğunu ve prensiplere uymadığımızı nasıl anlayacağımızı açıkladıktan sonra birkaç prensibi örnek uygulamalarla göstererek yazımı noktalamak istiyorum.

SOLID Prensipleri “Robert C. Martin” tarafından 2000 yılında “Design Principles and Design Patterns” adlı makalesinde öne sürülen prensiplerdir. Bu prensipler günümüzde her yazılımcının bilmesi gereken, geliştirilen projelere kullanılabilirlik, dayanıklılık, sürdürülebilirlik, esneklik sağlayan ve karmaşıklığın azalmasını sağlayan prensiplerdir. “SOLID” kelimesine baktığımız zaman “sağlam, katı, devamlı, bütün” gibi Türkçe karşılıklarını görebilirken, aslında 5 prensibin baş harflerinden oluştuğunu söyleyebilirim. Prensiplerin bu kısaltmaya sahip olması “Michael Feathers” tarafından tanımlanmış ki prensiplerin akılda kalmasını sağlayan hem anlamlı hem iyi bir kısaltma olmuş diyebilirim. Prensipleri uygulamanın temel avantajlarını ele almak gerekirse;

  • Yazılıma sürdürülebilirlik ve esneklik sağlar,
  • Kod karmaşıklığını azaltır,
  • Gereksinimlerin değişmesi halinde kolay değişilebilirlik sağlar,
  • Değişilebilirliğin kolaylaştırılması zaman kaybını minimilize eder,
  • Projeye sonradan katılacak paydaşların kolay adapte olmasını sağlar.

Şimdi prensipleri ayrıntılı bir şekilde inceleyelim

1) S -> Single Responsibility Principle

Single Responsibility prensibi,temelde her bir nesnenin sadece tek bir işi yapması gerektiğini vurgulamaktadır. Eğer ben üzerinde çalıştığım projenin içindeki herhangi bir nesnede yapmam gereken değişiklik için birden fazla sebep buluyorsam bu prensibe uymuyorum demektir. Şimdi bu prensibi bir örnekle açıklayalım.

Bu örnekte Car adlı bir sınıf, bu sınıf içerisinde sınıfa ait propertyler ve bir araba galerisinde yapılan işlemler ayrı metotlar olarak belirtilmiş. Fakat araba galerisinde yapılan işlemleri göz önüne aldığımızda aslında “Sell_RentCar” ve “RecieveCar” işlemlerinin galeri çalışanları tarafından, “BuyCar” ve “RentCar” işlemlerinin ise müşteri tarafından gerçekleştiğini söyleyebiliriz. Bu şekilde bir sınıf içerisinde farklı işlevlerin yer alması yapının SRP’ye uygun olmadığını göstermektedir. Bu yapıyı SRP’ye uygun bir hale getirmek için sınıf içerisindeki tüm iş yüklerini parçalara ayırmamız daha doğru olacaktır.

Gerçekleştirdiğimiz bu parçalama işleminin sonucunda; araba satma ve kiralama işlemleri, araba teslim alma işlemleri için “Staff” sınıfının kullanımı, araba satın alma ve kiralama işlemleri için “Customer” sınıfının kullanımı, araba tanımlamak için de “Car” sınıfının kullanımı yeterli olacaktır. Böylece her sınıf kendi payına düşen işlemleri gerçekleştirecek ve diğer nesneler bu değişimlerden etkilenmeyecektir.

2) O -> Open-Closed Principle

Open-Closed prensibi, bir nesnenin gelişime AÇIK fakat değişime KAPALI olduğunu vurgulamaktadır. Aslında aktarılmak istenen nesnelerin temel özelliklerinin değiştirilmeden nesneye ekleme yapılabiliyor olması gerektiğidir. Eğer ben üzerinde çalıştığım bir projeye yeni bir özellik eklemek istediğimde mevcutta bulunan bir nesneyi değiştirmek zorundaysam bu prensibe uymuyorum demektir. Şimdi bu prensibi bir örnekle açıklayalım.

Verilen örnekte bir alışveriş merkezindeki mağazalarını tutan bir sınıf mevcuttur. Sınıfta bulunan “TypeCount” fonksiyonu yeni mağaza açılması durumunda mağaza türünüve o türdeki mevcut mağaza sayısını alarak sayıyı arttırmaktadır. Ancak mevcutta bulunan mağaza türleri dışında yeni bir tür mağaza açılması istendiğinde metot içindeki if yapısına yeni case eklenmesi gerekmektedir. Fakat bu yöntem OCP’ye ters düşmektedir. Bunun yerine;

Öncelikle “TheMall” sınıfımızı abstract olarak tanımlamamız gerekir. Bu bize bundan sonraki yeni eklenen her mağazanın ortak olan özelliklerini tek çatı altında toplarken aynı zamanda abstract metot olarak tanımlanan “TypeCount” un kalıtılan her sınıf içinde override edilip doldurulmasını gerektirmektedir.

Görüldüğü üzere başlangıçta string değişken olarak tutulan “StoreType” değişkeni oluşturulan abstract sınıfın alt sınıfları şeklinde yeniden düzenlenmiştir. Böylece yeni bir mağaza türün mağaza açılması durumunda “TheMall” sınıfından türetilmiş yeni bir sınıf yazılması yeterli olacaktır.

3) L-> Liskov Substitution Principle

Liskov Substitution prensibi, bir sınıftan miras alan iki sınıfın birbirlerinin yerine ve üst sınıftan oluşan nesnenin yerine İSTİSNASIZ kullanılabilmesi gerektiği vurgulamaktadır. Yani, miras alarak türetilen sınıflar önce miras alındıkları nesnenin tüm özelliklerini kullanmalı, daha sonra kendi özelliklerini eklemesi gerekmektedir. Eğer ben bir sınıftan miras alan her sınıfın kendi nesnesine özel kod blokları ekliyorsam bu prensibe uymuyorum demektir.

4) I -> Interface Segregation Principle

Interface Segregation prensibi, her nesnenin kendi amacına uygun property veya metotlar içeren interface’leri implement etmesi gerektiğini vurgulamaktadır. Yani bu prensip bizlere herhangi bir interface’e ait bir metot için tüm interface’i implement etmememiz gerektiğini ve bu gibi durumlarda interface’leri ayırmamız gerektiğini söylemektedir. Eğer ben bir interface’i implement ettiğimde bu interface’in bir metodu benim sınıfım için anlamsızsa bu prensibe uymuyorum demektir ve yapmam gereken, interface’i parçalara ayırarak sadece kullanacağım metodları bir interface’te toplamaktır.

5) D-> Dependency Inversion Principle

Dependency Inversion prensibi, büyük sistemlerin küçük sistemlere değil, küçük sistemlerin büyük sistemlere bağlı olması gerektiğini vurgulamaktadır.

Bu prensibe günlük hayattan bir örnek vermek istiyorum. Örneğin telefonumun ekranı çatladı ve telefonumu tamir için servise götürdüm. Servisteki adam bana “Bu telefonun camı kırılmış sen bunu kullanamazsın artık yeni telefon alman gerekiyor…” dedi. Böyle bir durum söz konusu olamaz değil mi :) Çünkü aslında telefon cama bağımlı değil, cam telefona bağımlı. Prensimiz de bize tam olarak bunu söylemekte. Kurduğunuz sistemlerde bağımlı olunan büyük sistem ve bağımlı olan da küçük sistem olmalı.

--

--