Dependency Injection vs Dependency Inversion
Yazılımdaki herkesin ara ara açıp okuduğu, öğrense de unuttuğu ama bilmeden de kullandığı yapılardan Dependency Injection ve Dependency Inversion’i inceleyeceğiz.
Bu yapılar genelde çok karışık anlatılmaktadır. Fakat ben size çok basit bir örnek üzerinden anlatmaya çalışacağım.
İlk olarak Dependency Inversion ve dependency injection nedir gibi bilgileri öğrenelim.
Dependency Inversion S.O.L.I.D prensiplerinin son harfi olan D ile temsil edilmektedir. Dependency Injection ise dependency inversionun uygulanma tekniklerindendir. Buradaki amaç başka classlara olan bağımlılığı en aza indirmektir.
Dependency Injection ve Dependency Inversion’i bir örnekle anlatalım.
Xmarka bir televizyon aldığımızı varsayalım bu televizyonun ayni marka bir de kumandası olacaktır. Fakat artık yeni televizyonları telefon, tablet gibi cihazlardan da yönetebiliyoruz biz de bu durumu inceleyeceğiz.
class XmarkaKumanda(): def ac(self): print("Televizyon aciliyor...") def kapat(self): print("Televizyon kapatiliyor...") class XmarkaTelevizyon(): def __init__(self): self.kumanda = XmarkaKumanda() # XmarkaTelevizyon classi XmarkaKumada classina bagimli self.tv_acik_mi = False def press_red_button(self): if self.tv_acik_mi: self.kumanda.kapat() self.tv_acik_mi = False else: self.kumanda.ac() self.tv_acik_mi = True tv1 = XmarkaTelevizyon() tv1.press_red_button() print("Televizyon acildi.") tv1.press_red_button() print("Televizyon kapatildi.")
Yukarıdaki örneği incelediğimizde XmarkaTelevizyon class’i XmarkaKumada class’ina bağımlı olduğunu göreceğiz. Biz bu bağımlılığı en az indirmek için ilk olarak dependency injection sonrasında ise dependency inversion uygulayacağız.
Dependency Injection bağımlıkların dışarıdan alınması ile olmaktadır.
class XmarkaKumanda(): def ac(self): print("Televizyon aciliyor...") def kapat(self): print("Televizyon kapatiliyor...") class XmarkaTelevizyon(): def __init__(self, kumanda: XmarkaKumanda): self.kumanda = kumanda self.tv_acik_mi = False def press_red_button(self): if self.tv_acik_mi: self.kumanda.kapat() self.tv_acik_mi = False else: self.kumanda.ac() self.tv_acik_mi = True # kumanda instance uretip televizyon classina verdik kumanda = XmarkaKumanda() tv1 = XmarkaTelevizyon(kumanda) tv1.press_red_button() print("Televizyon acildi.") tv1.press_red_button() print("Televizyon kapatildi.")
Yukarıdaki kodu incelediğimizde bagimligimiz olan kumandayı class içerisinde üretmek yerine dışarıdan aldık. Üretilmiş her hangi bir Xmarka kumanda isimizi görecektir burada.
Dependency Injection ilk bakışta sorunumuzu çözüyor olarak görünse de tam olarak çözmemektedir. Telefon veya Tablet gibi cihazlardan televizyonu kontrol etmek istediğimizde o class’lardan üretilmiş nesneleri televizyon class’ina gönderemeyeceğiz.
Bu sorunu bir interface yardımıyla çözebiliriz. Üretilen kumanda, telefon ve tablet gibi cihazlar bu interface ‘den implement aldığında bu sorun çözülecektir. Bu işleme dependency Inversion denir. gelin birlikte inceleyelim.
from abc import ABC, abstractmethod class KumandaOzelligi(ABC): @abstractmethod def ac(self): pass @abstractmethod def kapat(self): pass class XmarkaKumada(KumandaOzelligi): def ac(self): print("Televizyon XmarkaKumada ile aciliyor...") def kapat(self): print("Televizyon XmarkaKumada ile kapatiliyor...") class YMarkaTelefon(KumandaOzelligi): def ac(self): print("Televizyon YMarkaTelefon ile aciliyor...") def kapat(self): print("Televizyon YMarkaTelefon ile kapatiliyor...") class XmarkaTelevizyon(): # kumanda instance'inin, Kumanda ozelligi olan herhangi bir cihaz olmasi yeterli def __init__(self, cihaz: KumandaOzelligi): self.cihaz = cihaz self.tv_acik_mi = False def press_red_button(self): if self.tv_acik_mi: self.cihaz.kapat() self.tv_acik_mi = False else: self.cihaz.ac() self.tv_acik_mi = True kumanda = XmarkaKumada() tv1 = XmarkaTelevizyon(kumanda) tv1.press_red_button() tv1.press_red_button() telefon = YMarkaTelefon() tv2 = XmarkaTelevizyon(telefon) tv2.press_red_button() tv2.press_red_button()
Yukarıdaki kodu incelediğimizde KumandaOzelligi adında interface oluşturulduğunu görüyoruz. Televizyon class’i ise KumandaOzelligi olan herhangi bir cihaz alıyor. Kumanda ve telefon class’larimiz ise KumandaOzelligi interface ‘inden implement alıyor.