Özgür Belül

x += x++;
posts - 11, comments - 3, trackbacks - 0

Tuesday, September 30, 2008

Design Patterns : Strategy Pattern

Strategy Pattern bir algoritmanın o algoritmayı içinde barındıracak olan class'tan ayrılması ve ayrı classlar olarak kapsüllenmesi demektir. Daha da basitleştirecek olursak class ve algoritmayı ayırmaktır, böylece class'a bağımlı olmadan istediğiniz zaman çalışma anında algoritmayı değiştirebilirsiniz.

Strategy Pattern kullanarak birden fazla davranış göstermesini istediğiniz nesneleriniz varsa bütün davranışları ayrı bir class haline getirerek projenin takip edilebilirliğini artırabilirsiniz. Temelde aynı ancak farklı davranışlar gösteren nesnelerle çalışacaksanız Strategy Pattern çok uygun bir kalıp. 

Strateji kullanarak aynı zamanda bir çok kontrol mekanizması kullanmaktan da kurtulursunuz. Bir çok davranışın bir class içerisinde olduğunu var sayarsak hangi davranışın seçileceğini belirlemek için kontrol mekanizmalarına başvurmak zorunda kalırız.

Bir strateji oyunu tasarlayacak olursak; Örneğin 2 tane asker tipi olsun.

 

Saldır metodu taban sınıf içerisinde çünkü iki asker tipi de saldırabiliyor. Askerlerin görünüşleri farklı olacağı için ikisininde kendi göster metotları mevcut.

Bir süre sonra oyunumuza yeni bir karakter ekleyerek geliştirmek istiyoruz ve yaralanan askerleri iyileştirmek için büyücü eklemeye karar veriyoruz. Burada bir problem var, büyücüler diğer askerler gibi saldıramıyor.

Diğer iki askere yaptığımız gibi büyücüyü de taban sınıftan türetirsek bu sefer büyücüler de saldırabiliyor olacak. Bizim senaryonumuzda büyücüler saldıramazlar. İlk akla gelen taban sınıftaki Saldir metodunu virtual yapmak ve Büyücü sınıfında metodu override edip içini boş bırakmak. Ancak o zaman da modellememiz yukarıdaki gibi görünmeye başlıyor. Saldıramayan büyücülerin içerisinde bile Saldır metodu var. Kodların zamanla daha da gelişeceğini düşünürsek şimdiden bizi zor günlerin beklediğini söylemek yanlış olmaz. Çünkü işin sonunda davranışı farklı olan tüm karakterler için tekrar eden işe yaramaz kodlar yazmak zorunda kalacağız. Tıpkı büyücü içinde Saldır metodunu override edip içini boş bırakmamız gibi. Şöyle yapsak nasıl olur? Saldır metodunu taban sınıfın içerisinden alıp bir interface içerisine koyalım ve saldırabilen tüm birimler de onu implemente edelim.

Bu biraz daha temiz bir koda benziyor ancak oyunu daha da geliştirip askerlerin farklı saldırı tiplerine sahip olmalarını istersek sadece sorunu başkalaştırdık. Okçu ve Şövalye için aynı saldırı tipini kullanmış olduk. Değişiklik gösteren kısmın askerlerin nasıl saldırdıkları olduğunu burada açıkça görebiliyoruz. Saldırı tipi bir algoritma ancak çalışma anında saldırı biçimin değiştirilebilmesi hatta upgrade edilebilmesi ise asıl sorun.

Bu durumda saldırı mantığını taban sınıftan ayıralım ve saldırı şekillerini kendi başlarına birer class haline getirerek Strategy Pattern'i uygulamaya başlayalım.

Artık classlarımızın davranış biçimleri onlardan tamamen ayrı halde. Askerlerimiz için ayrı saldırı şekilleri belirleyebiliriz. Yeni bir asker ekleyebilir ona özgü hareketleri ise ISaldırabilir interface'ini bir class' a implemente edip kullanabiliriz ve setSaldiriSekli(ISaldirabilir saldiriSekli) metodu ile de çalışma anında saldırı tipini ve şeklini değiştirebiliriz. Büyücüler ise saldırı şekli olarak Saldırma class'ını kullanacak ve böylece biz istemediğimiz sürece saldıramayacaklar.

posted @ Tuesday, September 30, 2008 2:04 AM | Feedback (0) | Filed Under [ Design Patterns ]

Sunday, July 06, 2008

WPF / Silverlight uygulamalarını çalıştırmak için IIS 5.0 ve IIS 6.0 ayarları

Multipurpose Internet Mail Extensions (MIME) uygun şekilde yapılandırıldığı sürece WPF uygulamalarınızı web serverlardan çalıştırabilirsiniz. IIS 7.0’da bu ayarlar yapılı olarak geldiği için bir sorun yok ancak IIS5.0 ve IIS6.0 için durum aynı değil.


Başlat menüsünden çalıştıra %SystemRoot%\system32\inetsrv\iis.msc yazıp enter’a basın ve Internet Information Services (IIS) Manager’ı çalıştırın.


Default WebSite’a gelip sağ klik properties’e girin. HTTP Headers sekmesini secip Enable Content Expiration seçeneğini 1 dakika olarak ayarlayın.


Aşağıdaki script’i notepad’de açıp .vbs uzantılı olarak kaydedin ve üzerine çift tıklayın. İş bittiğinde Presentation Foundation MIME tipleri kaydedildi. mesajı gelecek karşınıza.

Dim MimeMapObj, MimeMapArray, MimeTypesToAddArray, WshShell, oExec
Const ADS_PROPERTY_UPDATE = 2

MimeTypesToAddArray = Array(".manifest", "application/manifest", ".xaml", _
    "application/xaml+xml", ".application", "application/x-ms-application", _
    ".deploy", "application/octet-stream", ".xbap", "application/x-ms-xbap", _
    ".xps", "application/vnd.ms-xpsdocument")

Set MimeMapObj = GetObject("IIS://LocalHost/MimeMap")

For counter = 0 to UBound(MimeTypesToAddArray) Step 2
    AddMimeType MimeTypesToAddArray(counter), MimeTypesToAddArray(counter+1)
Next

Set WshShell = CreateObject("WScript.Shell")

Set oExec = WshShell.Exec("net stop w3svc")
Do While oExec.Status = 0
    WScript.Sleep 100
Loop

Set oExec = WshShell.Exec("net start w3svc")
Do While oExec.Status = 0
    WScript.Sleep 100
Loop

Set oExec = Nothing

WScript.Echo "Windows Presentation Foundation MIME tipleri kaydedildi."

Sub AddMimeType (Ext, MType)

    MimeMapArray = MimeMapObj.GetEx("MimeMap")

    i = UBound(MimeMapArray) + 1
    Redim Preserve MimeMapArray(i)
    Set MimeMapArray(i) = CreateObject("MimeMap")
    MimeMapArray(i).Extension = Ext
    MimeMapArray(i).MimeType = MType
    MimeMapObj.PutEx ADS_PROPERTY_UPDATE, "MimeMap", MimeMapArray
    MimeMapObj.SetInfo
   
End Sub

posted @ Sunday, July 06, 2008 11:38 PM | Feedback (0) | Filed Under [ WPF ]

Saturday, June 28, 2008

NGen.exe – Native Code Generator

.Net Framework ile birlikte gelen bir araç olan NGen.exe kurulum anında uygulamanın IL kodlarını makine diline çevirmeye yarıyor. Kod kurulum esnasında makine diline çevrildiği için çalışma anında JIT derleyicilerin derleme yapmasına gerek kalmadığından performans avantajı sağlanıyor.

Makine diline çevrilen kod aşağıdaki gibi bir dizine kaydediliyor.

C:\Windows\Assembly\NativeImages_v2.0.50727_32

Son dizin ismindeki rakamlar CLR versiyonunu ve kodun 32bit işletim sistemi için oluşturulduğunu belirtiyor.

Peki bu kod nasıl çalışıyor? CLR bir assembly yüklediğinde NGen.exe ile oluşturulan dosyanın olup olmadığını kontrol ediyor. Eğer dosya varsa CLR bunu kullanıyor ve çalışma anında derleme işini aradan çıkartıyor dosya yoksa CLR standart prosedürü uygulayıp çalışma anında kodu makine diline çeviriyor.

Managed kod avantajlarından (Garbage collection, tip güvenliği, vs. ) yararlanıp dezavantajlarından kurtulmak (Performans kaygıları) ilk anda kulağa hoş geliyor. Ancak gerçekte işler göründüğü kadar iyi değil.

Öncelikle birçok yazılım geliştiricinin düştüğü hata sadece NGen kullanılarak çevrilmiş kodu çalıştırmanın yeterli olacağıdır. Ancak bu mümkün değil. CLR’ın çalışma anında reflection, serialization gibi işlemler için assembly’nin metadatasına erişmesi gerekiyor. Bu sebeple IL kodu da NGen tarafından çevrilmiş kodla birlikte olmalıdır. Bununla birlikte CLR aşağıdaki sebelerden dolayı ya da bir şekilde NGen tarafından çevrilmiş kodu kullanamazsa IL kodunu çalışma anında derlemektedir.

CLR, NGen tarafından çevrilmiş kodu  yüklediğinde IL üzerinden bir takım özellikleri mevcut çalışma ortamıyla karşılaştırır. Bunlardan bazıları: İşlemci tipi, CLR versiyonu, Uygulamanın build şekli (Release, debug, optimized debug, vs.), MVID (Assembly Module Version ID), vs. Eğer bu özelliklerden herhangi birisi uyumsuz olursa CLR NGen tarafından çevrilmiş kodu çalıştırmaktan vazgeçip çalışma anında IL kodunu makine diline çeviriyor. Burada şunu da belirtmekte fayda var NGen.exe update modunda çalıştırabilirsiniz böylelikle son kullanıcı framework’ün yeni bir service pack’ini kurduğunda service pack kurulum programı otomatik olarak NGen.exe’yi çalıştırabilir ve dosyaların bilgisayarda yüklü son CLR versiyonu ile uyumluluğu sağlanmış olur.

Diğer bir nokta ise assembly dosyaları standart Windows PE (Portable Executable) dosyalarıdır ve belirlenmiş bellek adreslemelerine sahiptirler. Windows NGen tarafından çevrilmiş kodu çalıştırdığında bellek adreslemesi yapılan alanları kullanıp kullanamadığına bakar. Eğer bir sebepten dolayı belirlenmiş adresleri kullanamıyorsa Windows uygulamadaki bellek adreslemesini yeniden yapılandırır. Bu oldukça zaman tüketen bir durumdur çünkü öncelikle tüm uygulama belleğe alınır ve burada düzeltmeler yapılır. Bununla birlikte değiştirilen tüm dosyalar içinde bir yedekleme dosyası oluşturulur ki bu da bir başka maliyettir. Diğer bir araç olan CSC.exe’nin (C Sharp Compiler) /baseaddress komutunu kullanarak iyi bir bellek adreslemesi yapma şansına sahip olabilirsiniz. Şans diyorum çünkü malesef Microsoft bu konuda pek yardımcı olmuyor. JIT kullanılarak derlenen kodlar için bunların hiç birisi problem değil çünkü doğru bellek adres referansları çalışma anında hesaplanıyor.

Diğer bir eksi ise kodlar çalışma anında oluşturulmadığından oluşturulmuş kodlar ortam hakkında çalışma anında derlenenler kadar bilgiye sahip olamıyor.

Özellikle sunucu taraflı uygulamalarda NGen kullanmak oldukça gereksiz çünkü performans sorununu,  çoğu zaman kullanıcılar bu yavaşlığın farkında bile olmazlar, sadece ilk kullanıcı yaşıyor. Bir çok sunucu uygulamasında kodun sadece bir instance’ı gerektiğinden diğer kullanıcılar için böyle bir etkilenme yaşanmıyor.

Uygulamanızda NGen kullanmayı düşünüyorsanız NGen tarafından çevrilen kodlarla çalışma anında çevrilenler arasında mutlaka karşılaştırma yapın ve hangisinin daha hızlı olduğundan emin olun.

posted @ Saturday, June 28, 2008 12:49 AM | Feedback (1) | Filed Under [ Framework ]

Sunday, June 15, 2008

Managed mı Unmanaged mı?

İnanması belki zor olabilir ancak managed kodlar unmanaged kodlara göre daha performanslı olabilmektedir.

Örneğin JIT derleyici IL kodunu çalışma anında makine diline çevirdiğinden derleyici unmanaged derleyiciye göre çalışma ortamı hakkında daha fazla bilgiye sahip oluyor. Bu durumda Pentium 4 işlemcili bir makinede çalıştığımızı düşünürsek derleyici çalışma anında derleme yaparken P4 işlemciye özel komutları kullanabiliyor. Unmanaged uygulamalar genelde en düşük CPU’ya göre derlendiğinden performans artışı sağlayan özel komutlardan faydalanma imkanı olmuyor.

Bununla birlikte, örneğin sonucu sürekli false dönecek bir kodumuza varsa JIT bu kod için makine dili oluşturmuyor.

İf(CPUSayisi > 1)

{

...

}

Yukarıdaki kod tek işlemcili makinede her zaman false döneceğinden gereksiz yere makine dilinde işlemci komutu oluşturmaya gerek yok. Bu durumda oluşan kod makineye özel, daha kısa ve daha hızlı oluyor.

Başka bir nokta ise CLR kodun çalışma planının profilini çıkartıp uygulama çalışırken IL kodunu farklı bir şekilde makine diline çevirebilir. Yeniden oluşturulan kod diğerine göre daha hızlı olacaktır.

Bunlar sadece bir kaç örnek ama yakın gelecekte managed kodların günümüzün unmanaged kodlarına oranla daha hızlı çalışacağının sinyallerini veriyor.

Ayrıca .Net Framework SDK ile gelen NGEN.exe’yi kullanarak IL kodlarınızın tamamını makine diline çevirebilirsiniz. Bu durumda bir dosya oluşacak ve sürücünüze kaydedilecektir. Çalışma anında CLR assembly’nin çevrilmiş bir versiyonu olup olmadığına bakacak ve eğer varsa bunu kullanacaktır.

posted @ Sunday, June 15, 2008 6:51 PM | Feedback (0) | Filed Under [ .NET ]

Module, metadata, assembly, manifest, component

Özellikle yeni başlayanlar için kavramlar arasında kaybolmak oldukça kolay olduğundan module, metadata, assembly, manifest, component gibi temel bir kaç kavrama açıklık getirmek istedim.

Derleyici tarafından derlenen kod sonucunda ortaya çıkan en küçük birime module denir. .Net platformunda CLR tarafından yönetilen kod yazdığımız için ise bu birime managed module denir. Managed module çalışmak için CLR’a ihtiyaç duyan standart bir 32-bit Microsoft Windows portable executable (PE32) ya da 64-bit (PE32+) dosyasıdır.

Bu dosya içerisinde şu kısımlar yer alır.

PE32/PE32+ Header :  Eğer header kısmında PE32 formatı kullanılmışsa uygulama çalışmak için 32-bit sisteme, PE32+ kullanılmışsa 64-bit sisteme ihtiyaç duyar. Burada ayrıca dosyanın tipi bilgisi (DLL, GUI, CUI), dosyanın üretildiği tarihin tutulduğu tarih bilgisi gibi bilgiler yer alır.

CLR Header :  Bu dosyayı managed hale getiren CLR versiyon bilgisi, başlangıç metodu olan Main metodunun bilgisi, metadata bilgisinin yeri ve büyüklüğü, kaynaklar gibi bilgileri tutar.

Metadata :  Her module metadata tablolarına sahiptir. 2 tip metadata tablosu vardır. Birincisi kaynak kodunuzda yer alan tiplerin ve üyelerin tanımlarını tutarken ikincisi kaynak kodunuz tarafından refere edilen tiplerin ve üyelerin tanımlarını tutar.

Intermediate Language (IL) Code : IL Microsoft tarafından bazı akademik ve ticari dil / derleyici yazarları ile görüşülerek yaratılmış bir dildir. Kaynak kodu derlendiğinde ortaya çıkan CPU bağımsız yüksek seviyeli makine dilidir. IL'i nesne yönelimli makine dili olarak da düşünebilirsiniz. Sembolik makine dili olan Assembly (Aşağıda geçen assembly ile sadece isim benzerliği var.) kullanılarak IL kodu yazılabilir. Bunun için ILAsm.exe'yi kullanabilirsiniz. Ancak C# gibi yüksek seviyeli bir dil kullanan developerlar için bu iş derleyici tarafından yapılır ve kod derlendiğinde derleyici tarafından IL koduna çevrilir, calışma anında ise CLR bu kodu makine dilinde işlemci komutlarına çevirir.

Aslında CLR doğrudan module ile çalışmaz, bunun yerine bir ya da daha fazla module’ün mantıksal gruplamasından meydana gelen Assembly ile çalışır. Assembly tekrar kullanılabilirlik, güvenlik ve versiyonlama uygulanabilirliği açısından en küçük birimdir. Bir ya da daha fazla dosyadan meydana gelen assembly olabilir. Assembly’nin CLR dünyasında geçen adı Component’tir.

Assemblyler de içerisinde Manifest denilen bilgileri taşırlar. Manifest aslında metadata tablolarının bir başka setidir. Bu set içerisinde ise assembly’i oluşturan dosyaların bilgilerini, assembly ile ilgili kaynak (.jpg, .html vb.)  veya data dosyalarının bilgilerini tutarlar.

posted @ Sunday, June 15, 2008 3:54 PM | Feedback (0) | Filed Under [ .NET ]

Tuesday, June 10, 2008

Kısa yol nasıl konur?

Uygulamanızdan istediğiniz yere kısayol oluşturmak için referanslara COM sekmesinden Windows Script Host Object Model'i ekleyin. Kodlar aşağıda.

private void button1_Click(object sender, EventArgs e)
        {
            IWshRuntimeLibrary.WshShellClass Hede = new IWshRuntimeLibrary.WshShellClass();

            IWshRuntimeLibrary.IWshShortcut Kisayol = (IWshRuntimeLibrary.IWshShortcut)Hede.CreateShortcut(@"C:\Kisayol.lnk");

            Kisayol.TargetPath = Application.ExecutablePath;

            Kisayol.Description = "Çalıştırsanaaaa...";

            Kisayol.IconLocation = @"C:\Program Files\Microsoft Office\OFFICE12\REFBAR.ICO";

            Kisayol.Save();
        }

 

posted @ Tuesday, June 10, 2008 11:33 PM | Feedback (0) | Filed Under [ C# ]

Tuesday, May 20, 2008

Try Catch & Response.Redirect()

Try Catch bloğu içerisinde Response.Redirect("hede.aspx") gibi bir yönlendirme yapıyorsanız size Thread was being aborted şeklinde bir hata mesajı dönecektir. Bunu engellemenin yolu Response.Redirect("hede.aspx", false) şeklinde redirect metodunun diğer bir overloadını kullanmaktır. Server.Transfer("hede.aspx") kullanmışsanız, onun yerine Server.Execute("hede.aspx") kullanarak da sorunu aşabilirsiniz.

posted @ Tuesday, May 20, 2008 12:43 AM | Feedback (0) | Filed Under [ C# ASP .NET ]

Monday, May 19, 2008

Lazy Loading

İçeriği sürekli kullanılan bir propertyniz varsa, özellikle de çok büyük data tutuyorsa, içerisindeki dataları veritabanından tekrar tekrar çekmek performans bakımından yorucu olacaktır. Bu sorunu aşağıdaki gibi Lazy Loading kalıbını kullanarak çözebilirsiniz.

public sealed class Siparis
    {
        private DataSet _Siparisler;

        public DataSet Siparisler
        {
            get
            {
                if (_Siparisler == null) _Siparisler = SiparisleriGetir();
                return _Siparisler;
            }
        }

        private DataSet SiparisleriGetir()
        {
            SqlDataAdapter da = new SqlDataAdapter("select * from [Order Details]", "server=.;database=Northwind;integrated security=yes");
            DataSet ds = new DataSet("Siparisler");
            da.Fill(ds);
            return ds;
        }
    }

posted @ Monday, May 19, 2008 11:23 PM | Feedback (0) | Filed Under [ Design Patterns C# ]

Sunday, May 11, 2008

Constructor Overloading

İyi kod kendini mümkün olduğunca az tekrar eden kod dur. Bu düşünceyi constructorlara uygulayacak olursak :

public sealed class Student
    {
        private string _Name, _Surname;
        private byte _Age;

        public byte Age
        {
            get { return _Age; }
            set { _Age = value; }
        }
        public string Surname
        {
            get { return _Surname; }
            set { _Surname = value; }
        }
        public string Name
        {
            get { return _Name; }
            set { _Name = value; }
        }

        public Student() { }

        public Student(string name)
        {
            this.Name = name;
        }
        public Student(string name, string surname) : this(name)
        {
            this.Surname = surname;
        }
        public Student(string name, string surname, byte age) : this(name, surname)
        {
            this.Age = age;
        }
    }
            Student nS = new Student("Özgür", "Belül", 18);
            Console.WriteLine(nS.Age + " " + nS.Name + " " + nS.Surname);

posted @ Sunday, May 11, 2008 11:46 PM | Feedback (0) | Filed Under [ C# ]

Lazy Singleton

Singleton kalıbını doğru bir şekilde kullanmıyorsanız  class içerisinden sadece static method çağırsanız bile instance yaratmış olabilirsiniz. Belki de hiç kullanmayacağınız bu instance bellekte boşu boşuna yer işgal eder. Bu sorunu Singleton kalıbını lazy olarak tasarlarsanız aşabilirsiniz. Aşağıdaki gibi bir kullanımda construtorlara breakpoint koyup Singleton class'ı içerisinden MyMethod1()'i çağırdığınızda instance yaratılmadığını ancak metodun çağırılabilir olduğunu göreceksiniz. Instance sadece gerektiğinde oluşturuluyor.

public sealed class Singleton
    {
        Singleton()
        {
            Console.WriteLine("Singleton contructor çalıştı.");
        }

        public static Singleton Instance
        {
            get
            {
                return Nested.instance;
            }
        }

        public static void MyMethod1()
        {
            Console.WriteLine("MyMethod1 çalıştı..");
        }

        public void MyMethod2()
        {
            Console.WriteLine("MyMethod2 çalıştı..");
        }

        class Nested
        {
            static Nested()
            {
                instance = new Singleton();
                Console.WriteLine("Nested constructor çalıştı");
            }

            internal static readonly Singleton instance;
        }
    }

posted @ Sunday, May 11, 2008 10:27 PM | Feedback (0) | Filed Under [ Design Patterns C# ]

Powered by: