Yazılım geliştirme sürecinde kod kalitesi, sürdürülebilirlik ve genişletilebilirlik gibi konular oldukça önem arz etmektedir. Bu nedenle geliştiricilerin kod yazarken takip etmesi gereken temel ilkeler vardır. SOLID prensipleri olarak bilinen bu ilkeler bir yazılım geliştiricinin Nesne Yönelimli Programlama (OOP) ile yazılım geliştirirken, yazılımın esnek ve geliştirilmeye uygun olması için uyması gereken kurallar bütününü ifade eder. SOLID doğrultusunda geliştirilen uygulamalar ne kadar büyük olursa olsun, kod karmaşıklığı minimum seviyede olacaktır.
SOLID, Robert C. Martin tarafından önerilmekte ve yazılım mühendisliğinde kullanılan en temel prensiplerden biri olmakla birlikte birçok yazılım geliştirme şirketi tarafından kullanılmaktadır. Ayrıca, “Spaghetti Code” dediğimiz karmaşık kod yazımından kurtulup “Clean Code” dediğimiz çok daha yalın, kaliteli ve kolay anlaşılır bir kod dünyasını karşımıza çıkarmaktadır.
SOLID prensipleri, beş temel prensipten oluşur:
- Single Responsibility Principle (Tek Sorumluluk Prensibi)
- Open/Closed Principle (Açık/Kapalı Prensibi)
- Liskov Substitution Principle (Liskov Yerine Geçme Prensibi)
- Interface Segregation Principle (Arayüz Ayrımı Prensibi)
- Dependency Inversion Principle (Bağımlılığın Ters Çevrilmesi Prensibi)
Şimdi SOLID prensiplerini detaylı bir şekilde ele alalım.
1. Single Responsibility Principle (Tek Sorumluluk Prensibi)
Single Responsibility Principle (SRP), bir sınıfın veya fonksiyonun sadece bir işlevi veya sorumluluğu olması gerekliliği prensibidir. SRP’ye göre, bir sınıfın yalnızca tek bir işlevi veya sorumluluğu olması, kodun sürdürülebilirliğini ve değişiklikleri yönetilebilirliğini artırır.
SRP, sınıfların ve fonksiyonların modülerleştirilmesini sağlar. Bir fonksiyona birden fazla görev verilmez ve her iş için ayrı metodlar oluşturulur. Bir değişiklik yapılması gerektiğinde diğer bölümler etkilenmez ve birbiriyle ilişkili kod blokları bir arada bulunur. Kodun daha okunaklı ve anlaşılır hale gelmesinde çok etkili bir prensiptir.
Örneğin, bir kullanıcının kimlik doğrulamasını gerçekleştiren bir sınıf, aynı zamanda bir kullanıcının profil bilgilerini de alıyorsa, aynı sınıf iki sorumluluğu yerine getiriyor demektir. Karmaşıklığı önlemek için sınıfı iki bölüme ayırmak daha sağlıklı olacaktır. Biri kimlik doğrulama işlevselliğini yerine getirirken, diğeri de profil bilgilerini alma işlevselliğini yerine getirecektir.
2. Open/Closed Principle (Açık/Kapalı Prensibi)
Open/Closed Principle (OCP), bir sınıfın değiştirilmesine kapalı, ancak yeni işlevsellik eklenmesine açık olması gerektiğini belirtir. Yazılımın esnekliğini artırır ve daha kolay bir şekilde genişletilebilmesini sağlar.
OCP, yazılımın değişime karşı dirençli olmasını sağlar. Bir sınıfın var olan işlevselliği değiştirilmemelidir. Yeni işlevselliği sınıfın dışındaki bir yerde eklemek daha iyidir. Böylece, var olan işlevsellik bozulmadan yeni işlevsellik eklenmiş olur. Bir sınıfın koduna dokunmadan yeni işlevsellik eklenmesi, kodun daha az hata ile çalışmasını ve daha kolay bir şekilde genişletilmesini sağlar.
Örneğin, bir kütüphane yönetim sistemi yazıyorsanız, kitapların özelliklerini saklamak için bir sınıf kullanabilirsiniz. Ancak, ileride kitapların farklı türleri eklenmek istenebilir. Böyle bir durumda, sınıfın değiştirilmesi yerine, yeni bir sınıf ekleyebilirsiniz. Örneğin, “E-kitap” veya “Sesli Kitap” sınıfları ekleyebilirsiniz. Eklenen yeni sınıflar, var olan kitap sınıfını değiştirmeden sisteme yeni işlevsellik katmanızı sağlar.
3. Liskov Substitution Principle (Liskov Yerine Geçme Prensibi)
Liskov Substitution Principle (LSP), bir alt sınıfın, üst sınıfın yerine geçebilmesi gerektiğini belirtir. Bir üst sınıfın özelliklerine sahip olan bir alt sınıfın, üst sınıfın kullanıldığı herhangi bir yerde yerine geçebilmesi gerekir. Yani alt sınıfın, üst sınıfın kullanıldığı herhangi bir yerde beklenen tüm davranışları sergilemesi anlamına gelir. Başka bir deyişle, bir alt sınıfın davranışları, kullanıldığı yerde beklenen davranışlarla uyumlu olmalıdır.
LSP, bir alt sınıfın davranışını tanımlayan bir anlaşma olarak da düşünülebilir. Alt sınıfın, üst sınıfın tanımladığı davranışları tam olarak yerine getireceğini garanti eder ve üst sınıfın kullandığı herhangi bir algoritma, alt sınıflarda da aynı şekilde çalışır. LSP’nin en önemli yararlarından biri, yazılımın esnekliğini artırmasıdır. Esneklikle birlikte yazılımın güvenilirliğini ve kalitesini artırır. LSP ile birlikte yazılımın davranışı daha tutarlı hale gelir ve hatalı kodlama nedeniyle beklenmeyen sonuçların ortaya çıkması önlenir.
Örneğin, bir Araba sınıfı ve onun alt sınıfları olan “Benzinli Araba” ve “Elektrikli Araba” sınıflarını düşünelim. Araba sınıfı, bir “hız” metodu içerebilir. Benzinli Araba ve Elektrikli Araba sınıfları, Araba sınıfının özelliklerini içermelidir ve ayrıca kendilerine özgü özellikleri de içerebilirler. Ancak, Araba sınıfının kullandığı bir algoritma, her iki alt sınıf için de aynı şekilde çalışmalıdır. Bu sayede, Araba sınıfının herhangi bir yerinde kullanılan algoritmalar, Benzinli Araba veya Elektrikli Araba sınıflarında da kullanılabilir.
4. Interface Segregation Principle (Arayüz Ayrımı Prensibi)
Interface Segregation Principle (ISIP), bir arayüzün, ihtiyaç duyulan her şeyi içerecek şekilde tasarlanmaması gerektiğini belirtir. Diğer bir deyişle yalnızca onu kullanan istemci için gerekli olan özellikleri içermesi gerektiğini belirtir. Yani, bir arayüz, ihtiyaç duyulmayan özellikleri içermemelidir. ISP, kullanılmayan özelliklerin mevcudiyetinin, kodun karmaşıklığına ve bakımının zorluğuna neden olduğu durumlarda özellikle önemlidir.
ISP’nin temel amacı, yazılım bileşenlerinin birbirleriyle olan bağımlılıklarını azaltmaktır. Bir arayüz, başka bir bileşen tarafından kullanılıyorsa, ilgili bileşen yalnızca ihtiyaç duyduğu özelliklere erişmelidir. Kontrollü erişim ile birlikte bileşenler arasındaki bağımlılık ve değişikliklerin diğer bileşenler üzerindeki etkisi azaltır.
Örneğin, bir veritabanı erişim arayüzü düşünelim. Tasarlanacak arayüzün, veritabanına erişim için ihtiyaç duyulan temel işlevleri içermesi gerekiyor. Ancak, arayüz ayrıca, gereksiz özellikler, örneğin veritabanı şemasını değiştirme işlevini de içeriyorsa, bahsedilen işlevin kullanılmadığı yerlerde bile bileşenin gereksiz bir şekilde bağımlı hale gelmesine neden olabilir. Bağımlılıktan kaçınarak ayrı bir arayüzde tanımlama işlemini gerçekleştirmek esnekliği arttıracaktır.
ISIP, yazılımın gereksiz özelliklerle şişmesini önler ve bileşenler arasındaki bağımlılığı azaltır. Yazılım daha esnek ve bakımı daha kolay hale getirir.
5. Dependency Inversion Principle (Bağımlılığın Ters Çevrilmesi Prensibi)
Dependency Inversion Principle (DIP), yazılım bileşenleri arasındaki bağımlılıkları yönetmek için kullanılır. Üst seviye bileşenlerin, alt seviye bileşenlere doğrudan bağımlı olmaması gerektiğini belirtir. Bunun yerine, her iki bileşen de soyutlamalar üzerinden birbirine bağımlı olmalıdır. Yani, üst seviye bileşenler, alt seviye bileşenlerin nasıl çalıştığına dair ayrıntılarla ilgilenmemeli, soyutlama aracılığıyla bağımlılık oluşturmalıdır.
DIP’nin temel amacı, bir bileşenin alt seviye bileşenlerinin değiştirilmesi veya yükseltilmesi gerektiğinde, üst seviye bileşenlerde herhangi bir değişiklik yapmadan bunu yapabilmektir. DIP ile yazılımın esnekliği artar ve bakımı daha kolay hale gelir.
Örneğin, bir müşteri siparişi işlemi düşünelim. Bir veritabanından sipariş bilgileri okunsun ve müşteriye sipariş onayı göndersin. Eğer ilgili işlem, doğrudan veritabanına bağlıysa, veritabanında yapılan herhangi bir değişiklik, sipariş işleminin değiştirilmesini gerektirebilir. Bunun yerine, bir arayüz vasıtasıyla veritabanı işlemlerine bağımlılık sağlanmalı ve sipariş işlemi, veritabanı arayüzünün soyutlanmış bir sürümüne bağımlı olmalıdır. Yapılan bağımlılık düzenlemesi, veritabanında gerçekleştirilen herhangi bir değişiklik, sipariş işleminin değiştirilmesini gerektirmez ve üst seviye bileşenlerin alt seviye bileşenlerden bağımsız olarak çalışmasını sağlar.
Kaynakça:
- https://it.badykov.com/blog/2020/03/14/solid-principles/ (Erişim Tarihi : 2023-04-11)
- https://yazilimcigenclik.com.tr/solid-yazilim-gelistirme-prensipleri/ (Erişim Tarihi :2023-04-11)
- https://en.wikipedia.org/wiki/SOLID (Erişim Tarihi :2023-04-11)
- https://www.educative.io/blog/solid-principles-oop-c-sharp (Erişim Tarihi :2023-04-11)