Bağımlılığın tersine çevrilmesi ilkesi

Bağımlılıkların tersine çevrilmesi ilkesi ( ), nesne yönelimli programlamada kullanılan temel tasarım örüntülerinden biridir. Bu ilkeye göre:

Üst düzey modüller, karmaşık iş mantığını içeren bileşenler olup, kolayca yeniden kullanılabilir olmalı ve alt düzey modüllerdeki (yardımcı işlevleri sağlayan detaylar) değişikliklerden doğrudan etkilenmemelidir.

Bu bağımsızlığı sağlamak için, her iki modül seviyesi de soyutlamalara (abstract interface’ler veya temel sınıflar) bağlı olmalı, böylece modüller arasındaki doğrudan bağımlılık ortadan kaldırılmalıdır.

Bu yaklaşım, sistemlerin esnekliğini artırır ve sürdürülebilir kod yazımını destekler.

Bağımlılıkların tersine çevrilmesi ilkesi şu iki ana maddeyle özetlenir:

Yüksek seviyeli modüller, düşük seviyeli modüllerden hiçbir şey ithal etmemelidir. Her ikisi de soyutlamalara (örneğin arayüzlere) bağımlı olmalıdır.
Soyutlamalar alt seviye modüllere bağlı olmamalıdır. Bunun tersine, alt seviye modüller soyutlamalara(arayüzlere) bağlı olmalıdır.

Bu prensip, hem yüksek hem de düşük seviyeli modüllerin aynı soyutlamaya dayanmasını gerektirerek, geleneksel nesne yönelimli programlamaya farklı bir bakış sunar.

Bağımlılığın soyutlama ile azaltılması
Yüksek seviyeli ve düşük seviyeli modüller arasındaki etkileşim bir soyutlama üzerinden tasarlandığında, hem bağımlılık azalır hem de sistemin yeniden kullanılabilirliği ve sürdürülebilirliği artar. Bu yaklaşım aynı zamanda iç içe geçmiş karmaşık bağımlılıkları da soyutlama sayesinde sadeleştirir.
Kod Örnekleri
Kötü Tasarım (DIP'yi İhlal Eden)
Aşağıdaki örnekte, üst seviye `ReportService` sınıfı, alt seviye `PDFReportGenerator` sınıfına doğrudan bağımlıdır:

// Alt seviye modül
class PDFReportGenerator {
public void generatePDF(String content) {
System.out.println("PDF oluşturuluyor: " + content);
}
}

// Üst seviye modül (DIP ihlali)
class ReportService {
private PDFReportGenerator pdfGenerator = new PDFReportGenerator();

public void createReport(String data) {
pdfGenerator.generatePDF(data);
}
}

Bu tasarımda, rapor formatı değiştiğinde (örneğin HTML formatında bir rapor eklenmesi gerekirse) ReportService sınıfı değiştirilmek zorunda kalacaktır.

İyi Tasarım (DIP Uyumlu)
DIP uygulamak için bir arayüz tanımlayalım:

// Soyutlama (Arayüz)
interface ReportGenerator {
void generate(String content);
}

// Alt seviye modül - 1
class PDFReportGenerator implements ReportGenerator {
@Override
public void generate(String content) {
System.out.println("PDF oluşturuluyor: " + content);
}
}

// Alt seviye modül - 2
class HTMLReportGenerator implements ReportGenerator {
@Override
public void generate(String content) {
System.out.println("HTML oluşturuluyor: " + content);
}
}

// Üst seviye modül (DIP uyumlu)
class ReportService {
private ReportGenerator reportGenerator;

public ReportService(ReportGenerator generator) {
this.reportGenerator = generator;
}

public void createReport(String data) {
reportGenerator.generate(data);
}
}

// Kullanım
public class Main {
public static void main(String[] args) {
ReportService pdfService = new ReportService(new PDFReportGenerator());
pdfService.createReport("Satış verileri");

ReportService htmlService = new ReportService(new HTMLReportGenerator());
htmlService.createReport("Satış verileri");
}
}

Bu tasarımda:

ReportService, sadece ReportGenerator arayüzüne bağlıdır

Yeni rapor formatları eklemek için mevcut kod değiştirilmez (Açıklık-kapalılık ilkesi)

Bağımlılıklar constructor üzerinden enjekte edilir (Bağımlılık enjeksiyonu)

Faydalar
Değişime direnç: Alt seviye modüller değişse bile üst seviye etkilenmez

Test edilebilirlik: Mock nesnelerle kolay test imkanı

Esneklik: Yeni implementasyonlar sisteme kolayca eklenebilir

Geleneksel katmanlı yapı
Geleneksel mimaride düşük seviyeli bileşenler (örneğin, yardımcı kütüphaneler) doğrudan yüksek seviyeli bileşenler (örneğin, politika katmanı) tarafından kullanılır. Bu yapı, yüksek seviyeli bileşenlerin yeniden kullanımını sınırlar.

Dış bağlantılar
The Dependency Inversion Principle – Robert C. Martin
DIP in the Wild – Brett L. Schuchert

Kaynakça