Her yazılımcının bilmesi gereken SOLID yazılım geliştirmenin temel ilkeleri olarak kabul edilmektedir.
SOLID Yazılım Prensipleri
SOLID yazılım prensipleri; Yazılımın esnek, yeniden kullanılabilir, sürdürülebilir ve anlaşılır olmasını sağlayan, kodun tekrarını önleyen ve Robert C. Martin tarafından tek bölme esasen bütündür. Kısaltması Michael Feathers tarafından temel bu ilkelerin amacı;
- Geliştirmemiz yazılımın zaman aralıklarına kolayca adapte olabilmesi,
- Yeni özellikler kodda bir bozulma gerekmeden kolayca ekleyebileceğimiz
- Yeni masraflara rağmen kodun üzerinde en az değişim sağlanması,
- Kod üzerinde sürekli düzeltme, hatta yeniden yazma gibi işletim yolunu açma zaman kaybı da minimum indirmedir.
Bunların prensip olarak uygulanarak uygulamalarımızın büyümesi, karmaşıklığın da kalıcının ötesine geçmiş olması. “ İyi kod ” yazmak için bunlara uygun yazılım geliştirmelisiniz.
Biraz açalım;
S — Tek sorumluluk ilkesi
ÖZET: Bir sınıf (nesne) yalnızca bir amaç uğruna değiştirilebilir, o da o sınıfa yüklenen sorumluluktur, yani bir sınıfın (fonksiyona da indirgenebilir) yapılması yalnızca bir işin olması gerekir.
O — Açık-kapalı prensibi
ÖZET: Bir sınıfın ya da fonksiyonun yapısı var olan özelliklerin dengeli ve bağımsız olmasına izin verilmemelidir. Yani davranışı değişmemeli ve yeni özellikler kazanabiliyor olmalı.
L — Liskov ikame ilkesi
ÖZET : Kodlarımızda herhangi bir değişiklik yapmaya gerek duymadan alt sınıfları, türedikleri(üst) sınıfların yerine kullanabilmeliyiz.
I — Arayüz ayrımı ilkesi
ÖZET : Sorumlulukların hepsini tek bir genişletmeyi toplamak yerine daha özelleştirilmiş ve fazla tasarımlar oluşturmamalıyız.
D — Bağımlılık Tersine Çevirme İlkesi
ÖZET : Sınıflar arası bağımlılıklar oranları az olmalıdır özellikle üst seviye sınıflar alt seviye sınıflara bağımlıdır.
Tek Sorumluluk; Tek iş, tek sorumlulukta yapma sistemi olarak özetlenebilir.

Tek sorumluluk ilkesi
Tek sorumluluk sınıflarımızın iyi tanımlanmış tek bir sorumluluğu olması anlatılmaktadır. Bir sınıf (nesne) yalnızca bir amaç uğruna değiştirilebilir, o amaçta o sınıfa yüklenen sorumluluktur, yani bir sınıfta yapılması gereken yalnızca bir işin olması gerekir.
Eğer geliştirdiğiniz sınıf ya da fonksiyon birden fazla amaca hizmet ediyorsa, bu kurala aykırı bir gelişme sürecinin gerçekleşebileceği anlamına geliyor. Bunu fark ettiğinizde ayrıntılarına uygun olarak parçalamanız gerekmektedir.
Gereksinimler gerçekleştiğinde, yazılan kodun içeriğinde olması gereken kısımlar olacaktır. Bu da yazılı sınıfların(nesnelerin) bir kısmının ya da tamamının değiştirilmesinin anlamı gelir.Bir sınıf ne kadar fazla sorumluluk alırsa, o kadar fazla değişime uğramak zorunda kalır.Böylece birçok kodun içeriğinin içeriğine göre, yeniden yazımda; Bilgisayarların da bir o kadar zorlaşır.
Bir veya sınıf fonksiyonu geliştirmemizde ya da amacını iyi belirleyip, sınıfına göre tasarlamamız gerekir, böylece herhangi bir değişiklikten, miktarlarda az şeyi güncelleyerek ve düzelterek istenen iyileştirmeyi gerçekleştirmiş olursunuz. Sorumluluğun azaltılması demek değişime daha kolay adapte olmak demektir.
Test — Bir sorumluluğu olan bir sınıfta çok daha az sayıda test durumu olacaktır.
Daha az bağımlılığı — Tek bir sınıfta daha tek bir gelişmesinin olması daha az bağımlılık güvenliği.
Yalın ve anlaşılır yapılar — Daha az sorumluluk daha basit veya küçük yapılara erişilmesini sağlar. Daha küçük yapılar ise monolitik yapılara göre çok daha avantajlıdır ve kodun anlaşılırlığını/okunurluğunu arttırır.
Kötü bir örnekle başlıyoruz.
public class User {
private Long id;
private String name;
private String street;
private String city;
private String username;
//Getter’lar, setter’lar
public void changeAddress(String street,String city) {
//mantık
}
public void login(String username) {
//mantık
}
public void logout(String username) {
//mantık
}
}
- Burada Adres ile ilgili cadde ve şehir gibi veriler doğrudan olarak Kullanıcı sınıfı içerisinde bulunmalı mı gerçekten?
Herhangi bir ek adres bilgisi istendiğinde(ülke yada zipCode gibi) burada tamamen Kullanıcı sınıfını içerir. Kullanıcı sınıfı olarak sorumlu olmayan bir işlemden etkilenmiş olacaktır. “cadde”, “şehir” gibi veriler sadece adres için gereklidir, bu durumda Adres olarak yeni bir sınıf oluştursak nasıl olur?
public class LoginService{
public void login(String kullanıcı adı) {
//giriş mantığı
}
public void logout(String kullanıcı adı) {
//çıkış mantığı
}
}
Giriş ve çıkış gibi işlemler ne kadar Kullanıcı bilgisine ihtiyaç duysa da Kullanıcı sınıfının sorumluluğunda değildir. Bu dosyaları ayrı bir sınıfın sorumluluğuna bırakmamalıyız. Böylece oturum açma kullanıcı sınıflarını sınıftan arındırmış olacaksınız ve LoginService’ini de tek sorumluluk için düzenlemiş olduk.
Diyelim ki Kullanıcı sınıfından değişiklik Adres kısmı düzenlendik. Yine böyle kötü bir örneğimiz var.
genel sınıf AddressService{
genel void change Address (Kullanıcı kullanıcı) {
//mantık
}
}
Bu sınıf ve fonksiyon içerisinde her şey sadece Adres’le ilgilenilmelidir. Dolayısıyla kullanıcı bu yöntemin içinde yer almamalıdır. Çünkü fonksiyon sadece adres değişiklikleriyle ilgilenmektedir.
Daha önce değindiğim yeni Adres sınıfımız var ve bundan faydalanalım, bu durumda doğru olanı kesmeniz gerekiyor.
public class User {
private Long id;
private Address name;
//Getter,setter
}
ve
public class Adres {
private String sokak;
private String şehir;
private String ülke;
//Alıcı, ayarlayıcı
}
yeni oluşan durumda
public class AdresService{
public void changeAddress(Address adresi) {
// Sadece adresle ilgium ve ondan sorumluyum kullanıcıdaki değişiklikleri beni etkilemez.
//mantık
}
}
Sorumlulukları onun bir sınıfında etkili bir şekilde ayırdı ve böylece bir yerdeki kodu değiştiren açıklık ve koddaki herhangi bir yerin diğerini bozma duyusunu azalttı. Güncelleştirmeler kolayca entegre edilebilecek bir yapı kurmuş durumdaydı.
Her bir sınıf ve fonksiyon için tek bir iş, kusurların önlenmesi, anlaşılır kod yazmanızı sağlar ve yazılımınıza yeni özellikler seçmeniz için rahatlıklar sağlar. Şu ana kadar yazdığınız kodlara göz atın ve şu andan itibaren yazdığınız kodlarda bu parçaları göz ardı etmeyin.
