.NETin Temelleri -2

.NETin Temelleri 2 .NETin Temelleri 2 Makale

Bir .NET programı nasıl çalışır ?

Her ne kadar bir .NET programı sıradan bir exe dosyası gibi görünse de arada sağlar kadar fark vardır. Bir .NET exesi içinde MSIL denilen Microsoft Intermediate Language kodlarını taşır. Bu dosyaya PE, yani Portable executable da diyoruz. Normalde siz bir exe dosyasını çalıştırdığınız zaman makine kodunu çalıştırırsınız. Ancak NET .exe leri ile durum bundan çok farklıdır. İki exe arasındaki bu farkı şu şekilde özetleyebiliriz. 

Standart Executable:

Kaynak kod -> Derleyici -> Obje kodu -> Bağlayıcı -> EXE uzantılı çalıştırılabilir dosya.

.NET Executable:

Kaynak kod->Derleyici-> MSIL-> EXE uzantılı çalışabilir dosya ( PE )

Buradan da görebileceğiniz gibi aslında .net ile exe olarak tanımladığımız dosyalar, daha derlenmemiş oluyorlar. Bu noktada genelde programcıların düştüğü hata, bu kodun yavaş çalışacağı, çünkü derlenmediği oluyor. Ancak ilk kullanımda bu kod JIT Compilation yani Just in time Compilation denilen bir işlemle makine koduna çevriliyor, ve bu native makine kodu bir cachee atılıyor.Bir daha bu exe çalıştırılmak istenirse, o zaman cachedeki bu derkenmiş kkod kullanılıyor. Dolayısıyla .NET programları MSIL ile dağıtılsalar bile, ilk kez çalıştırıldıklarında derlenmeleri dışında bir yavaşlama yaşamıyorlar.

Genelde bu yanlış düşüncenin kaynağı Java ile dağıtılan bytecode gibi MSILin de interpreted edildiği fikri oluyor. Ancak belirttiğim gibi .NET kodu derlenerek çalışıyor, ve managed executionun getirdiği ufak performans farkları haricinde öyle pek bir yavaşlama da olmuyor.

Yani Javanın hissedilir yavaşlığı söz konusu değil. Bu yapıda MSIL  kodu JIT ile çalıştıran CLR (Common Language Runtime ) ise .NET frameworkün platformlar arası taşınabilirliğini sağlıyor. Yani siz bir platform için bir CLR yazdığınız takdirde, MSIL kodunuz o platforma otomatik olarak taşınabiliyor.

Bu yazının birinci bölümünde değindiğim gibi alıştığımız anlamda bir windows programı kurulduğunda, DLLler ve registry setingleri ile harddiskinizde yerini alıyor.Ancak .NET ile birlikte yazdığınız programların çalışması, dağıtımı ve kurulumu çok büyük değişikliklere uğruyor. En önemli noktalardan biri de, bu programların dağıtılması, yani deployment denilen aşamanın tamamen değişmiş olması.

Şimdi klasik bir Windows programının kurulum aşamasını göz önüne getirmeye çalışın. Karşınıza çıkan kurulum programı, bir sürü dll ve dosyayı hard diskinize kopyalar, ve daha sonra da bu dll’ler ile ilgili gerekli bazı bilgileri registry’e yazar.Bu işlemin nedenleri ve bu metodun ortaya çıkardığı zorlukları yazının bir önceki bölümünde ele almıştık.

Bir çok kullanıcı zaman zaman, programların daha kolay kurulmasını ve gerektiğinde daha kolay taşınmasını ister. Mesela sık kullandığınız bir programı, tüm ayarları, ve dosyaları ile bir başka bilgisayara aktarmak istiyorsunuz. Bu durumda diğer bilgisayara programınızı kurup, eğer config dosyalarını taşıma şansınız varsa, onları da kopyalayarak programınızı aktarabilirsiniz. Hemen her kullanıcının, özellikle registry denilen sistemden haberi olmayan kullanıcıların aklına aynı soru gelir : dosyaları olduğu gibi kopyalasam olmaz mı ? Tabii ki olmaz, çünkü registry’deki bilgiler bu şekilde kopyalanamayacağı için program taşındığı bilgisayarda çalışmaz.. Şimdi gelelim işin .NET boyutuna: artık bu bahsettiğimiz işlem mümkün !! Yani gayet kapsamlı, oturaklı bir .NET programı bile bulunduğu dizin başka bir makinaya taşındığında orada çalışabilir. Tabii bunun gerçekleşmesi için gereken bazı ön şartlar var, onları da göreceğiz. 

.NET ve ASSEMBLY kavramları 

Assembly nedir ? İşin aslı ben de ilk başlarda assembly’lerin   .NET framework altında kullanımını hemen kavrayamadım. Ancak biraz araştırma ve çalışma ile sorun çözüldü. Bu yazı dizisi bittiği zaman  sizin de bir sorun yaşamayacağınızı umuyorum.

Assembly kavramı için bir tanım yapmamız gerekirse, .NET altında programlarınızı oluşturan temel yapı bloğu olarak assembly’leri düşünebiliriz.

Kafanızda biraz daha somut bir fikir oluşturmak için bir duvar düşünün.Bu duvar, değişik büyüklükte ve renklerde tuğlalar ile örülmüş olsun. Bu tuğlaların hepsini birer assembly, duvarı da sizin uygulamanız olarak düşünebiliriz.

Ancak assembly dediğimiz birimler, yapı olarak oldukça esnek. Yani bir assembly, sadece tek bir dll veya .exe dosyasından oluşabileceği gibi, değişik türde bir sürü dosyanın bir araya gelmesi ile de oluşabilir. Bu açıdan renkleri ve büyüklükleri farklı tuğlalar iyi bir benzetme diye düşünüyorum. Eğer isterseniz, elinizdeki birkaç tuğlayı bir araya getirip, ortaya daha büyük bir blok çıkarabilir, ve duvarınızı örerken o bloğu da kullanabilirsiniz .

Şimdi bu benzetmeyi bir kenara bırakıp biraz daha teknik detaya girelim.

Assembly’lerin teknik yapısı. 

Assembly dediğimiz .NET binary’leri temel olarak MSIL ( Microsoft Intermediate Language ) kodu içeren yapı taşlarıdır. (MSIL hakkında ufak bir hatırlatma yaparsak: .NET altında yazılan programlar, hangi dil ile yazılırlarsa yazılsınlar, MSIL veya IL diye tabir ettiğimiz ara koda dönüştürülürler, ve daha sonra bu ara kod çalıştırıldığında, Just in time compilation denilen işlemle belli bir CPU ve platform için native kod haline gelirler.)

Ancak assembly’ler içinde sadece IL değil, aynı zamanda METADATA denilen bilgiler de bulunur. Peki neden metadata büyük harfle yazılıyor ? Sebebi şu: çok önemli !!! Daha önce COM ile çalışmış olan herkesin bileceği gibi COM dll’leri bazı bilgileri registry’e yazıp sonra buradan okuyarak çalışırlar. Bu da daha önce bahsettiğim sorunların en büyük sebebidir. İşte metadata, bu bilgilerin program parçacıkları olan assembly’ler ile birlikte dağıtılmasını sağlıyor. Yani önceden taşınması zor olan bu bilgiler .NET tarafından otomatik olarak sizin oluşturduğunuz programların içine yerleştiriliyor, ve kod paylaşımı ve dağıtımı açısından çok daha esnek bir yapıyı bizlere sunuyor.

Artı bu bilginin gerektiğinde dinamik olarak runtime sırasında okunması gibi işimizi çok kolaylaştıracak özellikler .NET altında mevcut.

İşte bu gibi bilgileri sunan, ve her assembly ’de mutlaka bulunması gereken öğeye assembly manifest veya assembly metadata  diyoruz. Manifest (isminden de görevi açıkça anlaşılıyor zaten ) bir assembly içinde bulunan yapı taşlarını tanımlar, ve bunlara ilişkin gerekli bilgiler depolar ve versiyon bilgisi gibi bilgileri de içerir. Hemen bir başka somut örnek verelim: demin bahsettiğimiz tuğlalardan oluşan bir bloğu karton bir kutuya koyup kutuyu kapatsak, kimse içinde ne olduğunu bilemez. Ancak bu kutunun üzerine bir kağıt yapıştırıp, sonra da bu kağıdın üzerine kutunun içinde ne olduğunu son derece detaylı bir biçimde yazarsak ne olur? O zaman o kutudaki bir tuğlaya gereksinim duyan bir kişi bu kağıt sayesinde kutunun içindeki her tuğla hakkında gerekli bilgiye kavuşur. İşte kutuya yapıştırılan bu kağıt “manifest” oluyor. Kutunun kendisini de üzerinde kağıdı ile beraber assembly olarak düşünebiliriz. Klasik COM’da ise  bu bilgi kutunun üzerinde yer almaz, sadece bir seri no’su kutuda bulunur, ve o no ile ulaşılan bir kağıt, koskoca bir panoya asılır ( yani registry ), bu yüzden programınızı oluşturan kutuları alıp başka bir yere götürmeye kalktığınızda pano olduğu yerde kalacağı, ve kutuların üzerinde detaylı bir açıklama olmadığı için, kutunuz bir işe yaramaz.

Şimdi kutular ve tuğlalardan, tekrar assembly ‘lere dönüyoruz :) Assembly’lerin sadece bir dosya ( mesela bir dll ) veya birkaç dosyadan oluşabileceğini söylemiştik. Şimdi genelde karşımıza çıkan duruma, yani bir tek dosyadan oluşan bir assembly’e göz atalım 

İşte burada biraz önce bahsettiğimiz yapıyı görüyoruz, burada açıklanacak yeni bir şey yok.

Bir de birden fazla dosyadan oluşan bir assembly neye benziyor görelim :

İşte burada biraz daha farklı bir durum var. Şimdi burada assembly’nin bir dosyadan, yani fiziksel bir dll veya exe’den ziyade  bir “kavram” olduğu  daha kolay anlaşılıyor. Mesela yukarıda üç dll ve bir de resim dosyasından oluşan bir assembly var. Bu şekilde birbirine bağlanan dosyaların belirtildiği yer assembly manifest. Yani buradaki assembly tamamen manifest’de tanımlanan dosyalardan oluşuyor. Bunun bize sağladığı bir başka fayda da , internet veya intranetler gib dağınık ortamlarda yazılım hazırlarken, bir assembly içindeki sadece bir module ( yani bu örnekte dll veya resim) ihtiyaç duyarsak, .NET tüm assemblyi değil sadece bize gereken modulu manifest sayesinde bulup kullanacaktır. Bileşenleri download ederek kullandığımız internet gibi bir ortamda, gerçekten önemli bir avantaj.. 

Buraya kadar, genel olarak bir assembly’nin fiziksel yapısı ile ilgili yorumlar yaptık. Şimdi de bir programcı açısından, .NET içinde kullanılırken assembly’ler nasıl görünüyor ona bakalım. 

Bizim açımızdan programlarımızda kullanırken assembly’lerin fiziksel yapısının ne şekilde organize olduğu önemli değil .Biz sadece assembly tarafından bize sunulan kaynakları kullanıyoruz, ve bu kaynakların hangi dosyanın içinde bulunduğu bizim için önemli değil. 

Temel olarak .NET kod paylaşımını assembly’ler ile gerçekleştirerek, oldukça basit ve esnek hale getiriyor.

Şimdilik bu kısımda verilen bilgiler assembly ve kod paylaşımı açısından yeterli bir giriş oluşturacaktır diye umuyorum. Yazının bir sonraki bölümünde assembly’leri ve detaylarını daha detaylı olarak göraceğiz.Bu yazıda değindiğimiz konuları kafanızda biraz  topladıktan sonra hepinizi bekliyorum :)

 

Döküman Arama

Başlık :

Kapat