Makale Özeti

Bu makale, Microsoftun Patterns & Parctices sitesi hakkında giriş, referans bilgisi vermektedir ve en bilinen patternlerden "Singleton" patternini tanıtılmaktadır.

Makale

Gerekli Araçlar

  • Visual Studio.Net 2003

Giriş:

Patterns & Practices:

Sakın kızmasınlar; bütün iş Javacıların başının altından çıkıyor. Java mimarları, bol bol program yazıyor, daha sonra bunlar birbirine benziyor deyip ortaya "Pattern" (şekil) diye bir kavram atıyorlar. Bu programcılar daha sonra, genel amaçlı problemleri çok iyi analiz edip, var olan en kodları inceleyip; genel amaçlı, hataları çok az olan kodlar yayınlıyorlar, bu kodlara da "Best Practices" (en iyi deneyimler) diyorlar. Ve bir zaman sonra "Pattern"lerini ve "Best Practices"lerini internette yayınlıyorlar. .Net ile birlikte Microsoft da, uzman programcıları toparlayıp, http://www.microsoft.com/resources/practices/ adresinden bu kervana katılıyor.

Şaka bir yana "Patterns" konusu nesne yönelimli kod yazan programcıların çok uzun süredir uğraştıkları, büyük bir değer yarattıkları bir bilgi yığınıdır. Microsoft da kendine düşeni yapıp bu alana bolca yatırım yapıyor. Yukarıda bahsettiğim linkte, gerçekten okunmaya değer pek çok "Patterns" içeriği ve "Best Practices" örneği var. Şu anda bildiğim kadarıyla, oniki adet kitap (PDF dosyası) var.

Buradan şu çıkıyor; artık programcılar belirli bir seviyeye ulaşmak için bolca okuyarak zaman geçirecekler.

Microsoftun en çok kullanılan "Best Practice"i olan "Data Access Application Block for .Net"i http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnbda/html/daab-rm.asp adresinden indirip inceleyebilirsiniz. Bu blok sayesinde;

DataSet dataSet = SqlHelper.ExecuteDataset("ConnectionString", CommandType.StoredProcedure, "GetPage");

gibi bir kod yazarak tek satırda bir DataSeti doldurabilirsiniz. Connection açık kaldı mı, parametreleri doldurmak gibi sorunları düşünmenize gerek yok! Bu kod bloğunu hararetle indirip incelemenizi öneririm.

Singleton "Pattern"i:

Singleton patterni en çok kullanılan patternlerden biridir.

Çözdüğü problem, uygulama içinde (.Nette bir AppDomainde) nereden erişirseniz erişin, bir nesnenin, sadece ve sadece tek bir instanceına erişilmesini sağlamaktır. Bu genelde global bir değişken yaratıp onu kullanmaya benzer. Ama nesne yönelimli programlamada, global değişkenlerin yaratılması biraz sorunludur.

Singleton programlarken, nesnenin kod yazımı sırasında çok enteresan bir teknik kullanılır; nesnenin constructorı "private" olarak tanımlanır böylece nesne dışından erişilemez ve nesne kod içinden yaratılamaz. Peki nesne nasıl yaratılacak? Çok basit, nesneye "public static" olarak tanımlanmış bir metod veya özellik (property) konur. Bu özelliğin tipi nesnenin kendisidir ve kendini yaratmaktan sorumludur. (Pattern camiasında nesne yaratan nesnelere Factory denir ve kullanıldığı alanlar ve amaçları çok geniştir. Factory de ayrı bir patterndir).

Aşağıdaki kodu göz önüne alın;

using System;
using System.IO; 
public class SingletonCls { private static SingletonCls instance;
private SingletonCls() {
property1 = "test";
Console.WriteLine("nesne yaratıldı"); }
   public string  property1;
public static SingletonCls GetInstance() { if (instance == null) { instance = new SingletonCls(); } return instance; } }

Ne oluyor?

  1. SingletonCls sınıfının içinde ilk önce, kendi tipinde bir nesneye referans veren "instance" adlı "private static" değişkeni tanımladık.
  2. Daha sonra nesnenin constructorunu yazdık. Tipinin "private" olduğuna dikkat edin. Böylece constructor nesne dışından çağrılamaz.
  3. Bir tane "property1" adlı property tanımladık. Bunu test etmek amacıyla yaptık. Normalde bu şekilde bütün property ve metodlar tanımlanabilir.
  4. Daha sonra asıl büyünün olduğu ve instanceı gerçekten yaratan metodu yazdık; "GetInstance". Bu metod "instance" değişkeninin "null" olup olmadığına bakıyor. İlk seferinde değer atanmadığı için her zaman "null" olur. Böylece "instance" değişkenine yeni bir SingletonCls nesnesi oluşturulup atanır. Daha sonra bu metod tekrar çağrıldığında, "instance" null olmayacağı için "if" komutunun içine girilmez. Sonuçta her zaman bir "instance" döndürülür.

Yukarıdaki örnek, en basit singleton yaratım tekniğidir. Bir Singletonı "Static initialization" tekniği ile de yaratabilirsiniz. Bazı durumlarda Thread-Safe, Singleton nesneleri yaratmanız gerekebilir. Bu konuda, bu yazının kaynağı olan "Referanslar" bölümündeki Singleton referansından daha fazla bilgi alabilirsiniz.

Singleton nesneler aynı zamanda performans artışı sağlar, çünkü, nesne sadece bir kere yaratılır, daha sonra hep aynı instancea ulaşılır. Böylece nesneyi yaratmak için zaman kaybedilmez (Nesne yaratmak, nesne yönelimli programlamada en zahmetli işlerden biridir).

Singletonın kullanımı da çok basittir, ama unutmayın ne zaman singleton nesneye ulaşmak isterseniz, onun Instanceını döndüren statik metodunu çağırın.

[STAThread]
static void Main(string [] args)
{
  
SingletonCls singleton1 = SingletonCls.GetInstance(); 
  
SingletonCls singleton2 = SingletonCls.GetInstance(); 
  
SingletonCls singleton3 = SingletonCls.GetInstance(); 
  
SingletonCls singleton4 = SingletonCls.GetInstance(); 
   Console.WriteLine(singleton1.property1); 
   Console.WriteLine(singleton2.property1); 
}

Yukarıdaki kod dört adet singleton nesnesi yaratır. Ancak Singleton constructorundaki "nesne yaratıldı" yazısı sadece bir kere çalışır. Çünkü kod ilk çalıştığında, nesne yaratılıyor, daha sonra "instance", "null" olmadığı yenisi için yaratılmıyor, hep ilk seferde yaratılan referans döndürülüyor.

Uygulamanın çıktısı F5 ile çalıştırıldığında aşağıdaki gibi olacaktır:

nesne yaratıldı
test
test

Sonuç:

Tüm kodu aşağıda Kod1de bulabilirsiniz. Dikkat etmeniz gereken şey; "Singleton" patterni, belirlenemeyen hatalara neden olabilir. Her zaman aklınızda olsun, eğer bir nesne "Singleton"sa o nesnenin verisi hafızada sadece ve sadece bir tanedir ve değiştirdiğinizde, bütün referansları da değiştirirsiniz. Bu problem özellike, kod aynı anda çok kişi tarafından kullanılıyorsa ortaya çıkar (Örn. Web uygulamaları). Kodu ona göre yazmak gerekir.

Singletonın Webde uygulaması da enteresandır. Örnek kullanımı; sadece okunan, çoz az değişen, metadata amaçlı XML dosyaların hafızada "Cache"lenmesi ve gereksiz yere instancelarının oluşturulmamasıdır. Böylece Web uygulaması içinde nereden erişirsek erişelim, hep aynı referansa gidilir (instance tektir). Aynı başka sınıflara veya metodlara, aynı AppDomain içinde, Singleton nesneyi geçirmeye gerek yoktur, her zaman GetInstance() metoduyla referansa erişebilirsiniz.

Referanslar:

Microsoft patterns & practices: http://www.microsoft.com/resources/practices/

Data Access Application Block for .Net: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnbda/html/daab-rm.asp

Singleton: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnpatterns/html/DesSingleton.asp

Yazar hakkında:

Mert Sakarya, Doğan İletişim A.Ş.de Uygulama Mimarı olarak görev yapmaktadır. Kendisinin 17 yıllık profesyonel yazılım deneyimi vardır. .Net, XML, Scripting ve SQL Server veri tabanı konularında uzmandır. Kendisine msakarya@e-kolay.com veya mertsakarya@hotmail.com adreslerinden ulaşabilirsiniz.

Kod 1:

using System;
using System.IO;

namespace ConsoleApplication1
{
	public class SingletonCls {
		private static SingletonCls instance;
		private SingletonCls() {      
			property1 = "test";      
			Console.WriteLine("nesne yaratıldı"); 
		}

		public string  property1;

		public static SingletonCls GetInstance() {
			if (instance == null) {
				instance = new SingletonCls();
			}
			return instance; 
} }
/// <summary> /// Summary description for Class1. /// </summary> class Class1 {
/// <summary> /// The main entry point for the application. /// </summary> [STAThread] static void Main(string[] args) { SingletonCls singleton1 = SingletonCls.GetInstance(); SingletonCls singleton2 = SingletonCls.GetInstance(); SingletonCls singleton3 = SingletonCls.GetInstance(); SingletonCls singleton4 = SingletonCls.GetInstance(); Console.WriteLine(singleton1.property1); Console.WriteLine(singleton2.property1); Console.ReadLine(); } } }

Mert Sakarya
Uygulama Mimarı
Doğan Online A.Ş.
msakarya@e-kolay.com