SOLID prensipleri, yazılım geliştirme süreçlerinde kodun daha sürdürülebilir, esnek ve ölçeklenebilir olmasını sağlar. Bu prensiplere uygun kod yazmak, bakım maliyetlerini azaltır ve yazılımın gelecekteki değişikliklere daha uyumlu olmasını sağlar. SOLID prensiplerini takip eden bir yazılımcı olarak, kod kalitenizi ve mesleki yetkinliğinizi artırabilirsiniz.
1. Single Responsibility Principle (SRP) – Tek Sorumluluk Prensibi
Bu prensibe göre, bir sınıfın yalnızca tek bir sorumluluğu olmalıdır. Yani, bir sınıf yalnızca bir işi yapmalı ve yalnızca bir nedenle değiştirilmelidir.
// Yanlış Kullanım: Bir sınıf hem kullanıcı yönetimini hem de e-posta işlemlerini yapıyor.
class UserManager {
public void createUser(String name, String email) {
// Kullanıcı oluşturma işlemi
}
public void sendWelcomeEmail(String email) {
// E-posta gönderme işlemi
}
}
// Doğru Kullanım: Ayrı sınıflara bölündü.
class UserService {
public void createUser(String name, String email) {
// Kullanıcı oluşturma işlemi
}
}
class EmailService {
public void sendWelcomeEmail(String email) {
// E-posta gönderme işlemi
}
}
2. Open/Closed Principle (OCP) – Açık/Kapalı Prensibi
Bir sınıf genişletilmeye açık, ancak değiştirilmeye kapalı olmalıdır. Yani, mevcut kodu değiştirmeden yeni işlevsellikler ekleyebilmeliyiz.
// Yanlış Kullanım: Bir sınıf hem kullanıcı yönetimini hem de e-posta işlemlerini yapıyor.
class UserManager {
public void createUser(String name, String email) {
// Kullanıcı oluşturma işlemi
}
public void sendWelcomeEmail(String email) {
// E-posta gönderme işlemi
}
}
// Doğru Kullanım: Ayrı sınıflara bölündü.
class UserService {
public void createUser(String name, String email) {
// Kullanıcı oluşturma işlemi
}
}
class EmailService {
public void sendWelcomeEmail(String email) {
// E-posta gönderme işlemi
}
}
3. Liskov Substitution Principle (LSP) – Liskov’un Yerine Koyma Prensibi
Türeyen sınıflar, temel sınıflarının yerine geçebilmeli ve beklenen davranışı değiştirmemelidir.
// Yanlış Kullanım: Mevcut kodu değiştirmek gerekecek.
class Invoice {
public double calculateDiscount(String type, double amount) {
if (type.equals("Gold"))
return amount * 0.2;
if (type.equals("Silver"))
return amount * 0.1;
return 0;
}
}
// Doğru Kullanım: Yeni indirim türleri eklemek için mevcut kodu değiştirmeye gerek yok.
interface Discount {
double applyDiscount(double amount);
}
class GoldDiscount implements Discount {
public double applyDiscount(double amount) {
return amount * 0.2;
}
}
class SilverDiscount implements Discount {
public double applyDiscount(double amount) {
return amount * 0.1;
}
}
4. Interface Segregation Principle (ISP) – Arayüz Ayrımı Prensibi
Bir arayüz, yalnızca ilgili olan metotları içermelidir. Gereksiz metotları içeren büyük arayüzlerden kaçınılmalıdır.
// Yanlış Kullanım: Bir arayüz tüm metotları içeriyor.
interface Worker {
void work();
void eat();
}
// Doğru Kullanım: Ayrı arayüzler oluşturuldu.
interface Workable {
void work();
}
interface Eatable {
void eat();
}
5. Dependency Inversion Principle (DIP) – Bağımlılıkların Ters Çevrilmesi Prensibi
Yüksek seviyeli sınıflar, düşük seviyeli sınıflara doğrudan bağımlı olmamalıdır. Bunun yerine, soyutlamalar üzerinden bağımlılık sağlanmalıdır.
// Yanlış Kullanım: Doğrudan bağımlılık var.
class FileLogger {
public void log(String message) {
// Log işlemi
}
}
class OrderService {
private FileLogger logger = new FileLogger();
public void processOrder() {
logger.log("Sipariş işlendi");
}
}
// Doğru Kullanım: Bağımlılık enjekte edildi.
interface Logger {
void log(String message);
}
class FileLogger implements Logger {
public void log(String message) {
// Log işlemi
}
}
class OrderService {
private Logger logger;
public OrderService(Logger logger) {
this.logger = logger;
}
public void processOrder() {
logger.log("Sipariş işlendi");
}
}