May 16 2010

Stored Procedure ve Entity Framework

Kategori: .NET | C# | Entity Framework | SQL   — Veli Sezer  

Merhabalar.

Bu yazımızda SQL veri tabanındaki stored procedure'ün Ado.Net Entity Framework aracılığıyla kullanılmasına göz atacağız. Bildiğimiz gibi .Net'in gözde Object Relational Mapping (ORM) aracı olan EF yardımıyla LINQ sorguları yazarak veri tabanı sorguları yapabilmekteyiz. EF ile sadece LINQ sorguları yapmak yerine, veri tabanında daha önce kaydedilmiş olan SP'leri de kullanabilmekteyiz. Bu şekilde EF'in kod geliştirme rahatlığı ve SP'ün performansı birleşerek daha etkin yazılım geliştirme imkanımız sunmkatadır.

Uygulamamızda bir önceki yazımızda oluşturduğumuz ve kullandığımız SP'leri kullanacağız. Bunun için yine daha önceki EF yazımızda bahsettiğimiz yolu izleyerek bir adet Entity Data Model oluşturuyoruz. Modelimize Northwind veritabanındaki Products ve Categories tablolarını ve daha önce oluşturduğumuz 5 adet SP'ü ekliyoruz.

Modeli oluşturduktan sonra SP'leri aktifleştirmemiz gerekiyor. Modelde herhangi bir yere sağ tıklayarak Add ->Function Import adımlarını izleyerel yeni fonksiyon eklemeye başlıyoruz. Bu fonksiyonlar, veri tabanımızdaki SP'lerin kod tarafındaki karşılıkları olan metodlar olacak. Bu metodları çağırarak ve parametre göndererek SP'leri kullanmayı hedefliyoruz.

Karşımıza gelen wizard yardımıyla SP'leri metodlaştırıyoruz. Ben metod adına da SP'ün adını atamayı tercih ediyorum. Ayrıca metodun geri dönüş tipini de belirtmemiz gerekmekte. Bunun için 4 seçeneğimiz var. Biz de SP'lerin geri dönüş tipine uygun olanları seçiyoruz. Geri dönüş değeri olanlar için, dönüş tipinin veri tabanındaki ve kod tarafındaki özellikleri de görülebilmekte.

Metodları eklendi. Model Browser'dan modelimizin son durumuna baktığımızda eklemiş olduğumuz SP'leri görebiliriz.

Ayrıca model'in designer.cs dosyasına baktığımızda eklemiş olduğumuz SP'lerin metoda dönüştürüldüğünü görebiliriz.

Gelelim bu metodları kullanmaya. NorthwindEntities nesne öreği aracılığıyla eriştiğimiz bu metodlarda intellisence aktif olduğundan dolayı işimiz oldukça kolaylaşmaktadır.

SP'leri temsil eden metodlarımızı aşağıdaki örneklere benzer biçimde kullanabiliriz.

ORM araçları yardımıyla yapılan veri tabanı sorgularının arka tarafta saf SQL sorgularına gönüştürüldüğünü biliyoruz. Ancak EF aracılığıyla SP kullanıldığında durum değişmektedir. SQL Profiler aracılığıyla üretilmiş ve veri tabanına gönderilmiş olan sorguları görebilmekteyiz. Bu aracı çalıştırdığımızda veri tabanına giden sorguların aşağıdaki gibi olduğunu görürüz.

Yani EF ve SP birlikte kullanıldığında, bir SQL sorgusu üretilmemekte, sadece SP çalıştırılmaktadır. Dikkat etmemiz gereken bir diğer nokta da, normal EF ile yapılan update/delete/insert işlemlerinde kullandığımız  SaveChanges() metodunu kullanmadığımızdır.

Stored Procedure ve Entity Framework'un birlikte kullanımını incelediğimiz bu yazımızın sonuna gelidk. Yeni bir yazıda görüşmek üzere.

Tags: , , , , , , ,

May 13 2010

Stored Procedure ve Ado.Net

Kategori: Ado.Net | Asp.Net | C# | SQL   — Veli Sezer  

Merhabalar.

Bu yazımızda SQL'in temel taşlarından biri olan stored procedure (saklı yordam) kavramını ve kullanımını ele alacağız. SP'ler veri tabanında saklanan SQL ifadeleridir. Normal olarak sunucuya gönderilen SQL sorguları öncelikle derlenir ve daha sonra çalıştırılır. SP'ler ise bir kere derlendikten sonra, sonraki kullanımlarda derlenmeden çalıştırılmaktadır. Sorgunun derlenmesi için zaman kaybedilmediğinden dolayı performans artışı söz konusu olmaktadır. SP'lerin faydalarını ve özelliklerini şu şekilde sıralayabiliriz.

  • Kod içerisinde yazılan SQL sorgularından daha performanslı çalışır.
  • İçerisinde mantıksal kontroller yer alabilir.
  • Kod içerisinde yazılan SQL cümleleri string olarak yazıldığından dolayı, her seferinde doğru yazıldığından emin olma ihtiyacı doğar. 
  • Kompleks SQL cümleciklerini tekrar tekrar yazma zorunluluğu ortadan kalkar.
  • Tanımlandıktan sonra farklı uygulama ve platformlardan çağırılabilirler.
  • Dışarıdan parametre aldığı için kullanımı kolay ve etkilidir.
  • Dış ortam veri alırken aynı zamanda dış ortama veri de döndürebilir.
  • Normal SQL sorgularına göre daha güvenlidir.

Yeterince teorik bilgiden sonra uygulamamıza geçebiliriz. Öncelikle ihtiyacımız olan SP'leri yazmamız gerekiyor. Uygulamalarımızı Northwind veri tabanı üzerinde gerçekleştiriyor olacağız. SQL'in dört işlemi sayılan select, insert, update ve delete işlemleri için SP'leri aşağdaki gibi oluşturuyoruz. Parametre alan SP'lerde parametrelerimiz '@' karakteri ve veri tipi bilgisini de içermektedir.

Kaydedilen SP'ler Stored Procedures klasörü altında yerini aldı. Northwind veri tabanında bizim eklediklerimiz dışında default olarak gelen SP'ler olduğu da görülmektedir. Bunların incelenmesi faydalı olabilir.

Stored Procedure'leri yazdıktan sonra bunları kullanacak istemci uygulamaları yazabiliriz. Bu yazımızda Ado.Net yardımıyla SP kullanımını ele alacağız. İleriki yazılarda SP'lerin farklı kullanım alanlarını incelemeye devam edeceğiz. Bu yazıda ben Asp.Net projesi geliştirmeyi tercih ediyorum. Tasarım tarafı ile fazla bir işimiz olmadığından dolayı, sadece kod tarafından bahsetmeyi tercih ediyorum. İlk olarak DropDownList nesnesine veri tabanındaki Categories tablosundaki verileri yükleyeceğiz. Daha sonra seçilen bu kategoriye ait ürünlerin DataGrid'de listelenmesini sağlayacağız. Kullanacağımız 'sp_GetCategories' isimli SP'yi SqlDataAdapter nesnesine parametre olarak gönderiyoruz. Daha sonra kullanacağımız SQL cümleciği olarak sistemde kayıtlı olan SP kullanılacağını belirtiyoruz. Veri çekme ile ilgili diğer kısımlar Ado.Net'in klasik işlemlerinden ibaret. SP ile çalışırken yapmamız gereken tek şey, SQL cümleciğinin SP'den geldiğini belirtmek. Unutmadan DropDownList ile kullanıcıya gösterilecek değer ve arka planda işlemleri yürüteceğimiz değerleri DropDownList'in ilgili özelliklerine atıyoruz.

Seçilen kategoriye ait ürünlerin getirilmesi için '@CategoryID' parametresini alan 'sp_GetProductsByCategoryID' isimli SP'ü kullanacağız. Parametreye değer ataması için, parametre ve parametrenin veri tipini SqlParameterCollection koleksiyonuna ekliyor ve buna değer ataması yapıyoruz. Sorgu sonucu gelen verileri önce DataTable'a, daha sonra da DataGrid'e bağlayarak listeliyoruz.

SP yardımıyla silme işlemi gerçekleştirmek için SqlCommand nesnesinden faydalanıyoruz. Sorgu için gereken diğer işlemler SqlDataAdaper ile çalışırken yaptıklarımız ile aynı. Bundan farklı olarak SqlCommand nesnesi bağlantılı katmanda çalıştığı için bağlantı açma ve kapama işlemlerini de yapmamız gerekmekte.

Veri ekleme ve güncelleme işlemleri, biraz önce bahsettiğimiz silme işlemi ile aynı.

Görüldüğü gibi Ado.Net içerisinde  Stored Procedure kullanılması, SQL cümleciklerinin kullanılmasına çok benzemektedir. Özel olarak yapılması gereken şey, SQL ifadesinin SP olduğunun belirtilmesidir. Daha sonraki yazılarda SP konusunu incelemeye devam edeceğiz.

Bir sonraki yazıda görüşmek üzere.

Tags: , , , , ,

May 2 2010

Desing Patterns:Composite

Kategori: C# | Design Patterns | OOP | Yazılım Mimarisi   — Veli Sezer  

Merhabalar.
Tasarım desenleri serimize yeni bir yazı ile devam ediyoruz. Bu yazımızda yapısal tasarım desenlerinden biri olan composite tasarım desenini ele alacağız. Composite tasarım deseninin amacı, belli bir ağaç hiyerarşik yapısına sahip nesneleri bu hiyerarşiye uygun olarak ele alabilmektir. Hiyerarşik yapı söz konusu olduğundan işlemler yukarıdan aşağıya doğru sırayla uygulanır. Bu deseni en iyi açıklayan örnek askeriyedeki hiyerarşik yapıdır. Düşük rütbeli askerler daha üst rütbeli başka bir askerin komutasındadır. Hatta bu üst rütbeli asker de yine daha üst rütbeli başka bir askerin komutasındadır. Bu yapının bütün üyeleri askerlerdir. Yukarıdan verilen bir emir, sırayla alt rütbelere doğru iletilir. Bir komutanın verdiği emir, onun altındaki bütün askerleri ilgilendirir. Zincir böyle sürer gider.

Composite tasarım desenin başlıca öğeleri şunlardır.

  • Component: Ağaç yapısındaki nesnelerin şablonunun tutulduğu sınıf. Bu sınıf composite (node) ve leaf (yaprak) nesnelerinin kullanacağı üye ve metodlara sahiptir. Abstract veya interface olarak tanımlanır.(component:tamamlayıcı )
  • Composite: Ağaç yapısında kendisinden dal ve yapraklar türeyen nesneler. Yani dalların kendisi. Hiyerarşide alt nesnelere sahiptirler. (composite:bileşik)
  • Leaf: Ağaç yapısında kendisinden dal veya yaprak türemeyen nesneler. Yani yaprakların kendisi. Hiyerarşide alt nesnelere sahip değildirler. (leaf:yaprak)
  • Client: İstemci nesne.

Composite tasarım deseninin UML şeması aşağıdaki gibidir. Temel olarak bir adet component nesnesi ve bunu iplemente eden composite ve leaf nesneleri bulunmaktadır. Component tipi pozisyonundaki Personel sınıfındaki metodlar abstract veya virtual olarak tanımlanabilir. Ancak abstract metodların, o abstract sınıfı uygulayan sınıflar tarafından iplemente edilmesi zorunluluğu olduğundan dolayı, daha esnek olan virtual metodları kullanmayı tercih edebiliriz. Çünkü leaf ve composite nesnelerinin uyguladığı metodlar bazen ortak olsa da, ortak olmadığı durumlar da söz konusudur.


Görüldüğü gibi composite nesnesi pozisyonundaki Amir sınıfında component tipe  ait bütün metodlar uygulanmışken, leaf nesnesi konumundaki Memur sınıfında sadece kendisini ilgilendiren metodlar uygulanmıştır. Çünkü leaf nesnesi ağaç yapısının yaprağını oluşturduğundan alt üyelere sahip değildir. Bu yüzden kendisine bağlı üyeleri eklemeye ve silmeye yarayan PersonelEkle() ve PersonelSil() metodlarına ihtiyacı yoktur.

Yukarıda UML şemasını gördüğümüz uygulamamızın kodlarını yazmaya başlamadan önce senaryomuzdan bahsedelim. Uygulamamızda bir işlemeye ait çalışanların hiyerarşik yapısını ele almaya çalışacağız. Aşağıdaki şekilde de izah etmeye çalıştığım gibi bir genel müdür, genel müdüre bağlı şube müdürleri ve bunlara bağlı memurlarımız var.

İlk olarak component nesnemizi yazıyoruz. Diğer tipler bu tipin metodlarını iplemente edecek.

Composite nesnemiz olan Amir sınıfımız aşağıdaki kodlardan oluşuyor. Görüldüğü gibi PersonelEkle(Personel personel) şeklinde tanımlanmış olan bu metod, belli bir tip ayrımı yapmadan, component tipini uygulamış olan bütün tiplerin örneklerini parametre olarak alabilmektedir. Bu şu anlama geliyor. Bu parametre Amir nesnesi de olabilir Memur nesnesi de. Daha da açmak gerekirse bir amir, bir memurun amiri olabileceği gibi bir amirin de amiri olabilir.

Leaf nesnemiz  olan memur sınıfı, kendisinden alt rütbede üyeye sahip olmadığından dolayı bütün metodları iplemente etmemiştir.

Rütbeleri bir enum sınıfından alabiliriz.

Gelelim istemcimizi yazmaya. İlk olarak bir Amir tipinden bir nesne örnekliyoruz. Bu nesne hiyerarşinin en üstünde yer alan genel müdür. Daha sonra iki adet şube müdürü oluşturup bunları genel müdürün kadrosuna ekliyoruz. Daha sonra örnek memurlar oluşturup bunları da şube müdürlerinin kadrosuna ekliyoruz. Bunlar aynı zamanda genel müdürün kadrosuna da eklenmiş oldular. Bir memuru, bir amirin kadrosuna eklerken, amirinin sicil no'sunu memurun gerekli alanına ekleyerek hiyerarşiyi sağlama almaya çalışıyoruz.

Uygulamamızı çalıştırdığımızda aşağıdaki gibi bir görüntü elde ederiz. Görüldüğü gibi, genel müdürün kadrosu listelenirken listedeki herkes listelendi. Ancak şube müdürlerinin kadrosu listelenirken sadece kendi altındaki memurlar listelendi.

Bu yazumızda yapısal desenlerden biri olan composite tasarım desenini incelemeye çalıştık. Başka bir yazıda görüşmek üzere.

Tags: , , ,

Apr 25 2010

Design Patterns: Builder

Kategori: C# | Design Patterns | OOP | Yazılım Mimarisi   — Veli Sezer  

Merhabalar.
Bu yazıda tasarım desenleri serimize builder tasarım deseni ile devam ediyoruz. (Builder: yapıcı, inşaatçı) Yaratımsal tasarım desenlerinden biri olan bu desenin amacı, karmaşık işlemlerin birlikte gerçekleştirilmesi ile meydana gelen ürünlerin, daha basit bir şekilde oluşturulmasını sağlamaktır. İstemci direkt olarak ürünün üretim safhalarıyla ilgilenmez. Sadece oluşturulacak nesne tipini belirtir ve işlemlerin başlatılmasını sağlar. Böylece karmaşık işlemler ile karşılaşmak zorunda kalmaz.

Builder tasarım deseninin temel yapı taşlarımız şunlardır:

  • Builder: Oluşturulacak ürünün şablonunun belirlendiği kısım. Abstract veya interface olarak tanımlanır.
  • Director: Builder arayüzünü kullanarak nesne oluşturulması işlemini yöneten sınıf.
  • Concrete Builder: Nesnenin oluşturulduğu sınıf. Builder abstract veya interface'ini iplemente ederek gerekli metodları uygular.
  • Product: Oluşturulan nesne.
  • Client: Sadece director ile temasta bulunur. Director'a nesne tipi belirterek o nesnenin oluşturulmasını sağlar.

Builder tasarım deseninin UML şeması aşağıdaki gibidir. İstemci pozisyonunda olan Program.cs sınıfı, sadece director pozisyonundaki SantiyeYonetimi sınıfıyla ilişki içerisindedir.

Projenin mimarisel yapısına bakacak olursak aşaıdaki gibi bir görüntü ile karşılaşırız. Okların kalınlığı ilişkilerin kuvvetliliği ile doğru orantılıdır. Uygulamamızda istemci pozisyonunda olan Program nesnesinin en önemli ilişkisi SantiyeYonetimi nesnesi iledir. Üretimin gerçekleştirildiği yer olan Mesken ve IsYeri nesneleri ile olan ilişki daha zayıftır.

Bu kadar teorik bilgiden sonra, demomuzu kodlamaya başlayabiliriz. Öncelikle üretmeyi hedeflediğimiz nesne olan Bina sınıfını oluşturuyoruz.

Bina tiplerini belirlerken bir enum tipinden faydalanabiliriz.

Daha sonra demomuzun builder nesnesi olan IBinaSablonu interface'ini yazıyoruz. Görüldüğü gibi ürün üretimi sırasında gerçekleştirilecek işlemler özetlenmiş durumda.

Demomuzda 2 adet concrete builder nesnesi olacak. Bunlara üretilecek olan ürünlerin farklı modelleri olarak bakabiliriz. İstemci bu farklar ile ilgilenmeyecek, sadece üretmek istediği modeli belirleyecektir.

İstemcinin direkt olarak muhatap olacağı nesne director nesnesidir. Bu nesne ürünün üretilme aşamalarını yönetmek ile görevlidir. Parametre olarak gelen IBinaSablonu nesnesine ait metodları sırası ile çalıştırıp ürünün üretilmesini sağlar.

Artık istemcimizi yazabiliriz. İstemcide concrete builder örneklemesi yapılarak director'in bu ürünü üretmesi sağlanır. İstemci üretim işleminin detayları olan ProjeCiz(), TemelAt(), KatlariCik(), CepheKapla() metodları ile ilgilenmez. Bu işlemler director nesnesi olan SantiyeYonetimi tarafından gerçekleştirilir.

Uygulamamızı çalıştırdığımızda aşağıdakine benzer bir çıktı alırız.

Builder tasarım desenini incelediğimiz bu yazının sonuna gelmiş bulunuyoruz.

Başka bir yazıda görüşmek üzere.

 

Tags: , , , , ,

Apr 24 2010

Design Patterns: Prototype

Kategori: .NET | C# | Design Patterns | OOP | Yazılım Mimarisi   — Veli Sezer  

Merhabalar.
Bu yazımda sizlere, yaratımsal desenlerden biri olan prototype design pattern (prototip tasarım deseni)'den bahsedeceğim. Bu tasarım deseni özellikle new operatörü ile gelen nesne yaratma maliyetlerini en aza indirmek amacıyla kullanılır. Kullanılması oldukça kolay olan bu desen gerçek uygulamalarda ihmal edilse de, spesifik uygulamalarda oldukça faydalı olabilmektedir. Bu desenin faydalarını şöyle sıralayabiliriz.

  • New operatörü ile oluşturulması maliyetli olan nesnelerin yeniden yaratılması yerine, daha önce yaratılmış olan prototipinin kopyalanmasını sağlandığı için, nesne yaratma maliyeti azaltılmış olur.
  • Uygulama sırasında, çalışmaya nesnenin kopyası üzerinden devam etme imkanı doğar. Böylece orjinal nesne korunmuş olur.
  • Yaratılan nesnelerin özelliklerinin çoğunun ortak olduğu durumlarda, yeni nesne öncekilerden kopyalanır ve sadece değişik olan kısımlar güncellenir. Böylece aynı işlemlerin tekrar tekrar yapılması engellenmiş olur. Mesela gömlek üretimi sırasında boyut, kumaş, düğme, model vs bilgiler aynı olsun. Sadece renk bilgisi zamanla değişsin. Böyle bir senaryoda, kopyalama işleminden sonra yeni nesnede sadece renk bilgisinin güncellenmesi yeterli olacaktır.


Prototip tasarım deseni ile .Net ile gelen bir özellik sayesinde daha anlamlı hale gelmektedir. IClonable interface'i içerisinde yer alan MemberwiseClone() metodu, nesnenin bire bir kopyasını üretmektedir. Yani deep copy işlemiyle, bellekte yeni bir nesne oluşturmaktadır. Bu nedenle prototip tasarım deseni için MemberwiseClone() metodu vazgeçilmez bir araçtır.

Prototype Desing Pattern'in UML şeması en basit haliyle asaşıdaki gibidir.

Yukarıdaki şekilde de görüldüğü gibi bu desende 3 temel nesnemiz vardır:

  • Prototype: Abstract veya interface olarak tanımlanabilir. İçerisinde klonlama yapmamızı sağlayan metod bulunur.
  • Concrete Prototype: Prototype nesnesini iplemente eden, dolayısıyla klonlama metoduna sahip olan nesnedir. Bir uygulamada birden fazla sayıda olabilir. (Somut prototip)
  • Clinet: Concrete prototype nesnelerinin kopyalarına ihtiyaç duyan ve bu kopyaları kullanan istemci nesnesi.


Teorik bilgilerden sonra uygulamamıza geçebiliriz. Demomuzda az önce bahsettiğim gömlek senaryosunu ele alacağız. Öncelikle GomlekPrototip adında prototipimizi oluşturuyoruz.

Gomlek adında somut prototipimizi oluşturuyoruz. Bu sınıf GomlekPrototip abstract sınıfını iplemente edip metodlarını uygulayacak. Sınıf içerisinde Klonla() isimli metodu override ediyoruz. this anahtar sözcüğü ile gene nesnenin klonunu oluşturup Gomlek tipine cast ediyoruz.

Bunların dışında yardımcı tiplerimiz de olabilir. Demomuza bir adet enum tipimiz de olsa fena olmaz.

Sıra geldi demomuzun istemcisi olan Main() metodunu yazmaya. Gomlek tipinden veri tutan generic listeye oluştırduğumuz nesneyi ve bu nesneden klonladığımız diğer nesneleri sırasıyla ekliyoruz. Burada dikkat etmemiz gereken noktalar şunlardır. Klonlanan nesneler farklı referanslara sahip olduğundan, tamamen birbirinden bağımsıdırlar. Silme ve güncellemelerden diğer nesneler etkilenmez.

Programımızı çalıştırdğımızda aşağıdaki gibi bir çıktı alırız. Görüldüğü gibi klon nesnelerin değişmeyen özellikleri, orjinal nesnenin özellikleri ile aynıdır. Ayrıca orjinal nesnede yapılan değişiklikler, klonları etkilememiştir.

Bu yazıda prototip tasarım deseni ve bunun vazgeçilmezi olan MemberwiseClone() metodunu ele aldık. Umarım faydalı olmuştur.

Başka bir yazıda görüşmek üzere.

Tags: , , , ,

Apr 19 2010

Kodu Konuşturma Zamanı

Kategori: .NET | C# | Paralel Programlama   — Veli Sezer  

Merhabalar.

Daha önceki bir yazımda kodumuza okuma kabiliyeti kazandırmayı görmüştük. Şimdi yanlızca okuma yetmez diyerek konuşma kabiliyeti de kazandırmayı hedefliyoruz. Çeşitli uygulamalarda karşımıza çıkan, yazılan metni sesli olarak okuyan programı biz de yazabiliriz. Bunun için .Net ile gelen hazır kütüphaneleri kullanmak yeterli olacaktır. Bunu nerede kullanacağız kısmı, yazılımcının hayal gücüne kalmış. Mesela yazdığımız uygulamanın, görme engelliler için de kullanılabilir olmasını isteyebiliriz. Veya okuma bilmeyen küçük yaştaki kullanıcıların da kullanabildiği uygulamalar yazabiliriz. Böyle durumlarda alıştığımız sınırların dışına çıkmamız gerekecektir. Şimdiden yola koyulmakta yarar olabilir.

Konuyu dağıtmadan asıl konumuza dönelim. Yazılan metnin okunması (Text To Speech) için .Net ile gelen kütüphaneler var. Aşağıdaki resimde görülen bu kütüphaneler, ihtiyacımızın büyük kısmını karşılamaktadır. Bu kütüphaneler içerisindeki SpVoice ve SpeechSynthesizer sınıfları yardımıyla, yazdığımız metinlerin okunmasını sağlayabiliriz. Daha önce geliştirilmiş olan Microsoft Sam, Mary ve Mike karakterleri insan sesini yeterince taklit edememesine rağmen başlangıç olarak iyi seviyedeydiler. Şimdiki favori olan Microsoft Anna karakteri onlardan daha doğal telafuza sahiptir. Bahsettiğim sınıflardaki telaffuz karakteri de budur.

Uygulamamızı geliştirmek için bir windows form projesi açıyoruz. Bu projeye aşağıda görülen DLL'leri referans olarak ekliyoruz.

Form tasarımımız aşağıdaki gibi olabilir. Senaryomuz şu şekilde. En üstteki combobox'taki örnek metinler seçilerek textbox'a yazılabilecek. Okuma hızı ve volume ayarlamaları trackbar yardımıyla yapılacak. Bunların yanında okuma işlemini başlatıp bitirecek butonlarımız da mevcut.

Form tasarımımızı da bitirdikten sonra kodlarımızı yazmaya başlayabiliriz. Unutmadan ilk olarak SpeechLib ve System.Speech.Synthesis isim alanlarını ekliyoruz. Kodlarımızı aşağıdaki gibi oluşturuyoruz.

3 türlü okuma söz konusu. Bunları teker teker ele alalım.

  • SpVoice tipinden örneklenmiş voice nesnesi okuma yapmakta.
  • SpeechSynthesizer tipinden örneklenmiş speaker nesnesi  okuma yapmakta. Bu nesne concurrent olarak çalışmakta.
  • SpeechSynthesizer tipinden örneklenmiş speaker nesnesi  okuma yapmakta. Bu nesne asenkron olarak çalışmakta ve bize okuma esnasında duraklatma, durdurma gibi işlemler yapma imkanı sunmaktadır.

3 farklı okuma şeklimiz olmasına rağmen bunlardan en anlamlısı asenkron okuma şeklidir. Çünkü diğer okuma şekillerinde, okuma bitene kadar programın diğer özelliklerinden faydalanılamamaktadır. Kodlamamız bittiğine göre programımızı test edebiliriz.

Başka bir yazıda görüşmek üzere.

Tags: , ,

Apr 18 2010

Design Patterns: Observer

Kategori: C# | Design Patterns | OOP | Yazılım Mimarisi   — Veli Sezer  

Merhabalar.
Bu yazımda sizlere davranışsal tasarım desenlerinden biri olan Observer Design Pattern'den bahsedeceğim. (Observer:gözlemci) Bu tasarım deseni, bir nesnenin durumunda meydana gelen değişikliklerden, başka nesnelerin haberdar edilmesini hedeflemektedir. Bu duruma örnek olarak, RSS yayını yapan web sitelerinde, yeni bir girdi yapıldığında, RSS takipçilerine bu girdinin gönderilmesi senaryosu örnek verilebilir.
Observer tasarım deseninde, en önemli nesneler takip edilen nesne (subject) ve gözlemci nesne (concrete observer)'lerdir. Bunlar arasında bire çok ilişki söz konusudur. Yani bir nesneyi, birden fazla nesne takip edebilir.
Observer tasarım deseninin UML şeması en basit haliyle aşağıdaki gibidir.


Nesnelerimizi teker teker ele alalım:
Subject : Gözlemcilerin takip ettiği nesnedir. (Bizim uygulamamızdaki Urun nesnesi)
Observer : Subject'te meydana gelen değişikliklerden gözlemcilerin haberdar edilmesini sağlayan nesnedir. Genellikle interface olarak tanımlanır. (Bizim uygulamamızdaki IMusteri nesnesi)
Concrete Observer : Subject'i takip eden gözlemciler. Bu nesne interface olarak tanımlanan observer nesnesini iplemente ederek, observer içerisindeki metodları uygularlar. (Bizim uygulamamızdaki Musteri nesnesi)

Konuyu teorik olarak anlattığımıza göre, kodlarımızı yazmaya başlayabiliriz. Öncelikle gözlemcilerin bilgilendirilmesini sağlayacak interface'i yazalım. Gözlemcilerin iki durumda bilgilendirilmesini istiyoruz. Fiyat ve stok durumlarından haberdar etmek adına 2 tane metod yazıyoruz.

Daha sonra takip edilecek olan nesnemizi yazıyoruz. Burada stok adedi ve fiyat bilgileri değiştiği takdirde müşterilerin bilgilendirilmesini hedeflediğimiz için, özelliklerin (property) set blokları içerisinde uygun koşullar sağlandığında müşterilerin bilgilendirilmesini sağlayan metodları çağırıyoruz.

Ayrıca bu sınıf içerisinde, IMusteri tipinden veri tutan generic list ve bu listeye, ürünü takip eden müşterileri ekleyip silmeye yarayan metodlarımızı yazıyoruz. Daha sonra, foreach döngüsü yardımıyla, listedeki bütün elemanların teker teker bilgilendirilmelerini sağlıyoruz.

Subject tipini takip edecek olan nesnemizi yazmaya sıra geldi. Bu nesne, IMusteri tipini iplemente eden Musteri isimli tipimiz.

Temel nesnelerimizi yazdığımıza göre istemcimizi temsil eden kodlarımızı yazabiliriz. Bunun için 2 adet müşteri tanımlayıp ürün nesnesini takip edenler listesine ekliyoruz. Daha sonra ürün nesnemizin özelliklerinde güncellemeler yapıyoruz.

Ürünün fiyatında düşme olduğunda, veya stok miktarı 10'un altına düştüğünde müşterilerin bilgilendirilmesini sağlıyoruz. Uygulamamızı çalıştırdığımızda aşağıdaki gibi bir çıktı elde ederiz.

Observer tasarım desenini ele aldığımız bu yazının sonuna geldik. Başka bir yazıda görüşmek üzere.

Tags: , , , ,

Apr 1 2010

Design Patterns: Strategy

Merhabalar.
Bu yazımda tasarım desenleri serimizin bir başka halkası olan strateji tasarım deseninden (strategy design pattern) bahsedeceğim. Davranışsal desenlerden olan bu tasarım deseni şu amaçla kullanılır. Geliştirdiğimiz uygulamanın zamanla değiştiği ve yeni eklenen özelliklerin kolayca sisteme adapte edilmesi gereken durumlarda, sistem yönetimini kolaylaştırmak adına bu desen tercih edilebilir.
Daha anlaşılır olması adına biraz daha açalım. Elimizde her hangi benzer görevleri yerine getiren sınıflarımız olsun. Bu sınıfları ortak bir çatı (strateji tipi) altında birleştirip, belli bir standarda göre metodlaştırdığımızda, sistemimize eklenen yeni bir nesneyi sisteme adapte etmek kolaylaşacaktır. Yani yeni nesnemizi sistemin özelliklerine sahip hale getirmek için, yeni nesnemizi bu çatı altına almamız yeterli olacaktır. Burada bahsi geçen ortak çatı olarak, genellikle interface ve abstract sınıflar tercih edilmektedir. Sistemimizdeki sınıflara ulaşırken, aracı olarak bir tek sınıfı (context tipi) kullandığımızdan dolayı, her bir sınıfın nasıl çalıştığı ile ilgilenme zorunluluğu ortadan kalkmaktadır.

Uzatmadan uygulamamıza geçelim. Örneğimizde, elimizdeki bir diziye ait elemanları farklı şekillerde listelemek isteyelim. Hem farklı yolları tek bir yol ile temsil edeceğiz hem de sistemimizin genişleyebilirliğini garanti altına alacağız. Öncelikle listeleme işlemini yerine getirecek metodları standartlaştıran bir çatımız olması gerektiğini düşünüyoruz. Bunun için bir interface tasarlayıp, bu interface'i sınıflarımıza iplemente edebiliriz. IListeleyici isimli interface'imiz aşağıdaki metodlardan oluşmakta.

Daha sonra bu interface'i kullanan sınıfları yazabiliriz. Ben demo için, normal for ve foreach döngülerinin olduğu bir sınıf ve bunların paralel versiyonlarının olduğu başka bir sınıf yazıyorum. Tabi az önce oluşturduğumuz interface'i sınıflarımıza iplemente etmeyi unutmuyoruz.

Sıra geldi context tipimizi yazmaya. Context tipimizde, strateji tipimiz olan interface tipinden bir parametre alan yapıcı metoda (constructor) sahibiz. Bu parametre yardımıyla, işlemlerimizi yerine getirecek somut tipimizi (concrete type) belirliyoruz. Daha sonra, metodlarımızın içerisinde, içerik (context) tipimizden örneklenmiş nesne yardımıyla, asıl işlemleri yerine getirecek metodlarımıza erişiyoruz.

Bu sınıfları kullanacak olan üst katmanı şöyle kodlayabiliriz. Öncelikle içeriki (context) tipimiz olan Listeleyici tipinden bir örneklemeyle, kullanılacak somut (concrete) tipimizi belirliyoruz. İçerik tipinin metodlarını çağırdığımızda, dolaylı olarak somut tipimizin ilgili metodu çağırılacaktır. Görüldüğü üzere, buradaki kodu yazarken, somut tipimizde neler olup bittiği ile ilgilenmiyoruz.

Strateji tasarım deseni sayesinde,  hem kodlarımız belli bir standarda uygun olarak üretilmekte, hem de kodlaması ve okunması kolaylaşmaktadır. Programımız çalıştığında aşağıdaki gibi bir çıktı olacaktır.

Son olarak, mevcut sistemimizde yeni bir tip eklediğimizi varsayalım. Bunun için listeyi tersten listeleyen bir sınıf yazıyoruz.

Yeni tipimizin sistemde kolayca kullanılabilmesi için bu tipe, IListeleyici interface'ini uygulamak yeterli olacatır. Artık yeni tipimizi uygulayabiliriz.

Strateji tasarım deseninin amacını ve kullanımını ele aldığımız bu yazımızın sonuna geldik. Yeni bir yazıda görüşmek üzere.

Tags: , , , , ,

Mar 28 2010

Design Patterns: Facade

Merhabalar.
Bu yazımda sizlere, yapısal tasarım desenlerinden biri olan, facade desing pattern'den bahsedeceğim. Bu desenin kullanım amacı, istemcilerin sistemimizin alt parçaları olan sınıflar, servisler veya metodlarla direkt olarak ilişkiye geçmelerini engellemektir.  Bu desenin tasarımı şu şekildedir.

Sistemimizin alt parçaları, istemcilerin doğrudan kullanımına kapalıdır. İstemci ve alt sistemlerin ilişkisi başka bir katman (facade) tarafından yönetilmektedir. Böylelikle sistem güvenliği artırılmakla beraber, kullanım kolaylığı da artmaktadır. Sistem alt parçaları, tamamen birbirinden bağımsız olduğundan dolayı, her parça bu sistemden alınıp, başka sistemlere kolayca iplemente edilebilmektedir. Hatta bir alt sistem öğesi, birden fazla facade tarafından da kullanılabilme imkanına sahiptir. Facade katmanı sistem için yararlı olmasına rağmen, zorunlu değildir. Çünkü facade, sistemde asıl işi yapan katman değil, asıl işi yapan katman ile kullanıcı arasında çalışan bir ara katmandır. Her bir alt sistem, kendi içerisinde başarıyla çalışmaktadır. Bu nedenle, facade katmanı sistemden çıkarıldığında, alt sistemler çalışmaya devam edeceklerdir. Burada şunu da belirtmeliyiz. facade katmanı, alt sistemleri referans almasına rağmen, bunun tersi kesinlikle yanlıştır. Eğer, alt sistemler, facade katmanını rafarans alırlarsa, facade katmanının sistemdeki zorunluluğu artacaktır. Bu ise facade'ın kullanım mantığına aykırıdır.

Facade tasarım deseni, bir çok farklı tipteki uygulamalarda kullanılabilmektedir. Özellikle güvenlik önlemlerinin yoğun olduğu finansal uygulamalarda kullanılmaktadır. Kritik işlemlerin yapıldığı katmanlar ile kullanıcı ilişkisi, facade katmanı sayesinde dolaylı olarak sağlanmaktadır. Facade deseni bunun yanında, servis yönelimli mimarinin de bir parçası olabilmektedir. Biz de uygulamamızda buna benzer bir demo yapacağız.
Uygulamamızda, XML web servisi modelini kullanacağız. Bunun için öncelikle web servisleri ile ilgili yazımı okumanız faydalı olacaktır. Uygulamamızda, sayı ve yazı işlemlerini yerine getiren iki alt sistem öğesi bulunmatadır. Web servisi olarak çalışan bu iki alt sistemden aldığı verileri istemciye ileten üçüncü bir web servisimiz daha vardır. Bu servis, diğer iki servisi referans olarak eklemekte ve onlarla karşılıklı veri alış verişi yapmakadır.

Bu kadar teorik bilgiden sonra uygulamamızı kodlamaya başlayabiliriz. Öncelikle sayısal işlemleri yerine getirecek servisimizi yazıyoruz.

Diğer bir alt sistem parçamız ise yazı işlemlerini yerine getiren servisimiz.

Alt sistemlerin kodlanması bittikten sonra facade katmanını kodlayabiliriz. Öncelikle alt sistemlerimizi, facade katmanı olan projemize  referans olarak ekliyoruz. Bunun için, alt sistemlerin URL'lerini, facade katmanı olan projemizde Add Web Referance diyerek ekliyoruz. Referans ekledikten sonra facade katmanımızın doslaları aşağıdaki gibi olacaktır.

Facade katmanının kodlarını aşağıdaki gibi yazıyoruz. Kodlardan da anlaşıldığı gibi, bu katman, alt sistemlerin metodlarını tek bir çatı altında topladı ve tek bir yerden servis edilmesini sağlıyor.

Facade katmanını da kodladıktan sonra, artık istemci uygulamamızı yazabiliriz. Bunun için basit bir form projesi açıyoruz. İlk olarak yapmamız gereke şey, projeye sağ tıklayıp, Add Service Reference demek ve facade katmanının URL'ini girmek. Böylelikle facade katmanı olan projemizi, istemci uygulamamıza referans olarak eklemiş oluyoruz. Daha sonra formumuzun görünümüzü yazımızın sonunda görüldüğü şekilde tasarlıyoruz. Artık kodlarımızı yazabiliriz.

Projemiz çalışmaya hazır.

Görüldüğü gibi uygulamamız başarıyla çalışıyor. Başka bir yazıda görüşmek üzere.

Tags: , , , ,

Mar 26 2010

Design Patterns: Singleton

Merhabalar.
Bu yazımda sizlere yaratımsal tasarım desenlerinden biri olan Singleton Design Pattern'den bahsedeceğim. Bu deseni kullanmamızın nedeni ve kullanım şekli, Proxy Desing Pattern'e çok benzemektedir. Proxy'de olduğu gibi, burada da daha önce yaratılan nesnenin bir daha yaratılamaması gibi bir durum hedeflenmektedir.
Genel olarak yazdığımız sınıflarda public tanımlı yapıcı metodlar (constructor method) kullanıyoruz. Public olarak tanımlanan yapıcı metodlar sayesinde, new anahtar sözcüğü ile nesne örneklenebilmektedir. Ancak singleton tasarım deseninin temelinde, sınıfımızın yapıcı metodunun private olarak tanımlanması yatmaktadır. Bu yüzden bu sınıftan new anahtar sözcüğü ile nesne örneklenememektedir. New ile yapılan nesne örnekleme işlemi, bahsedilen sınıf içerisinde yapılmakta ve sınıf adı üzerinden bu na ulaşılmaktadır.

Singleton tasarım deseninin farklı bir kullanımı da şudur. Aynı çalışma zamanı (runtime) içerisince, bir sınıftan yaptığımız nesne örneklemelerinin hep aynı değeri vermesini isteyebiliriz. Uygulamamızı da bu çerçevede geliştireceğiz.

Genel olarak tasarım desenlerinde, ihtiyaca yönelik uygulama söz konusu olduğundan dolayı, öncelikle ihtiyacın belirlenmesi gerekir. Mesela şöyle bir senaryomuz olsun. Security.Cryptography isim alanında bulunan RijndaelManaged sınıfını kullanarak yaptığımız şifrelemelerde, bir adet anahtar (Key) ve bir adet de vektör (IV) şifreleme değerlerine  ihtiyacımız var. Bir veriyi şifrelemek ve çözmek için aynı anahtar ve vektör değerlerine ihtiyacımız var. Bir şifreleme uygulamasında, aynı anahtarve vektör değerlerini elde etmek için, singleton tasarım deseni tercih edebilirsiniz. Dilerseniz bu kısa bilgiden sonra uygulamamıza geçelim. Öncelikle SingletonKeyVector adında bir sınıf oluşturuyor ve aşağıdaki gibi kodluyoruz. Program ilk çalıştığı zaman, RijndaelManaged nesnesi üzerinden anahtar ve vektör değerlerini üretiyoruz. Daha sonraki çağırımlarda, if koşulu içerisindeki kodlar çalıştırılmayacağından dolayı, daha önce üretilen değerler döndürülecektir. Dikkat etmemiz gereken diğer noktalar, özelliklerimizin (property), sadece get metodu yer aldığından salt okunurdur (readonly).

RijndaelManaged sınıfı için anahtar ve vektör değerleri üreten sınıfımızı yazdık. Sıra geldi bu sınıfı kullanacak uygulamayı yazmaya. Öncelikle şifrelemek istediğimiz veriyi temin ediyoruz. Ben demo için krediKartiNo adında bir string nesnesini şifrelemek ve çözmek istiyorum. Bunun için aynı anahtar ve vektör değerleri kullanılacağını hatırlatayım.

Kod arasında da açıklamalar yapıldığı üzere, öncelikle veriyi şifreliyoruz. Bunun için CryptoStream ve SingletonKeyVector sınıfından örneklediğimiz nesneleri kullanıyoruz. Şifrelenen veriyi çözmek için de aynı yöntemi uyguluyoruz. Çözme işlemi için ise, yine SingletonKeyVector nesnesi üzerinden anahtar ve vektör değerleri elde ediyoruz. Uygulamamız çalışmaya hazır.

Görüldüğü gibi uygulamamız başarıyla çalışıyor. Ancak şöyle bir şüphemiz var. SingletonKeyVector sınıfı yardımıyla üretilen anahtar ve vektör değerlerinin aynı olduğundan emin olmalıyız. Hazır başlamışken bunu da deneyelim. Bunun için Program.cs dosyasını aşağıdaki gibi değiştirebiliriz.

Görüldüğü gibi anahtar ve vektör değerleri için farklı zamanlarda üretilen değerler bile tamamen aynı. Bu uygulamada, singleton tasarım deseninin yanında RijndaelManaged sınıfını da ele almış oldu. Yeni bir yazıda görüşmek üzere.

Tags: , , , ,