Orjinal yazar Tatham Oddie... Bu yazıyı Tatham'ın verdiği bir sunumdan izniyle çevirdim.

Giriş

Inversion of Control (IoC) bir modülün bağımlılık, çözülme, konfigürasyon ve hayat döngüsü konularına çözüm sağlayan dizayn kuralıdır. IoC’nin en önemli özelliği bir modülün bağımlı olduğu diğer assembly bileşenlerinin çözülümünde yatmaktadır.

IoC’nin en iyi bilinen olayı Dependency Injection Principle’dır (DIP). Diğer bir adıda Hollywood kuralı’dır (Bizi arama, biz sana haber veririz). Bu kural bir dizayn paterni değildir.

Genel olarak modüllerin gevşek olarak birbirine bağlanmasını sağlar. Gevşek bağlılığın sağladığı yararları sıralarsak:

  1. Yeniden kullanılabilirliğin arttırılması
  2. Test işlemlerinin kolaylaştırılması
  3. Bir araya getirmesi ve konfigürasyonu kolay sistemler (Modül bazında)

Dependency Resolution

Basitçe özetlersek, IoC kuralına göre dizayn edilmiş bir modül (Modül A), işlerini tamamlamak için kullandığı diğer modülleri (Modül B, Modül C, Modül D) yada assembly’leri çağırmaz. Bunun yerine bağımlı olduğu modülleri (Modül B, Modül C, Modül D) tanımlar ve bir container nesnesi bu tanımlanan modülleri kullanıma sunar. Yani çağırılan modüllerin kontrolü ters yüz edilir. Modül A çağırdığı modüllerin (Modül B, Modül C, Modül D) kontrolünü yapmaz, bu işlem artık container nesnesinin işidir.

Çağırılan modüller 3 şekilde tanımlanabilir.

Constructor Injection – çağırılan modül sınıfın “constructor” fonksiyonunda “property” olarak tanımlanır ve sınıf nesne olarak oluşturulduğunda container tarafından doldurulur.

public class SimpleMovieFinder : IMovieFinder

{

private IMovieDatabase database;

public SimpleMovieFinder(IMovieDatabase database)

{

this.database = database;

}

public string[] GetByTheatre(long theatreId)

{

string filter = string.Format("[TheatreId] = {0}", theatreId);

return database.GetByFilter(filter);

}

}

Setter Injection – bağımlı modüller “public property” olarak tanımlanır (get - set) ve “container” sınıfın nesne olarak oluşturulduğu sırada bu “public property”leri set eder.

public class SimpleMovieFinder : IMovieFinder

{

private IMovieDatabase database;

public SimpleMovieFinder()

{

}

public IMovieDatabase Database

{

get { return database; }

set { database = value; }

}

public string[] GetByTheatre(long theatreId)

{

string filter = string.Format("[TheatreId] = {0}", theatreId);

return database.GetByFilter(filter);

}

}

Contextualized Dependency – sınıf bir “service manager” sınıfından miras alır ve çağırılan diğer modüller bu servis yönetici sınıfı tarafından doldurulur.

public class SimpleMovieFinder : IMovieFinder, IServicable

{

private IMovieDatabase database;

public SimpleMovieFinder()

{

}

public void Service(ServiceManager manager)

{

database = (IMovieDatabase)manager.Lookup("MovieDatabase");

}

public string[] GetByTheatre(long theatreId)

{

string filter = string.Format("[TheatreId] = {0}", theatreId);

return database.GetByFilter(filter);

}

}

Dependency Injection kullanılan sınıfın yapısını bozmaz. Bu, modülleri herhangi bir container nesnesi olmadan da kullanabileceğimiz anlamına geliyor. İyi dizayn edilmiş modülleri IoC kuralına göre kullanmak için her hangi bir değişiklik yapmamıza da gerek yoktur. Üçüncü parti modülleri bile IoC uygulamaları içinde kullanabiliriz.

Diğer taraftan yukarıda anlatılan “Contextualized Dependency Lookup” metodu sınıfın yapısını bozar. Tipik olarak bu, modüllerin bir container içinde kullanılmasını ve uygun bir framework’ten ithal edilmesini gerektirir. Ayrıca IoC yaklaşımında kullanılacaksa ekstra iş gerektirir. Hal böyle olunca CDL çok az kullanım alanı bulmaktadır.

Konfigürasyon

IoC framework, “dependency resolution” prensipleri ile aynı prensipleri kullanarak konfigürasyon servisleride sunar. Örneğin SmtpEmailSender isimli bir sınıfın aşağıdaki gibi bir constructor sunduğunu düşünelim. IoC framework otomatik olarak bu konfigürasyon detaylarını doldurur ve bizim bu iş için ayrıca kod yazmamıza gerek kalmaz. Bunu bir XML konfigürasyon dosyası kullanarak yapar.

public SmtpEmailSender(string serverHostname, int serverPort)

Eğer hazır sınıfları IoC framework içine dahil ediyorsak “Setter Injection” metodunu kullanarak konfigürasyon parametrelerini doldurabiliriz.

Yaşam Süreci

Bir modülün yaşam süreci, oluşturulmasından sonra hangi aşamalardan geçeceğini tayin etmektir. Diyelim ki modülümüz bir kaç “thread” açıyor ve bir “socket” üzerinden dinleme yapıyor. Bu genelde constructor seviyesinden olacak bir iş. IoC framework için kullanılacak modüllerin bir start/stop arayüzü vardır ve “container” bu arayüz ile modüllerin yaşam sürecini kontrol edebilir.

Daha karmaşık yaşam süreçleri için bazı IoC framework’lerinde daha detaylı yönetim biçimleri vardır.

Neden DIP Kullanalım?

Tabii ki iki tane sınıf için IoC sisteminin uygulanması zaman harcamaktan başka bir şey olmaz. IoC sisteminin yararı karmaşık bağımlılık bulunduran uygulamalarda ortaya çıkar. Yandaki şemaya bir göz atalım. Bu şemada yeşiller sınıfları sarılarda arayüzleri temsil eder. Sınıflardan her hangi birini kullanmaya kalktığınızda ortaya çıkacak kod karmaşasını tahmin edebiliyor musunuz?

Uygulama terimi içinde, DIP çok basit bir teknik. Tek başına tüm nesneleri yaratıp parametreleri oluşturan bir uygulamadan ziyade, DIP ile bir dizi gevşek bağlı modül olarak geliştirme yapmak çok daha karlı. Ayrıca bu modüllerin birbirleri ile nasıl ilişki kuracaklarını bilmelerine gerek yok. Çüknü tüm modüller bir container nesnesi içinde çalışıyorlar ve container nesnesi kofigürasyon dosyasından (XML formatında bir dosya) gerekli tüm parametreleri ve birlikte çalışma prensiplerini alıyor.

http://blogs.pragprog.com/cgi-bin/pragdave.cgi/Tech/TransparentIOC.rdoc

Mevcut IoC Sistemleri

IoC kavramı henüz .NET dünyasında tam olarak gerçeklenebilmiş değil. Bunun sonucu olarak ortaya çıkan IoC framework’leri Java dünyasında olduğu kadar zengin değil. Aşağıda iki IoC sisteminin kısa açıklamalarını bulacaksınız.

Spring.NET (http://www.springframework.net/)

Java Spring Framework’ünden adapte edilmiştir. (http://www.springframework.com/)

Bazen başka bir sistemden adapte etmek iyi bir yöntem olmuyor ve sonuçta aynı fonksiyonellik sunulabilmesi için pek çok takla atmak gerekiyor. Bu da sistemin performansını etkiliyor

Java içindeki IoC kavramı daha iyi oturduğu için Spring.NET aynısını yapmaya çalışıyor. Kavram olarak iyi sayılabilir.

Kullanılan diğer modüllerin otomatik olarak bağlanması yok.

XML konfigürasyon dosyaları çok karmaşık ve bazen kodunuda yazmak gerekiyor.

Konfigürasyon dosyalarının kod ile olan senkronizasyonu kolayca bozulabiliyor.

<object id="smtpEmailSender" class="BulkEmailSender.Logic.SmtpEmailSender, BulkEmailSender.Logic">

<constructor-arg><value>mail.ssw.com.au</value></constructor-arg>

<constructor-arg><value>25</value></constructor-arg>

</object>

Castle Framework (http://www.castleframework.net/)

Kullanılan diğer modüllerin otomatik olarak bağlanması var.

Anlaşılabilir konfigürasyon dosyaları.

<component id="smtpEmailSender">

<parameters>

<serverHostname>mail.ssw.com.au</serverHostname>

<serverPort>25</serverPort>

</parameters>

</component>

Dökümantasyon yok denecek kadar az ve varolan dökümantasyon değişiklik olduğunda güncellenmiyor.

IoC’nin uygulanması

Container Oluşturmak

IoC tüm nesnelerimizi yönetmek için bir “container” nesnesini kullanıyor. Container nesnesinin sorumluluğu kullanılan diğer nesnelerin istendiği zaman hazır edilmesidir.
Container nesnesinin işini yapabilmesi için kullanılacak nesnelerin container nesnesine eklenmesi ve sundukları servislerin tanımlanması gerekir. Nesnelere daha sonra erişebilmek ve konfigürasyon dosyaları ile bağlamak içinde tekil bir anahtar verilir.

Container nesnesini yaratmak kolay:

IWindsorContainer container = new WindsorContainer();

Ve kullanılacak nesneleri de eklemek çok zor değil. Ayrıca nesneye verdiğimiz tekil anahtara dikkat edin. Daha sonra konfigürasyon dosyalarına bağlamak için işimize yarayacak. Birde arayüz referansına dikkat edin IBulkEmailSender ile nesnenin sunduğu servislere erişim sağlanıyor.

container.AddComponent("newsletterBulkEmailSender",

typeof(IBulkEmailSender),

typeof(NewsletterBulkEmailSender));

İhtiyacımız olduğunda kullanacağımız fonksiyonun tipine bağlı olarak herhangi bir nesneyi çağırabiliriz. Tabii ki bunu arayüzü kullanarak yapacağız. Bir satırda arayüzün ismini 3 kere kullanıyoruz ama genede tüm sınıfları birbirine kodla bağlamaktan daha az kod yazıyoruz.

IBulkEmailSender sender = (IBulkEmailSender)container[typeof(IBulkEmailSender)];

Reklamlar


Bu girdiye atılan yorumlar:

# Art??k MyFaces ile &amp;#8220;Dependency Injection&amp;#8221; yap??labiliyor &amp;laquo; Mustafa Ulu

Art??k MyFaces ile &amp;#8220;Dependency Injection&amp;#8221; yap??labiliyor &amp;laquo; Mustafa Ulu

Pingback/TrackBack tarafından  7/14/2009 11:16 AM tarihinde atılmıştır.

Yorumunuzu buradan giriniz

Yorumlar onaylandıktan sonra yayınlanacaktır

*


*


 (Görüntülenmeyecek)


 (İsminizde link olarak görüntülenecek)


*
Bold Italic Underline Blockquote Hyperlink Hyperlink

 

Please add 1 and 3 and type the answer here:

Yorum Önizleme:

 

Arama



Hakkımda

Merhaba, ben Gürkan Yeniçeri. 10 yılı aşkın süredir özel sektör ve hükümet iştiraklerinde yazılım mühendisliği yapıyorum. Bu sitede 2005 Mart ayından beri genelde yazılım mühendisliği ve Microsoft teknolojileri hakkında yazmaktayım. Profesyonel iş geçmişim hakkında daha fazla bilgiyi aşağıdaki Linkedin.com linkinden alabilirsiniz.
Gürkan Yeniçeri'nin profilini görmek için tıklayın
Faturaları ödeyen günlük işim dışında Açık Kaynak Subtext Projesine katkıda bulunuyorum. Bu blogun alt yapısıda Subtext ile hazırlanmıştır. Ayrıca 1999 yılından beri Programlama.com sitesinde VB6 editörlüğü yapıyorum. Fakat takdir edersinizki VB6 artık ölü bir dil, bu nedenle beta sürümlerinden beri C# ve ASP.NET programcılığı ile uğraşıyorum.

Kontak

Soru sormak veya öneride bulunmak isterseniz buradaki kontak formunu kullanın. Mesajlarınıza en kısa zaman içinde cevap vermeye çalışacağım. Ayrıca Windows Live Messenger kullanarak gyeniceri {AT} hotmail {DOT} com adresinden bana ulaşabilirsiniz.

Eğer İngilizce blogumu okumak isterseniz buraya buyrun.
Blogumu RSS Bandit gibi bir RSS okuyucusu ile de takip etmek için kullanın.
Ayrıca aşağıdaki linklerden hakkımda ayrıtılı bilgi alabilirsiniz.
Twiter
Friendfeed
Facebook

RSS 2.0

Reklamlar


Vezir

Vezir Proje Danışmanı
Sitede birde Vezir isminde wikimiz var. Bu wikiyi yazmayı düşündüğüm bir kitap için oluşturmuştum daha sonra herkese açmaya karar verdim. Vezir yazılım firması kurmak isteyenlere tavsiyeler vermek için hazırlandı. Ayrıca UML ve Modül Tabanlı Geliştirme hakkında da bilgiler mevcut. Vakit buldukça yeni eklemeler yapıyorum. Değişikliklerden haberdar olmak için RSS çıktısına üye olabilirsiniz.

Tag Bulutu

Tüm taglar...
www.flickr.com
This is a Flickr badge showing public photos from gurkanyeniceri. Make your own badge here.
Bu blogda 261 yazı ve 429 yorum var. Diğer sitelerden 22 adet link gelmiş.

Buradayım

my blogmap

Reklamlar