WWETR - WWE Türkiye - WWE Turkey - TRWWE
Hoşgeldiniz . Kaliteli Hizmet İçin Üye Olunuz .
WWETR - WWE Türkiye - WWE Turkey - TRWWE
Hoşgeldiniz . Kaliteli Hizmet İçin Üye Olunuz .
WWETR - WWE Türkiye - WWE Turkey - TRWWE
Would you like to react to this message? Create an account in a few clicks or log in to continue.

WWETR - WWE Türkiye - WWE Turkey - TRWWE

WWETR - WWE Türkiye - WWE Turkey - TRWWEHoş geldin, .
Son Ziyaretiniz: Perş. Ocak 01, 1970
Mesaj Sayınız: 0

 
AnasayfaLatest imagesAramaKayıt OlGiriş yap

 

 Fluent Interface Örnegi

Aşağa gitmek 
YazarMesaj
Legend
Admin
Admin
Legend


Mesaj Sayısı : 134
Reputation : 10000
Kayıt tarihi : 14/11/10
Nerden : Bilebilirdim ?

Fluent Interface Örnegi Empty
MesajKonu: Fluent Interface Örnegi   Fluent Interface Örnegi EmptyPaz Kas. 14, 2010 2:46 pm

Fluent Interface Örneği

Fluent Interface kavramı ile ilk olarak bu sene Martin Fowler’ın bir yazısını okuyunca tanışmıştım. Hatta örnekte gösterdiği

Kod:
[b][i]TimeInterval meetingTime = fiveOClock.until(sixOClock);[/i][/b]



kodu beni oldukça etkilemişti. Tabi kısa bir an bir kendi yazdığım koda birde şekilde yazılan koda bakakaldım diyebilirim. Okunabilir kod deyip dururuz ya; bu kodu okuyunca “İşte okunabilir kod budur” dediğim anlardan biridir.
Duymayanlar,bilmeyenler aslında çok fazla birşey kaçırmıyor.Fluent Interface kısaca kodun okunulabilirliğini artırmak için kullanılan bir API tasarım stili diyebiliriz. Ne tasarımınıza bir esneklik katıyor, ne de daha az kod yazmanızı sağlıyor. Amacı kodun okunulabilirliğini arttırmak ki, bence bunu da çok iyi yapıyor.
Kullandığınız birçok kütüphanede de farketmesenizde bu şekilde tasarlanmış API’ler ile karşılaştığınızı düşünüyorum. Mesela benim aklıma gelenler .NET’de kullandığım Rhino Mocks,Ninject.. Java’da kullandığım Nonblocking IO,EasyMock.. gibi birçok kütüphane bu stil ile tasarlanmış. Dikkat edecek olursanız bu kütüphanelerde yazdığınız kod aynı satırda sırayla birbirini çağıran metodlar şeklindedir.(method chaining).
İlk karşılaştığımda oldukça etkilendiğimi söylemiştim. Tabi ne zaman böyle etkilensem hemen kendi kodumda kullanmak için yer aramaya başlarım. Fakat ne kadar uğraşsamda çok fazla uygulayabileceğim yer bulamamıştım. Fluent Interface’i kodun heryerine uygulamak biraz zahmetli ve gereksiz olabiliyor. Genelde en uygun kullanım şeklinin sınıfların,kütüphanelerin konfigürasyon işlemleri olduğunu düşünüyorum.(Fluent NHibernate buna çok güzel bir örnek.).
Lafı fazla uzatmadan örneğimize dönelim.Geçenlerde geliştirdiğim bir kodda Fluent Interface şeklinde bir sınıf yazmanın oldukça faydasını gördüm sizinlede paylaşayım.
Genelde bazı uygulamalarda ekranda seçtiğiniz bir seçeneğe göre bazı alanların,girilmesi gereken kontrollerin enable,visible… olması, bazılarının ise o seçeneğe göre disable,hidden… olması gerekir. Benimde yaptığım örnek kısaca bu tarz bir uygulamaydı. ASP.NET Webforms ile geliştirilen bu uygulamada ekranda bulunan bir adet DropDownList kontrolü ile yapacağınız işlem türünü seçiyorunuz. Ardından o işlem türüne göre ekranda bazı alanlar enable, bazı alanlar disable oluyor. Vede seçtiğimiz türe göre veritabanından bazı kontrolleri dolduruyoruz,kısacası bazı işlemleride yapıyoruz.






google_protectAndRun("ads_core.google_render_ad", google_handleError, google_render_ad);


Öncelikle akla ilk gelen yöntem seçtiğiniz kontrolün altında if-else kontrolü yapıp uygun seçeneğe göre uygun kontrolleri enable,disable edebiliriz. Fakat bu çözüm hem bu kodun diğer ekranlarda kullanılması, hemde esnekliği açısından hoş bir çözüm olmaz bu yüzden hemen aklımızdan çıkarıyoruz [Resimleri görebilmek için üye olun veya giriş yapın.]
Daha uygun olarak daha önceden bahsettiğim Table Driven Methods yöntemini kullanabiliriz. Bu şekilde if-else kontrollerinden kurtulup daha genel bir yapı tasarlamış oluruz ve bu yapıyı bu şekilde çalışan diğer ekranlarda da kullanabiliriz.


Kod:

[table]

[tr]
[td class=content][b][color=#006699]private[/color][/b] [b][color=#006699]void[/color][/b] ConfigureScreen() [/td][/tr][/table]
[table]

[tr]
[td class=number]02[/td]
[td class=content]{ [/td][/tr][/table]

[table]

[tr]
[td class=number]03[/td]
[td class=content]    screenState = [b][color=#006699]new[/color][/b] ScreenState(); [/td][/tr][/table]

[table]

[tr]
[td class=number]04[/td]
[td class=content]    ControlState onay =[b][color=#006699]new[/color][/b] ControlState(); [/td][/tr][/table]

[table]

[tr]
[td class=number]05[/td]
[td class=content]    onay.AddControlToEnable(pnlOnay); [/td][/tr][/table]

[table]

[tr]
[td class=number]06[/td]
[td class=content]    onay.AddControlToDisable(pnlItiraz); [/td][/tr][/table]

[table]

[tr]
[td class=number]07[/td]
[td class=content]    onay.AddControlToDisable(pnlYonlendirme); [/td][/tr][/table]

[table]

[tr]
[td class=number]08[/td]
[td class=content]    screenState.AddControlState(ONAY, onay); [/td][/tr][/table]

[table]

[tr]
[td class=number]09[/td]
[td class=content]    ControlState yonlendirme = [b][color=#006699]new[/color][/b] ControlState(); [/td][/tr][/table]

[table]

[tr]
[td class=number]10[/td]
[td class=content]    yonlendirme.AddControlToEnable(pnlYonlendirme); [/td][/tr][/table]

[table]

[tr]
[td class=number]11[/td]
[td class=content]    yonlendirme.AddControlToDisable(pnlItiraz); [/td][/tr][/table]

[table]

[tr]
[td class=number]12[/td]
[td class=content]    yonlendirme.AddControlToDisable(pnlOnay); [/td][/tr][/table]

[table]

[tr]
[td class=number]13[/td]
[td class=content]    yonlendirme.Do(()=>BirimleriYukle()); [/td][/tr][/table]

[table]

[tr]
[td class=number]14[/td]
[td class=content]    screenState.AddControlState(YONLENDIRME, yonlendirme); [/td][/tr][/table]

[table]

[tr]
[td class=number]15[/td]
[td class=content]    ControlState itiraz = [b][color=#006699]new[/color][/b] ControlState(); [/td][/tr][/table]

[table]

[tr]
[td class=number]16[/td]
[td class=content]    itiraz.AddControlToEnable(pnlItiraz); [/td][/tr][/table]

[table]

[tr]
[td class=number]17[/td]
[td class=content]    itiraz.AddControlToDisable(pnlYonlendirme); [/td][/tr][/table]

[table]

[tr]
[td class=number]18[/td]
[td class=content]    itiraz.AddControlToDisable(pnlOnay); [/td][/tr][/table]

[table]

[tr]
[td class=number]19[/td]
[td class=content]    itiraz.Do(() => UrunleriYukle([b][color=#006699]false[/color][/b])); [/td][/tr][/table]

[table]

[tr]
[td class=number]20[/td]
[td class=content]    screenState.AddControlState(ITIRAZ, itiraz); [/td][/tr][/table]

[table]

[tr]
[td class=number]21[/td]
[td class=content]    ControlState secim = [b][color=#006699]new[/color][/b] ControlState(); [/td][/tr][/table]

[table]

[tr]
[td class=number]22[/td]
[td class=content]    secim.AddControlToDisable(pnlYonlendirme); [/td][/tr][/table]

[table]

[tr]
[td class=number]23[/td]
[td class=content]    secim.AddControlToDisable(pnlOnay); [/td][/tr][/table]

[table]

[tr]
[td class=number]24[/td]
[td class=content]    secim.AddControlToDisable(pnlItiraz); [/td][/tr][/table]

[table]

[tr]
[td class=number]25[/td]
[td class=content]    screenState.AddControlState(DEFAULT, secim); [/td][/tr][/table]

[table]

[tr]
[td class=number]26[/td]
[td class=content]}[/td][/tr][/table]


Her durum için bir ControlState sınıfı oluşturuyoruz. Ona enable,disable etmesi gereken kontrolleri veriyoruz,ardından yapması gereken işlemleri söylüyoruz. Ardından bu sınıfı ekranı temsil eden ScreenState sınıfına ekliyoruz.
ScreenState adındaki sınıfımız ekranın bütün durumlardaki durumunu simgeliyor. ControlState ise belirli bir seçim sırasındaki durumunu simgeliyor. Sınıfları şuanda çok fazla düşünmeyin. Yukarıdaki gördüğünüz koddaki okunabilirliği, ve kodun yazılım şekline dikkat etmenizi istiyorum.
Bu kodda herhangi bir problem yok gayet güzel çalışıyor. Fakat birde olaya biraz daha akıcılık katıp Fluent bir API ile yukarıdaki kodu tekrar yazalım bakalım hangisi gözümüze daha hoş gözükecek [Resimleri görebilmek için üye olun veya giriş yapın.] Razz

Kod:

[table]

[tr]
[td class=content][b][color=#006699]private[/color][/b] [b][color=#006699]void[/color][/b] ConfigureScreen() [/td][/tr][/table]
[table]

[tr]
[td class=number]02[/td]
[td class=content]{ [/td][/tr][/table]

[table]

[tr]
[td class=number]03[/td]
[td class=content]    screenState = [b][color=#006699]new[/color][/b] ScreenState(); [/td][/tr][/table]

[table]

[tr]
[td class=number]04[/td]
[td class=content]    screenState [/td][/tr][/table]

[table]

[tr]
[td class=number]05[/td]
[td class=content]        .WhenStateIs(ONAY) [/td][/tr][/table]

[table]

[tr]
[td class=number]06[/td]
[td class=content]        .EnableControls(pnlOnay) [/td][/tr][/table]

[table]

[tr]
[td class=number]07[/td]
[td class=content]        .DisableControls [/td][/tr][/table]

[table]

[tr]
[td class=number]08[/td]
[td class=content]        ( [/td][/tr][/table]

[table]

[tr]
[td class=number]09[/td]
[td class=content]            pnlItiraz, [/td][/tr][/table]

[table]

[tr]
[td class=number]10[/td]
[td class=content]            pnlYonlendirme [/td][/tr][/table]

[table]

[tr]
[td class=number]11[/td]
[td class=content]        ); [/td][/tr][/table]

[table]

[tr]
[td class=number]12[/td]
[td class=content]    screenState [/td][/tr][/table]

[table]

[tr]
[td class=number]13[/td]
[td class=content]        .WhenStateIs(YONLENDIRME) [/td][/tr][/table]

[table]

[tr]
[td class=number]14[/td]
[td class=content]        .EnableControls(pnlYonlendirme) [/td][/tr][/table]

[table]

[tr]
[td class=number]15[/td]
[td class=content]        .DisableControls [/td][/tr][/table]

[table]

[tr]
[td class=number]16[/td]
[td class=content]        ( [/td][/tr][/table]

[table]

[tr]
[td class=number]17[/td]
[td class=content]            pnlItiraz, [/td][/tr][/table]

[table]

[tr]
[td class=number]18[/td]
[td class=content]            pnlOnay [/td][/tr][/table]

[table]

[tr]
[td class=number]19[/td]
[td class=content]        ) [/td][/tr][/table]

[table]

[tr]
[td class=number]20[/td]
[td class=content]        .Do(() => BirimleriYukle()); [/td][/tr][/table]

[table]

[tr]
[td class=number]21[/td]
[td class=content]    screenState [/td][/tr][/table]

[table]

[tr]
[td class=number]22[/td]
[td class=content]        .WhenStateIs(ITIRAZ) [/td][/tr][/table]

[table]

[tr]
[td class=number]23[/td]
[td class=content]        .EnableControls(pnlItiraz) [/td][/tr][/table]

[table]

[tr]
[td class=number]24[/td]
[td class=content]        .DisableControls [/td][/tr][/table]

[table]

[tr]
[td class=number]25[/td]
[td class=content]        ( [/td][/tr][/table]

[table]

[tr]
[td class=number]26[/td]
[td class=content]            pnlYonlendirme, [/td][/tr][/table]

[table]

[tr]
[td class=number]27[/td]
[td class=content]            pnlOnay [/td][/tr][/table]

[table]

[tr]
[td class=number]28[/td]
[td class=content]        ) [/td][/tr][/table]

[table]

[tr]
[td class=number]29[/td]
[td class=content]        .Do(() => UrunleriYukle([b][color=#006699]false[/color][/b])); [/td][/tr][/table]

[table]

[tr]
[td class=number]30[/td]
[td class=content]    screenState [/td][/tr][/table]

[table]

[tr]
[td class=number]31[/td]
[td class=content]        .WhenStateIs(DEFAULT) [/td][/tr][/table]

[table]

[tr]
[td class=number]32[/td]
[td class=content]        .DisableControls [/td][/tr][/table]

[table]

[tr]
[td class=number]33[/td]
[td class=content]        ( [/td][/tr][/table]

[table]

[tr]
[td class=number]34[/td]
[td class=content]            pnlItiraz, [/td][/tr][/table]

[table]

[tr]
[td class=number]35[/td]
[td class=content]            pnlOnay, [/td][/tr][/table]

[table]

[tr]
[td class=number]36[/td]
[td class=content]            pnlYonlendirme [/td][/tr][/table]

[table]

[tr]
[td class=number]37[/td]
[td class=content]        ); [/td][/tr][/table]

[table]

[tr]
[td class=number]38[/td][/tr][/table]


Yukarıdaki kodu ingilizce olarak okumaya çalışın. Mesela ikincisini sizin için ben okuyayım.Ekran durumu YONLENDIRME olduğunda pnlYonlendirme’yi enable et,pnlItiraz,pnlOnay disable et ve Birimleri yükle. Okunuşu diğerine göre daha akıcı değil mi? Peki okunuşu bizim için neden önemli?
Yukarıdaki kodda da gördüğünüz gibi Fluent Interface tekniği ile kodun okunulabilirliğini oldukça geliştirdik. Aslında küçük bir Internal DSL yaptık diyebiliriz. Uygulamamızın küçük bir bölümüne göre bir dil tasarladık yani.Fluent Interface olarak API geliştirmek için aslında çok değişik bir teknik yok. Metodların sonunda void yerine sınıfın kendisini döndürüyoruz. Bu şekilde noktadan sonra o sınıfın başka metodlarınıda çağırabiliyoruz. Özellikle sınıflara konfigürasyon yapılırken işimizi oldukça kolaylaştırdığını düşünüyorum.Fluent NHibernate bunun çok güzel bir örneği. XML konfigürasyon dosyalarından tamamen kurtulup Fluent Interface şeklinde NHibernate mapping konfigürasyonunu yapabiliyorsunuz.Fluent Interface tekniğinin aklınızın bir köşesinde bulunmasını tavsiye ederim.
Sayfa başına dön Aşağa gitmek
https://trwwe.forum.st
 
Fluent Interface Örnegi
Sayfa başına dön 
1 sayfadaki 1 sayfası
 Similar topics
-
» Basit Bir Abstraction Örnegi

Bu forumun müsaadesi var:Bu forumdaki mesajlara cevap veremezsiniz
WWETR - WWE Türkiye - WWE Turkey - TRWWE :: Konu Dışı :: Yazilim ve Programlama-
Buraya geçin: