SOLID Prensipleri Nedir ? OOP Tasarım Prensipleri

Ubeyde Akgül
Huawei Developers - Türkiye
6 min readSep 11, 2020
S.O.L.I.D.

2000’li yılların başında Michael Feathers tarafından ortaya atılarak hayatımıza giren S.O.L.I.D. prensipleri, Object-oriented programming OOP geliştirme yapan her yazılımcının bilmesi gereken yazılım geliştirmenin temel prensipleri olarak kabul edilmektedir. Robert C. Martin tarfından “first five principles of object-oriented programming and design” olarak derlenerek SOLID kısaltma adını aldı.

SOLID prensipleri; geliştirilen yazılımın anlaşılır ve daha okunur, geliştirilebilir ve yeniden kullanılabilir, sürdürülebilir ve esnek olmasını sağlayan, kod tekrarını önleyen yaklaşım ve prensipler bütünüdür. Daha basit şekilde; geliştirilen proje için ileride istenecek değişimlere açık olan ve bu değişimlere en az eforla ayak uydurabilecek yapı ve mimaride kod yazmayı sağlayan yaklaşımlardır.

Prensiplerin Michael Feathers tarafından tanımlanan temel amaçları şu şekilde :

  • Geliştirilen yazılımın gelecekte ortaya çıkacak gereksinimlere kolayca adapte olması,
  • Yeni özellikleri, kodda bir değişikliğe gerek kalmadan kolayca ekleyebilmek
  • Yeni gereksinimlere karşı, kod üzerinde en az değişimin sağlanması,
  • Kod üzerinde sürekli düzeltme, yeniden yazma gibi sorunların yol açtığı zaman kaybının minimuma indirilmesi.

Bu prensipler uygulanarak geliştirilen yazılımlar büyürken, karmaşıklığın da büyümesinin önüne geçmiş oluruz. Temiz kod yazmak için bu prensiplere uygun şekilde yazılım geliştirmeyi benimsemek gerekiyor. Ki, geliştirme sürecinde yaşadığımız temel sorunları ortadan kaldırmış olalım veya kolayca aşalım.

Neler bu geliştirme aşamasında karşılaşılan en temel sorunlar :

  • Esnemezlik: Kullanılan tasarımın geliştirilememesi ve ekleme yapılamaması.
  • Kırılganlık: Bir yerde yapılan değişikliğin başka bir yerde sorun çıkarması.
  • Sabitlik: Geliştirilmiş bir modülün başka yerde tekrar kullanılabilir (reusable) olmaması.
  • Maliyet: Geliştirme maliyetinin ve sürecinin giderek artması.
coding issues in development

SOLID Prensipleri nelerdir :

S — Single Responsibility Principle : SRP ( Tek Sorumluluk Prensibi ) :

Her bir sınıf veya metodun tek bir sorumluluğu ve işlevi olmalı. Yani bir sınıfın veya methodun sorumluluk alanı, yapması gereken yalnızca bir iş olmalı ve içeriği sadece kendi sorumluluğu ile ilgili olmalıdır. Aksi durumda spaghetti code diye tabir ettiğimi anlaşılırlığı olmayan değiştirilmesi ve geliştirilmesi çok maliyetli olan çöp kodlar ortaya çıkıyor.

Örneğin :

Database işlemleri yapan bir sınıf içerisine loglama işlemlerini yürüten metodlar konulmamalı. Loglama işlemi yapan metodlar Logger sınıfı içerisinde olmalı ve bu sınıfın nesnesi üzerinden kullanılmalı.

Veya, login işlemleri yapılan sınıf içerisinde mail adresi validation kontrolü yapan bir metod bulunmamalı. Bu ayrı bir bir sınıf içerisinde olmalı ve bu sınıfın nesnesi üzerinden kullanılmalı.

O — Open-Closed Principle : OCP ( Açık/Kapalı Prensibi ) :

Bir sınıf veya metod var olan temel özelliklerini korumalı ve bunlar üzerinde değişikliğe izin vermemelidir. Mevcut davranışını değiştirmeden yeni özellikler kazanabiliyor olmalıdır. Yeni özelliklere ve gelişime açık, özellik kaybına ve değişiliğine kapalı olma durumu.

L — Liskov Substitution Principle : LSP ( Liskov’un yerine geçme prensibi ) :

İlk defa 1988 yılında MIT professor Barbara Liskov tarafından Abstraction and Hierarchy adlı kitabında ortaya koyulmuş. Hem de zor anlaşılabilecek bir şekilde :)

“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!”

Alt sınıflar (sub class) türetildiği üst sınıfın (super class) bütün özelliklerini kullanmalıdır.

Alt sınıflarda oluşturulan nesneler üst sınıfların nesneleriyle yer değiştirdiklerinde kullanılmayan özellik olmaksızın aynı davranışı göstermek zorundadırlar.

Örneğin :

Kare bir dikdörtgendir ve Dikdörten sınıfından türemiş olsun. Böylelikle Kare sınıfı istenildiği yerde Dikdörtgen sınıfı gibi davranabilecek.

Fakat Kare ve dikdörtgen sınıflarının yükseklik ve genişlik parametrelerinin değiştirilmesi farklı davranışlara yol acaçacaktır ve bu durumda Kara sınıfı Dikdörtgen sınıfı yerine geçemez. Böyle bir durumda örneğin alan hesaplama metodu Kare sınıfı için doğru sonuç vermeyecektir.

Bu durumda; Şekil isimli bir arayüz oluşturarak Kare ve Dikdörtgen sınıflarını Şekil arayüzünden implemente etmeliyiz.

Alan hesaplama metodu da Şekil arayüzü içinde bulunmalı.

Böylelikle Şekil arayüzünü ve içindeki alanHesapla metodunu implemente eden Kare ve Dikdörten sınıfları için alan hesaplama işlemini doğru şekilde özelliştirmiş oluruz.

I — Interface segregation principle : ISP ( Özelleşmiş Kontrat/Arayüz Ayrımı prensibi ) :

Bir arayüz bir sınıfa implemente edildiğinde, arayüz’ün barındırdığı metotları barındırmak veya oluşturmak zorundadır. Oluşturulan ve kullanılmayan implemente metodlar işlevsiz ve dummy kodlar ortaya çıkacaktır.

Bu sebeple arayüz içerisine kullanılmayan ve gereğinden fazla metod ve özellik eklenmemeli, birden fazla ve daha çok özelleştirilmiş arayüzler yazılarak sorumluluklar ayrıştırılmalıdır.

Örneğin :

Animal isimli bir arayüz oluşturalım ve içeriğinde eat(), fly(), bark() metodlarını barındırdığını düşünelim. Bu durumda Animal arayüzünü implemente eden Dog sınıfı fly() metodunu gereksiz yere implemente etmiş olacak. Aynı şekilde Animal arayüzünü implemente eden Bird sınıfı bark() metodunu gereksiz yere kullanmış olacak.

Bu örnek için ; fly() metodunu Flyable arayüzünde, bark() metodunu Barkable arayüzünde tanımlarsak ve sınıflara ilgili arayüzleri implemente edersek daha çok özelleştirilmiş ve ayrıştırılmış bir yapı elde ederiz. Dog sınıfı bark() metodunu barındıran Barkable arayüzünü implemente ederse fly() metodunu gereksiz şekilde barındırmamış olacak.

D — Dependency Inversion Principle : DIP ( Bağımlılığın ters çevrilmesi prensibi ) :

Sınıflar arası bağımlılıklar olabildiğince az olmalıdır. Katmanlı mimarilerde üst seviye modüller alt seviyedeki modüllere doğruda bağımlı olmamalıdır. Bir sınıf diğer bir sınıfa doğrudan bağımlı olmak yerine, aralarındaki bağ abstract (soyut) kavramlar üzerinden sağlanmalıdır. Bu soyut kavram interface de olabilir abstract class da olabilir.

Örneğin :

Studentds tablosunu xml çıktı olarak veren bir metod yazılacak olsun. Export etme işlemini ilgili sınıfta bir metod içerisinde xml convert yaparak yazmak ileriye yönelik doğru bir yöntem olmayacaktır. Çünkü şuan sadece xml export işlemi gerekiyor olabilir, fakat bir süre sonra json, csv, txt, html vb formatlarda export talep edilebilir.

Bu durumda, export işlemi yapan metodu bir IDataExporter gibi bir arayüz içerisine alarak bu arayüzü ilgili sınıflara implemente etmeliyiz. Farklı bir formatta export ihtiyacı olduğunda, istenilen parametreye göre sadece IDataExporter arayüzündeki metodu güncelleyerek maliyetsiz ve pratik şekilde güncelleme yapılmış olacak.

İyi bir yazılım geliştirici olmak için SOLID prensipleri mutlaka öğrenmeli ve uygulanmalıdır. Geliştirilen koda yeni işlevler eklerken veya hata düzeltmeleri yaparken mutlaka refactoring pratikleri ve SOLID bilgisi ile kodun SOLID prensiplerine uygunluğunu arttırılmalıdır.

cleanCode

SOLID’e ek olarak Kiss, Yangi, Dry, Reuse Release Equivalence, Common Closure prensipleri de bulunmakta.

Kiss ( Keep it Simple Stupid / Keep It Short and Simple — Basit Aptal Tutmak ) :

Bir problemi çözerken olabilecek en basit, sade ve anlaşılır çözüm yöntemini seçerek uygulama geliştirmeliyiz. Minimalist yaklaşımın da temeli olan “Less is More” akımına benzer diyebiliriz.

İlk olarak 1960’lı yıllarda Amerikan donanmasında ifade edilmiştir.

Einstein da bu konuda birşeyler söylemiş: “Everything should be made as simple as possible, but no simpler.”

Yangi ( You Aren’t Gonna Need It! — Buna ihtiyacım yok! ) :

Gerekli görülene ve kullanılana kadar bir işlevsellik eklenmemesi gerektiğini belirten yazılım geliştirme ilkesidir. Yani şu an ihtiyacımız olmayan kodları sisteme dahil etmemeliyiz, ileride eklenebilecek özellikler hakkında öngürüde bulunup ek geliştirmeler yapmamalıyız. Kullanılmayan kodları buna ihtiyacım yok diyerek kaldırmalıyız.

Dry ( Don’t Repeat Yourself — Kendinizi Tekrar Etmeyin ) :

Proje içerisinde kod tekrarının (code duplication) ve buna bağlı olarak ortaya çıkabilecek fazlalıkların / karmaşanın önlenmesini amaçlayan yazılım geliştirme ilkesidir. Tekrarlı kodları tekilleştirerek merkezileştirecek bir yaklaşımda geliştirme yapmak gerekmektedir.

DRY prensibi, “Her bilginin bir sistem içinde tek, kesin ve yetkili bir temsili ile var olması” gerektiğini vurgular. Prensip Andy Hunt ve Dave Thomas tarafından Pragmatic Programmer2 kitabında formüle edilmiştir.

Reuse ( Release Equivalence Principle ) :

Sistemde kullanılan paketler/namespace’ler arasındaki bağımlılıkları düzenle şekilde yönetmek için tekrar kullanılabilir yapılar kurmak gerekir.

Common Closure ( Ortak Kapama Prensibi ) :

Single Responsibility’nin paketler/namespace’ler için uyarlanmış halidir. Ortaya çıkan aynı sebepten dolayı değişebilecek sınıflar, aynı namespace altında bulunmalıdır. Böylelikle sistemde oluşabilecek değişikliklerin tüm sistemi etkilemesinin önüne geçilmesi amaçlanır.

--

--