Ninject, Gevşek Bağlı Sistemler : Modül

   Önceki makalemle birlikte Ninject’e yaptığımız giriş ardından Dependency Injection’ın hayatımızı ne kadar kolaylaştırabildiğini size örnekleyebildiğimi umarım. Şimdi sıra bunu bir adım daha ileri taşımakta. Dependency Injection konusu boyunca hedefimiz her zaman için olabildiğince gevşek bağlı (loosely coupled) bileşenler ortaya koyabilmek olmalı. Bu bakış açışıyla yazı dizisi boyunca örnek olarak kullandığım uygulamanın aşağıdaki main metoduna bir daha göz atalım;

class Program {
    static void Main(string[] args) {
        var ogrenci = new Ogrenci {
            No = 12345,
            Adi = "Fatih",
            Soyadi = "Boy",
            Bolum = "Bilgisayar Mühendisliği"
        };

        IKernel kernel = new StandardKernel();

        kernel.Bind<IVeriDeposu>().To<XmlDosyaVeriDesposu>();
        kernel.Bind<IGunlukDeposu>().To<TextGunlukDeposu>();

        var ogrenciIslemleri = kernel.Get<OgrenciIslemleri>();

        ogrenciIslemleri.OgrenciKaydet(ogrenci);
    }
}

   Burada OgrenciIslemleri sınıfının XmlDosyaVeriDesposu ve TextGunlukDeposu depolarıyla doğrudan bir bağlantısı olmadığı oldukça net. Bu noktada gevşek bağlılık prensibine uyduk. Öte yandan uygulamamızın Main fonksiyonu her iki türden haberdar ve bunları ilgili arayüzlere bağlıyor. Bu durumda bir adım geri çekilip uygulama geneline baktığımızda aslında tam olarak bir gevşek bağlılıktan söz edebilmemiz mümkün değil. İstediğimiz bir anda bu bağımlıkları yenileri ile değiştirebilmemiz için uygulama kodumuzu güncelleyip yeniden derlememiz gerekli…

   Bu tasarımsal eksikliğin çözümü ise kesinlikle tür eşleştirmelerinin tamamen uygulamamız dışına taşınması olacaktır. Bu ihtiyaç Ninject’in tasarımında da göz önüne alınarak Modül kavramı ortaya çıkmıştır. Ninject için modül tür bağlamalarının gruplar halinde yapıldığı kod parçacıklarıdır. Uygulamanız için bir modül oluşturmak için yapmanız gereken öncelikle INinjectModule arayüzünü implemente eden bir sınıf oluşturmak olmalıdır. Hatta modülünüzde detaylarla uğraşmadan sadece türlerinizi bağlamak amacındaysanız aşağıdaki örnekte olduğu gibi doğrudan NinjectModule sınıfından da türetebilirsiniz;

public class AnaModul : NinjectModule {
    public override void Load() {
        Bind<IVeriDeposu>().To<XmlDosyaVeriDesposu>();
        Bind<IGunlukDeposu>().To<TextGunlukDeposu>();
    }
}

   Tabi AnaModul sınıfının uygulamanız dışındaki bir dll içerisinde yer alması yola çıkış noktasındaki prensibimizi korumamız adına önemli. Bu işlem ardından son adım olarak modülümüzden Ninject çekirdeğini haberdar etmeliyiz. Bunun için ilk ve en basit yöntem aşağıdaki şekilde çekirdeği oluştururken modüllerin parametre olarak çekirdeğe geçilmesidir;

IKernel kernel = new StandardKernel(new AnaModul());

   Bu yöntemin dezavantajı; ana uygulamamızın derleme zamanında modülümüzden haberdar olma zorunluluğudur. Bu durumda, ilk baştaki tasarımımızdan daha iyi bir noktada olmakla beraber henüz tam olarak gevşek bağlı bir uygulama oluşturabilmiş değiliz. Yapmamız gereken uygulamamız içerisinde modülümüzü dinamik yüklemek olmalı. Bu durum için Ninject çekirdeğinde yer alan Load fonksyonunu kullanabiliriz;

kernel.Load("*.dll");

   Ninject, Load fonksiyonu ile uygulamanın çalıştığı klasörde yer alan ve belirtilen kriterlere uygun olan tüm dll’leri tarayarak içlerinde yer alan modülleri tespit edecektir. Daha sonra, tespit edilen bu modüller otomatik olarak Ninject çekirdeği tarafından yüklenecektir. Bu noktada, size tavsiyem yukarıdaki gibi genel geçer bir “tüm dll’leri incele” şablonu kullanmak yerine aşağıdakine benzer şekilde seçenekleri azaltacak şablonlar kullanmanız;

kernel.Load("Com.Enterprisecoding.Moduller.*.dll");

   Modül kullanımına bir başka örnek de Ninject eklentileridir. Ninject, Ninject.Extensions.*.dll ve Ninject.Web*.dll şablonları ile kendi eklentilerine ait modülleri otomatik yüklemektedir. Ninject, string şeklinde aldığı modül assembly bilgisini aynı zamanda Assembly türünde de alabilmektedir. Bu sayede, örneğin aşağıdaki şekilde uygulama AppDomain’inde yüklü tüm assembly’lerin taranmasını ve bulunan modüllerin yüklenmesini sağlayabilirsiniz;

kernel.Load(AppDomain.CurrentDomain.GetAssemblies());

   Bu adımlar ardından artık uygulamamızı tam anlamı ile gevşek bağlı hale getirmiş oluyoruz. Artık örneğin Com.Enterprisecoding.Domain.WS.dll’i içerisinde yer alan modül ile tanımlayacağımız tür bağlamaları bize işlemlerimizi web servisler üzerinden yapmamızı sağlarken, Com.Enterprisecoding.Domain.Entity.dll’i sayesinde doğrudan Entity framework ile işlem yapar duruma kolaylıkla gelebiliriz. Bir başka kullanım örneğinde de Com.Enterprisecoding.Domain.Oracle.dll’i ile uygulamamız Oracle veritabanı üzerinde işlem yapabiliyorken, Com.Enterprisecoding.Domain.MsSql.dll’i ile MsSql server üzerinde işlem yapabilir. Aslında, uygulamanın versiyonlanmasına varıncaya kadar bu örnekleri çoğaltabilmemiz mümkün.

Fatih Boy

Ankara'da yaşayan Fatih, bir kamu kurumunda danışman olarak çalışmaktadır. ALM süreçleri, kurumsal veri yolu sistemleri, kurumsal altyapı ve yazılım geliştirme konularında destek vermektedir. Boş zamanlarında açık kaynak kodlu projeler geliştirmeyi ve bilgisini yazdığı makalelerle paylaşmayı seven Fatih, aynı zamanda Visual C# ve Visual Studio teknolojileri konusundan Microsoft tarafından altı yıl üst üste MVP (En Değerli Profesyonel) ödülüne layık görülmüştür. İş hayatı boyunca masaüstü uygulamaları, web teknolojileri, akıllı istemciler gibi konularda Asp.Net, Php, C#, Java programlama dilleri ve MySql, MsSql ve Oracle gibi veritabanı yönetim yazılımları ile çalışmıştır. İngilizce ve Türkçe olarak yayınlanan makalelerini gerek İngilizce bloğunda, gerekse de Türkçe bloğunda bulabileceğiniz gibi web sitesinden de açık kaynak kodlu geliştirdiği yazılımlarına ulaşabilirsiniz. vCard - Twitter - Facebook - Google+

Bir Cevap Yazın

E-posta hesabınız yayımlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir