SOLID prensipleri teorisi, "Uncle Bob" olarak da bilinen Robert Martin tarafından ilk defa 2000 yılında yayınlanan Tasarım Prensipleri ve Tasarım Desenleri (Design Principles and Design Patterns) adlı makalesinde tanıtılmıştır.
Nesne yönelimli bilgisayar programlamasında, SOLID, yazılım tasarımlarını daha anlaşılır, esnek ve sürdürülebilir hale getirmeyi amaçlayan beş tasarım ilkesinin baş harfleriyle oluşturulmuş kısaltmasıdır.
Her ne kadar nesne yönelimli bir tasarıma başvursalar da, SOLID prensipleri agile geliştirme veya uyarlanabilir yazılım geliştirme gibi metodolojiler için temel bir felsefe oluşturabilir.
Bu prensipler, yazılım geliştiricilerinin sağlam, test edilebilir, genişletilebilir ve sürdürülebilir nesne yönelimli yazılım programları tasarlamalarına yardımcı olur.
SOLID'in açılımı şudur:
- S - Tek Sorumluluk Prensibi
- O - Açık Kapalılık Prensibi
- L - Liskov Değiştirme Prensibi
- I - Arayüz Ayrıştırma Prensibi
- D - Bağımlılık Değiştirme Prensibi
Bu beş tasarım ilkesinin her biri, yazılım sistemlerinin geliştirilmesi sırasında ortaya çıkabilecek belirli bir sorunu çözer.
SOLID’in ne olduğunu öğrendiğimize göre şimdi bu prensiplere daha yakından bakalım. 👀
Yazılım Mühendisliğinde SOLID Tasarım Prensipleri
SOLID tasarım prensiplerinin Tek Sorumluluk Prensibi, Açık Kapalılık Prensibi, Liskov Değiştirme Prensibi, Arayüz Ayrıştırma Prensibi ve Bağımlılık Değiştirme Prensibi gibi beş prensibin kısaltması olduğunu bir önceki bölümde söylemiştik.
Bu prensipleri benimsemek, kodu yeniden düzenlemeden kaçınmamıza ve Agile yazılım üretmemize yardımcı olabilir.
Tek Sorumluluk Prensibi (SRP)
Basitçe söylemek gerekirse, SOLID tasarım prensibindeki tek sorumluluk, bir sınıfın, modülün veya işlevin yalnızca bir işi olması gerektiğini belirtir. Yani her sınıfın değişmesi için yalnızca bir nedeni olması gerektiğini söyler.
Bir sınıfı değiştirmek için birden fazla sebep varsa, o zaman sınıfın birden fazla sorumluluk aldığı değerlendirilebilir. Sınıf içerisindeki metotlar başka sınıflar içerisindeki metotlarla olmaması gereken derecede ilişki içerisinde bulunuyor olabilir. O zaman bu sınıfın yüksek derecede bağlı olduğu düşünülebilir. Bu duruma göre, bağlılığın hareketsiz tasarımlara yol açtığı ve herhangi bir gereksinim veya değişiklik yaparken istenmeyen bir yolla sonuçlanabileceği söylenebilir.
Bir sınıf birden fazla işi gerçekleştirme mantığını içeriyorsa, kod tabanı büyüdükçe hata ayıklamak ve sürdürmek kolay olmaz. Yeni geliştiriciler kodu okuyup anlamaya çalışırken zorluk çekebilirler.
Her sınıfın tek bir işi gerçekleştirmesini sağlarsak, yalnızca kodu sürdürmek ve hata ayıklamak kolay olmayacak, aynı zamanda her bir çekirdek işlev tek bir sınıf tarafından gerçekleştirildiği için kod yeniden kullanılabilir hale gelecektir.
Bunu bir örnekle gösterecek olursak 👇;
Yukarıdaki kod tek sorumluluk prensibini ihlal ediyor çünkü hayvanın ismini yazdırmaktan sorumlu sınıf aynı zamanda hayvanın çıkardığı sesi ve beslenme şeklini de gösteriyor.
Peki bu durumda ne yapmalı diye düşünüyor olabilirsin. Bunu düzeltmek için ses ve besleme metotları için ayrı bir sınıf oluşturman gerekiyor:
Bu şekilde, sınıfların her biri yalnızca bir şey yapıyor:
- ilki hayvanın adını yazdırıyor
- ikincisi ise çıkardığı sesin türünü yazdırır
- üçüncüsü de beslenme şeklini yazdırıyor.
Bu daha fazla kod yazmayı gerektirir ancak daha iyi okunabilirlik ve sürdürülebilirlik sağlar.
Açık - Kapalılık Prensibi
SOLID tasarım prensiplerindeki açık-kapalılık prensipi, yazılım varlıklarının genişlemeye açık ancak değişikliğe kapalı olması gerektiğini belirtir.
Bu prensip kendi içinde çelişiyor gibi görünebilir, ancak yine de bunu kodda daha iyi anlamlandırabilirsin.
Yazılım parçaları eklenti için açıkken, modifikasyon için kapalı olmalıdır. Mevcut kodu değiştirmeden daha fazla kod ekleyerek bir sınıfın, modülün veya işlevin işlevselliğini genişletebilmen gerektiği anlamına gelir.
Bir yazılım bölümünün bağlamı, kaynak kodunu değiştirmeden davranışını genişletebilir veya bir sınıf, sınıf davranışı değiştirilmeden kolayca genişletilebilir. Gereksinimler değiştiğinde, zaten çalışan eski kod değiştirilerek değil, yeni kod eklenerek bu tür modüllerin davranışı genişletilebilir.
Liskov Değiştirme Prensibi
Liskov değiştirme prensibi, nesne yönelimli programlamada (OOP) uyulması gereken en önemli ilkelerden biridir. Bilgisayar bilimci Barbara Liskov tarafından 1987'de Jeannette Wing ile birlikte yazdığı bir makalede tanıtılmıştır.
Bu prensip bize bir tip eğer temel olan bir temel tipten türetilmişse, türetilmiş tipin, temel tip ikame desteğine sahip olması gerektiğini söyler. Basitçe söylemek gerekirse, alt sınıfların ana sınıflar veya üst sınıflar için ikame edilebilir olması gerektiğini belirtir. Başka bir deyişle, alt sınıf ana sınıfı değiştirebilmelidir.
Aşağıdaki kodun Liskov yer değiştirme prensibini nasıl ihlal ettiğine bakalım:
Bird sınıfı, üst sınıf Animal'dan kendi özel bir ses çıkarma yöntemi (makeSound) uygulamıyor. Bunun yerine, genel bir ses çıkarma yöntemi (makeAnimalSound) kullanıyor ve bu da Liskov değiştirme prensibini ihlal ediyor.
Arayüz Ayrıştırma Prensibi
SOLID tasarım prensiplerindeki arayüz ayrıştırma, daha büyük arayüzlerin daha küçük arayüzlere bölünmesi gerektiğini belirtir. Bunu yaparak, sınıfları uygulamanın yalnızca kendileriyle ilgili yöntemlerle ilgilenmesini sağlayabiliriz.
Bu, kod tabanının bakımını kolaylaştırabilir. Başka bir deyişle, birden fazla istemciye özgü arayüz, tek bir genel arayüzden daha iyidir.
Bağımlılık Değiştirme Prensibi
Bağımlılık değiştirme, yazılım modüllerini birbirinden ayırmakla ilgilidir. Böylece sınıf A değişirse, sınıf B'nin değişiklikleri önemsemesi veya farkında olması gerekmez.
Bu prensip, yüksek seviye modüllerin düşük seviye modüllere bağlı olmaması gerektiğini belirtir. Bunun yerine, her ikisi de soyutlamalara bağlı olmalıdır. Ek olarak, soyutlamalar ayrıntılara bağlı olmamalı, ancak ayrıntılar soyutlamalara bağlı olmalıdır.
Daha basit bir ifadeyle, bu, alt düzey kodun nasıl çalıştığına ilişkin belirli ayrıntılara dayanan kod yazmak yerine, farklı şekillerde uygulanabilen daha genel soyutlamalara dayanan kod yazmak gerektiği anlamına gelir.
SOLID Neden Önemlidir?
SOLID prensiplerinin Nesne Yönelimli Programlama'da (OOP) neden önemli olduğunu yukarıda zaten gördün. Ancak bir listeleme yapmak gerekirse 👇;
- Değişiklikleri Kolaylaştırır: Büyük bir yapboz düşün. Her bir parça belirli bir yere uyar. Bir parça kırılırsa, sadece o parçayı değiştirmen yeterlidir. Aynı şekilde, SRP (Single Responsibility Principle) prensibini takip ettiğinde, her sınıfın belirli bir görevi olur. Bu da, bir değişiklik yapman gerektiğinde tam olarak nereye bakacağını bilmeni sağlar. OCP (Open-Closed Principle) ise, mevcut kodu değiştirmeden yeni özellikler ekleyebilmeni sağlar, bu da kodun stabil kalmasına yardımcı olur.
- Kodu Tekrar Tekrar Kullanmayı Sağlar (OCP ve ISP): LEGO parçalarını düşün. Aynı parçaları kullanarak farklı şekiller inşa edebilirsin. Benzer şekilde, OCP (Open-Closed Principle) ile mevcut sınıfları genişleterek yeni özellikler oluşturabilirsin. Bu yeniden kullanılabilirlik, zaman ve emek tasarrufu sağlar. ISP (Interface Segregation Principle) ise sınıfların yalnızca ihtiyaç duydukları şeylere bağlı olmasını sağlar, bu da onları daha esnek ve yeniden kullanılabilir hale getirir.
- Test Etmeyi Kolaylaştırır (DIP): Değiştirilebilir parçaları olan bir araba düşün. Bir parça kırılırsa, tüm arabayı yeniden inşa etmeden o parçayı değiştirebilirsin. Aynı şekilde, DIP (Dependency Inversion Principle) ilkesini uyguladığında, kodun soyutlamalara bağımlı olur ve test etmek çok daha kolay hale gelir. Test amaçlı bileşenleri değiştirip geri kalan kodu etkilemeden test yapabilirsin.
- Uyum İçinde Çalışır (DIP): Bir hastanenin farklı bölümlerinde çalışan bir doktor düşün. Her doktor, neyle sorumlu olduğunu tam olarak bilir. Aynı şekilde, DIP prensibine uyulduğunda, geliştiriciler proje üzerindeki farklı bölümler üzerinde aynı anda çalışabilirler. Bu da yanlış anlamaları azaltır ve daha sorunsuz bir iş birliği sağlar.
SOLID Prensipleri Hala Geçerli mi?
Robert Martin'in SOLID yazılım tasarım prensiplerini ilk geliştirdiği yıllardan bu yana teknoloji ve yazılım endüstrisi büyük bir değişim geçirdi. Yine de temel fikirleri bugün küresel olarak geçerliliğini koruyor.
SOLID prensibi bağımlılıkları azaltmayı ve bakım yapılabilirliği arttırmayı amaçlar. Yazılım geliştirme sırasında, her ilke için ekstra bir zaman ve ekstra çaba harcanması gerekir. Böylece kodun karmaşıklığı azaltılabilir ve kodun sürdürülebilirliği yani bakım yapılabilirliği artırılabilir.
Esnek bir tasarım ve düşük bağımlılık ve daha yüksek bakım kolaylığı sağlarlar. Kod daha sağlam, daha kararlı ve daha iyi anlaşılabilir hale gelir.
SOLID tasarım prensipleri ilk başta bunaltıcı gelebilir, ancak onlarla düzenli olarak çalışma alışkanlığı edindiğinde, kodundaki karmaşıklık azalacak, işin daha kolay hale gelecek. :)