şükela:  tümü | bugün
  • inversion of control ile aynı şey değildir. inversion of control programın akışını bir framework'ün kontrol ettiği bir programlama yaklaşımıdır. event driven programming buna örnektir: kullanıcı arayüzü eventler aracılığıyla kontrolü sizin kodunuza verir. başka bir örnek olarak asp.net page lifecycle'ını düşünebiliriz. kullanıcı isteği sayfanın server side code'una ulaşana kadar kontrol asp.net'dedir, program akışını yöneten asp.net'tir, gerektiğinde kontrolü size verir. bu yapı artık çok yaygındır, bunun gibi birçok framework vardır ve katmanlı bir mimari kurmamıza imkan veren yaklaşımlardan biridir ioc.

    ioc kullanılmayan bir durum için konsol uygulamalarını gösterebiliriz: uygulamanın başlangıç noktası main methodudur. programın başından sonuna kadar kontrol bizdedir. tüm akışı bizim yönetmemiz gerekmektedir.

    martin fowler dependency injection (di) terimini ortaya atmadan önce dependency'leri yöneten framework'lere ioc container deniyordu. ancak bu framework'ler program akışından çok dependency'lerin yönetimiyle ilgilendikleri için dependecy injection terimi bu işi daha iyi karşılamaktadır. bu terim genel olarak kabul edilmiş olsada ioc container terimi de hala oldukça yaygın. bunun sebebi ioc'nin daha kapsamlı bir kavram olduğunun ve container'lardan önce de var olduğunun gözden kaçırılması.

    di, yıllardır etrafta olmasına rağmen tam olarak anlaşılamamış bir teknik. service locator gibi bir anti-pattern'in yaygın olarak kullanılması buna bir örnek. go to implementation'ı bozuyor diyen arkadaşlara da kayda değer herhangi bir refactoring tool kullanmalarını tavsiye ediyorum. di ile ilgili birkaç yanlış inanç daha:

    - di sadece late binding için gereklidir : di bu imkanı sağlasa da bu resmin küçük bir kısmını görmek demektir, di çok daha fazla şey yapabilir.

    - di sadece unit testing'i desteklemek içindir : di unit testing için zorunlu olsa da diğer özelliklerini göz ardı etmek yanlış olur. yine de unit testing'i doğru bir şekilde yapmayı amaçlayan herkesin karşısına di eninde sonunda çıkacaktır.

    - di gelişmiş bir abstract factory'dir : di bütün object graph'ını oluşturmak için kullanılsa da service locator'dakinin aksine bu iş sistemin kalanı için transparent olmalıdır. di container bir seam ile uygulamaya tek bir yerden bağlanmalıdır (composition root) ve sistemin kalanı di container hakkında hiçbirşey bilmemelidir.

    - di için di container gereklidir : di container işleri her zaman kolaylaştırsa da kesinlikle zorunlu değildir. yine de di container kullanmamak yönünde bir kısıt varsa (örneğin internette paylaşacağımız küçük bir library var, herhangi bir di container'a bağımlı olmamız mümkün değil) poor man's injection geçerli bir yöntemdir.

    peki bunlar değilse nedir di? di; loosely coupled, maintainable, testable, extensible kod yazmayı hedefleyen bir araçtır. diğer solid prensiplerine destek olur. aynı zamanda bu prensipler ve unit testing, di'ın ortaya çıkmasında rol oynamıştır. bana göre bu yüzden tdd'ye girmeden ve en azından single responsibility principle'ını sindirmeden ne gibi sorunları çözdüğünü somut olarak görmek mümkün değildir. üzerine okuyup, kafa yorulması gerekir.

    zaman içinde referans verdiğim boş başlıkları doldurmayı umuyorum. herhangi bir soru veya öneri için mesaj atabilirsiniz. entry'nin büyük bir kısmı dependecy injection in .net kitabından referans alınmıştır.
  • (bkz: #27719581)'den devam ederek:

    dependency'ler nelerdir:

    - kullandığımız framework
    - 3rd party kütüphaneler
    - database
    - file system
    - email server
    - servisler
    - sistem kaynakları ( saat, tarih vs. )
    - configuration
    - new keyword'ü ile oluşturulan nesneler
    - static metotlar

    burada framework'ü stable dependency olarak değerlendiriyoruz çünkü uygulamamınızın modülerliğini engellemiyor. bcl her zaman için kullanıma açık çünkü uygulamanın çalışması için şart. bunları stable dependency olarak değerlendirmemizin nedeni bizim için yazılmış, test edilmiş olmaları, deterministik davranış göstermeleri, yerlerine başka class'lar yerleştirmeyi düşünmememiz. kullandığımız kütüphaneler de çoğu zaman(kendisi stable ise tabi) stable dependency olarak görülür.

    öte yandan listedeki diğer tüm öğeler volatile dependency olarak sınıflandırılır. bu dependency'lerin davranışları hiçbir zaman consumer nesne tarafından bilinemez bu yüzden nesnenin test edilebilirliğini engeller.

    örneğin saat başı bir işlem yapan bir sınıfın çalıştığını nasıl test edebiliriz? testi saatlerce çalıştırmak pek iyi bir çözüm olmaz. peki sistem saatini öğrenme işlemini basit bir abstraction arkasına alırsak? consumer sadece bu abstraction'ı bilirse test içinde bunu bir test double ile değiştirmek çok kolay.
    böylece database, file system gibi dependency'leri aynı yöntemle yönetmek, her test için istediğimiz durumu yaratmak bizim elimizde. bir diğer önemli nokta bu dependency'lerin new keyword'ü ile oluşturulmaması. new keyword'ü hem abstraction'ı implemente eden concrete class'a ayrı bir dependency yaratıyor, hem de bir test double ile değiştirmeyi imkansız kılıyor(public olarak kullanmak istemediğimizi varsayarsak).

    bu noktada constructor injection yardımımıza koşuyor. consumer, constructor'ında ihtiyaç duyduğu tüm dependency'leri parametre olarak belirtiyor. artık bu nesnenin çalışabilmesi için hangi dependency'lere ihtiyacı olduğunu açıkça görebiliyoruz. belirtilen tüm parametreler concrete class yerine abstraction olduğu için bunları test double'ları ile değiştirmek artık mümkün, class new keyword'ü ile dependency'yi oluşturduğunda bu mümkün değildi. peki uygulama üzerinde concrete class'ları bu sınıfa inject etmek kimin işi? cevap tabi ki di container.
  • özetle anlatmak gerekirse; bağımlılık oluşturacak parçaların ayrılıp bunların dışardan verilmesiyle sistem içerisindeki bağımlılığı minimize etme işlemidir
  • bu konuda hic bilgi sahibi degilseniz ama adam akilli ogrenmek istiyorsaniz su sirayi takip etmeniz kavramlarin dogru duzgun oturmasi acisindan faydali olacaktir :

    1) dependency inversion principle
    2) inversion of control
    3) dependency injection
  • dünyanın en sıradan programlama olayına verilmiş en karizmatik isim. insanın aklına eroin bağımlılarının kollarına eroin enjekte etmelerini getirir.
  • wiring diye de geçer bu kavram. iki tibi vardır biri constructor based dependecy injection diğeri ise setter based dependency injectiondır. bunları ayrı ayrı kullanabilidiğiniz gibi birlikte de kullanıbilirsiniz.

    temel olarak oluşturacağınız classın içinde başka bir classı new ile oluşturmamanız gerektiğini söyleyen bir yaklaşımdır. gereken classı ya constructorda yada setter methodunda parametre olarak almalısınız. böylece iki classı birbirinden izole etmiş olursunuz.
  • dependency inversion ile aynı şey değildir.
  • yazılım geliştirme sürecinde en önemli konulardan biri şüphesiz yazılımın iyi tasarlanmış olmasıdır. bu projenin geliştirilmesi yönetilmesi ve devamlılığı için çok önemlidir. proje büyümeye başladıkça yeni ihtiyaçlar, yeni geliştirmeler, ekstra özellikler kazanarak devleşmeye başlar.

    büyük şirketler dahil çoğunlukla önce projenin hayata geçirilmesini isterler; şimdilik bu şekilde yapalım ilk versiyonu çıkartalım biraz ilerleyelim, ileride bunları raylara oturturuz gibi düşünceler yer almaktadır. ancak iyi hazırlanmamış bir zemine sürekli yeni şeyler inşa etmek sallantılı bir süreç getirir. ilk zamanlarda problem yaşanmasa da ileride proje geliştikçe büyüdükçe ortaya çıkması kaçınılmaz olabiliyor. ve ileride ya toparlanma zamanı hiç gelmez yada toparlamaya kalktığınızda işin içinden çıkamaz hale gelinebiliyor. bazen yeni bir özellik eklemek projeyi yeniden yazmaktan daha zor olabiliyor bu sebeple. bunların bir çok sebebi olmasına karşın çözüm dependency injectiondır.

    dependency injection: bağımlılıkların dışarıdan enjecte edilmesi anlamına gelir.

    yani nedir; yazılımı oluşturan yapıların birbirleri ile olan bağı en aza indirmek. buna loosely coupled-gevşek bağlılık denir.

    peki dependency injection ne sağlar:

    yazılımı oluşturan yapıların birbirleri ile olan sıkı bağ azaldığı için, uygulamaya yeni özellikler eklenip çıkartılabilmesi kolay hale gelir.

    uygulama içerisinde değiştirilmesi müdahale edilmesi gereken yerler minumuma iner.

    test edilebilir yapılar ortaya çıkar.
  • dependency injection yapabilmeyi saglayan bir framework yazabilmek icin oncelikle bir custom classloader'a ihtiyac vardir. cunku dependency injection, class'larin dinamik (bkz: dynamic class loading) olarak kullanilmasina ihtiyac duyar. bu durumda custom classloader ile bir class hash olusturur, bunlarin interface'lere baglar, ve reflection kullanarak ihtiyac duyuldugu gibi bu class'leri load eder, ve bunlarin instance'larini o interface'lere gomersiniz. elbet burada bir caching mekanizmasi, ve dolayisiyla bir flyweight/factory pattern kullanilacaktir diye tahmin ediyorum.

    (bkz: classloader)