Skip to main content

Debug ve Release Modlarda Farklı Kod Çalıştırma

Uygulama geliştirme sürecinde canlı ortamda çalışması gereken bazı kodların test amaçlı olarak local ortamlarda değiştirilmesi, denenmesi gerekebiliyor. Bu durum uygun teknikler kullanmazsa kod tarafında değişiklikler yapılmasını, dolayısıyla
çalışan kodun değiştirilmesini gerektirebiliyor. Gözden kaçması durumunda test amaçlı yazılan bir kodun canlı ortama atılması ve çalıştırılmasının ne gibi sonuçlar doğurabileceğini anlatmaya gerek yok sanırım! Bu yazımda .NET uygulamalarında ve bilhassa ASP.NET uygulamalarında bir kod veya kod bloğunun debug ve release modlarda farklı çalıştırılmasını sağlayan 3 farklı tekniği
biraz detayına girerek incelemeye çalışacağız.

Önce örnek senaryo üzerinden sorunu inceleyelim. Projemizde bir web servisine bağlanıyoruz, ancak bu servis bilhassa local ve test ortamlarımızda çok yavaş çalışıyor, bu da geliştirme sürecimizi yavaşlatıyor. Servis GetProduct isimli bir metottan bize ID=58, Name=”Kalem”, Price=3,9 … gibi bilgileri içeren bir Product nesnesi döndürüyor. Sonuçta test ortamında çalıştığımız için içi dolu bir Product nesnesi sayfamızın çalışması ve UI testlerimizin yapılmasına yeterli olacaktır. F5 tuşuna basıp sayfayı görmek istediğimiz her durumda 15-20 saniye beklemek hem bizi yavaşlatır, hem de developer olarak kod yazma şevkimizi azaltır değil mi? Web servisinden onlarca metot çağırdığımızı ve her işlem için gereksiz yere beklediğimizi düşünürsek zaman kaybının bizim için ne kadar önemli boyutlara ulaştığını daha iyi anlarız. O zaman şöyle bir yol bulabilsek;

Product p = null;
if (mode == "release")
{
    MyWebService proxy = new MyWebService();
    p = proxy.GetProduct(id);
}
else
{
    p = GetDummyProduct(id);
}

Süper bir çözüm olmayabilir, ama sorunumuzu ortadan kaldırdığı kesin. Bu ve buna benzer örnekleri çoğaltmamız mümkün. Peki .NET uygulamalarında bu tip bir sorunu en sağlıklı şekilde nasıl çözebiliriz?

Çözüm-1: #if DEBUG Önişlemci Direktifi

Kullanım şekli:

public partial class WebForm1 : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {
        #if DEBUG
            Response.Write("Debug modda calisiyorum");
        #else
            Response.Write("Release modda calisiyorum");
        #endif
    }
}

#if DEBUG ifadesi ile #endif arasında kalan satırlar C#(veya VB.NET) derleyicisi tarafından proje eğer debug modda ise IL(Intermediate Language) kodları içerisine alınır, release modda ise alınmaz. Eğer bu ifade yukarıdaki gibi #else ile kullanılırsa, proje release modde iken IL kodlarına sadece else kısmındaki kodlar alınır. Yukarıdaki kodu debug modda derleyip, daha sonra oluşan dll dosyasını .NET Reflector veya ILSpy gibi bir programda açarak IL içerisinde tutulan kodları gözlemlediğimizde Page_Load metodunda sadece debug mode için yazılan kodu görürüz.

Resim: #if DEBUG direktifli kodu debug modda derlediğimizde IL içerisine alınan kodlar

 

Çözüm-2: System.Diagnostics.Conditional Attribute Nesnesi

Kullanım şekli:

public partial class WebForm1 : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {
        DebugMetodu();
    }
    [Conditional("DEBUG")]
    protected void DebugMetodu()
    {
        Response.Write("Debug modda calisan metot");
    }
}

Sadece debug modda çalışması istenilen bir kod bloğumuz varsa ve bu kod bloğunu metot olarak yazmak istersek Conditional attribute nesnesini kullanabiliriz. Kod debug modda derlendiğinde DebugMetodu() isimli metot assembly içerisinde kalacaktır, ancak Page_Load’daki metot çağırımı koddan çıkarılacaktır. Yukarıdaki kodu önce debug modda, sonra release modda derlediğimde ILSpy’da
sırasıyla aşağıdaki görüntüleri elde ediyorum. Release modda Page_Load’da herhangi bir metot çağırımının yapılmadığı görülüyor.

Resim: Debug modda elde edilen kod

Resim: Release modda elde edilen kod(Page_Load’da metot çağırımı yok)

 

Çözüm-3: HttpContext.Current.IsDebuggingEnabled Özelliği

Kullanımı:

public partial class WebForm1 : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {
        if (HttpContext.Current.IsDebuggingEnabled)
            Response.Write("web.config'de debugging acik");
        else
            Response.Write("web.config'de debugging kapali");
    }
}

HttpContext.Current.IsDebuggingEnabled özelliğini Http context’den de anlayacağımız üzere sadece web uygulamalarında kullanabiliyoruz. #if DEBUG ve Conditional attribute kullanımlarından farklı olarak IsDebuggingEnabled özelliği derleyici tarafından ele alınmayan ve kod olarak her zaman IL içerisinde yer alacak bir kullanım şeklidir. Bu özellik web uygulamasının web.config dosyasında yer alan system.web > compilation elementindeki debug niteliğinin değerine göre kod akışının belirlenmesini sağlar. Eğer debug niteliği true ise IsDebuggingEnabled özelliği true değerini getirir ve yukarıdaki kod örneğinde if bloğu çalıştırılır. web.config elementleri dll çıktıları alındıktan sonra da değiştirilebildiği için yukarıda incelediğimiz ilk iki kullanımdan farklı olarak çıktısı alınan uygulamada web.config’de yapılacak değişikliğe göre kod akışını değiştirebilme özelliğine sahiptir.

web.config’de debug özelliğini açık bırakmak için;

<configuration>
 <system.web>
 <compilation debug="true" targetFramework="4.0"/>
 </system.web>
</configuration>

şeklinde bir ifade yer almalıdır. Ancak web uygulamasının performansını etkileyeceği için zorunlu kalmadıkça bu özelliğin değerini false olarak belirlemeliyiz.

Yukarıdaki kodu derleyip oluşturulan dll dosyasının içeriğini incelediğimizde yazdığımız kodların aynen muhafaza edildiğini görebiliriz.

Resim: IsDebuggingEnabled özelliği ile ilgili yazılan kodlar aynen IL içerisinde saklanır

Bu şekilde uygulamanın debug ve release modlarda derlenmesi durumunda istenilen modda istenilen kodun çalıştırılmasını üç farklı yolla nasıl gerçekleştirebileceğimizi gördük. İncelediğimiz ilk iki yol tüm .NET uygulamarında, üçüncü yol ise sadece web uygulamalarında kullanılabilen bir yöntemdir.

Bir Cevap Yazın

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