Bu site emekli olmuştur. Arşiv amaçlı olarak BT AKADEMİ sponsorluğunda yayın hayatına devam etmektedir.




C#nedir?com
 
YAZAR HAKKINDA
Sefer Algan
Sefer Algan
http://www.seferalgan.com
İletişme geçmek için tıklayın.
71 Makalesi yayınlanmakta.
Yazar hakkında detaylı bilgi için tıklayın.
Yayınlanan diğer makaleleri için tıklayın.
İlgili etiketler: basarili birbirinden deseni deseninin exception ilgili isimli logbase nesneler nesnelerin sonraki tasarim yazilmasi zinciri zincirin C# / VC#/.NET Sefer Algan
 
YAZI HAKKINDA
Türü : Makale
Serbest Köşede C#nedir?com üyelerinin hazırladıkları yazılar yayınlanır. Bu yazılar editör incelemesine girmeden yayınlanır.
Seviyesi : İleri
Kategori : C# / VC#/.NET
Yayınlanma Tarihi : 20.2.2005
Okunma Sayısı : 33781
Yorum Sayısı : 3     yorum yaz
Site İçi AramaSİTE İÇİ ARAMA
Üye Girişini AçÜye GİRİŞİ
Üye girişi için tıklayın.
Kullanıcı Adı
Şifre
 
Beni her zaman hatırla
Bir hafta boyunca kullanıcı bilgilerinizi kullanıcı çıkışı yapana kadar hatırlar. (Paylaşılan bilgisayarlarda önerilmez.)
 
Şifremi / Kullanıcı Adımı unuttum.
 
.net TV RSS Serbest KÖŞE (?)
Serbest Köşede C#nedir?com üyelerinin hazırladıkları yazılar yayınlanır. Bu yazılar editör incelemesine girmeden yayınlanır.
emre TAŞ
Silindi
emre TAŞ
yazının devamı >
emre TAŞ
silindi
emre TAŞ
yazının devamı >
emre TAŞ
silindi
emre TAŞ
yazının devamı >
emre TAŞ
silindi
emre TAŞ
yazının devamı >
emre TAŞ
silindi
emre TAŞ
yazının devamı >
Makale Gönder Bende Yazmak İstiyorum
.net TV RSSBlogroll
Turhal Temizer
Conda install environment.yml Package 23.11.2024
Turhal Temizer
Mac OS/X Removing CUDA 23.11.2024
Burak Selim Şenyurt
Rust ile ECS Yaklaşımını Anlamak 23.11.2024
Burak Selim Şenyurt
Birlikte Rust Öğrenelim Serisi 23.11.2024
  Diğer Herşey
Sponsorlar
BT Akademi
Medya Portakal
Video Hosting Sponsoru
Csharpnedir.com bir Ineta üyesidir
Uzman Abi
Her Yönüyle C# - Sefer Algan
"Chain of Responsibility(CoR)" (Sorumluluk Zinciri) Tasarım Deseni
 
Kapat
Sayfayı Yazdır Sık Kullanılanlara Ekle Arkadaşıma Gönder MySpace Del.Ico.Us Digg Facebook Google Mixx Reddit StumbleUpon
Tasarım desenleri ile ilgili geçen yıl başlamış olduğum yazı dizisine GoF desenlerinden biri olan Chain of Responsibility yani Sorumluluk Zinciri isimli desenin açıklaması ile devam ediyoruz. Yazının bundan sonraki bölümlerinde bu desenden kısaca CoR şeklinde bahsedeceğim. Yazı disini başından beri takip etmeyenler için aşağıda daha önceden yazmış olduğum makalelere bağlantı bulabilirsiniz.

"Singleton" Tasarım Deseninin(Pattern) C# ile Gerçekleştirilmesi

Abstract Factory Tasarım Deseni(Design Pattern)

"Builder" Tasarım Deseninin C# ile Gerçekleştirilmesi

"Prototype" (Prototip) Tasarım Deseni

CoR deseni GoF olarak anılan desenlerden "Behavioral" yani nesneler arasındaki lişkiyi düzenleyen kategorisine girmektedir. Bu ve bundan sonraki yazılarımda Behavioral - Davranışsal desenleri inceleyeceğim.

CoR bütün olarak ele alınabilecek bir dizi işlemi gerçekleştiren nesnelerin birbirlerinden bağımsız bir şekilde çalışabilmesini ve her sınıfın sadece kendisi ile ilgili işleri yapmasını sağlayan bir desendir. Sorumluluk zinciri ismide bu tanımdan gelmektedir. Birbirinden farklı olarak çalışan bu nesneler arasındaki tek bağ ise ortak bir mesaj(request) yapısıdır. Bütün nesneler bu mesaj yapısını kullanarak işlerini gerçekleştirir. Bu tasarım deseni, nesnelerin aynı görevde yer alması fakat birbirlerinin yaptığı işten çok da haberdar olmama durumunu temel alır ki nesnelerin bu şekildeki ilişkisine terminolojide loosly coupled (gevşek bağlı) nesneler denilmektedir.

CoR tasarım deseni daha çok, aynı işte görev alan bir çok nesnenin birbirinden haberdar olmamasını aynı zamanda bu nesneleri kullanacak istemcinin de (asıl program) bu nesnelerin ne şekilde ilişkide olduğunu bilmemesi gerektiği durumlarda kullanılır. CoR deseni olmazsa yapılacak iş sadece bolca if-else blokları yazmaktır. Bu da kontrolü ilerleyen zamanlarda kaybetmek anlamına gelecektir.

Daha somut örneklerden yola çıkarsak daha net anlaşılacaktır. Bu anlamda CoR deseninin bir kaç kullanım amacını incelemekte fayda var.

Basit bir iş akışı(workflow) uygulaması düşünün. Bu uygulamada şirket içinde yapılacak olan projelerin maliyetlerinin personele ödenmesi için bir masraf geri ödeme uygulaması yaptığımızı farzedelim. Proje maliyeti 1000 YTL ve altında ise bir üst yöneticinin onayı, 1000 YTL ile 2000 YTL arasında ise insan kaynakları müdürünün onayı ve 2000 YTL den fazla ise genel müdürün onayının olması gerektiğini farzedelim. Ve her bir durumda (case) farklı işlemlerin yapılacağını varsayalım. İşlem zincirinin en alt yöneticiden başladığı için ilk onay alınması gereken yer bir üst yoneticidir. Eğer masraf 1000 YTL den büyükse bu durumda gelen istek bir sonraki yoneticiye (sorumluluk zincirinin bir sonraki adımı) pas edilir. Ve bu böylece zincirin son halkasına kadar devam eder. Bu durumun yazılıma dökülmesi bir çok yöntemle yapılabilir, örneğin her bir durumu ifade eden if blokları yazılıp her if bloğunda ilgili sınıf ın ilgili metotları çağrılabilir. Ancak durumların ileride değişebileceği ve daha da karmaşıklaşabileceği ihtimalide gözönünde bulundurularak nesne tasarımını daha sistematik hale getirmek nerdeyse zorunludur. Zaten şunu açık yüreklilik ile soyleyebilirim : bir kaç istisna durum dışında eğer programınızda onlarca if -else satırı yer alıyorsa programınızda nesnel tasarım açısından mutlaka bir sorun var demektir. CoR desenine göre, verdiğimiz bu örnekte her bir onay adımı ayrı bir sınıf ile temsil edilir ve her bir sınıfın çalışması diğerinden soyutlanır, ve her bir nesnenin ortak olarak kabul ettiği bir istek (request) yada mesaj (message) vardır. Bu ornekte mesaj proje maliyet tutarıdır. CoR deseninin asıl amaçlarından birisi de her bir onayı temsil eden sınıfların ne şekilde birbirleri ile iletişime geçeceği ve sorumluluk zincirinde ilerlemenin nasıl sağlanacağının koda dökülmesidir. Bu örnekte verdiğim sorumluluk zincirinin şeması aşağıdaki gibi çizilebilir.


Şekil 1 - Örnek bir CoR Zinciri

Pratikte CoR deseninin bir çok kullanım alanı vardır. İsterseniz bu örnekleri inceleyelim. Bu arada aşağıdaki örnekler CoR desenini kullanmak için seçilmiş uygun uygulamalardır, ancak örnekler bu kadarla sınırlı değildir. Boyle bir yapının varlığını bir şekilde zihninize yerleştirdikten sonra bir çok uygulamanın çatısını oluştururken CoR deseninden faydanacağınızı söyleyebilirim.

Mail Sunucularındaki Mesaj Filtreleri

Bir çok mail sunucusunda mesaj mail kutunuza gelene kadar bir çok filtreden geçer. Size biri mail gönderdiğinde bu mail ilk önce spam filtresinden geçer ki bu ayrı bir modüldür genelde. Spam filtresinden geçen mail eğer başarılı ise ardından çeşitli mail filtrelerinden de geçtikten sonra en son mailin iletilmesi modülüne gönderilir. Spam belirleme, fake mail belirleme ve mail gönderme modülleri birbirinden tamamen bağımsız ve habersizdir dolayısıyla mail gönderme işlemini bir bütün olarak ele alabilmek için her bir modülün ortak mesaj/request olan mail nesnesi üzerinde çalışması gerekir. CoR deseni bu işlemleri gerçekleştirebilmek için nasıl bir çatı kurmamız gerektiği hakkında ipucu verir.

Derleyiciler

Bildiğiniz üzere nesne yönelimli programlamanın temelinde türetme mantığı yatar. Birbirinden türemiş nesne zincirinde hiyerarşinin an altında bulunan bir sınıf nesnesi üzerinden herhangi bir metodu çağırdığımızda derleyici o metodun hangi sınıflarda bulunduğunu tespit etmek ve hangi sırada çalışacağını belirlemek amacıyla CoR desenindeki mantıktan faydalanır. Çağrılan metot ilk sınıfta yok ise bir sonraki sınıfa eğer ondan da yoksa daha üstlere doğru ilerleyerek uygun sınıfı bulana kadar zincirde ilerlemeye devam eder. Eğer zincirde uygun çağrılabilecek metot ise yok ise derleyiciler çoğunlukla derleme hatası dediğimiz hataları vermektedir. Bir çok derleyicinin metot çağırma mantığı bu şekildedir.

Yorumlayıcılar

Bir çok yorumlayıcı içeren uygulama girdi olarak aldığı komutları çeşitli mekanizmalara göre katorgorize eder. Örneğin komut olarak girilen yazı çalıştırılabilir dosya ise yeni bir proses açıp onu çalıştırması, kout bir resim dosyasının açılması veya mail gönderilmesi ise ilgili aksiyonların alınması hep belirli bir öncelik sırasında gerçekleşir. Zira bir komut iki anlama geliyorsa zincirin halkasındailk hangi blok var ise o devreye girecektir. Komutların bu tarz sıralı bir şekilde işletilmesi ve ilgili modülün devreye girmesinin altında yatan tasarım da yine CoR deseni ile açıklanabilmektedir.

Görsel Event(Olay)’ların Yakalanması

Bir windows uygulamasında container dediğimiz bir çok kontrol bulunmaktadır. Her bir container farklı sayıda diğer kontrolleri yapısnda bulundurabilir. Bir çok kontrol ve konteyner kontroller aynı türden olaylara tepki verebilirler. Örneğin farenin ekranda hareket etmesini hem bir Panel hemde textbox hemde form nesnesi yakalayabilir. Ancak ekranın her noktasında form veya panel bulunmamakta, bu durumda olayların hangi kontroller tarafından ele alınacağı nasıl belirlenecek? Yani farenin hareket etmesine hangi kontroller nasıl cevap verecek? İşte bu noktada CoR alt yapısından faydalanılır. Olaya tepki verebilecek nesneler zinciri kurulur ve bir noktadan başlayarak zincirde devam edilir, taki son halkaya kadar.

Loglama

Literatürde logloma ile ilgili herhangi bir uygulama alanı varmı bilmiyorum ama CoR tasarım desenini bir uygulamada önermiştim. Uygulamada karşılaşılan problem şuydu : Uygulama çalışırken alınan hatalar bir şekilde bir veri kaynağına yazılmalı ve saklanmalıydı. Bu veriler ile programın çalışma zamanında ne kadar istisna yarattığının ölçülmesi hedefleniyordu. Ama bu veri kaynağının ne olacağı çok da tahmin edilemiyordu. Duruma göre bir text dosyası, SQL sunucusu yada event log mekanizması olabilirdi. Bunun yanında şu şekilde bir istek daha vardı. Eğer ulaşılabilecek ve yazma hakkı olan bir SQL Server tanımlanmış ise loglama bu veritabanına yazılacak yoksa event log’a yazılacak bunada imkan tanınamıyorsa yazma hakkı tanımlanmış varsayılan bir dizindeki metin dosyasına yazılması isteniyordu. Yani öncelik şu şekilde : Veritabanı, Event Log, Metin Dosyası. Bu durumda her bir loglama çeşidini farklı bir sınıf ile temsil edip ortak Exception sınıfı ile çalışabilecek hale getirip CoR altyapısını kullanmayı tavsiye ettim. Bu makalede bu örneğin ana çatısını CoR ile ne şekilde oluşturabileceğimizi ayrıntılı bir şekilde inceleyeceğiz.

CoR UML Modeli

CoR tasarım deseni temel olarak 3 ana bileşenden oluşmaktadır. Bu bileşenlerin açıklaması ve UML diyagramı aşağıda verilmiştir.

1 - Temel Chain(Zincir) Sınıfı : Örneğimizdeki LogBase sınıfına karşılık gelmektedir. CoR zincirini oluşturan her bir eleman bu sınıftan türemiştir. Zincirin her elemanının ortak olan mesajı işlemesi için gerekli olan arayüzü (interface) sunar. Bu sınıf içerisinde ayrıca zincirin bir sonraki halkasına referans vardır. Bu referansın türüde yine kendi cinsindendir. Bu çok mantıklı bir yaklaşımdır , çünkü zincirin diğer bütün halkalarıda bu sınıftan türemiştir.

2 - Somut Zincir Elemanları : Örneğimizdeki DatabaseLogger, EventLogger ve TextLogger sınıflarına karşılık gelmektedir. Teorik olarak bu sınıfların sayısı istenildiği kadar olabilir. Ancak pratikte CoR deseni, zincirdeki eleman sayısının 10’u aşmadığı durumlar için uygundur. Diğer durumlar için ayrı bir tasarım deseni mevcuttur, ilerleyen makalelerimde bundan da bahsedeceğim. Bu sınıfların her biri tamamen birbirinden bağımsızdır, ve aralarındaki tek ortak nokta yukarıda soylediğimiz temel sınıftan türemiş olması ve ortak bir mesaj üzerinde çalışmasıdır. Burada geliştireceğimiz örnekte bu mesaj Exception sınıfı türünden bir nesne olacaktır.

3 - İstemci : CoR tasarım deseninde geliştirilen nesneleri kullanan ve zinciri şekillendiren istemci nesnesidir. Bu makaledeki örnekte Main metodu istemcidir. Zincirdeki elemanların sırasını belirleyen ve zincirdeki ilk elemana isteği (request) gönderen de yine client(istemci)’tır.

Not : CoR tasarım deseninde klasik olarak mesajı işleyen yalnızca bir başarılı zincir halkası vardır. Mesajı başarılı bir şekilde işleyen halkaya successor denilmektedir. Ancak bu bir zorunluluk değildir. İstenirse mesajı birden fazla halkada başarılı bir şekilde işleyebilir. Bu makaledeki örneğimizde de yalnızca bir halka başarılı olacaktır. Benim kişisel tavsiyemde bu yönde olacaktır. Zira CoR desenin temel çıkış amacı da işi yapacak halkayı bulabilmektir. Eğer her halkada mesaj işlenecekse CoR deseninin bir anlamı kalmamaktadır.

Aşağıda resim, yukarıda bahsettiğim nesnelerin örnek UML diyagramıdır.



UML diyagramından CoR tasarım deseninin ne şekilde koda dökebileceğimizi az çok tahmin etmiş olmalısınız. Gördüğünüz gibi SqlLogger,EventLogger yada TextLogger yapısındaki bir üye yardımıyla LogBase’deki LogYaz metodunu çağırarak zincirin bir sonraki halkasına isteği göndermektedir. Şimdi sırasıyla diyagramda görülen yapıların C# ile nasıl gerçekleştiğine bakalım.

CoR Deseninin C# ile Gerçekleştirilmesi

LogBase Sınıfı

public abstract class LogBase
{
     protected LogBase NextLogger;      public void SetNextLogger( LogBase logger )
     {
           this.NextLogger = logger;
     }

     abstract public void LogYaz( Exception exc );
}

Görüldüğü üzere LogBase sınıfında, diğer sınıflarda override edilmek üzeri LogYaz isimi bir metot Exception türünden bir nesne parametresi ile bildirilmiştir. LogBase sınıfında ki bu metodun kullanımı bir anlam ifade etmeyeceği için abstract olarak bildirilmiş ve metodun gövdesi yazılmamıştır. Ayrıca zincirin (chain) bir sonraki halkasını referans etmek için yapısında LogBase türünden bir referans barındırmaktadır. Bu referans ise SetNextLogger isimli metot ile belirlenmektedir. İstemci ve diğer somut sınıflara ait kaynak kodları inceledikten sonra amacımızı daha net anlayacığınızı tahmin ediyorum.

SqlLogger,EventLogger,TextLogger Sınıfları

public class SqlLogger :LogBase
{
     public override void LogYaz( Exception exc )
     {
          try
          {
               //Veritabanıa exc nesnesine ait verinin yazılması işlemi
               //Bu bölümün yazılması size bırakılmıştır.
          }
          catch
          {
               if(NextLogger != null)
                    NextLogger.LogYaz(exc);
          }
     }
}

public class EventLogger :LogBase
{
     public override void LogYaz( Exception exc )
     {
          try
          {
               //Event Loga exc nesnesine ait verinin yazılması işlemi
               //Bu bölümün yazılması size bırakılmıştır.
          }
          catch
          {
               if(NextLogger != null)
                    NextLogger.LogYaz(exc);
          }
     }
}

public class TextLogger :LogBase
{
     public override void LogYaz( Exception exc )
     {
          try
          {
               //Metin dosyasına exc nesnesine ait verinin yazılması işlemi
               //Bu bölümün yazılması size bırakılmıştır.
          }
          catch
          {
               //Zincirin son halkası. Eğer burada da başarılı olunamıyorsa ona göre aksiyon alınmalıdır.
          }
     }
}
Yukarıdaki her 3 sınıfında tek ortak yani LogBase den türemiş olmaları ve dolayısıyla LogYaz isimli metoda ve NextLogger isimli metoda sahip olmalarıdır. Boylece eğer herhangi bir adımda hata alınırsa bir sonraki adıma geçilerek devam edilir. Hata alma kontrolü bu ornekte try-catch blokları ile yapılmıştır. Sizler kendi koşullarınızı pek tabiki farklı yontemlerle gerçekleştirebilirsiniz.

Son olarak xxxLogger isimli sınıflardan belirlediğimiz çalışma sırası koşulu dahilinde nasıl zincir(sorumluluk) oluşturacağımızı ve işlemi başlatacağımız istemci nin kaynak kodunu yazalım.

SqlLogger sqllogger = new SqlLogger();
EventLogger eventlogger = new EventLogger();
TextLogger textlogger = new TextLogger();

sqllogger.SetNextLogger = eventlogger; // Zincirin adımlarını oluşturuyoruz.
eventlogger.SetNextLogger = textlogger; // Zincirin adımlarını oluşturuyoruz.
try
{
      //Programın normal akışı
}
catch(Exception exc)
{
      sqllogger.LogYaz(exc); // bir hata oluştuğunda logluyoruz. Zincir kendi içinde işlemey başlıyor.
}

Gördüğünüz gibi başlangıç adımını attıktan sonra gerisi ile client ilgilenmemekte. Böylece ilerleyen zamanlarda yeni bir log kaynağımız oldugunuda yapacağımız tek şey ilgili log sınıfını yazmak ve zincirin istediğimiz halkasına eklemek. Üstelik bunun için client programda herhangi bir değişiklik yapmıyoruz. Tabi zinciri oluşturma işlemini ayrı bir sınıfi içerisinde yaptığınızı varsayıyorum.

Bu makalede temel bir CoR çatısını nasıl yazabileceğimizi ve CoR tasarım deseninin kullanılabileceği gerçek uygulamalara örnek verilmiştir. Yukarıda kodları ile verdiğim örnek gerçek bir uygulamadan alınmıştır. Sizlerde bu tür tasarım problemlerinize çözüm aramadan önce varolan desenleri incelemeyi unutmayınız. Bir sonraki tasarım deseni makalesinde görüşmek üzere herkese iyi çalışmalar diliyorum.

Makale:
"Chain of Responsibility(CoR)" (Sorumluluk Zinciri) Tasarım Deseni C#, Visual C# ve .NET Sefer Algan
  • Yazılan Yorumlar
  • Yorum Yaz
MAY
27
2005
Sanki pattern composite design pattern ile benzer gibi duruyo UML gösteriminde. Ama uygulamada farklıymış öyle gözüküyo kodlarda... Yazı için teşekkürler
MAY
1
2005
Örnek çok güzel.Pattern lerin gerçek yaşamda kullanıldığını görmek daha bir güzel.
ŞUB
3
2005
Exception Management icin iyi bi pattern..
Sayfalar : 1 
Yorum yazabilmek için üye girişi yapmalısınız. Üye girişi için tıklayın.
Üye değilseniz Üyel Ol linkine tıklayarak üyeliğinizi hemen başlatabilirisniz.
 
  • Bu Konuda Son 10
  • Eklenen Son 10
  • Bu Konuda Geçmiş 10
Bu Konuda Yazılmış Yazılmış 10 Makale Yükleniyor
Son Eklenen 10 Makale Yükleniyor
Bu Konuda Yazılmış Geçmiş Makaleler Yükleniyor