Caner Tosuner

Leave your code better than you found it

Log4Net İmplementasyonu

"Log uğrunda ölen olmadıktan sonra log değildir !!"

Önceki çalıştığım firmalardan birinde uzun soluklu bir bankacılık projesi geliştiriyorduk ve daha önce ilgilenen arkadaşlar bilirler ki development süreci oldukça meşakatlidir. Önce Dev de çalış sonra Test'e at sonra UAT e al sonra PROD a taşı orda testleri yap vs. vs. bir sürü ortam birsürü bug ve en önemlisi yüzlerce şöyle cümleler duyabilirsiniz "TEST te sıkıntı yok ama UAT de çalışmıyor yada sadece PROD da rastladığımız bir durum..." bu gibi durumlarda loglardan yürüyerek ilerlemek sorunun kaynağına en kısa sürede ulaşmanızı sağlayabilir. Tabi log alt yapınız var ise :) Ama bitmedi log altyapınızın olmasıda o loga bir bakış attığınızda ahanda tamam sorunu buldum diyebileceğiniz anlamına gelmeyebilir. Çok fazla yaşadığım bir olaydan bahsetmek istiyorum ve bir arkadaşımın bu olay sonrası projedeki Test Müh. arkadaşa söylediği bir cümle varki efsane :)

Birgün yine üstte bahsettiğim bankacılık projesinde dev yapıyorum ve ekip yaklaşık olarak 10 kişi falan (.net-ios-android-pm-tester vs.). Yine o sihirli cümle geldi ve test müh arkadaş android yazan arkadaşa "droidci arkadaş PROD da rastlanan bir hata varmış ve müşteri ilgili maddeyi JIRA da açmış ve logları paylaşmış. Sorunu kısa sürede çözebilir misin.." vs şeklinde bir cümle kurdu. Developer arkadaş JIRA yı açtı madde yi okudu ve loglara baktıktan sonra test müh arkadaşa "maddeyi bulamadım, müşteriye geri assign ediyorum.." gibi birşey söyledi ve test müh arkadaş da "ama nasıl bulamazsın loglarıda yollamışlar ki.. -%&?!?.." Bu cümleye atarlanan developer arkadaş işte o anda o efsane atasözünü söyledi. "Log uğrunda ölen olmadıktan sonra LOG değildir arkadaşım..!" Sonuç olarak ne oldu sizce ? Log var madde var ama çözüm için elde hiçbir şey yok. Yazılım projelerinde çok büyük öneme sahip olan log yapıları emin olun hayat kurtarır.  Çeşitli loglama türleri vardır. DBLog, FileLog vs gibi. Bu örnekte hemen hemen herkesin en azından duymuş olduğu Log4Net kütüpanesini kullanarak orta çaplı bir FileLog yapısı nasıl kurulur ondan bahsedicem. Log4Net için öncelikle Nugetten ilgili dosyayı indirip projemize kuruyoruz Install-Package log4net    Daha sonra aşağıda olduğu gibi ILog adında bir interface tanımlıyorum. Parametre olarak LogModel türünde bir obje alıyor olacak. Bu obje içerisinde loglamak istediğimiz alanlar mevcut olacak.

public class LogModel
    {
        public string ExcMessage{get;set;}
        public Exception ExceptionModel{get;set;}
      }

  public interface ILog
    {
        void Log(LogModel entry);
     }

Log4Net için WebConfig de birtakım ayarlar yapmamız gerekiyor. Bu ayarların kapsamı çok fazla ancak kısaca özetlemek gerekirse LogDosyalarının adlandırılması, LogDosyalarının bulunacağı path bilgisi, max kaç MB lık dosyalar tutulacak ve enfazla kaç dosya olmasına izin verilecek gibi bir çok LogConfig Settings diyebileceğimiz şey içermekte. Bu projedeki WebConfig dosyası asağıda olduğu şekildedir.

 

 <appender name="LogFileAppender" type="log4net.Appender.RollingFileAppender">

      <file value="LogFiles\\" />

      <appendToFile value="true" />

      <DatePattern value="yyyy\\\\MM\\\\dd'.day.logs.txt'" />

      <rollingStyle value="Date" />

      <maxSizeRollBackups value="7" />

      <param name="StaticLogFileName" value="false" />

      <layout type="log4net.Layout.PatternLayout">

        <conversionPattern value="%newline%date %newline%logger [%property{NDC}] %newline>> %message%newline" />

      </layout>

     </appender>

 

Şimdi sırada Loglama işlemini yönetecek bir Log4Manager' ihtiyacımız var. Burda yarın bir gün XManager YManager da tanımlayabiliriz. Bunun bir çok implementasyonu olabilir. Ben böyle birşey kullanmayı tercih ettim. ILog, IDisposable interfacelerinden türeyen Log4NetLogManager adında bir class yazıyoruz. Class ın içeriği aşağıdaki gibi olacaktır. 

 

 

public class Log4NetLogManager : ILog, IDisposable
    {
         private log4net.ILog log4Net;
         public Log4NetLogManager()
        {
            log4net.Config.DOMConfigurator.Configure();
            log4Net = log4net.LogManager.GetLogger(typeof(Log4NetLogManager));
        }
         public void Log(LogModel entry)
        {
            log4Net.Error(entry.ExpMessage, entry.ExceptionModel);
        }
         public void Dispose()
        {
            if (log4Net != null)
                log4Net.Logger.Repository.Shutdown();
        }
    }

 

İşlemlerimiz bu kadar. Bu saatten sonra tek yapmamız gereken bu manager'ı kullanan logic ler yazmaktır. Bir sonraki örneğimizde ASP.Net WebApi tarafında ExceptionHandling olaylarına girip yukarıda yazmış olduğumuz Manager'ı kullanan bir app yazacağız.

 

 

C# "params" Kullanımı

C# dilinde yazmış olduğumuz bir metoda params keyword'ü ile parametre tanımlaması yaptığımızda bu o metodun çok sayıda parametresi olduğuna işaret eder ve bu parametreleri teker teker metodu çağırdığımız yerde ayrı ayrı "," ile ayırıp set etmek yerine bir sefer de parametre olarak verebiliriz. Parametre olarak bir array alan metod olmalı ve tanımlarken tip belirtecinden önce "params" keyword'ü eklenmelidir. Göndereceğimiz array tek boyutlu olmalı ve bir metodda tek bir params anahtar sözcüğü kullanmalıyız. Params keyword'ü alan ilgili metoda yanında başka parametrelerde gönderebiliriz. ancak dikkat etmemiz gereken şey params tanımlamasını tüm parametrelerden sonra yazmamız gerektiği.

Örnek olarak bir tane int array alan bir metod olsun ve metod bu aldığı array de bulunan sayıların toplamını geriye return etsin.

Params kullanmadan

int SayilariTopla(int a, int b, int c, int d, int e)
{
    return a+b+c+d+e;
}

static void Main(string[] args)
{
     int result = SayilarTopla(2,1,4,5,7);
}

Yukarıda ki örnekte görüldüğü gibi 5 tane int parametre alan bir metod ve geriye bu sayıların toplamını dönüyor. Peki bu metod 6-7 veya 1-2 parametre alarakta çalışmasını istersek ne yapacağız ? Ayrı ayrı birkaç metod daha yazacak değilizdir. İşte burda params'ın gücü devreye giriyor

 

Params kullanarak 

int SayilariTopla(params int[] sayilar)
{
  int toplam= 0;
  foreach (int i in sayilar) 
  {
     toplam+= i; 
  }
  return toplam;
}

static void Main(string[] args)
{
    int result1= SayilariTopla(5);
    int result2= SayilariTopla(1, 2,-3);
    int result3= SayilariTopla(-4,4,3,7,-7,1,8,0);
}

Params ile birlikte yukarıda ki gibi SayilariTopla metoduna artık istediğimiz kadar parametre geçip kullanabiliriz. 

C# Extension Method Kullanımı

Kelime anlamı genişletilebilir metod olan Extension Method'lar C#3.0 ile hayatımıza girmiştir ve yaptığı iş itibatiyle kullanım açısından son derece faydalı metodlardır. Tek cümleyle özetlemek gerekirse class ve struct yapılarını modify etmeden ilgili struct yada class'için extension metodlar eklememizi sağlar.

 Extesion metod yazarken uymamız gereken bir kaç kural vardır. Bunlar;

  • Extension metodlar static bir class içerisinde static olarak tanımlanmalıdır. 
  • Extend edilecek class ilgili extension metoda metodun ilk parametresi olarak verilip önünde this keyword'ü ile tanımlanmalıdır
  • Extension metod da tanımlı parametrelerden sadece 1 tanesi this keyword'ü ile tanımlanır

Hemen bir örnek üzerinde inceleyelim. Case'imiz şu olsun; Bir tane extension metodumuz var ve bu metod integer bir değer alıp asal mı değil mi diye kontrol etsin.

public static class MyExtensions
   {
       public static bool IsPrime(this int integer)
       {
           //tembellik edip implementation'ı yazmakla uğraşmadım :)
           return true;
       }
   }

Yazdığımız metodu aşağıdaki görselde olduğu gibi kullanmak istediğimizde int tanımlı değişkenin adı"." nokta dediğimizde extensionMetod'u intellisense de görebileceğiz. 

class Program
{
    static void Main(string[] args)
	{
		int anyNumber = 123456;
		if(anyNumber.IsPrime())
		{
			//asal sayı
		}
		else
		{
			//asal sayı değil
		}
	}
}

Heralde en güzel yanı da bu olsa gerek metodu extension tanımladığımız için sanki o metod int struct'ına içerisinde tanımlı bir metodmuş gibi direkt olarak "." nokta deyip kullanabiliyoruz. 

Yukarıda ki örnekte int tipini baz alarak ilerledim ancak ihtiyaç dahilinde bütün tipler ve kendi tanımladığımız objeler içinde extension metodlar yazabiliriz.

Yine örnek olarak ; bir Person class'ımız ver ve içerisinde DateTime tipinde ismi BirthDate olan bir property olsun. Bir tane GetBirthDate adında extension metod tanımlayalım ve bu metod bize parametre olarak aldığı Person objesinde bulunan BirthDate alanını return ettirsin.

public class Person
{
	public string FullName {get;set;}
	public DateTime BirthDate {get;set;}
}

public static class MyExtensions
{
	public static DateTime GetBirthDate(this Person prs)
	{
			return prs.BirthDate;
	}
}

 

Şimdi bu metodu kullanan kısmı yazalım

using System;
					
class Program
{
    static void Main(string[] args)
	{
		Person prs=new Person();
		DateTime bDAte = prs.GetBirthDate();
	}
}

Görüldüğü gibi Extension metod kullanım alanımızı ihtiyaca göre genişletip metodlarımızı istediğimiz yerde "." nokta diyerek fıtı fıtı çağırıyoruz :)

C# 6.0 ile Gelen Yenilikler

Microsoft C# 6.0 'ı daha önce release ettiği sürümlere istinaden çok büyük major feature'lar ile kullanıma sunmadı desek çokta yanlış olmaz herhalde. Ancak 6.0 ile major feature'ların dışında geliştirici için development yapmasını çok daha kolaylaştıracak diyebileceğimiz bir takım önemli değişiklikler sundu. Daha öncesinde aynı işlemleri yapabilmek için satırlarca kod yazdığımız işlemler artık birkaç satırda yapılabilecek duruma gelmiş. 

6.o ile gelen feature listesi aşağıda ki gibidir.

 

1) Auto-Property Initializer

Daha önceki C# sürümlerinde field'lar için kullanılabilir olan initializer artık auto-property'ler için de kullanılabilecek. 

Öncesinde

using System;

namespace CSharpSix
{
    class Program
    {
        static void Main(string[] args)
        {
            Customer cust = new Customer();
            Console.WriteLine(cust.customerID);
            Console.ReadLine();
        }
    }

    public class Customer
    {
        public Customer()
        {
            customerID = Guid.NewGuid();
        }
        public Guid customerID { get; set; }
    }
}

 C# 6.0 ile

using System;
using static System.Console;

namespace CSharpSix
{
    class Program
    {
        static void Main(string[] args)
        {
            Customer cust = new Customer();
            WriteLine(cust.customerID);
            ReadLine();
        }
    }

    public class Customer
    {
        public Guid customerID { get; set; } = Guid.NewGuid();
    }
}

  

2) Using Static

Daha önceleri projede ilgili class'ta herhangi bir yerde static sınıfları kullanmak istediğimizde sınıfın adıyla birlikte o sınıfın fonksiyonlarını çağıra bilmekteydik. 

Öncesinde

class Program
{
    static void Main()
    {
        Console.WriteLine(Math.Sqrt(5*2 + 4*3)); 
        Console.WriteLine(System.DayOfWeek.Friday - System.DayOfWeek.Monday); 
    }
}

Artık C# 6.0 ile birlikte bu statik sınıfları using ile tanımlayıp sonrasında o sınıfa ait metotları kullanabileceğiz. 

C# 6.0 ile

using static System.Console;
using static System.Math;
using static System.DayOfWeek;
class Program
{
    static void Main()
    {
        WriteLine(Sqrt(5*2 + 4*3)); 
        WriteLine(Friday - Monday); 
    }
}

 

3) Expression-bodied methods

Lambda expresiion C# 3.5 ile gelen en büyük değişiklikti ve lambda sayesinde uzuuunnn mu uzun delegate kodları yazmaktansa o satırlara karşılık gelen lambda tanımlamalarını yazabilmekteyiz. Eğer yazılan metod geriye tek satırlık bir işlem yapıp değeri return ediyorsa bu işlem lambda expression ile de yazılabilecektir. 

Öncesinde

namespace CSharpSix
{
    class Program
    {
        private static double MultiplyNumbers(double num1, double num2) 
        { 
           return num1 * num2;
        }

        static void Main(string[] args)
        {
            double num1 = 3;
            double num2 = 6;

            Console.WriteLine(MultiplyNumbers(num1, num2));
            Console.ReadLine();
        }
    }
}

C# 6.0 ile

using static System.Console;

namespace CSharpSix
{
    class Program
    {
        private static double MultiplyNumbers(double num1, double num2) => num1 * num2;

        static void Main(string[] args)
        {
            double num1 = 3;
            double num2 = 6;

            WriteLine(MultiplyNumbers(num1, num2));
            ReadLine();
        }
    }
}

 

4) Null Conditional Operator

Developerlar için kaçınılmazdır ki bir objenin veya tanımlanmış olan bir değerin "null" mı değil mi diye sürekli kontrol etme durumunda kalmışızdır ve bu kontrol için genelde min 2 satır kod yazmak zorundayızdır. if(obj!=null) ... şeklinde. C# 6.0 ile birlikte null check yapma işlemleri biraz daha kolay hale getirilmiş.

Öncesinde

using System;

namespace CSharpSix
{
    class Program
    {
        static void Main(string[] args)
        {
            Person person = new Person();
            if (person.Name == String.Empty)
            {
                person = null;
            }

            Console.WriteLine(person != null ? person.Name : "Field is null.");
            Console.ReadLine();
        }
    }

    public class Person
    {
        public string Name { get; set; }
    }
}

C# 6.0 ile

using System;
using static System.Console;

namespace CSharpSix
{
    class Program
    {
        static void Main(string[] args)
        {
            Person person = new Person();
            if (person.Name == String.Empty)
            {
                person = null;
            }

            WriteLine(person?.Name ?? "Field is null.");

            ReadLine();
        }
    }

    public class Person
    {
        public string Name { get; set; } = "";
    }
}

 

5) String Interpolation

String bir ifadeyi formatlayıp farklı şekilde bir string birleştirme işlemi vs yaparak göstermek itediğimizde string.format("{0} {1}","Caner", "Tosuner"); vs şeklinde tanımlıyorduk. 6.0 il birlikte bu formatları ve ifadeleri yapmak biraz daha kısa hale getirilmiş diyebiliriz. 

Öncesinde

using System;

namespace CSharpSix
{
    class Program
    {
        static void Main(string[] args)
        {
            string firstName = "Caner";
            string lastName = "Tosuner";

            Console.WriteLine("Name : " + firstName + " " + lastName);
            Console.WriteLine("Name : {0} {1}", firstName, lastName);

            Console.ReadLine();
        }
    }
}

C# 6.0 ile

using static System.Console;

namespace CSharpSix
{
    class Program
    {
        static void Main(string[] args)
        {
            string firstName = "Caner";
            string lastName = "Tosuner";

            WriteLine($"{firstName} {lastName} is my name!");

            ReadLine();
        }
    }
}

Bu yazım şekliyle birlikte string format yazımının karmaşasından da kurtulmuş oluyoruz.

 

6) Exception Filters

try içerisinde bir exception alınıp carch'e düştüğünde exceptiona neden olan şeyle ilgili bir spesification yapmak istediğimizde genelde catch bloğu içerisinde if(ex.Message.Equals("bişey bişey")) şeklidne yazarız. 6.0 ile catch bloğu yanına bu if condition'ları yazabilir hale geliyoruz ve her condition'nın kendi catch'i oluyor.

Öncesinde 

using System;

namespace CSharpSix
{
    class Program
    {
        static void Main(string[] args)
        {
            try
            {
                throw new Exception(404);
            }
            catch (Exception ex)
            {
                if (ex.Message.Equals("500"))
                    Console.Write("Bad Request");
                else if (ex.Message.Equals("401"))
                    Console.Write("Unauthorized");
                else if (ex.Message.Equals("402"))
                    Console.Write("Payment Required");
                else if (ex.Message.Equals("403"))
                    Console.Write("Forbidden");
                else if (ex.Message.Equals("404"))
                    Console.Write("Not Found");
            }
           Console.ReadLine();
        }
    }
}

C# 6.0 ile

using System;
using static System.Console;

namespace CSharpSix
{
    class Program
    {
        static void Main(string[] args)
        {
            try
            {
               throw new Exception(404);
            }
            catch (Exception ex) if (ex.Message.Equals("400"))
            {
                Write("Bad Request");
            }
            catch (Exception ex) if (ex.Message.Equals("401"))
            {
                Write("Unauthorized");
            }
            catch (Exception ex) if  (ex.Message.Equals("402"))
            {
                Write("Payment Required");
            }
            catch (Exception ex) if (ex.Message.Equals("403"))
            {
                Write("Forbidden");
            }
            catch (Exception ex) if (ex.Message.Equals("404"))
            {
                Write("Not Found");
            }
            ReadLine();
        }
    }
}

 

7) Await in a Catch and Finally Block

C# 6. ile birlikte artık Catch ve Finally blockları arasında await keyword'ünü kullanıp asynchronous çalışan kodlar yazabiliyoruz. Daha önce bunu yapabilmemiz mümkün değildi ve ihtiyaç halinde (logging etc.) çeşitli kontroller yapıp catch bloğundan çıktıktan sonra async yapmak istediğimiz işlemi yapardık.

Öncesinde 

using System;
using System.Net.Http;
using System.Threading.Tasks;

namespace CSharpSix
{
    class Program
    {
        static void Main(string[] args)
        {
            bool isException=false;
            try
            {
                throw new notimplementedexception();
            }
            catch (Exception exception)
            {
                isException = true;
            }
             if(isException)
                 var result = await LogManager.Log("Hata oluştu !" + exception.Message);
            Console.ReadLine();
        }
    }
}

C# 6.0 ile

using System;
using System.Net.Http;
using System.Threading.Tasks;
using static System.Console;

namespace CSharpSix
{
    class Program
    {
        static void Main(string[] args)
        {
            try
            {
                throw new notimplementedexception();
            }
            catch (Exception exception)
            {
                var result = await LogManager.Log("Catch => Hata oluştu !" + exception.Message);
            }
            finally
            {
                var result = await LogManager.Log("Finally => Hata oluştu !" + exception.Message);
            }            
           ReadLine();
        }
    }
}

 

8) Index initializers

Önceden bir List'e veya Dictionary'ye belirli bir index'ine item atamak istediğimizde önce initialize eder sonra nokta operatörüyle değerleri atardır. 6.0 ile birlikte initialize sırasında bu bu atam işlemlerini yapabilmekteyiz.

Öncesinde 

using System;

namespace CSharpSix
{
    class Program
    {
        static void Main(string[] args)
        {
           var dic = new Dictionary<int, string>
                        {
                            { 1, "one" },
                            { 4, "four" },
                            { 10, "ten" }
                        };
        }
    }
}

C# 6.0 ile

using System;

namespace CSharpSix
{
    class Program
    {
        static void Main(string[] args)
        {
           var dic = new Dictionary<int, string>
                          {
                             [1] = "one",
                             [4] = "four",
                             [10] = "ten"
                          };
        }
    }
}

Yukarıda 2 syntax'a baktığımızda ne fark var ki ikisi de aynı diyebiliriz ancak şöyle bir ayrım var. 6.0'dan önceki yazımda .Add() metodu kullanılarak initialize işlemi yapılıyor. Yeni syntax'da ise direkt olarak index assignments kullanılmakta ve bu da performans olarak daha verimli bir hale gelmekte. 

 

9) nameof Operatörü

Tanımlamış olduğumuz değişkenin veya objenin string olarak adına ulaşmak istediğimizde 6.0 ile birlikte gelen nameof operatörünü kullanabiliriz.

Öncesinde 

using System;

namespace CSharpSix
{
    class Program
    {
        static void Main(string[] args)
        {
            DoSomething("Selam");
            Console.ReadLine();
        }

        public static void DoSomething(string name)
        {
            if (name == null) throw new Exception("Name is null");
        }
    }
}

C# 6.0 ile

using System;
using static System.Console;

namespace CSharpSix
{
    class Program
    {
        static void Main(string[] args)
        {
            DoSomething("Selam");
            ReadLine();
        }

        public static void DoSomething(string newName)
        {
            if (newName == null) throw new Exception(nameof(newName) + " is null");
        }
    }
}

C# Destructor Nedir ?

Destructor kısaca constructor'ın tam tersidir.Constructor için bir nesnenin instance'ı alınırken Ram'de ki Heap bölümünde yer ayırmadan önce çağrılan metod diyebiliriz. Destructor tam bu nesne ram'den silinmeden önce çağrılan metod dur. 

Peki neden buna gerek var dersek; garbage collector sağ olsun bizim için ram'de işleri bitmiş nesneleri ram'den siliyor ve bazen tam bu silinme anını bilmek isteriz. Aslında C# tarafında çok fazla ihtiyaç duyulan bir şey değil ancak C-C++ gibi Ram yönetimini developer'a bırakan programlama dillerinde Destructor'a çok fazla ihtiyaç duyuluyordu. C# ram yönetimini tamamiyle developer'a bırakmadığından gerek kalmadıkça bu metodu kullanmıyoruz.

Destructor Özellikleri

  • Her class'ın sadece bir tane Destructor'ı olabilir,
  • Destructor tanımlanırken class ismini başına "~" işareti koyulur,
  • Struct'lar için tanımlanamaz, sadece class'lar için tanımlanırlar,
  • Dışarıdan çağrılamaz, otomatik olarak invoke olur,
  • Destructor parametre alamaz.
  • Kalıtım yapılamazlar ve overload edilemezler.

 

Örnek kullanım olarak;

	class Person
	{
		~Person()  // destructor
		{
			// cleanup statements...
		}
	}

Kullanımı yukarıda olduğu gibidir. Yazım olarak Constructor tanımlar gibi yazıyoruz ancak isminin başına "~" işaretini koyuyoruz.

Android'den fazla C# kodu yazılan Google Hackathon'u :)

     ODTÜ Teknokent, Google Türkiye ve Amerika Birleşik Devletleri Büyükelçiliği iş birliği ile 16-17 Mayıs 2013 tarihinde Orta Doğu Teknik Üniversitesi’nde gerçekleşen “Social Entrepreneurship Hackathon” adlı yarışmaya Kadir Has Üniversitesi'ni temsilen 5 arkadaş katıldık.

         Aslında üniversitede ki hocam Selçuk Öğrenci bana ilk "Android hackathon var gitmek ister misin ?" diye sorduğunda ilk başta "tabi hocam hemen giderim, nerede ne zaman ?.. " gibi konuştuktan sonra kendi kendime bi sordum "Caner hayırdır ?.. Markette 16 tane uygulamam ver derken bu android market değil Windows Phone abicim..." falan filan derken bu düşüncemi sonrasında Selçuk hocamla da paylaştım ama o yinede benden katılmamı ve şakayla karışık takımın "Core" denen şeysi olmamı söyledi :)

Bende emir büyük yerden deyip tamam hocam elimden gelen neyse üstüne dahasını katarak arkadaşlara yardım edeceğimi söyledim. Neyse 15 Mayıs günü yola çıktık ve yaklaşık 6-7 saat içerisinde gece 23:15 gibi Ankara'ya vardık. Ankara dışından gelen öğrenciler TEDAS Misafirhanesi'nde konaklayacak diye söylemişlerdi bizde geceyi orada geçirdik.Sabah ODTU Kültür Merkezine geçtik ve orada açılış konuşmasının olacağı salona gittik. Google Türkiye ekibinden, ODTU Teknopark ekibinden, ABD Büyük elçiliğinden ve Teknoloji bakanlığından gelen konuşmacıları dinledikten sonra 2-3 saatlik bir ara verdik ve sonradan 22 saat sürecek olan non-stop coding yani Hackathon başladı. Arkadaşlarla geliştirmeye karar verdiğimiz uygulamanın adı "EBS" Engelli Bildiri Sistemi'ydi. Ne yapacaktı EBS ; aslında içinde biraz Twitter biraz Instagram olan bir uygulama gibi düşünebiliriz.

        Engelli vatandaşlara hizmet verecek olan uygulamanın ana işlevi şu şekilde olacak; diyelim ki engelli bir   vatandaşımız sokakta yolda giderken kendisine engel teşkil eden bir durumla karşılaştığında uygulamasını açıp lokasyon bilgisine göre bulunduğu yerin Belediyesi'ne Fotograf, Açıklama, Yer Bilgilerini göndererek engel hakkında bildiri/şikayet yapabiliyor olacaktı. Sağtarafta bulunan fotoğrafı uzun bir süre önce internette görmüştüm örnek olacağını düşünerek paylaşmak istedim. Bu vatandaşımızı örnek alacak olduğumuzda ;

        Engelli vatandaş bu karşılaştığı engel karşısında uygulamasını açıp sorumlu belediyeye sorunun fotoğrafını çekip, açıklamasını yazıp gönder butonuna basacak ve bu bildiri Belediye nin sahip olduğu Web arayüzüne düşüp görüntülenecek Belediye tarafından görüntülenecek ve sorun giderildiğinde o şikayeti yapan vatandaş mail yoluyla "Sorun giderilmiştir" şeklinde bilgilendirilecek.

    Aslında fikir bence gayet güzeldi çünkü etkinliğin adı Sosyal Girişimcilik olduğundan uygulamanın içeriği hem Sosyal olmalıydı ve toplumsal bir soruna parmak basıyor olması gerekiyordu. 

Yazılımsal olarak neler gerekli diye düşündüğümüzde ;

  1. Öncelikle Server'da tutulan Sağlam bir Database 
  2. Mobil uygulama ile iletişimi sağlayıp bütün ihtiyaçlara cevap verecek iyi bir WebService,
  3. Belediyeler tarafında gelen bildirimleri görüntülemek için kullanılacak fonksiyonel bir Web Sayfası.
  4. Ve tabi son olarak da Android uygulaması :)

        1, 2 ve 3. şıklar benim yapacağım konulardı. İlk olarak MS-SQL kullanarak kullanışlı bir Database geliştirdim ve bu Database'i Azure Cloud servisimde sakladım. Sonrasında WCF kullanarak json formatında yayın yapan bir adet Web Service geliştirdim. En son olarak da ASP.Net kullanarak belediyeler için bir adet Web Sayfası geliştirdim. Şaka gibi ama bütün bunlar 6 saat içerisinde bitmişti Hackathon bu olsa gerek Smile.

Android uygulaması üzerinde çalışan arkadaşlar o sırada geliştirmeye devam ediyorlardı. 22 saatin sonunda maalesef arkadaşlar Android uygulamasını tam istediğimiz haliyle yetiştiremediler Frown Sunumumuzu yaptık ve sıralamaların açıklanmamıştı ve birincide olamamıştık.

Aslında bi ara şey diye düşünmedim değil; "Acaba çok mu fazla Microsoft'u işin içerisine soktum ?.." çünkü baktığımızda üstte saydığım gibi yazılımsal olarak 4 adet görev yada geliştirilecek yapı vardı ve bunlardan 3 tanesinde tamamiyle Microsoft'un izi vardı, MS-SQL Database, WCF WebService ve Asp.Net Web Sayfası :) Etkinlik sonunda arkadaşlarla oturup bi baktığımızda şaka maka Android kodundan fazla C# vardı işin içerisinde Cool 

Ama her şeye rağmen gayet güzel ve eğlenceli bir hackathon oldu, kişisel deneyim olarak bir çok şey kazandım gibi zira önümüzdeki sene Microsoft'un her yıl düzenlediği Imagine Cup yarışmasına katılmayı düşünüyordum ve bu deneyim benim için gerek sunum noktasında, gerek takım olarak çalışabilme konusunda gerekse işin sosyallik kısmında son derece katkıları oldu diye düşünüyorum. Umarım Selçuk hoca bize ilerleyen zamanlarda da bu tür görevler paslar ve bizde okulumuzu (1. olamazsakda) en iyi şekilde temsil etmeye çalışırız Laughing

 

 

WCF Nedir ? (Windows Communication Foundation)

  • .Net Framework 3.0 ile birlikte gelmiştir.
  • Farklı platformlar arasında iletişim sağlamak ve Service Oriented Architecture – SOA için uygulamalar geliştirmek için geliştirilmiştir.
  • Web servisini yayımlamak için HTTP, WSHTTP gibi protokoller kullanılabilir.
  • Servisler IIS üzerinde http kuralları kullanılarak yayınlanabilir, ya da Windows üzerinde TCP - Pipe gibi yöntemlerle barındırılabilir.

 

WCF ana hatlarıyla 3 kısma ayrılır (A-B-C)

1.   Address

-        Bir servisin nerede olduğunu, hangi protokol ile yayınlama yaptığını bildiren bilgidir. Aktif olarak çalışan her servis WCF’ye göre eşsiz bir adrese sahip olmalıdır. 

 

WCF servisine ulaşabilmek için kullanılabilecek protokoller;

-        HTTP (http:// veya https://)

-        TCP (net.tcp://)

-        Peer 2 Peer (net.p2p://)

-        IPC (net.pipe://)

-        MSMQ (net.msmq://)

2.   Binding

-        Uygulamalar tarafından veri göndermek ya da veri almak için servis ile nasıl iletişime geçileceğinin tanımlandığı bölüm. WCF hizmetleri için kullanılabilecek ön tanımlı binding’ ler;

 

 

3.   Contract

-        Bir servisin ne iş yaptığının bilinmesinde rol oynar. Bazı sözleşmeler şunlardır:

·        Servis sözleşmesi (Service Contract): Servis ile yaratılacak olan operasyonların tanımlanmasında kullanılır.

 
 [ServiceContract]

   public interface IService1

   { }
 

·        Veri Sözleşmesi (Data Contract): Servis içerisinde bulunan class’ları tanımlamak için kullanılır. Sınıfların üyeleri Data Member olarak tanımlanır.

 

   [DataContract]
   public class MyClass
   { }
 
            [DataMember]

            public string StringValue

            {

               get { return stringValue; }

               set { stringValue = value; }

            }


 

·        Hata Sözleşmesi (Fault Contract): Servis tarafından tanımlanacak olan hatalar bu yolla tanımlanır.

·        Mesaj Sözleşmesi (Message Contract): Servisler ile mesajlar arasında iletişim kurulmasını sağlar.

 

Endpoints

Clients ile Host arasındaki iletişimi şağlamak için kullanılan bir arayüzdür. Her endpoint’in kendi adresi vardır ve bu adresin benzersiz olması için servisin kendi ana adresine eklenmektedir. Bir WCF servisini aslında endpoint topluluğu olarak düşünebiliriz.

Behaviors

Servis davranışları, servislerin veya istemcilerin fonksiyonelliklerini arttırmak için kullanılırlar. Örneğin servislerin metadata bilgisinin paylaşılıp paylaşılamayacağı, ekstra güvenlik eklenmesi, tracking tracing logging gibi bilgilerin tutulması, parametre ve mesajların validasyonları, hata alındığı durumlarda detayları exception bilgisinin istemci tarafına gönderilip gönderilemeyeceği gibi.

 

Yeni bir WCF hizmeti tanımlarken ilk olarak sunulması hedeflenen fonsiyonaliteler netleştirilip ve bir contract ile duyurulur. Bu contract’ lar interface’lerin içerisine yazılırlar.

  [ServiceContract] //Contrat’ın bir hizmette kullanılacağını belirtmek için interface’in üst kısmına ServiceContract yazılır
    public interface IServiceImpl
    {
        [OperationContract] //Oluşturulan metodların service tarafından kullanılabilmesi için uygulanan etikettir.
        bool SaveData(string Val); //string tipinde bir parametre alarak gelen değeri kaydeden bir metod.
 
//XML ya da JSON formatında internet üzerinde ya da local’de veri yayınlamak istediğimizde aşağıda bulunan kodlara benzer yapılar kullanılır.
        [OperationContract]
        [WebInvoke(Method = "GET",  //GET metodunun kullanılacağı belirtildi.
            ResponseFormat = WebMessageFormat.Xml, //Geriye dönen veri XML formatındadır.
            BodyStyle = WebMessageBodyStyle.Wrapped,
            UriTemplate = "xml")]      //Url’de bu metodun çağırılmasını sağlayacak string
        List<Employee> XMLData();       //Geri dönüş tipi ile birlikte Metod ismi.
    }

 
//Belirtilmiş olan kontratlara uygun metodlar class içerisine yazılır.
namespace MyService
{
    public class ServiceImpl : IServiceImpl
    {
        public bool SaveData(string val)  //interface içerisinde tanımlanan servis kontratı.
        {
            return true;
        }
 
        public List<Employee> XMLData()//interface içerisinde tanımlanan XMLData servis kontratı
        {
            return new List<Employee>();           
        }
   }
}

 

Proje içerisinde bulunan app.config/Web.config sayfaları içerisinde kullanılacak kontratlar endpoint’ ler içerisinde tanımlanır ve servis yayınlanmaya hazır hale getirilir.

<servicename="Services.ServiceImpl "behaviorConfiguration="ServiceBehaviour">
       <endpointaddress=""binding="webHttpBinding"contract="Services.IServiceImpl "behaviorConfiguration="web">
        </endpoint>
     </service>xm

     

Endpoint ile servisi hangi adres, protokol ve kontrat ile yayınlayacağımızı belirtmekteyiz.  Bu kullanım hizmet sınıfını birden fazla kontrat ile farklı farklı adres ve protokollerle yayınlayabilme olanağı sağlamaktadır.