Yazılım Mimarileri ve Tasarım Desenleri Üzerine

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…

Mobil sürümden çık