Dependency Injection Nedir?

Yazılım geliştirmedeki en önemli süreçlerden biri de şüphesiz ki yazılımın tasarlanmasıdır. İyi tasarlanmamış bir yazılım ilk başlarda sorun çıkartmasa da özellikle proje bittikten sonra eklenecek yeni özellik ya da yapı değişikliklerinde sıkıntı çıkartmaya başlayacaktır. İlk başta yamalı bir şekilde ilerleyen proje daha sonra patlak verecektir. Hatta bazen öyle bir hal alıyor ki, eklemek istediğiniz bir özellik için harcayacağımız zaman projeyi sıfırdan yazmanızdan daha fazla sürebiliyor. Bunun için koda bodoslama girmek yerine bir ön çalışma yapılması gerekir. Bu ön çalışmayı kağıt üzerinde yapmak iyi bir fikirdir diye düşünüyorum. (ki ben her projede kağıt üzerinde çizer, keser, hesaplar, class/klasör oluşturur ondan sonra kodlama işlemine geçerim)
Yazılımda sonradan sıkıntılar çekmemek için yazılımı tasarlarken oluşturulan sınıfların(class) birbiri ile bağını en aza (loosely coupled-Gevşek bağlılık) indirmek gerekir. En az olsun ki sonradan bir özellik eklemek ya da çıkartmak istediğimizde minimum yer etkilensin.
Dependency_Injection_Nedir
Şimdi örnek verecek olursak; aşağıda Google ve Yahoo'dan hava durumunu çeken bir yapı mevcuttur.

Havadurumunu Google ve Yahoo’dan Çeken Sınıfı

class Weather
{   
    public void GoogleProvider(string sehir)   
    {        
	 Var derece = 20; // burada sıcaklığı istediğiniz yerden alabilirsiniz.
        Console.WriteLine(“Sıcaklık : ” + derece + “ derecedir.”));    
    }

    public void YahooProvider(string sehir)   
    {        
	 Var derece = 20; // burada sıcaklığı istediğiniz yerden alabilirsiniz.
        Console.WriteLine(“Sıcaklık : ” + derece + “ derecedir.”));    
    }

}

Ve Console uygulalamızda bu hava durumunu ekrana basalım

static void Main(string[] args)
{    
   	Weather weather  = new Weather();        
        weather. GoogleProvider(“istanbul”);
}

Gelelim sonuca. Programı çalıştırdığımızda öncelikli olarak process çalışacak o da bir hava durumu sınıfı yaratıp sonrada içinde hava durumunu getiren metodu çağıracak ve sonuç olarak da ekrana şu çıkacak;

“Sıcaklık : 30 derecedir.”

Ama gelin görün ki bir gün Google yerine Yahoo'nun hava durumu API'sini kullanmaya karar verdiniz. O zaman şunu yapmamız gerekecektir.

static void Main(string[] args)
{    
   	Weather weather  = new Weather();        
        //weather.GoogleProvider(“istanbul”);
        weather.YahooProvider(“istanbul”);

}

Ozaman Google'ı kapat sonrada Yahoo Provider'ını kullan. Sonra build et ve sonra güncelle. Biraz uzun geldi sanki. :) O zaman bu kodu biz şöyle değiştirelim.

Öncelikli olarak bir tane Interface oluşturalım.

public interface IWeatherProvider
{
	IWeatherProvider GetWeather(string sehir); 
}

Sonrada oluşturduğumuz Interface sınıftan Inherit Providerlarımızı oluşturalım.

internal class GoogleProvider : IWeatherProvider
{
      public void GetWeather(string sehir)   
      {        
	    Var derece = 20; // burada sıcaklığı istediğiniz yerden alabilirsiniz.
          Console.WriteLine(“Sıcaklık : ” + derece + “ derecedir.”));    
      }
}

internal class YahooProvider : IWeatherProvider
{
      public void GetWeather(string sehir)   
      {        
	    Var derece = 20; // burada sıcaklığı istediğiniz yerden alabilirsiniz.
          Console.WriteLine(“Sıcaklık : ” + derece + “ derecedir.”));    
      }
}
// sayısı artabilir ben şimdilik 2 tane kullandım.

Ve son olarak da Providerlar için Interface sınıfı yaratan bir sınıf oluşturalım.

public class WeatherProviderFactory
    {
        public IWeatherProvider CreateProvider(string providerType)
        {
            IWeatherProvider provider = null;

            switch (providerType)
            {
                case “Google”: provider = new GoogleProvider();break;
                case “Yahoo”: provider = new YahooProvider(); break;                
            }

            return provider;

        }
    }

Yukarıda uygulamamız için interface’leri kullanarak hiyerarşik bir yapı oluşturduk ve yeniden kullanımın mümkün olduğu bir yapı geliştirdik.
Şimdi ise artık bunu Console uygulamamızın içinde bu hiyerarşik yapıyı çağıralım.

static void Main(string[] args)
{    
   var providerType = ConfigurationManager.AppSettings[“providerType”]
    var factory = new WeatherProviderFactory();
   var provider = factory.CreateProvider(providerType);
   var data = provider.GetWeather("istanbul");

   Console.Write(“Sıcaklık : ” + data);
     // Burada type olarak ben Enum kullanıyorum genel de ama anlatım kısa olması için string olarak ayarlarım.

}

Çalıştırdığımızda da ekrana şöyle bir sonuç çıkacak.

“Sıcaklık : 30 derecedir.”

İşte bu kadar. Uyarladığımız hiyerarşik yapı ile dinamik bir akış sağlamış olduk. Eğer Google dan Yahoo ya geçiş yapıyorsak sadece config dosyasını açıp "Google" yazan kısmı "Yahoo" olarak güncellememiz yeterli. Bu şekilde yeni bir hava providerı eklediğimizde sadece Provider'a özel metodu güncelleyip yeni bir type eklememiz yeterli. Console uygulama içinde herhangi bir sınıf değişikliği yapmadan sadece type güncellemesi ile de yeni Provider'a geçiş yapmış oluyoruz. Burada Provider ile Console uygulama arasındaki bağı en aza indirdik. Bu yapıya yani minimum bağımlılığa "Dependency Injection" diyoruz.

Şimdi şunu diyenler olabilir: “İlk yazım hali çok daha kısa idi çok uzadı bu kodlama ben sadece tek satır değişiklikten kurtulmak için bu kadar kod mu yazacağım.”. Ancak şunu unutmamak lazım ki bu basit bir örnek. Büyük projelerde değişiklikler tek satırlık olmayabilir. “Hmm o zaman küçük projelerde gerek yok” diyenleri de duyar gibiyim. Unutmayın ki nasıl alışırsanız öyle gider. Bu yüzden her zaman minimum bağlılık iyidir. Herkese iyi kodlamalar :)

Erkan DURSUN