Bağımlılığın Ters Çevrilmesi Prensibi(Dependency Inversion Principle – DIP)
Merhaba,
Önceki yazılarımda SOLID prensiplerinden S–Tek Sorumluluk Prensibi(Single Responsibility Principle – SRP)‘ni, O–Açık Kapalı Prensibi(Open Closed Principle – OCP), L-Liskov’un Yerine Geçme Prensibi(Liskov Substitution Principle – LSP) ve I–Arayüz Ayrım Prensibi(Interface Segregation Principle – ISP) incelemiştik. Bu içeriğimizde ise sıradaki ve sonuncu olan D harfine denk gelen Bağımlılığın Ters Çevrilmesi Prensibi(Dependency Inversion Principle – DIP) ele alacağız.
Dependency Inversion prensibine göre yazdığımız program soyutlama üzerine dayandırılmalıdır, katılaştırma üzerine değil.
İçeriğimize böyle bir giriş yapmayı uygun gördüm. Bunun sebebi, tasarladığımız kodun bağımlılığı implementation(uygulama) Class’lara değil, Interface’lere olması gerektiğini makalemizin başında vurgulamaktır.
Daha açık bir şekilde ifade etmek gerekirse, üst seviye sınıflar alt seviye sınıf implementasyonlarını değil Interface uygulamalarını kullanmalıdırlar.
Neden mi?
Üst seviyeli işlem yapan sınıflar(High Level Class – Yüksek Dereceli Sınıf), alt seviyeli işlem yapan sınıflara(Low Level Class – Düşük Dereceli Sınıf) bağımlı olmaktadırlar. Bir başka açıdan bakarsak, üst seviyeli işlem yapan metodlar, alt seviyeli işlem yapan metodları kullanmaktadırlar. Haliyle alt seviye metodlarda olası her değişiklik üst seviye metodlarda değişikliğe sebep olması üst seviyenin alt seviyeye bağımlılığını göstermektedir. Haliyle DIP bize bu bağımlılığın ters çevrilmesini prensip edinmemizi önermektedir.
Aşağıda örnek bir bağımlılık senaryosu paylaşılmaktadır.
class Imalat { //High Level Class public void Olustur() { Kek kek = new Kek(); kek.KekYap(true); } } class Kek { //Low Level Class public void KekYap(bool Kakao) { //Process } }
Yukarıdaki “Imalat” sınıfı içerisindeki “Olustur” metodu, “Kek” sınıfı içerisindeki “KekYap” isimli metoda bağımlıdır. Bunun sebebi “KekYap”‘ın “Olustur” içerisinde kullanılmasıdır. İlgili metotda yapılacak tüm değişiklikler “Olustur” içerisinde de değişiklik gerektirecektir.
Bağımlılığı aşağıdaki diyagramdan da net bir şekilde görebilmekteyiz.
Nesne tabanlı yaklaşımlarda bu tarz bağımlılıklar soyutlama kullanılarak minimize edilebilmektedirler.
interface IGida { void Yap(bool Kakao); } class Imalat { //High Level Class IGida gida; public Imalat() { gida = new Kek(); } public void Olustur() { gida.Yap(true); } } class Kek : IGida { //Low Level Method public void Yap(bool Kakao) { //Process } }
Yaptığımız bu işlemi aşağıdaki diyagramda ele alalım.
Dikkat ederseniz yaptığımız işlem neticesinde alt seviye sınıfımızı Interface sayesinde soyutlaştırarak, üst seviye sınıfımızda alt seviye sınıfına dair olan bağımlılığı tersine çevirmiş bulunmaktayız. Yani gördüğünüz gibi alt seviye sınıfımız, Interface’e bağımlı bir hale gelmiştir. Ee ilgili Interface’de üst seviye sınıf tarafından refere edildiğinden dolaylı yoldan bağımlılık alt seviyeden üst seviyeye doğru olmuştur diyebiliriz.
Okuduğunuz için teşekkür ederim…
Sonraki yazılarımda görüşmek üzere…
İyi çalışmalar dilerim…
S.a Hocam. Bütün SOLİD prensiplerini okudum. Bunlardan önce de dependency injection konusu ile ilgilenmiştim. Şahsi görüşüm olarak diyorum ki . Her yol dependency injection’a çıkıyor. Temelde bu tasarım desenini anlayıp kavramak SOLİD’i büyük oranda kavramayı sağlar bence. Ve netice olarak SOLİD bize diyor ki.
Herkes kendi işine baksın kardeşim. Üstünüze vazife olmayan işlere burnunuzu sokmayın sorun çıkmaz diyor.
Classa sen git sadece kendi işini yap diyor. İnterface ‘a sen git kendi işine bak diyor. Open closed ile sana ne gelenden gidenden sen verilen işi yap diyor sadece. Bence hepsinin özeti dependency injection tasarım deseni. 🙂
Harikasın 🙂 Güzel özetledin 🙂
Tebrik ederim cok harika izahat olmus
Merhaba, bunlar ne anlama geliyor aciklarmisiniz rica etsem:
Üst seviyeli işlem yapan sınıflar(High Level Class – Yüksek Dereceli Sınıf)
Alt seviyeli işlem yapan sınıflara(Low Level Class – Düşük Dereceli Sınıf)
yani soyle soyleyim, “Üst/Alt seviyeli işlem yapan sınıflar” derken neyi kast ediyorsunuz? tesekkurler
Merhaba,
Üst seviyeden kasıt operasyon sahası iken, alt seviyeden kastımız ise operasyonun ta kendisidir. Şöyle düşünebilirsiniz ki;
“Banka” sınıfı üst seviye bir sınıfken, “EFTIslemleri” sınıfı ise alt seviye bir sınıftır ve “Banka” sınıfında yeri ve zamanı geldiğinde çağrılıp kullanılır. Dolayısıyla “Banka” sınıfı “EFTIslemleri” sınıfına bağımlıdır.
Sevgiler.
Hocam benim anlayamadığım bir husus var alt sınıfta değişiklik yapınca üst sınıfın etkilenmemesi ve üst sınıftaki değişikliğe alt sınıfın uyum sağlaması hususu rica etsem bunu açabilmeniz mümkün mü ?
Sizin kodda böyle bir düzenleme yaptım DIP hakkında okuduklarımdan anladığım ile sizce doğru mudur ?
Tersine çevirme doğru bir isimlendirme mi gerçekten.. Yani şimdi Alt Sınıf, Üst Sınıfa öı bağımlı oldu tam olarak.. Aklıma yatmadı 🙂
Problem nedir?