Factory Design Pattern

Factory pattern design patternler arasında en başta gelenlerden biri olması sebebiyle buradan başlayıp ileride bahsedebildiğim kadar çok design pattern'den bahsetmeye çalışacağım.

   

Factory pattern adındanda anlaşılacağı gibi bir creational pattern (diğer örnekleri; abstract factory, builder, stereotype etc.), yani nesne yaratmamızı ve yaratılacak nesneyi seçememize imkan veriyor. Gerçek hayata uygun bir senaryo ile konuyu anlatmaya çalışacağım.

   

Yukarıda gördüğünüz diagramda iki büyük yuvarlak var bunları Kırmızı: UI - Client , Yeşil: Logic olarak düşünelim. Clientimiz ekrana şekil çizdermek istiyor bunun için Rectange, Triangle, Circle class'larinin birinden nesne yaratmalı ve draw methodunu çağırmalı. Draw() methodunun IShape interface'I içinde olduğunu düşünelim. Triangle, Rectangle ve Circle class'lari Ishape'I implement etmiş ve Draw() methodunu içeriyor. Client basit bir şekilde Triangle t = new Triangle(); t.Draw(); şeklinde bir komut ile Triangle çizdirebilir. Ancak yarın eklenecek yeni bir şeklin çizdirilmesi için client kodunda değişiklik gerekir. Bu sorunu önlemek için client sadece IShape interface'ini ve Factory class'ini bilir. Factory class'I tüm Triangle Rectangle Circle gibi classlari bilir. Client, factory üzerinden create komutu ile beraber istediği türün ismini veya key değerini parametre olarak vererek factorynin bir nesne yaratmasını ister. Factory içinde yaratılan tüm nesneler Ishape'I implement ettiği için; factory, client'a IShape türünde bir nesne gönderir ve Client gelen nesnenin Ishape olduğu için Draw(); methodunu içerdiğini bilir, böylece Draw(); methodunu çağırarak ekrana yazdırabilir.

   

Bu sayede gelecekte yarataılacak diğer class'lar için client kodunda değişiklik gerekmez örneğin ileride Ellipse isimli bir class yaratmak istersek class'I yaratıp factory içinde değişiklik yapmamız yeterli olacak. Ellipse bir IShape olduğu için sorun çıkmadan ve çok az kod değişikliği ile sisteme eklenebilir. Client tarafında hiç bir ekstra kod yazmaya gerek kalmadan sisteme ekleme yapılmış olur.

   

Kodlara bakalım

   

   

Örneğin Ellipse class'ini eklersek aşağıdaki kod'a ulaşmış olacağız. Gördüğünüz gibi yeni bir class eklemek dışında tek değişiklik Factory üzerinde yapıldı ve Client'ta hiç bir değişiklik gerekmedi.

   

   

Bonus Part (Reflection)

   

Peki bu tip değişikliklerin sadece class eklemek ile tamamlanmasını ve Factory üzerinde kod değişikliği yapmak istemezsek nasıl yapabiliriz? OOP gereği bu yöntemi ben pek tercih etmesemde, c#'in (java etc. dillerde aynı özellikler mevcut) reflection ile bu işi yapabiliriz. Aşağıda gödüğünüz kod ile artık her eklenen IShape implement etmiş class otomatik olarak client tarafından kullanılabilir hale gelmektedir.

   

   

Yukarıda göreceğiniz. "FactoryPattern". + typeName ile nesne yaratmak istediğimiz class adını ifade ediyoruz. "FactoryPattern." yazmamın sebebi benim application'imin default namespace'I "FactoryPattern" ve yeni oluşturulacak IShape implement eden class'in FactoryPattern namespace'inde olduğunu varsayıyorum.


Kodlara aşağıdaki linkten ulaşabilirsiniz.


https://github.com/altinokdarici/DesignPatterns

Microsoft Azure Kişisel İzleme Projesi: RescueTime

Yapmak istediğim şey şu şekilde, Azure üzerinde bir TableStorage olacak, hakkımdaki bazı bilgileri orada saklayacağım mesela günde %kaç üretkenlikle yaşıyorum :), kaç adım atıyorum vs. Bunun için biraz extensible bir yapı kurmaya çalışacağım. Bu blogda konu RescueTime,

   

Bir software var adı RescueTime. Bu uygulamanın bir chrome extension'i var birde desktop uygulaması, yaptığı asıl iş şöyle; bilgisayarınızda ve browserinizda kullandığınız uygulama ve websitelerini takip ediyor ve bir takım istatistikler sunuyor. Bence çok faydalı bir uygulama, bu uygulamadan Daron Yöndem hakkında bir kaç yıl önce haberdar olmuştum. İlgili blog yazısına buradan ulaşabilirsiniz. Daron Yöndem'in blog yazısı aslında uygulamayı çok iyi bir şekilde anlatıyor, tekrar yapmaya gerek yok.

RescueTime'in birde api'i mevcut, oldukça kolay kullanıma sahip ve bize json olarak bir takım veriler sunmakta. https://www.rescuetime.com/developers adresinden detayları öğrenebilirsiniz. Kısaca bir key yaratıyorsunuz ve api'a http request yaparak json sonuclari alıyorsunuz. Şahsi görüşüm api çok başarılı değil ama iş görüyor.

   

Ben bu api'dan bilgileri alıp, Azure Storage table'a yazmak istiyorum. Bunun için bir Azure WebJobs yaratacağım ve bu günde bir kaç kez çalışarak rescuetime api'i ile konuşacak ve sonuçları Azure Table Storage'a kayıt edecek. Henüz planlamamış olsamda daha sonraki blog yazılarımda bu veriyi değişik şekillerde kullanacağım. Mesela blog üzerinde gösterebiliriz. (Sağ tarafta göreceksiniz.)

   

Solution açıyoruz ve içinize bir kaç tane proje ekliyoruz. Amacimiz biraz güzel bir yapı kurmak. Bugun rescue time verilerini loglamaya çalışacağız ancak yarın Fitbit vs. gibi başka kaynaklarla kendimize özel bilgileri loglayabileceğimiz bir sistem olsun istiyorum. Kaynak kodları indirmek için postun altında github linki bulabilirsiniz.

   

Solution Explorer

   

Projeleri tanıtalım:

  1. PersonalTracking.StorageRepository: Bu proje aslında bir class library ve amacimiz Azure Storage Table ile iletişim kurmak.
  2. PersonalTracking.Web: Bir web projesi, basit bir arayüz ile şimdilik verileri gösterebiliriz.
  3. PersonalTracking.WebJob: Bir web job projesi, belirlediğimiz aralıkta çalışacak ve istediğimiz işleri yapacak.

       

    WebJob projesinden başlayalm; yapmak istediğim çok basit bir Factory Pattern, IEngine isimli bir interface olacak ve içinde bir start methodu bulunacak.

       

    IEngine.cs
     

    Birde factory olacak, uygun engine'i döndürecek ve dinamik olarak Start methodunu çağıracağız.

       

       

EngineFactory.cs

   

Gördüğünüz üzere kod yeni başlayan arkadaşlara biraz standart dışı gelebilir. Reflaction vs birşeyler yazıyoruz ve IEngine'i implement alan tüm class'lari bize IEnumarable olarak geri döndürecek.

   

Eee yazdıkda ne oldu. Bunları WebJob üzerinden çağırmamız lazım. Geri dönen Ienumarable<IEngine> içindeki her instance için tek tek Start() methodu çağırılmalı.

   

Functions.cs

   

Gördüğünüz gibi listedki tüm instance'larin Start() methodunu invoke ettik.

   

RescueTimeEngine.cs

RescueTimeEngine class'i IEngine implement eden bir class ve amaci rescue time api'i ile konuşup. Verileri storage'a göndermek hatırlarsanız StorageRepository bizim Azure Storage işlerimizin yürüdüğü katmandı diyebiliriz.

   

Ve işlem aslında bukadar artık veriler table storage'a kayıt ediliyor.

   

RescueTimeLogs Table

   

Gördüğünüz gibi loglarımızı TableStorage'a kayıt ettik.

   

Devamında Fitbit engine yazarak konuya devam edeceğiz.

   

Kodlar: https://github.com/altinokdarici/PersonalTracking