SOLID prensipleri, daha esnek, bakım yapılabilir ve genişletilebilir kodlar yazmamızı sağlar. Böylece, projelerimizin kalitesini ve sürdürülebilirliğini artırırız. Bu beş prensip; Single Responsibility Principle (SRP), Open/Closed Principle (OCP), Liskov Substitution Principle (LSP), Interface Segregation Principle (ISP) ve Dependency Inversion Principle (DIP) olarak sıralanmaktadır. Her birini Java örnekleriyle açıklayalım.

İçerik
Single Responsibility Principle (SRP)
Her sınıf, yalnızca bir tek sorumluluğa sahip olmalıdır. Yani, bir sınıfın yalnızca bir işi olmalı ve bu iş için değişmelidir.
Yanlış Kullanım:
public class User {
public void getUserInfo() {
// Kullanıcı bilgilerini getir
}
public void saveToFile() {
// Kullanıcı bilgilerini dosyaya kaydet
}
}
Doğru Kullanım:
public class User {
public void getUserInfo() {
// Kullanıcı bilgilerini getir
}
}
public class UserFileWriter {
public void saveToFile(User user) {
// Kullanıcı bilgilerini dosyaya kaydet
}
}
Open/Closed Principle (OCP)
Yazılım varlıkları genişletilmeye açık, ancak değiştirilmeye kapalı olmalıdır. Yeni özellikler eklerken mevcut kodu değiştirmek yerine genişletiriz.
Yanlış Kullanım:
public class Rectangle {
public double width;
public double height;
}
public class AreaCalculator {
public double calculateArea(Rectangle rectangle) {
return rectangle.width * rectangle.height;
}
}
Doğru Kullanım:
public interface Shape {
double calculateArea();
}
public class Rectangle implements Shape {
private double width;
private double height;
public Rectangle(double width, double height) {
this.width = width;
this.height = height;
}
@Override
public double calculateArea() {
return width * height;
}
}
public class Circle implements Shape {
private double radius;
public Circle(double radius) {
this.radius = radius;
}
@Override
public double calculateArea() {
return Math.PI * radius * radius;
}
}
Liskov Substitution Principle (LSP)
Bir alt sınıf, üst sınıfın yerine geçebilmeli ve aynı davranışı gösterebilmelidir. Alt sınıf, üst sınıfın yerine kullanıldığında programın doğru çalışması gerekir.
Yanlış Kullanım:
public class Bird {
public void fly() {
// Uçma işlevi
}
}
public class Ostrich extends Bird {
@Override
public void fly() {
throw new UnsupportedOperationException("Ostrich cannot fly");
}
}
Doğru Kullanım:
public abstract class Bird {
public abstract void move();
}
public class Sparrow extends Bird {
@Override
public void move() {
fly();
}
private void fly() {
// Uçma işlevi
}
}
public class Ostrich extends Bird {
@Override
public void move() {
run();
}
private void run() {
// Koşma işlevi
}
}
Interface Segregation Principle (ISP)
Kullanıcıların ihtiyaç duymadığı işlevlerle dolu büyük arayüzler yerine, daha küçük ve spesifik arayüzler oluşturmalıyız.
Yanlış Kullanım:
public interface Worker {
void work();
void eat();
}
public class HumanWorker implements Worker {
@Override
public void work() {
// Çalışma işlevi
}
@Override
public void eat() {
// Yemek yeme işlevi
}
}
public class RobotWorker implements Worker {
@Override
public void work() {
// Çalışma işlevi
}
@Override
public void eat() {
throw new UnsupportedOperationException("Robot cannot eat");
}
}
Doğru Kullanım:
public interface Workable {
void work();
}
public interface Eatable {
void eat();
}
public class HumanWorker implements Workable, Eatable {
@Override
public void work() {
// Çalışma işlevi
}
@Override
public void eat() {
// Yemek yeme işlevi
}
}
public class RobotWorker implements Workable {
@Override
public void work() {
// Çalışma işlevi
}
}
Dependency Inversion Principle (DIP)
Yüksek seviyeli modüller, düşük seviyeli modüllere bağımlı olmamalıdır. Her ikisi de soyutlamalara bağımlı olmalıdır.
Yanlış Kullanım:
public class LightBulb {
public void turnOn() {
// Ampulü aç
}
public void turnOff() {
// Ampulü kapat
}
}
public class Switch {
private LightBulb lightBulb;
public Switch(LightBulb lightBulb) {
this.lightBulb = lightBulb;
}
public void operate() {
lightBulb.turnOn();
}
}
Doğru Kullanım:
public interface Switchable {
void turnOn();
void turnOff();
}
public class LightBulb implements Switchable {
@Override
public void turnOn() {
// Ampulü aç
}
@Override
public void turnOff() {
// Ampulü kapat
}
}
public class Switch {
private Switchable device;
public Switch(Switchable device) {
this.device = device;
}
public void operate() {
device.turnOn();
}
}
Sonuç
SOLID prensipleri, kaliteyi artırır ve kodun daha sürdürülebilir olmasını sağlar. Dahası, bu prensipler projelerimizin başarısında da kritik bir roldedir. Bu prensipleri uygulayarak:
- Bakımı Kolaylaştırırız: Kodun yalnızca tek bir sorumluluğa sahip olması, hataların daha kolay izlenip düzeltilmesini sağlar. Ayrıca, değişiklik yaparken diğer işlevlerin etkilenme riskini azaltırız.
- Genişletilebilirlik Sağlarız: Kodumuzu yeni özellikler eklenmesine açık hale getiririz. Böylece, mevcut kodu değiştirmeden yeni işlevsellikler ekleyerek yazılımın genişlemesini sağlarız. Bu da projelerin uzun vadede sürdürülebilir olmasını sağlar.
- Esnekliği Artırırız: Alt sınıfların üst sınıfların yerine geçebilmesi, sistemin esnekliğini artırır. Bu şekilde, yeni gereksinimlere uyum sağlamak için daha az çaba sarf ederiz.
- Karmaşıklığı Azaltırız: Küçük ve spesifik arayüzler kullanarak gereksiz bağımlılıkları ortadan kaldırırız. Böylece kod daha anlaşılabilir ve yönetilebilir olur.
- Bağımlılıkları Yönetiriz: Yüksek seviyeli modüllerle düşük seviyeli modüller arasındaki bağımlılıkları soyutlamalar aracılığıyla yönetiriz. Böylece, modüller arasındaki sıkı bağlılığı azaltır ve bağımlılıkların daha kolay yönetilmesini sağlarız.
SOLID prensiplerini benimsemek, yazılım projelerinin başarısını doğrudan etkiler. Çünkü bu prensipler, karmaşık yazılım sistemlerini bile daha kolay anlaşılır ve bakım yapılabilir bir hale getirecektir.