*

  • (ing. dependency inversion principle)

    "ust seviye siniflar alt seviye sinif implementasyonlarini degil interface'lerini kullanmalidir" $eklinde ozetlenebilecek nesneye dayali yazilim geli$tirme prensibi. yani :

    sınıf hayvan
    {
    ...
    }

    fonksiyon bir_sınıf::bir_fonksiyon(hayvan o)...

    gibi bir tanimlama yerine :

    sınıf hayvan : icanli
    {
    ...
    }

    fonksiyon bir_sınıf::bir_fonksiyon(icanli i)...

    $eklinde bir tanimlama yeglenmelidir ki, ileride aynı interface'ten implemente edilmi$ ba$ka siniflar da kullanilabilsin.

    ayrica;
    (bkz: acik kapali prensibi)
    (bkz: arayuz ayirma prensibi)
    (bkz: liskov degistirme prensibi)
    (bkz: tek sorumluluk prensibi)
  • üst düzey politikalara bağlı olarak alt düzey ayrıntıları kontrol akışına karşı koymamızı sağlayan nesne yönelimli dizaynlarda olması beklenen prensip.
    üst düzey bir politika değiştiğinde, alt düzey ayrıntıların uyarlanması. bununla karşın, alt düzey ayrıntılar değiştiğinde üst düzey politikalara dokunulmaması.
    ood için olmazsa olmaz prensiplerden biri.
  • bir nesnenin bağımlılıklarını soyutlayarak, bağımlılıkları nesneye başka bir katmandan vermektir. sadece interface ile yapılmak zorunda değildir. bağımlılık bir abstract class'ta olabilir. en büyük getirilerinden birisi, kodu unit test yazılabilir hale getirmesidir.
  • (bkz: #94280510)

    sınıfların birbirine bağımlılığı soyut kavramlar üzerinden yapılmalıdır. bir sınıf diğer bir sınıfa doğrudan bağlanmamalıdır. özellikle yüksek seviyeli bir class düşük seviyeli bir class a asla bağılmlı olmamalıdır.
    bunun için güzel bir örnek anahtar ve ampüldür.
    bir ampül classımızın olduğunu düşünelim ve içinde de yak() ve sondur() metotları olsun.
    bir de anahtar classımız olsun. anahtar bir ampüle ve bir de anahtarla() metoduna sahip olsun. anahtarla metodu da eğer açıksa söndürsün, sönükse açsın.
    bu şekilde yapılan tasarımda, anahtar gibi hem ampül yakıp söndürebilecek hem de başka cihazları da açıp kapayabilecek derecede yüksek seviyeli bir class iken bizim tasarımımızda sadece ampül açıp kapayabiliyor. daha sonra başka bir cihaz açıp kapamak istersek anahtar sınıfını kullanamayacağız.

    bunun yerine anahtarlanabilir diye bir interface oluşturup ve içine de ac() ve kapa() diye bir metot eklersek ampülü soyutlamış oluruz. daha sonra anahtar içinde ampül kullanmak yerine anahtarlanabilir interface ini kullanırsak anahtar anahtarlanabilir olan bütün classları açıp kapayabilecektir.
  • ıki kurali da pratikte ele alacak olursak

    kural 1) yuksek seviye moduller dusuk seviye modullere bagimli olmamalidirlar. ıkisi de soyutlamalara bagimli olmalidir.

    modul denilince burda kastedilen sadece sinif degil, bildigimiz moduller de dip e dahiller.

    3 katmanli mimariden ornek : misal business layeri database layera dogrudan bagimli bir sekilde dizayn ettin.
    dal : data access layer
    bl : business layer
    ui : user interface

    problem i) daldaki kodlar degistikce onlari kullanan business layer kodlari da degismek durumunda kalabilir. business layer a ne dal degismis mi degismemis mi, dal uzerine dusen gorevi yapsin yeter.

    cozum : o zaman "uzerine dusen gorev" dedigimiz seyi soyutlarsak mesela bir interface ile, o zaman ben dalda ne degismis ne degismemis umursamadan isime bakabilirim.

    problem ii) user interface layer business layera , business layer data access layer a bagimli diyelim. uı i test etmek istiyorum nasil yaparim? her seferinde uı da bl yi cagirdigim yerleri test edecegim yerleri degistirir, haliyle acik kapali prensibini (open close principle) ihlal ederim : kod degisime kapali ,kapsam arttirmaya acik olmalidir. test icin kodu degistiriyorsak kapalilikta sikinti var demek bu.

    cozum : oysa ki bl dan beklediklerimizi interfacelerle soyutlasak (kocaman sisman interface yerine ufak ufak manali olanlarla bkz interface segregation principle) bagimliligi koskoca katman yerine interface e kaydirsak yani, test edecegimiz zaman interface in gereklilikliklerini testimize uygun fake objelerle saglayabiliriz.
    yani atiyorum bl in error dondurecegi bir durumu test ediyorsak ui icin, bl nin error dondurecegi interface e uygun bir fake sinif yazar, testimi gerceklestiririm.

    ayni mantiklar siniflar icin de gecerli, misal online e-commerce siten var, bunda bir siparis sinifin var, sinif siparis verirken mail atiyor, odeme yapiyor , logluyor vs. ust taraftaki "siparis" sinifi altindaki mail atma, odeme, loglama mekanizmasina bagimli yani. ben bunu test etmek istesem, bin tane takla atip belki bu bagimliliklarin bazilarini taklit edebilirim (fake smtp server kurarim bilgisayara var tool u, fake odeme servisi kuramam ama kolay kolay vs). oysa ki bagimliliklari bir sekilde soyutlasam, loglama odeme mail vs, soyut objeti sinifa enjekte etsem ve icini siniftan bagimsiz bir yerde doldursam o zaman
    a) bu mekanizmalar degistiginde sinifimin kodu sabit kalir (open close principle)
    b) test edecegim zaman istedigim gibi fake sekilde bu bagimliliklari saglayabilirim.

    kural 2) soyutlamalar detaylara bagimli olmamalidirlar. detaylar soyutlamalara bagimli olmalidir.
    yani basitce, database erisimini bir sekilde soyutladin diyelim, sen mssql e gectin, oracle kullandin, mysql e gecti sirket vs farketmez. databasele yapilan islemler zaten soyutlamada tanimli, kodun kalani bu degisimden haberdar olmadan bu degisime bagimli olmadan uzerine duseni yapabilir.
    ote yandan, detaylar (misal oracle a baglanti kurma kodun) soyutlamanin geregini yerine getirmelidir(bagimli olmalidir). yani soyutlamada store procedure cagirdin table dondurdun gibi bir metod varsa, o oracle erisim kodu bunu saglayacak fonksiyonlari bunyesinde barindirmalidir.

    normalde olmasi gereken bagimliligin tersi oluyor haliyle, test bagimlilik prensibi (dependency inversion principle) ismi de burdan geliyor.
  • yukarıda çok kez anlatılmış lakin inversion diyebilmek için bir şeyin atlanmaması gerek. o da interfacei değişikliği ve kontrolü high level classın elinde olmasıdır. aksi takdirde inversion olmaz.
hesabın var mı? giriş yap