SOLID Principles

Yunus Emre Ulusan
6 min readFeb 2, 2021

--

SOLID kısaltması Robert C. Martin tarafından ortaya atılan bir dizi Nesne Yönelimli Programlama (OOP — Object Oriented Programming) prensiplerinden 5 tanesinin baş harflerinden oluşturulmuş ve ilk defa Michael Feathers tarafından ortaya atılmış bir kısaltmadır. Şimdi sizlere yazılım dünyasında etki bırakmış bu kısaltmanın görevlerini ve amacını anlatmak istiyorum.

Principles
  • Single Responsibility :

Bir sınıf yalnızca bir amaç uğruna değiştirilebilir. Bir sınıfın yapması gereken yalnızca bir işi olması gerekir.

  • Open Closed :

Bir sınıf ya da fonksiyon bünyesinde var olan özelliklerini korumalı ve değişikliğe ekstrem durumlar hariç izin vermemelidir. Ama her türlü değişime açıktır.

  • Liskov Substitution Principle :

Kodlarımızda değişiklik yapmadan , alt sınıfları türedikleri sınıfların yerine kullanabilmeliyiz.

  • Interface Segregation Principle:

Sorumlulukların hepsini tek bir arayüze toplamak yerine daha özelleştirilmiş birden fazla arayüz oluşturmalıyız.

  • Dependency Inversion Principle:

Sınıflar arası bağımlılıklar olabildiğince az olmalıdır özellikle üst seviye sınıflar alt seviye sınıflara bağımlı olmamalıdır.

Solid Kısaca ;

“Projemizin sürdürülebilirliği için, yani yeni teknoloji ve eklentiler geliştirildiğinde , yapılacak bir değişikliğin projelerimizi etkilemeyip, geliştirmelere ve düzeltmelere açık olmasıdır.” diyebiliriz.

Single Responsibility (SRP);

“Her sınıf kendinden sorumludur.”

Single Responsibility prensibindeki asıl amaç bir class veya function’a sadece ve sadece tek bir sorumluluğu yerine getirmesine dayanmaktadır. Yani kısacası sınıflarımızın iyi tanımlanmış tek bir sorumluluğu olmalı. Bu düşüncenin sınırlarından dışarı çıkarsak bir süre sonra ortaya her değişikliğin birçok yeri etkilediği, okunması zor ve geliştirmesi güç olan “Makarna kod” diye bildiğimiz çöp bir proje ortaya çıkar.

  • ‘User’ class’ına sadece kendi içinde yapması gereken atamaları verdik.
  • Email işlemlerini yapması için bir ‘EmailHelper’ class açıp ‘User’ class’ını rahatlattık.
  • Artık kullanıcılar Email adreslerini değiştirmek yada kaydetmek için sadece ‘User’ class’ını kullanacak ve iş yükü hafifliyecek.
  • ‘EmailHelper’ sınıfına atadığımız işlem sadece o sınıfta çalışacak ve diğer sınıflarla karışmıyacak.

Basit ama anlaşılır bir şekilde sizlere aktarmaya çalıştım umarım yardımcı olabilmişimdir .

Open / Closed Principle (OCP) ;

“Yazılım varlıkları (sınıflar, modüller, işlevler vb.) Genişletme için açık, ancak değişiklik için kapalı olmalıdır.”

— Bu ilkenin genel fikri harika. Mevcut kodu değiştirmeden yeni işlevler ekleyebilmeniz için kodunuzu yazmanızı söyler. Bu, sınıflarınızdan birinde bir değişikliğin aynı zamanda tüm bağlı sınıfları uyarlamanızı gerektirdiği durumları önler. Ne yazık ki Bertrand Mayer, bu hedefe ulaşmak için mirası kullanmayı öneriyor.

— Bu yaklaşımın ana yararı, bir arayüzün, gevşek bağlantı sağlayan ek bir soyutlama seviyesi sunmasıdır. Bir arayüzün uygulamaları birbirinden bağımsızdır ve herhangi bir kodu paylaşmaya gerek yoktur. Bir arayüzün iki uygulamasının bazı kodları paylaşmasının yararlı olduğunu düşünüyorsanız, kalıtımı veya kompozisyonu kullanabilirsiniz .

— CoffeeApp aracılığıyla farklı kahve makinelerini kontrol etmek için örnek uygulamada bu prensibi kullandık . Bir kahve makinesi CoffeeMachine arayüzünü uyguladığı sürece , bunu uygulama üzerinden kontrol edebilirsiniz. Mevcut kahve makinenizi değiştirirken yapmanız gereken tek şey, arayüzün yeni bir uygulamasını sağlamak ve belirli uygulamayı somutlaştıran ana yöntemi değiştirmektir. Bunu bir adım daha ileri götürmek istiyorsanız, belirli bir sınıfın somutlaştırılmasını değiştirmek için bağımlılık ekleme, yansıtma veya hizmet yükleyici API’sini kullanabilirsiniz.

Open/Closed prensibi biraz karışıktır ama mantığı gayet anlışılır ve basittir. Temiz kod yazmanın bu prensibinde sizlere anlaşılır bi şekilde anlatmaya çalıştım umarım işinize yaramıştır.

Liskov Substitution Principle (LSP) ;

“Alt sınıflar ana sınıfın tüm özelliklerini ve metotlarını aynı işlevi gösterecek şekilde kullanabilme ve kendine ait yeni özellikler barındırabilmelidir.”

“Ana sınıfı, istenmeyen davranışlar olmadan her zaman türetilmiş sınıfıyla değiştirebilmelidir”
veya başka bir deyişle
“S, T’nin bir alt türü ise, o zaman bir programdaki T türü nesneler, o programın istenen özelliklerinden herhangi biri değiştirilmeden S türü nesnelerle değiştirilebilir.”

Pratik olarak türetilmiş sınıf, davranışını hiç değiştirmeden her zaman üst sınıfını genişletmelidir.

Aşağıda ki örnek LSP ihlal örneğidir.

//LSP MIT programlama metodolojileri Barbara Liskov tarafından öne sürülmüştür.

//LSP ihlalleri belirtileri
//LSP’nin ihlal edildiğini gösterebilecek bazı tipik sinyalleri gözlemleyebiliriz:

  • Tamamen yeni bir davranış sağlamak için temel sınıf yönteminin bir yöntemini geçersiz kılan türevler.
    *Üst sınıfın bir yöntemini boş bir yöntemle geçersiz kılan türevler.
    *Üst sınıftan miras alınan belirli yöntemlerin istemciler tarafından çağrılmaması gerektiğini belgeleyen türetilmiştir.
    *Ek (kontrol edilmemiş) istisnalar atan türevler.

Burdaki örnek istediğimiz metod gibidir.

LSP’ye uygunluk tam olarak sınıflardan beklenen davranışları karşılayabilecek bir hiyerarşi düzeni oluşturarak sınıf yapılarımızı geliştirmektir.

Interface Segregation Principle(LSP)

Tek bir interface kullanmaktansa eş parçalara bölüp bir çok interface kullanmalıyız .Yani her olayın bir yöneticisi olmalıdır .Böylece interface’i kullanan kişide sadece ihtiyacı olanlarla ilgilenmiş olur. Birden fazla amaç için yalnızca bir arayüzümüz var ise buna gerektiğinden fazla method ya da özellik ekliyoruz demektir.

Aşağıda ki örnekleri inceleyecek olursak tam olarak yapmak istediğimiz bu şekildedir.

Interface segregation prensibine uygun olarak geliştirdiğimiz arayüzlerde implement eden sınıflar ihtiyaç duymadıkları metodları uygulamak zorunda kalmaz böylece daha küçük arayüzler işleri kolaylaştırır. Bunun yanında birden fazla interface kodun okunabilirliğini artırırken, bakımını da kolaylaştırmaktadır. Böylece bir interface sadece ilgilendiği ve gerekli olan metodları barındırır.

Dependency Inversion Principle(DIP)

Dependency Inversion, yani üst sınıflar, alt seviyeli sınıflara bağlı olmamalı, çözüm ise her ikisi de soyut kavramlar üzerinden yönetilebilmelidir. Yüksek seviye ve düşük seviye sınıflar arasında bir soyutlama katmanı oluşturabiliriz.

Dependency Injection da 3 farklı class vardır ;

  1. Client Class : İstemci sınıfı (bağımlı sınıf), hizmet sınıfına bağlı olan bir sınıftır.
  2. Service Class : Hizmet sınıfı (bağımlılık), istemci sınıfına hizmet sağlayan bir sınıftır.
  3. Injector Class: Enjektör sınıfı, servis sınıfı nesnesini istemci sınıfına enjekte eder.

Bu prensipte ki amaç farklı sınıflarda farklı farklı işlemler yapılmasıdır . Bu da oluşabilecek spagetti kod durumunu engeller ve işimizi kolaylaştırır.

Seri bölümlerinden birinde daha önce bahsettiğim gibi — bu ilkeleri (ve diğer kalıpları) belirli bir fayda elde etmek için kullanıyoruz, sadece “profesyonel” olduğu için uygulamak için değil. Faydalar net ve görünür değilse, sadece zamanımızı boşa harcıyoruz. Çoğu durumda, sadece yerine getirmek için bir kural veya model uygulamak çok kötü bir şeydir ve sorunlara ve aşırı karmaşık kod tabanına yol açar. Bu kuralların size yardımcı olmak (kodunuzu geliştirmek) için yazıldığını unutmayın, bu yüzden işleri ihtiyacınız olandan daha fazla karmaşık hale getirmemeye çalışın. Gümüş kurşun yok. İşiniz sırasında yaptığınız her şeyde sağduyulu olun. Bu ilkelerin her birinden gelen ana fikirleri hatırlayın ve onlara iyi bir rehber gibi davranın.

Son olarak, dürüst olmalıyım — tüm bu kuralları, ilkeleri, kalıpları vb. Okuyup “Tamam! Şimdi, mükemmel kod yazacağım!” Demenin bir yolu yok. Bu sürekli bir süreçtir ve çok sayıda çok yazılmış kod satırı gerektirir.

--

--