Dependency Injection Pattern Üzerine
Merhaba sevgili yazılım aşıkları! Bu yazımızda Dependency Injection Pattern (bağlılığı enjekte etme deseni) üzerine konuşacağız. Konuya geçmeden önce hemen belirteyim; bu yazıda, IoC (Inversion of Control) Container konusunu ele almayı planlamıyorum. Sadece Dependency Injection’a odaklanacağız.
Bir önceki yazımda, Dependency Inversion prensibini ele almıştım (burada). Dilerseniz aynı örnek üzerinden ilerleyerek bu Dependency Injection Pattern’i aktarayım size. Öncelikle, bu deseni nerede kullanacağımıza bakalım.
Bir önceki yazımda geliştirmiş olduğum örnekte, IDataConverter tipindeki formatConverter alanına (field) değer atama işini, ProductService sınıfı içerisindeki Publish metodu üstleniyordu. Oysa prensibin amacı bağımlılığı tersine çevirmek olduğuna göre bu işin sınıfın dışına çıkarılması şart. Yani, XMLConverter veya JSONConverter sınıflarının implemente ettiği IDataConverter Interface’i ProductService sınıfına dışardan atanmalı. Tam bağımsızlığı ancak böyle elde etmiş olacağız sonuçta.
Çok mu karışık oldu? O zaman daha basite indirgeyelim. ProductService nesnesini kullanmadan önce; ürün listesinin neye (JSON mu yoksa XML mi?) dönüştürüleceğine karar vermem gerekir diyorum 🙂 gayet basit.
Peki, bunu nasıl yapabiliriz? Sizin de tahmin edebileceğiniz gibi IDataConverter interface’ini parametre olarak ProductService sınıfına sunmam en mantıklı yol olacaktır. O zaman hangi yapılarla gönderebilirim bu parametreyi?
Sınıf içine parametre ile değer alabileceğiniz üç yapı:
- Constructor
- Property
- Metot
İşte enjekte etme (dışarıdan atama) işlemimizi de bu üç yolla yapabiliriz. Hadi tek tek inceleyelim.
1. Constructor Injection
En çok kullanılan Dependency Injection yöntemidir. Sınıfın (ProductService) ihtiyaç duyduğu nesne (dependency), constructror üzerinden parametre ile verilir. Şimdi bunu yukarıdaki örnek üzerinde uygulayalım:
Gördüğünüz gibi, ProductService sınıfının constructor’unda IDataConverter interface’sini parametre olarak belirttim. Bu yöntemin bana birkaç faydası var. Bunlardan en önemlisi elinizde IDataConverter tipinde bir nesne olmadan ProductService sınıfının örneğini alamayacaksınız. Buna bağlı olarak; ProductService sınıfı dataConverter nesnesi hakkında daha fazla bir şey bilmek durumunda kalmayacak. Haliyle daha temiz, daha kullanışlı ve “loosely coupled” bir tasarım elde etmiş oldunuz.
2. Property Injection
İhtiyaç duyulan nesnenin (dependency) seçeneğe bağlı olarak verilebileceği durumlarda kullanılır. Tek yapmanız gereken değer atanabilir bir property yazmaktır. Sözle değil kodla anlatalım:
Eğer dikkatli bakacak olursanız; değer atanabilir (writable) bir property yazdığım için ekstra bir field kullanmama gerek kalmadı. Bu özelliğe ister değer atarsınız, istemezseniz atamazsınız. Madem öyle; Publish metodunun içerisinde null referans kontrolü yapmak zorundasınız demektir!
3. Method Injection
Her metot çağrısında değişebilecek bir bağımlılık durumu mu var? O zaman bu yöntem işinizi görecektir. İhtiyaç duyulan Interface’i, bağlılığı kullanacak olan metoda parametre olarak atarsanız, bu metodu her çağırdığınızda tam olarak arzu ettiğiniz durumu elde edersiniz. Nasıl mı?
Bu noktaya dek, Dependency Injection deseninin ne olduğunu umarım anlatabilmişimdir. Tam da bu noktada bir sorum var; ProductService nesnesinin bağımlılığını uygulama çalışırken (run-time) değiştirmek istersem ne yaparım?
İşte bu IoC Container konusuna giriyor ve o da başka bir yazıya kalıyor.
Sağlıcakla kalın.
hocam merhaba ;
birşey sormak istiyorum. IDataConverter nesnesini implemente edildiği bir sınıftan türetmediğimiz halde DataConverter objesi convert metodu ile ne yapacağını nereden biliyor ?
Hocam elinize sağlık çok güzel anlatmışsınız 🙂
Merhaba, sitenizde güzel konnulara değiniyorsunuz. Sizi daha iyi takip edebilmemiz için email aboneliği özelliğini sitenize ekler misiniz?