<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Fehmi Can SAĞLAM</title>
	<atom:link href="http://fehmicans.net/blog/feed/" rel="self" type="application/rss+xml" />
	<link>http://fehmicans.net/blog</link>
	<description>- benim iki yüzüm -</description>
	<lastBuildDate>Wed, 02 May 2012 20:57:22 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.2</generator>
		<item>
		<title>Bir Neo4j denemesi: Twitter takipçi grafı</title>
		<link>http://fehmicans.net/blog/2012/05/02/bir-neo4j-denemesi-twitter-takipci-grafi/</link>
		<comments>http://fehmicans.net/blog/2012/05/02/bir-neo4j-denemesi-twitter-takipci-grafi/#comments</comments>
		<pubDate>Wed, 02 May 2012 20:46:14 +0000</pubDate>
		<dc:creator>canavar</dc:creator>
				<category><![CDATA[canavARGE]]></category>

		<guid isPermaLink="false">http://fehmicans.net/blog/?p=1083</guid>
		<description><![CDATA[Neo4j ile ilk karşılaşmam 2009 yılında olmuştu. O sıralar -henüz badem bıyıklılarla dolmamış en bir bilimsel ve teknolojik kurumumuzda- çeşitli veritabanlarına ait kullanım istatistiklerini saklamak üzere embed edilebilir bir veritabanı arıyordum. Bu süreçte bir hafta kadar bir süre Neo4j&#8217;e şans &#8230;<p class="read-more"><a href="http://fehmicans.net/blog/2012/05/02/bir-neo4j-denemesi-twitter-takipci-grafi/">Sonraki Sayfa &#187;</a></p>]]></description>
			<content:encoded><![CDATA[<p><a href="http://neo4j.org/">Neo4j</a> ile ilk karşılaşmam 2009 yılında olmuştu. O sıralar -henüz badem bıyıklılarla dolmamış en bir bilimsel ve teknolojik kurumumuzda- çeşitli veritabanlarına ait kullanım istatistiklerini saklamak üzere embed edilebilir bir veritabanı arıyordum. Bu süreçte bir hafta kadar bir süre Neo4j&#8217;e şans versem de gerek disk alanı, gerekse performans sorunları yüzünden BerkeleyDB&#8217;ye geçiş yapmıştım. Şimdi dönüp baktığımda asıl sorunun bir graf(Türkçe karşılığı çizge olarak geçiyor ama benim kulağıma pek aşina gelmedi. Bilen birileri beni düzeltirse sevinirim.) <a href="http://en.wikipedia.org/wiki/Graph_database">veritabanının</a> ne amaçla kullanılacağını o zamanlar bilmeyen bende olduğunu düşünüyorum.</p>
<p>Geçen zaman içerisinde Neo4j büyük bir gelişme gösterdi ve yaygınlaştı. Ben de bu popüler veritabanını tekrar kurcalamak istedim. Örnek uygulamamda kendi Twitter takipçilerimden başlayarak bir takipçi grafı oluşturmaya karar verdim. Uygulama benim takipçilerimi çekecek ve ve aramızda FOLLOWS ilişkisi ile Neo4j veritabanına kaydedecek. Daha sonra takipçilerimin takipçilerini çekecek ve aynı işlemi veritabanında olmayan kişi kalmayana dek devam ettirecek.</p>
<p>İşe önce Neo4j&#8217;i indirerek başladım. Konsol aracılığıyla sunucuyu herhangi bir sorunla karşılaşmadan başlattım. neo4j-shell ile sunucuya bağlanıp komutları biraz kurcaladım. Daha sonra dokümantasyonda gezerken Neo4j&#8217;in bir <a href="http://docs.neo4j.org/chunked/stable/rest-api.html">REST API</a> sağladığını fark ettim. Benzer bir <a href="https://dev.twitter.com/docs/api">REST API</a>&#8216;yi Twitter da sağladığı için uygulamayı bu API&#8217;leri kullanarak JavaScript ile geliştirmeye karar verdim.</p>
<p>Twitter, istenilen kullanıcının takipçilerinin ID listesini döndüren bir API sunuyor. </p>
<pre>

http://api.twitter.com/1/followers/ids.json?user_id=...
</pre>
<p>Belki tek sıkıntı saatte 150 sorgu sınırının olması. Yazdığım kod bu API aracılığıyla her bir kullanıcının takipçilerini çekiyor ve createNode fonksiyonu ile Neo4j içinde her bir kullanıcı için bir düğüm oluşturuyor. Kullanıcıların tekrarlanmasını engellemek için Neo4j&#8217;in <a href="http://docs.neo4j.org/chunked/stable/rest-api-unique-indexes.html">unique indexlerinden</a> faydalandım. İndexlenmek istenen veri ilk kez indexleniyorsa API&#8217;nin kendisi otomatik olarak bir düğüm oluşturuyor. Aksi halde yeni düğüm oluşturulmuyor. 7474. portta çalışan bir Neo4j sunucusu olduğunu varsayan kodu aşağıda paylaşıyorum. </p>
<p><script src="https://gist.github.com/2579695.js?file=twitter-graph.js"></script></p>
<p>Mevcut kod kullanıcıların yalnızca ID&#8217;lerini çekiyor. Tüm graf oluştuktan sonra ayrı bir kodun bu ID&#8217;lere ait ayrıntıları çekip düğümleri güncellemesini planlıyorum. Böylece aynı anda en çok 100 kullanıcının ayrıntılarını döndürebilen <a href="https://dev.twitter.com/docs/api/1/get/users/lookup">Twitter API&#8217;sini</a> de etkin kullanmış olacağım.</p>
<p>Elde bu graf olduktan sonra iki düğüm arasındaki en kısa yolu hesaplamak <a href="http://docs.neo4j.org/chunked/stable/rest-api-graph-algos.html">Neo4j ile oldukça kolay</a>. Ayrıca graf, <a href="http://en.wikipedia.org/wiki/Centrality">centrality</a> açısından da kolayca incelenebilecektir diye tahmin ediyorum.</p>
]]></content:encoded>
			<wfw:commentRss>http://fehmicans.net/blog/2012/05/02/bir-neo4j-denemesi-twitter-takipci-grafi/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Senkronize olmayan java.util.Set gerçeklemelerinin performans karşılaştırması</title>
		<link>http://fehmicans.net/blog/2012/04/29/senkronize-olmayan-java-util-set-gerceklemelerinin-performans-karsilastirmasi/</link>
		<comments>http://fehmicans.net/blog/2012/04/29/senkronize-olmayan-java-util-set-gerceklemelerinin-performans-karsilastirmasi/#comments</comments>
		<pubDate>Sun, 29 Apr 2012 19:49:10 +0000</pubDate>
		<dc:creator>canavar</dc:creator>
				<category><![CDATA[canavARGE]]></category>

		<guid isPermaLink="false">http://fehmicans.net/blog/?p=1052</guid>
		<description><![CDATA[Yine bir Pazar günü evde aylaklık edip uzun zamandır birikmiş olan Twitter favorilerimi eritmeye çalışırken hangi durumda hangi java.util.Set gerçeklemesinin kullanılması gerektiği konusunda net bir fikrim olmadığını farkettim. Bu sebeple senkronize olmayan java.util.Set gerçeklemelerini performans açısından karşılaştırarak dokümantasyonlarında yazan bilgileri &#8230;<p class="read-more"><a href="http://fehmicans.net/blog/2012/04/29/senkronize-olmayan-java-util-set-gerceklemelerinin-performans-karsilastirmasi/">Sonraki Sayfa &#187;</a></p>]]></description>
			<content:encoded><![CDATA[<p>Yine bir Pazar günü evde aylaklık edip uzun zamandır birikmiş olan <a href="http://twitter.com/#!/fehmicansaglam/favorites">Twitter favorilerimi</a> eritmeye çalışırken hangi durumda hangi <a href="http://docs.oracle.com/javase/7/docs/api/java/util/Set.html">java.util.Set</a> gerçeklemesinin kullanılması gerektiği konusunda net bir fikrim olmadığını farkettim. Bu sebeple senkronize olmayan <a href="http://docs.oracle.com/javase/7/docs/api/java/util/Set.html">java.util.Set</a> gerçeklemelerini performans açısından karşılaştırarak dokümantasyonlarında yazan bilgileri doğrulamak istedim. Yaptığım testte <a href="http://docs.oracle.com/javase/7/docs/api/java/util/HashSet.html">HashSet</a>, <a href="http://docs.oracle.com/javase/7/docs/api/java/util/LinkedHashSet.html">LinkedHashSet</a> ve <a href="http://docs.oracle.com/javase/7/docs/api/java/util/TreeSet.html">TreeSet</a> için temel Set işlevlerini(add, remove, contains, size ve iterator) 1,000,000 kez tekrarladım ve geçen süreyi ölçtüm. Elde ettiğim sonuçlar bu üç gerçeklemenin de dokümantasyonlarında yazdığı şekilde çalıştığını gösterdi. Sonuçları aşağıdaki tabloda paylaşıyorum. Süreler µs(1/1000ms) cinsindendir.</p>
<table>
<tr>
<th></th>
<th>add</th>
<th>remove</th>
<th>contains</th>
<th>size</th>
<th>iterator</th>
</tr>
<tr>
<td><b>HashSet</b></td>
<td>2039583</td>
<td>970396</td>
<td>1032553</td>
<td>4176</td>
<td>44500</td>
</tr>
<tr>
<td><b>LinkedHashSet</b></td>
<td>2158727</td>
<td>987442</td>
<td>1073558</td>
<td>11339</td>
<td>34027</td>
</tr>
<tr>
<td><b>TreeSet</b></td>
<td>4754283</td>
<td>4287016</td>
<td>4394679</td>
<td>12125</td>
<td>114829</td>
</tr>
</table>
<p>Tabloyu şöyle özetleyebiliriz. HashSet ve LinkedHashSet performansı birbirine oldukça yakın. Fazladan yönetilmesi gereken LinkedList sebebiyle LinkedHashSet add, remove ve contains işlevlerinde HashSet&#8217;e göre çok az da olsa kötü performans sergiliyor. Buna karşılık LinkedHashSet&#8217;in iterator performansı HashSet&#8217;e göre %30 kadar daha iyi. TreeSet ise gerçekten Set elemanlarının sıralanması istenmiyorsa yanına yaklaşılmaması gereken bir gerçekleme olarak kendini gösteriyor. </p>
<p><del datetime="2012-05-01T07:23:38+00:00">Bu sonuçlara bakarak ben varsayılan gerçekleme olarak LinkedHashSet ile yoluma devam etmeye karar verdim. Başka bir Pazar günü de senkronize olan gerçeklemelere bulaşmaya çalışacağım.</del></p>
<p>Bu arada <a href="http://implement.asyonturkcedegil.com/">http://implement.asyonturkcedegil.com/</a></p>
<p><strong><u>Güncelleme</u></strong><br />
Ahmet A. Akın ve Mehmet D. Akın&#8217;ın önerileriyle test kodunu ve sonuç analizini güncelledim. Testleri art arda 3 kez çalıştırıp sonuçları add, remove ve contains için ayrı tablolarda gösterdim. Süreler ms cinsindendir. Denemek isterseniz Ahmet A. Akın&#8217;ın biraz daha geliştirdiği test kodu <a href="https://gist.github.com/2556469">burada</a>. </p>
<table>
<tr>
<th><b><u>add testi</u></b></th>
<th>Test 0</th>
<th>Test 1</th>
<th>Test 2</th>
</tr>
<tr>
<td><b>HashSet</b></td>
<td>1021</td>
<td>563</td>
<td>697</td>
</tr>
<tr>
<td><b>LinkedHashSet</b></td>
<td>978</td>
<td>984</td>
<td>800</td>
</tr>
<tr>
<td><b>TreeSet</b></td>
<td>3830</td>
<td>3569</td>
<td>3837</td>
</tr>
</table>
<table>
<tr>
<th><b><u>remove testi</u></b></th>
<th>Test 0</th>
<th>Test 1</th>
<th>Test 2</th>
</tr>
<tr>
<td><b>HashSet</b></td>
<td>489</td>
<td>497</td>
<td>686</td>
</tr>
<tr>
<td><b>LinkedHashSet</b></td>
<td>749</td>
<td>789</td>
<td>550</td>
</tr>
<tr>
<td><b>TreeSet</b></td>
<td>3786</td>
<td>3440</td>
<td>3291</td>
</tr>
</table>
<table>
<tr>
<th><b><u>contains testi</u></b></th>
<th>Test 0</th>
<th>Test 1</th>
<th>Test 2</th>
</tr>
<tr>
<td><b>HashSet</b></td>
<td>264</td>
<td>261</td>
<td>418</td>
</tr>
<tr>
<td><b>LinkedHashSet</b></td>
<td>359</td>
<td>432</td>
<td>334</td>
</tr>
<tr>
<td><b>TreeSet</b></td>
<td>3331</td>
<td>3247</td>
<td>3245</td>
</tr>
</table>
<p>&nbsp;</p>
<p><u><i>Ahmet A. Akın:</i></u></p>
<blockquote><p>
Eğer ciddi bir bellek ve performans kaygım yoksa,<br />
- Ekleme sırası önemsiz ise HashSet<br />
- Ekleme sırası önemli ise LinkedHashSet<br />
- Nesnelerin doğal sıralanışı önemli ise TreeSet<br />
gönül rahatlığı ile kullanıyorum. Yani bu durumda hızdan çok işe göre yapıyı seçmek daha makul. Özel durumlar için ise özel kütüphaneleri tercih edilebilir. Guava, muhtelif primitive collections vs.
</p></blockquote>
<blockquote><p>Mikrobenchmarking&#8217;i bu devirde doğru yapmak neredeyse mümkün değil (<a href="http://www.parleys.com/#id=2103&#038;st=5">http://www.parleys.com/#id=2103&#038;st=5</a> <a href="http://wiki.jvmlangsummit.com/images/1/1d/PerformanceAnxiety2010.pdf">http://wiki.jvmlangsummit.com/images/1/1d/PerformanceAnxiety2010.pdf</a>). O nedenle kafayı küçük farklara takmamak iyidir derim. Sonuçta farklı işletim sistemleri, işlemciler ve JVM sürümleri ile testler yapılıyor. </p></blockquote>
<p><u><i>Mehmet D. Akın:</i></u></p>
<blockquote><p>
size() metodunu olcmek cok anlamli degil cunku hepsi de sadece nesnenin icindeki size ismindeki bir integerin degerini donduruyor, rakamlardaki farklilik gürültuden ibaret.
</p></blockquote>
<blockquote><p>Microbenchmarking cok ince bir is, ozellikle Java gibi JVM userinde calisan ve GC iceren bir ortamda islemci, isletim sistemi, JVM versiyonu ve daha baska bir cok etken sonuclari degistirebiliyor.</p></blockquote>
]]></content:encoded>
			<wfw:commentRss>http://fehmicans.net/blog/2012/04/29/senkronize-olmayan-java-util-set-gerceklemelerinin-performans-karsilastirmasi/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Herkes RESTful Web API tasarlayabilir</title>
		<link>http://fehmicans.net/blog/2012/04/06/herkes-restful-web-api-tasarlayabilir/</link>
		<comments>http://fehmicans.net/blog/2012/04/06/herkes-restful-web-api-tasarlayabilir/#comments</comments>
		<pubDate>Fri, 06 Apr 2012 19:40:28 +0000</pubDate>
		<dc:creator>canavar</dc:creator>
				<category><![CDATA[canavARGE]]></category>

		<guid isPermaLink="false">http://fehmicans.net/blog/?p=1028</guid>
		<description><![CDATA[Herkes RESTful Web API tasarlayabilir ama bazı kurallara uymak koşuluyla&#8230;
Geçenlerde Twitter&#8217;da kaynağını tam olarak bilemediğim fakat çok beğendiğim bir tweet dolaştı.
HTTP response codes for dummies. 50x: we fucked up. 40x: you fucked up. 30x: ask that dude over there. 20x: &#8230;<p class="read-more"><a href="http://fehmicans.net/blog/2012/04/06/herkes-restful-web-api-tasarlayabilir/">Sonraki Sayfa &#187;</a></p>]]></description>
			<content:encoded><![CDATA[<p><b>Herkes RESTful Web API tasarlayabilir <em>ama bazı kurallara uymak koşuluyla&#8230;</em></b></p>
<p>Geçenlerde Twitter&#8217;da kaynağını tam olarak bilemediğim fakat çok beğendiğim bir tweet dolaştı.</p>
<blockquote><p>HTTP response codes for dummies. 50x: we fucked up. 40x: you fucked up. 30x: ask that dude over there. 20x: cool.</p></blockquote>
<p>Kısmen usturuplu Türkçe çevirisi şöyle:</p>
<blockquote><p>Zor öğrenenler için HTTP durum kodları. 50x: biz sıçtık. 40x: sen sıçtın. 30x: şu karşıdaki elemana sor. 20x: tamamdır.</p></blockquote>
<p><a href="http://tr.wikipedia.org/wiki/HTTP_durum_kodlar%C4%B1">HTTP durum kodları</a> bundan daha iyi anlatılamazdı sanırım. Bu tweetten bir zaman sonra <a href="http://openmymind.net/">Karl Seguin</a>&#8216;in <a href="https://twitter.com/#!/karlseguin/status/185582971871428608">şu tweeti</a> geldi. Kısaca söylediği şuydu:   web servisiniz hataları neden 200 durum kodu ile döndürüyor? </p>
<p>Bu iki tweet RESTful Web API geliştiricileri için önemli ipuçları veriyor. Ben de kendi tecrübelerim ışığında bir RESTful Web API&#8217;nin nasıl tasarlanması gerektiğinden bahsetmeye çalışacağım. Anlatacaklarımın %100 geçerli ya da doğru olmasını beklemek büyük bir yanılgı olur. Bu sebeple bu yazıyı bir tür başlangıç noktası olarak değerlendirmenizi öneririm. </p>
<h3>Hangi durumda hangi <a href="http://en.wikipedia.org/wiki/Hypertext_Transfer_Protocol#Request_methods">HTTP metodu</a> kullanılmalı?</h3>
<table style="width:100%">
<tr>
<th>HTTP Metodu</th>
<th>Açıklama</th>
</tr>
<tr>
<td><b>HEAD</b></td>
<td>
HEAD metodu ile yapılan isteklere verilen yanıt içeriği boştur. Geriye yalnızca <a href="http://en.wikipedia.org/wiki/List_of_HTTP_header_fields">HTTP Yanıt Başlıkları</a> ve durum kodu döner. Bu metod ile servis sağlayıcı hakkında bilgi alınabilir ya da bir kaynağın varlığı doğrulanabilir.
</td>
</tr>
<tr>
<td><b>GET</b></td>
<td>
GET metodunu bir kaynağın ayrıntılarına ulaşmak için kullanabilirsiniz. Buna örnek olarak 1 ID&#8217;li kullanıcının bilgilerini verebiliriz.
</td>
</tr>
<tr>
<td><b>POST</b></td>
<td>
POST metodu ile servis sağlayıcı üzerinde yeni bir kaynak oluşturabilirsiniz. Yine örnek olarak yeni bir kullanıcı oluşturmayı verebiliriz. Kaynağı güncellemek için ben PUT metodunu öneriyorum. Bu sebeple genelde POST metodu ile kaynak ID&#8217;sini göndermeye gerek yoktur. ID, servis sağlayıcı tarafından oluşturulmalıdır.
</td>
</tr>
<tr>
<td><b>PUT</b></td>
<td>
PUT metodu ile servis sağlayıcı üzerindeki bir kaynağı güncelleyebilirsiniz. Hangi kaynağın güncelleneceğini belirtmek için kaynağın ID&#8217;si servis sağlayıcıya gönderilmelidir.
</td>
</tr>
<tr>
<td><b>DELETE</b></td>
<td>
DELETE metodunu bir kaynağı silmek için kullanabilirsiniz. Hangi kaynağın silineceğini belirtmek için kaynağın ID&#8217;si servis sağlayıcıya gönderilmelidir. ID belirtilmezse tüm kaynakların silinmesi de sağlanabilir. Ancak bu durum dikkatle gerçeklenmelidir.
</td>
</tr>
</table>
<p>HTTP metodlarını kullanırken dikkat edilmesi gereken belki en önemli nokta <u>HEAD ve GET metodlarının salt okunur olması gereğidir</u>. Başka bir deyişle HEAD ve GET metodları ile kaynak bilgilerini güncellememeli ya da yeni kaynak oluşturmamalısınız. Yazma işleri için POST, PUT ve DELETE metodlarını kullanmalısınız. Diğer yandan PUT ve DELETE metodları idempotent metodlardır. Bu sebeple art arda çağrılmaları sorun oluşturmaz/oluşturmamalıdır.</p>
<h3>URI&#8217;ler nasıl olmalı?</h3>
<p>Google&#8217;da arama yaparsanız bu konuda pek çok farklı öneriye/gerçeklemeye ulaşabilirsiniz. Ben de kendi önerilerimi sıralayacağım. Wikipedia&#8217;da yapılan <a href="http://en.wikipedia.org/wiki/Representational_state_transfer#RESTful_web_services">açıklama</a> oldukça güzel. Benim önerilerim de bu tabloya benzer olacak.</p>
<p><b>URI&#8217;leriniz ID dışında parametre içermemeli.</b><br />
Parametreleri URI içine yazdığınızda URI&#8217;leriniz yönetilemez bir hale gelecektir. Bir örnek vereyim:</p>
<pre>
GET /api/{TICKET}/{DOMAIN}/users/{ROLE}/
</pre>
<p>Bu API ile belli bir etki alanında(DOMAIN) belli bir role(ROLE) sahip olan kullanıcıların sorgulandığını varsayalım. TICKET parametresinin ise güvenlik amacılığıyla gönderilen bir anahtar olduğunu kabul edelim. Bu URI&#8217;nin istemci tarafında oluşturulması oldukça zordur. Bu sebeple ben ID parametresi dışındaki parametrelerin URI&#8217;de bulunmasını pratikte çok uygun bulmuyorum. Buna bir istisna olarak örnekteki TICKET parametresini verebilirim. Eğer TICKET parametresi her URI&#8217;de bulunacak ise (bu tür parametrelere statik parametre diyorum) bu URI&#8217;lerin istemci tarafında ortak bir kod ile oluşturulması pek zor olmayacaktır. Bunun diğer bir faydası da TICKET içermeyen istekler için doğrudan HTTP 404 döndürülebilmesine imkan sağlamasıdır. Sonuç olarak önerilerim doğrultusunda yukarıdaki URI şu hale gelmelidir.</p>
<pre>
GET /api/{TICKET}/users?domain=...&#038;role=...
</pre>
<p><b>URI&#8217;lerde büyük harf kullanılmamalı.</b><br />
Bu önerimin nesnel bir açıklaması yok ama genel kullanımda /dailySessions yerine /daily_sessions ya da /sessions/daily kullanımı daha düzgün ve kolay görünüyor.</p>
<h3>Hangi durumda hangi <a href="http://tr.wikipedia.org/wiki/HTTP_durum_kodlar%C4%B1">HTTP durum kodu</a> kullanılmalı?</h3>
<p>Yazının başında verdiğim tweet örneği durum kodlarını oldukça iyi açıklıyor. 50x durum kodları servis sağlayıcı tarafında bir hata olduğuna, 40x durum kodları istemci tarafında bir hata olduğuna işaret ediyor. 20x durum kodları ise isteğin başarıyla sonuçladığını ifade ediyor. Bu sebeple hata mesajları asla ve asla 20x durum kodu ile gönderilmemelidir. Hata türüne uygun durum kodu seçilerek hata mesajı bu durum kodu ile istemciye gönderilmelidir. Oldukça fazla sayıda durum kodu olsa da ben 200, 400, 403, 404 ve 500 durum kodlarını yeterli buluyorum. Ama belli durumlarda diğer durum kodlarını kullanma gereği olabileceğini de aklınızdan çıkarmayın derim. </p>
<table style="width:100%">
<tr>
<th>HTTP Durum Kodu</th>
<th>Açıklama</th>
</tr>
<tr>
<td><b>200</b></td>
<td>
İşlemin başarıyla gerçekleştiğini belirtir. Yalnızca başarı durumunda kullanılmalıdır.
</td>
</tr>
<tr>
<td><b>400</b></td>
<td>
İsteğin geçersiz olduğunu belirtir. Eksik bir parametre ya da parametrenin hatalı olması durumunda kullanmanızı öneririm.
</td>
</tr>
<tr>
<td><b>403</b></td>
<td>
İstemcinin bu kaynağa erişiminin yasak olduğunu belirtir. Kendi kendini açıklıyor.
</td>
</tr>
<tr>
<td><b>404</b></td>
<td>
İstenen kaynağın bulunamadığı anlamına gelir. Örnek olarak belirtilen ID&#8217;ye sahip kullanıcı yok ise bu kodu kullanabilirsiniz.
</td>
</tr>
<tr>
<td><b>500</b></td>
<td>
Servis sağlayıcıda beklenmeyen bir hata olduğunda bu kodu kullanmalısınız.
</td>
</tr>
</table>
<p>Durum kodu ile birlikte hata mesajı gönderme zorunluluğunuz bulunmasa da hata mesajı vermek API kullanıcılarının işini oldukça kolaylaştıracaktır. Bu sebeple 400, 403, 404 ve 500 durum kodları ile birlikte mutlaka hata mesajı dönmenizi öneririm.</p>
<h3>Yanıt hangi formatta olmalı?</h3>
<p>Yanıt için yeni bir format keşfetmenize inanın hiç gerek yok. JSON formatı hem güzel, hem parse edilmesi kolay, hem de çok fazla kütüphane desteğine sahiptir. Bu sebeple yanıtlarınızı aksi çok gerekli olmadıkça JSON formatında dönmenizi öneririm. </p>
<h3><a href="http://en.wikipedia.org/wiki/JSONP">JSONP</a> ve <a href="http://en.wikipedia.org/wiki/Cross-Origin_Resource_Sharing">CORS</a></h3>
<p>Bu iki yöntemin ayrıntılarına burada değinmeyeceğim ama geliştirdiğiniz API Javascript istemciler ile kullanılacaksa iki yönteme de destek vermeniz yerinde olacaktır.</p>
<p>Buraya kadar sabırla okuduğunuz için teşekkür ederim. Umarım faydalı olmuştur.</p>
]]></content:encoded>
			<wfw:commentRss>http://fehmicans.net/blog/2012/04/06/herkes-restful-web-api-tasarlayabilir/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Akka ya da Java ExecutorService ve Hazelcast ile kullanıcı bildirim kuyruğu</title>
		<link>http://fehmicans.net/blog/2012/04/03/akka-ya-da-java-executorservice-ve-hazelcast-ile-kullanici-bildirim-kuyrugu/</link>
		<comments>http://fehmicans.net/blog/2012/04/03/akka-ya-da-java-executorservice-ve-hazelcast-ile-kullanici-bildirim-kuyrugu/#comments</comments>
		<pubDate>Tue, 03 Apr 2012 15:19:53 +0000</pubDate>
		<dc:creator>canavar</dc:creator>
				<category><![CDATA[canavARGE]]></category>

		<guid isPermaLink="false">http://fehmicans.net/blog/?p=1015</guid>
		<description><![CDATA[Son zamanlarda Hazelcast&#8217;i dağıtık bir bildirim kuyruğu olarak kullanmak üzerine kafa yoruyorum. Amacım, farklı node&#8217;ların sistem çapındaki herhangi bir kullanıcı için üreteceği bildirimleri ortak bir kuyrukta tutmak ve bu bildirimleri gerekli zamanlarda işleyerek ilgili kullanıcıya ulaştırmak. Burada gerekli zaman ile &#8230;<p class="read-more"><a href="http://fehmicans.net/blog/2012/04/03/akka-ya-da-java-executorservice-ve-hazelcast-ile-kullanici-bildirim-kuyrugu/">Sonraki Sayfa &#187;</a></p>]]></description>
			<content:encoded><![CDATA[<p>Son zamanlarda Hazelcast&#8217;i dağıtık bir bildirim kuyruğu olarak kullanmak üzerine kafa yoruyorum. Amacım, farklı node&#8217;ların sistem çapındaki herhangi bir kullanıcı için üreteceği bildirimleri ortak bir kuyrukta tutmak ve bu bildirimleri gerekli zamanlarda işleyerek ilgili kullanıcıya ulaştırmak. Burada gerekli zaman ile bir kullanıcı için bildirim kuyruğu uzunluğunun belli bir sayıyı geçmesi ya da bu kullanıcı için kuyruktaki en eski bildirimin belli bir zamandan önce oluşturulmuş olmasını kastetmekteyim. Bu doğrultuda bir yandan hangi Hazelcast veri yapısını kullanacağımı düşünürken bir yandan da yazma işlemini ne şekilde yapabileceğimi araştırıyorum.</p>
<p>Önceleri bildirimleri saklamak için <a href="http://www.hazelcast.com/docs/2.0/manual/single_html/#Queue">Queue</a> kullanmayı düşündüm. Fakat yukarıda belirttiğim ihtiyaçları değerlendirince her kullanıcı için ayrı bir kuyruğa sahip olmam gerektiğini fark ettim. Her kullanıcı için ayrı bir Queue oluşturmak ve bunları yönetmek çok maliyetli olacağından ihtiyacıma en uygun veri yapısının <a href="http://www.hazelcast.com/docs/2.0/javadoc/com/hazelcast/core/MultiMap.html">MultiMap</a> olduğuna kanaat getirdim. MultiMap içinde kullanacağım anahtarlar kullanıcı adına(username), değerler de bildirimlere(Notification) karşılık gelecek. Bir kullanıcı için birden fazla bildirim olabilecek. </p>
<p>Sonraki adımda bildirim kuyruğundaki bildirim sayısı belli bir değerin üstünde ve en eski bildirimin oluşturulma tarihi belli bir zamandan önce olan kullanıcıları en performanslı şekilde nasıl elde edebileceğimi düşündüm. Hazelcast, <a href="http://www.hazelcast.com/docs/2.0/manual/single_html/#Map">Map</a> içindeki değerleri sorgulayabilmemiz için SQL benzeri bir <a href="http://www.hazelcast.com/docs/2.0/manual/single_html/#MapQuery">DSL</a> sağlıyor. Yalnız bu özellik MultiMap için geçerli değil. Bu sebeple veriyi denormalize etmeye ve kullanıcı kuyruklarına ait bilgileri(her bir kullanıcı kuyruğu için eleman sayısı ve en eski bildirim zamanı) ayrı bir Map içinde tutmaya karar verdim.</p>
<p>MultiMap içine yazacağım bildirimler için bir Notification sınıfı oluşturdum.<br />
<script src="https://gist.github.com/2292578.js?file=Notification.java"></script></p>
<p>Her bir kullanıcı için kuyruk bilgilerini saklamak amacıyla oluşturduğum QueueMetaData sınıfı ise şöyle:<br />
<script src="https://gist.github.com/2292578.js?file=QueueMetadata.java"></script></p>
<p>Daha sonra, bir ExecutorService kullanarak 6 farklı kullanıcı için 16384 adet rastgele bildirim oluşturan bir kod yazdım. Buradaki belki en önemli problem Map ve MultiMap için senkronizasyonu sağlamak idi. Hazelcast&#8217;in sağladığı anahtar bazlı <a href="http://www.hazelcast.com/docs/2.0/manual/single_html/#Lock">lock</a> mekanizması yaptığım testlerde sorunsuz çalıştı. Yazma işleminin ayrıntısı için aşağıdaki Producer koduna bakabilirsiniz.<br />
<script src="https://gist.github.com/2292578.js?file=(ExecutorService)Producer.java"></script><br />
Her bir Producer opCount kadar Notification oluşturmakta. Serialization için JSON kullanmaya karar verdim. Bu sebeple <a href="http://code.google.com/p/google-gson/">google-gson</a> kütüphanesinden faydalandım. Farklı sayıda Producer ile testler yaptım. Sonuçları yazının sonunda paylaşacağım. Producer sınıfının çalışabilmesi için gerekli olan LatchWorker ve HazelcastManager sınıflarının kodları aşağıda.</p>
<p><script src="https://gist.github.com/2292578.js?file=LatchWorker.java"></script><br />
<script src="https://gist.github.com/2292578.js?file=HazelcastManager.java"></script><br />
<script src="https://gist.github.com/2292578.js?file=Main.java"></script></p>
<p>Son olarak yazma işlemini <a href="http://akka.io/">Akka</a> ile de denemeye karar verdim. Bundaki amacım hem Akka&#8217;yı öğrenmek, hem de performansını ExecutorService ile karşılaştırmaktı. Producer sınıfına benzer şekilde bir Producer aktörü yazdım.<br />
<script src="https://gist.github.com/2292578.js?file=(Akka)Producer.java"></script></p>
<p>Producer aktörlerini yönetmek için yazdığım Master aktörü aşağıda. Bu aktörün görevi belirtilen sayıda Producer oluşturarak bunların opCount kadar Notification oluşturmalarını sağlamak.<br />
<script src="https://gist.github.com/2292578.js?file=Master.java"></script></p>
<p>16384 adet bildirim için farklı thread/actor sayıları ile Akka ve ExecutorService yöntemlerini karşılaştırdım ve işlem sürelerini ölçtüm. Süreler µs(1/1000ms) cinsindendir. Sonuçlar aşağıdaki tabloda yer almakta.</p>
<table style="width:61%">
<tr>
<th>
</th>
<th>
ExecutorService
</th>
<th>
Akka
</th>
</tr>
<tr>
<td>1 thread/actor</td>
<td>21173751</td>
<td>16442245</td>
</tr>
<tr>
<td>2 thread/actor</td>
<td>15759791</td>
<td>12487179</td>
</tr>
<tr>
<td>4 thread/actor</td>
<td>13337575</td>
<td>9462002</td>
</tr>
<tr>
<td>8 thread/actor</td>
<td>11633355</td>
<td>8432141</td>
</tr>
<tr>
<td>16 thread/actor</td>
<td>11394124</td>
<td>8362550</td>
</tr>
</table>
<p>Eğer bariz bir hata yapmıyorsam Akka yöntemi hem yönetim hem de performans açısından ExecutorService yöntemine göre daha önde. Hata bildirimi/öneri için yorumlarınızı beklemekteyim.</p>
]]></content:encoded>
			<wfw:commentRss>http://fehmicans.net/blog/2012/04/03/akka-ya-da-java-executorservice-ve-hazelcast-ile-kullanici-bildirim-kuyrugu/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Play! Framework ile asenkron HTTP</title>
		<link>http://fehmicans.net/blog/2012/03/23/play-framework-ile-asenkron-http/</link>
		<comments>http://fehmicans.net/blog/2012/03/23/play-framework-ile-asenkron-http/#comments</comments>
		<pubDate>Fri, 23 Mar 2012 19:31:21 +0000</pubDate>
		<dc:creator>canavar</dc:creator>
				<category><![CDATA[Bir player olarak canavar]]></category>

		<guid isPermaLink="false">http://fehmicans.net/blog/?p=999</guid>
		<description><![CDATA[Geçtiğimiz hafta içerisinde Play! Framework Türkiye Google Grubu&#8217;nda güzel bir tartışma konusu oldu. Ahmet Alp Balkan&#8216;ın başlattığı tartışmaya Erdem Ağaoğlu&#8216;nun yazdığı mail damga vurdu:) Aynı tartışmada konuyla ilgili uzun boylu bir yazı yazacağıma söz vermiştim. Bu yazıda, söz verdiğim konulara &#8230;<p class="read-more"><a href="http://fehmicans.net/blog/2012/03/23/play-framework-ile-asenkron-http/">Sonraki Sayfa &#187;</a></p>]]></description>
			<content:encoded><![CDATA[<p>Geçtiğimiz hafta içerisinde Play! Framework Türkiye Google Grubu&#8217;nda güzel bir tartışma <a href="https://groups.google.com/forum/?fromgroups#!topic/play-framework-tr/JRSDsDVlg_M">konusu</a> oldu. <a href="http://ahmetalpbalkan.com/">Ahmet Alp Balkan</a>&#8216;ın başlattığı tartışmaya <a href="http://agaoglu.name.tr/">Erdem Ağaoğlu</a>&#8216;nun yazdığı <a href="https://groups.google.com/d/msg/play-framework-tr/JRSDsDVlg_M/_TiCVn8sPr0J">mail</a> damga vurdu:) Aynı tartışmada konuyla ilgili uzun boylu bir yazı yazacağıma söz vermiştim. Bu yazıda, söz verdiğim konulara değinmeden Play! Framework ile asenkron işlerin nasıl yapıldığını örneklemeye çalışacağım. Söz vermiş olduğum &#8216;Neden non-blocking IO, neden Tomcat &#8220;eski teknoloji&#8221;, neden Java ile ancak bu kadar&#8217; konularına ise daha fazla zaman ayırarak ileriki bir zamanda değinmeyi düşünüyorum.</p>
<p>Anlatmaya çalışacağım örnek iki ayrı uygulamadan oluşmakta. İlk uygulama bir REST API sağlayıcı olmakla birlikte <u>kullanıcı oluşturan</u> ve <u>kullanıcı ayrıntılarını döndüren</u> iki API sağlıyor olacak. Diğer uygulama ise ilk uygulamanın sağladığı API&#8217;leri kullanacak. İlk uygulamaya &#8220;<b>Provider</b>&#8220;, ikinci uygulamaya &#8220;<b>Client</b>&#8221; diyeceğim.</p>
<p>Önce Provider içinde kullanıcıları saklamak üzere User modelini oluşturarak işe başlayalım.</p>
<p><script src="https://gist.github.com/2173771.js?file=User.java"></script></p>
<p>Sonrasında kullanıcı oluşturmaya ve istenilen kullanıcının ayrıntılarını döndürmeye yarayan API fonksiyonlarını yazalım. Bu fonksiyonlar Provider uygulamasında Provider controller&#8217;ı içinde yer alsınlar.</p>
<p><script src="https://gist.github.com/2173771.js?file=Provider.java"></script></p>
<p>routes dosyasını güncelleyerek yazdığımız API&#8217;ler için HTTP route&#8217;ları belirleyelim.</p>
<pre>
GET     /api/user                               Provider.getUser
POST    /api/user                               Provider.createUser
</pre>
<p>Dikkat edeceğiniz üzere iki API için de aynı route&#8217;u kullanacağız. Hangi API&#8217;ye ulaşmak istendiği ayrımını HTTP metodu(GET ya da POST) ile yapıyoruz.</p>
<p>Provider uygulamasını böylece tamamlamış olduk. Client uygulamasına HTTP metodlarını içeren bir enum ekleyerek devam edelim. Bu enum yapacağımız API isteklerini yönetmemizi kolaylaştıracak. Provider içine eklediğimiz User modelinin bir benzerini Client uygulamasına da eklememiz gerekiyor. Fakat bu kez JPA annotation&#8217;larına ihtiyacımız olmayacak çünkü kullanıcıları Client uygulamasında veritabanına kaydetmeyeceğiz.</p>
<p><script src="https://gist.github.com/2173771.js?file=HttpMethod.java"></script></p>
<p>Sırada Client uygulamasının kalbi ClientJob ve Client sınıfları var.</p>
<p><script src="https://gist.github.com/2173771.js?file=ClientJob.java"></script></p>
<p><script src="https://gist.github.com/2173771.js?file=Client.java"></script></p>
<p>Provider uygulamasını http://localhost:9001 adresinde çalıştırıyoruz. ClientJob sınıfı Provider uygulamasına HTTP isteğini yaptıktan sonra sonucu <a href="http://www.playframework.org/documentation/1.2/libs">Either</a> içerisinde döndürüyor. Böylece dönen cevap ya bir Throwable ya da bir User oluyor. Client uygulamasındaki fonksiyonlar geriye Promise döndürüyorlar. Dönen Promise herhangi bir controller içerisinde await fonksiyonuna verilebilir. Örnek olarak Client uygulamasında Application.index içerisinde bu fonksiyonları kullanalım. Önce bir kullanıcı oluşturalım, sonra bu kullanıcının ayrıntılarını isteyelim.</p>
<p><script src="https://gist.github.com/2173771.js?file=Application.java"></script></p>
<p>Çıktıda şu logu göreceğiz.</p>
<pre>
INFO  ~ Kullanıcı oluşturuldu: name:Foo surname:Bar
</pre>
<p>Örneği oldukça basit tutmaya çalıştım. Ancak <a href="http://4primes.com">4Primes</a> bünyesinde geliştirmekte olduğumuz KURAM(*) platformu da çok benzer bir yapı kullanmakta. Bu yapının oldukça karmaşık ve büyük ölçekli ortamlarda sorunsuz çalıştığını da belirtmek isterim. Umarım faydalı olmuştur.</p>
<p>(*): KURAM platformu bir tür Tümleşik Yönetim Bilgi Sistemi Platformu&#8217;dur. SSO, Kullanıcı ve Yetki yönetimi, Doküman Yönetimi, Log Yönetimi, Dağıtık Arama, Dağıtık Önbellek gibi özellikler sunmaktadır. KURAM hakkında yakın zamanda güzel yazılar yazabilmeyi umuyorum.</p>
]]></content:encoded>
			<wfw:commentRss>http://fehmicans.net/blog/2012/03/23/play-framework-ile-asenkron-http/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Memcached, Redis ve Hazelcast performans karşılaştırması</title>
		<link>http://fehmicans.net/blog/2012/03/18/memcached-redis-ve-hazelcast-performans-karsilastirmasi/</link>
		<comments>http://fehmicans.net/blog/2012/03/18/memcached-redis-ve-hazelcast-performans-karsilastirmasi/#comments</comments>
		<pubDate>Sun, 18 Mar 2012 08:29:27 +0000</pubDate>
		<dc:creator>canavar</dc:creator>
				<category><![CDATA[canavARGE]]></category>

		<guid isPermaLink="false">http://fehmicans.net/blog/?p=972</guid>
		<description><![CDATA[Ankara Yazılım Atölyesi Mart Etkinliği&#8216;nde Osman Üngür başarılı bir Redis sunumu yaptı. Sunumda gelen performans soruları üzerine Memcached, Redis ve Hazelcast ürünlerini kendi makinamda karşılaştırmaya karar verdim. Makina konfigürasyonum şöyle:

OS:        Mac OS X &#8230;<p class="read-more"><a href="http://fehmicans.net/blog/2012/03/18/memcached-redis-ve-hazelcast-performans-karsilastirmasi/">Sonraki Sayfa &#187;</a></p>]]></description>
			<content:encoded><![CDATA[<p><a href="http://ankara.yazilimatolyesi.org/ankara-yazilim-atolyesi-mart-2012-etkinligi/">Ankara Yazılım Atölyesi Mart Etkinliği</a>&#8216;nde Osman Üngür başarılı bir <a href="http://redis.io/">Redis</a> sunumu yaptı. Sunumda gelen performans soruları üzerine Memcached, Redis ve Hazelcast ürünlerini kendi makinamda karşılaştırmaya karar verdim. Makina konfigürasyonum şöyle:</p>
<pre>
OS:        Mac OS X Lion 10.7.3
İşlemci:   2.4 GHz Intel Core 2 Duo
Bellek:    4 GB 1067 MHz DDR3
Memcached: 1.4.13
Redis:     2.4.8
Hazelcast: 2.0.1
</pre>
<p>Memcached testi için <a href="http://code.google.com/p/spymemcached/">spymemcached</a>, Redis testi için <a href="http://code.google.com/p/jedis/">Jedis</a>, Hazelcast testi için <a href="http://www.hazelcast.com/docs/2.0/manual/single_html/#JavaClient">Hazelcast Native Java Client</a> kütüphanelerini kullandım. </p>
<p>Uyguladığım testte üç ürüne de 16 byte uzunluğunda bir String&#8217;i 131072 kez yazıp okudum ve geçen süreyi ölçtüm. Aynı testi her ürün için 1, 2, 4, 8, 16, 32, 64 ve 128 thread ile tekrarladım. Ürünleri ayrı bir sunucuda değil yine kendi makinamda çalıştırdım. Başka bir deyişle test uygulaması ve ürünler aynı makinada çalıştılar. Hazelcast için yaptığım testi Memcached istemcisi ve Hazelcast Java istemcisi ile tekrarladım. Aslına bakılırsa sonuçlar üç ürün için de tatmin edici oldu. Yorumlamadan önce sonuçları paylaşayım. Süreler µs(1/1000ms) cinsindendir.</p>
<table>
<tr>
<th></th>
<th>Memcached</th>
<th>Redis</th>
<th>Hazelcast<br />(Memcached client)</th>
<th>Hazelcast<br />(Native Java client)</th>
</tr>
<tr>
<td style="white-space:nowrap"><b>1 thread</b></td>
<td>19360279</td>
<td>14835892</td>
<td>29543484</td>
<td>35666415</td>
</tr>
<tr>
<td style="white-space:nowrap"><b>2 thread</b></td>
<td>12641400</td>
<td>12658706</td>
<td>19478145</td>
<td>20427113</td>
</tr>
<tr>
<td style="white-space:nowrap"><b>4 thread</b></td>
<td>9895999</td>
<td>10881512</td>
<td>15548886</td>
<td>15163085</td>
</tr>
<tr>
<td style="white-space:nowrap"><b>8 thread</b></td>
<td>8329887</td>
<td>10256922</td>
<td>12627350</td>
<td>11314341</td>
</tr>
<tr>
<td style="white-space:nowrap"><b>16 thread</b></td>
<td><b>7406795</b></td>
<td>11011977</td>
<td>10999531</td>
<td>9453769</td>
</tr>
<tr>
<td style="white-space:nowrap"><b>32 thread</b></td>
<td>8069577</td>
<td>11247586</td>
<td>10274323</td>
<td>8596793</td>
</tr>
<tr>
<td style="white-space:nowrap"><b>64 thread</b></td>
<td>9271224</td>
<td>11589525</td>
<td>9545511</td>
<td><b>8171127</b></td>
</tr>
<tr>
<td style="white-space:nowrap"><b>128 thread</b></td>
<td>10165508</td>
<td>12162828</td>
<td><b>9350156</b></td>
<td>8398450</td>
</tr>
<tr>
<td style="white-space:nowrap"><b>Ortalama</b></td>
<td><b>10642583</b></td>
<td>11830618</td>
<td>14670923</td>
<td>14648886</td>
</tr>
</table>
<p>Genel görünümde Redis&#8217;in thread sayısından bağımsız olarak aynı performansı sürdürdüğünü görebiliyoruz. Thread sayısı arttıkça Hazelcast performansındaki artışa dikkat etmek gerek. Talip Ozturk ve Fuad Malikov çok iyi iş çıkarmışlar. Native Java Client ile Hazelcast&#8217;in 32, 64 ve 128 thread sayısındaki performansının üstüne çıkabilen yalnızca 8, 16 ve 32 thread sayısında Memcached oldu. Testin başlangıcında ürünler arasında en az özelliğe sahip olan Memcached performansının çok daha üstün olmasını bekliyordum. Memcached&#8217;in ortalama performansı üstün olsa da yoğun concurrent ortamlarda zirvenin sahibi Hazelcast olarak görünüyor. Redis de güçlü özellikleri, performansı ve kararlılığı ile kendini gösteriyor.</p>
<p>Testi tekrarlamak isteyenler için kodları aşağıda paylaşıyorum. Yaptığım testteki eksikleri/hataları yorum olarak bekliyorum.</p>
<p><span id="more-972"></span></p>
<p><script src="https://gist.github.com/2070166.js"> </script></p>
]]></content:encoded>
			<wfw:commentRss>http://fehmicans.net/blog/2012/03/18/memcached-redis-ve-hazelcast-performans-karsilastirmasi/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Bora Gönül ile Fonksiyonel programlama dilleri üzerine bir söyleşi</title>
		<link>http://fehmicans.net/blog/2012/03/15/bora-gonul-ile-fonksiyonel-programlama-dilleri-uzerine-bir-soylesi/</link>
		<comments>http://fehmicans.net/blog/2012/03/15/bora-gonul-ile-fonksiyonel-programlama-dilleri-uzerine-bir-soylesi/#comments</comments>
		<pubDate>Thu, 15 Mar 2012 20:15:10 +0000</pubDate>
		<dc:creator>canavar</dc:creator>
				<category><![CDATA[Bir player olarak canavar]]></category>
		<category><![CDATA[canavar'ın sesi radyosu]]></category>

		<guid isPermaLink="false">http://fehmicans.net/blog/?p=927</guid>
		<description><![CDATA[Fonksiyonel programlama dilleri deyince ülkemizde akla ilk gelen isimlerden olan Bora Gönül ile kısa bir söyleşi yaptık. Bilgi dolu yorumları için kendisine tekrar teşekkür ederim.

Okuyucuların sizi daha iyi tanıması adına kendinizi kısaca tanıtır mısınız?
Merhaba. Adım Bora Gönül, 1974 doğumluyum. Yazılımla &#8230;<p class="read-more"><a href="http://fehmicans.net/blog/2012/03/15/bora-gonul-ile-fonksiyonel-programlama-dilleri-uzerine-bir-soylesi/">Sonraki Sayfa &#187;</a></p>]]></description>
			<content:encoded><![CDATA[<p>Fonksiyonel programlama dilleri deyince ülkemizde akla ilk gelen isimlerden olan <a href="http://www.linkedin.com/in/boragonul">Bora Gönül</a> ile kısa bir söyleşi yaptık. Bilgi dolu yorumları için kendisine tekrar teşekkür ederim.</p>
<ol>
<li><strong>Okuyucuların sizi daha iyi tanıması adına kendinizi kısaca tanıtır mısınız?</strong></li>
<p>Merhaba. Adım Bora Gönül, 1974 doğumluyum. Yazılımla ilgilenmeye ortaokul yıllarında Commodore-64 ve Amiga oyun introlarını kırıp kendi adımı yazmak niyetiyle başladım. Daha sonra İTÜ Elektronik ve Haberleşme Bölümü&#8217;nde okudum. Buna paralel çalışmaya başladım. Yaklaşık 17 senedir İstanbul&#8217;da IT sektorundeyim. Pek çok yerli ve yabancı firmada çalıştım. Şu anda da Software &#038; Solutions Architect olarak freelance çalışıyorum.</p>
<li><strong>Fonksiyonel programlama dilleri aslında çok uzun zamandır ortalardalar. Siz ne kadar zamandır fonksiyonel programlama dilleri ile ilgileniyorsunuz?</strong></li>
<p>Yazılım benim hem işim, hem hobim. Bu yüzden birçok farklı dilde uygulama geliştirdim. Imperative dil olarak Java, fonksiyonel programlama dilleri olarak Scala, Haskell, Erlang ve Javascript favorilerim. Bu tanışıklığımız da yaklaşık 15 sene önce Haskell ile başladı.</p>
<li><strong>Fonksiyonel programlama dillerine olan ilginizin sebebi nedir?</strong></li>
<p>Bu biraz matematiğe olan sevgimle ilgili. Ortaokulda okuduğum ilk kitapta gördüğüm &#8220;X=X+1&#8243; beni o kadar rahatsız etmişti ki ( 0=1 ?) kitabı hemen kapatmıştım. Sonra merakım ve arayışım devam etti. Üniversitenin ilk yıllarında Haskell ile tanıştım. Matematiği kullanabileceğim bir yazılım dili bulmak benim için heyecan vericiydi.</p>
<li><strong>Fonksiyonel dillerin diğer dillere(nesne yönelimli, mantıksal, prosedürel) kıyasla temel avantajları nelerdir? Bu dillerin günümüzdeki kullanım alanları hakkında bilgi verebilir misiniz?</strong></li>
<p>Oldukça derin bir soru oldu. En temel fark şu:<br />
 &#8211; Imperative dillerde (C, Java, vs) sonuç odaklıyız; değişkenler tutup onları güncelleyerek sonuca ulaşıyoruz.<br />
 &#8211; Applicative dillerde (Scala, Haskell vs) olayın kendisini ifade etmek için hesaplamalara (sonuçlara değil!) odaklanıyoruz.</p>
<p>Şimdi sorsanız kimse fonksiyonel bir dil bilmediğini söyleyecek, halbuki her gün kullandığınız fonksiyonel bir dil var: &#8220;Javascript&#8221; <img src='http://fehmicans.net/blog/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' />  JS&#8217;deki &#8220;fonksiyon alan fonksiyonlar, fonksiyon dönen fonksiyonlar, closure&#8217;lar, callback&#8217;ler, vs.&#8221; ne kadar güçlüler bir düşünün.</p>
<p>Diğer bir önemli fark FP(Fonksiyonel Programlama) dillerinde State olmaması. &#8220;Y=X+1&#8243;.  İşte bu, benim bildiğim matematik&#8230; </p>
<p>Bir başka artısı paralel programlama konusunda. Bir örnek vereyim: Yazdığımız kod kendi makinamızda çalışır ama production ortamında aynı şekilde çalışmaz (Benim makinamda çalışıyor sendromu). Peki bunun sebebi nedir? <u>Determinism = State * Parallelism</u>. Bizse non-deterministik; çalışması ortama bağlı olarak değişmeyen kod istiyoruz.</p>
<p>Nasıl yapacağız?<br />
- Parallelism istenen bir şey olduğuna göre State&#8217;i ortadan kaldıracağız. Bu konuyu okurlara bırakıyorum, başka bir sohbette detaylarını anlatırım. </p>
<p>Bir başka önemli katkı olarak applicative dillerde business logic kodun içinde kaybolmaz. Örnek:</p>
<p><b>Java</b><br />
<script src="https://gist.github.com/2046699.js?file=Ornek-1.java"></script></p>
<p><b>Scala</b><br />
<script src="https://gist.github.com/2046699.js?file=Ornek-1.scala"></script></p>
<p>Peki neden şimdi FP? FP esasında yeni bir şey değil. Ama bildiğiniz gibi Moore yasası doyuma ulaştı. Çekirdeklere daha fazla transistor sığdıramıyoruz. Bunun yerine çekirdek sayısını arttırıyoruz. Amacımız da bu çekirdekleri daha iyi kullanmamızı sağlayacak dilleri bulmak. FP dillerde state olmadığı için multicore&#8217;dan verim almak daha kolay. Elbette ki sürekli değişken yaratmanın yan etkileri var(bellek açısından) ama kullandığımız makinalarda en az 4GB RAM var. Bu konu dediğim gibi oldukça derin. Umarım cevabım biraz tatmin etmiştir sizi. Özetle FP yeni değil, eski ve değerli. Her alanda kullanılabilir. Web programlamadan, data mining ya da real-time sistemlere kadar&#8230;</p>
<li><strong>Scala, fonksiyonel programlama dillerinin en popülerlerinden biri olmakla beraber prosedürel ve nesne yönelimli programlama özelliklerini bir arada barındıran C++ diline benzer şekilde nesne yönelimli ve fonksiyonel programlama özelliklerini birlikte sunuyor. C++ oldukça başarılı olsa da hiçbir zaman prosedürel bir dil olan C dilinin önüne geçemedi. Nesne yönelimli diller konusunda zirvenin sahibi ise Java oldu. Sizce Scala bu bilgiler ışığında başarılı olabilecek mi?</strong></li>
<p>Object oriented programlamanın avantajı insan zihninin bir sorun karşısında olayı küçük<br />
parçalara ayırıp; detayları tek tek çözüp, sonrasında bunları birleştirebilme yeteneğini simgeliyor olması. Örnek olarak bir film sahnesinde cam ekran üzerinde aktörün bir treni tutup pek çok küçük parçaya böldüğünü ve sonra birleştirdiğini hayal edin.</p>
<p>FP ise apayrı bir dünya. Bildiğiniz tüm tasarım kalıplarını bir kenara koyun, bir de fonksiyonlar ve recursion(özyineleme) ile yapabileceklerinizi.</p>
<p>Bir soru: bana &#8220;while&#8221; control structure&#8217;ının kendisini OO bir dilde gerçekleyebilir misiniz? Scala&#8217;da gayet basit:</p>
<p><script src="https://gist.github.com/2046699.js?file=Ornek-2.scala"></script></p>
<p>Şu kodda bile High-Order Fonksiyonlar, Currying gibi kavramlar var ve bunlar applicative(kendini anlatıyor). Kısaca Scala ya da FP bir rakip değil aksine bir tamamlayıcı.</p>
<li><strong>Scala hakkında son zamanlarda, özellikle çok karmaşık olduğuna dair olumsuz yorumlar yayınlanıyor. Hatta bu yorumlar adeta bir karalama kampanyasına dönüşmüş durumda. Sizce yapılan yorumlarda doğruluk payı var mı? Scala gerçekten çok mu karmaşık?</strong></li>
<p>Evet Scala zor bir dil çünkü:</p>
<p>- FP lisedeki biri için kolay, imperative dil bilen (Java, C vs) biri için çok zor.<br />
- Type oriented programming (Varyans, Covariant, Contravariant) karışık.<br />
- Implicit conversionlar ilginç.</p>
<p>Sanki bu yeni bir gezegen bulmak gibi, keşfetmek için biraz zaman gerekiyor. Ama tadını alınca dünyaya geri dönmek istemiyorsunuz. Bir diğer problemse bu dünyada yalnız kalıyorsunuz. Bu açıdan eleştirilere katılıyorum. Düşünsenize ben kime, nasıl Scala anlatacağım, öğreteceğim ve birlikte ortak bir proje yapacağız? </p>
<li><strong>Sizce Türkiye’de gerek üniversiteler, gerekse kurumlar ve şirketler açısından fonksiyonel programlama dillerine gereken ilgi gösteriliyor mu?</strong></li>
<p>Kesinlikle hayır <img src='http://fehmicans.net/blog/wp-includes/images/smilies/icon_sad.gif' alt=':(' class='wp-smiley' />  Pek çok üniversitede Scala ile ilgili seminerler verdim. Hocalarımızın çoğu dahil FP ne demek Türkiye&#8217;de bilinmiyor. Tüm gençlere aynı şeyi söyledim. Yurt dışında çalışmak mı istiyorsunuz? En az bir FP dili öğrenin.</p>
<li><strong>Türkiye’de bilişim sektöründe fonksiyonel dillerin payı ne orandadır? Bu konuda kendini geliştiren bir üniversite öğrencisinin sektörde kendine yer bulma şansı nedir?</strong></li>
<p>Şu anda Türkiye&#8217;de odaklanılan konu Web + DB programcılığı. Henüz hatırı sayılır real-time yazılımlarımız bile yok.</p>
<p>İki örnek;<br />
- Uçakların inmesini kalkmasını sağlayan, sensor verilerini toplayan merkezi bir real-time sistem. FP ve Message Passing Concurrency (Erlang / Akka) için biçilmiş kaftan.<br />
- Kredi kartı alışverişi real-time data mining. Kim hangi sektörde ne oranda kredi kartı kullanıyor. Yine FP ve Data-Mining/Data-Flow için ideal.</p>
<p>Bu konuda gençler Türkiye&#8217;yi değil yurtdışını düşünsün. Orada Haskell, Erlang ve Scala çok aranıyor.</p>
<p>Bir de söyle bir yanlış anlama var. Genişleme daha çok makina demek değil. Aynı makinadan daha iyi verim almak demek. FP&#8217;ye bir de bu gözle bakmak lazım.</p>
<li><strong>Nesne yönelimli programlama dillerinden birine yeterince hakim bir geliştirici fonksiyonel programlama dillerinden birinde sizce ne kadar zamanda yeterli hale gelebilir?</strong></li>
<p>Hiç gelemeyebilir. İkisi apayrı, iki farklı dünya. Biri makinaların dünyası(Java, C altında assembly), diğeri matematiğin, kümelerin, monad, monoidlerin dünyası.</p>
<li><strong>Türkiye’de Scala eğitimi verdiğini bildiğiniz üniversiteler ya da kurslar var mı? Sizin bu konuda çalışmalarınız oluyor mu?</strong></li>
<p>Ben Scala ve FP eğitimi vermeyi çok istiyorum. Ama henüz böyle bir oluşuma ihtiyaç yokmuş gibi görünüyor. Keşke olsa&#8230; </p>
<li><strong>Play! Framework 2.0 çekirdeği radikal bir şekilde değiştirilerek Scala ile yeniden yazıldı. Bu konuda yorum yapmak ister misiniz?</strong></li>
<p>Evet Play!, Scala ile yeniden yazıldı. Nedenlerini sitesinde bulabilirsiniz. Yukarıda saydığım tüm nedenler orda var. Ayrıca FP ile yazılan kod çok daha basit ve elegant(asil) oluyor. Ne demek istediğimi FP yazınca anlayacaksınız.</p>
<p>Play şu anda TypeSafe&#8217;e katıldı. Martin ve ekibi bu konuda çok iyi yoldalar. Özellikle Akka çok doğru bir şekilde Erlang temellerini Scala&#8217;da implement etti. 2000&#8242;li yıllarda Spring bir gün defakto standard olacak dediğimde kimse inanmamıştı, bugün herkes CV&#8217;sine Spring yazıyor. Aynı şekilde Akka(Message Passing Concurrency), concurrent programlama için defakto standart olacak diye düşünüyorum. Lütfen kayıtlara geçin <img src='http://fehmicans.net/blog/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' />  </p>
<li><strong>Son olarak eklemek istediğiniz noktalar var mı?</strong></li>
<p>Ne yazık ki FP ya da Scala&#8217;yı Türkiye&#8217;de kullanırız diyemeyeceğim. Startup olgusu keşke bizde de oluşsa ve düşük maliyetli, cloud üzerinde çalışan Internet tabanlı uygulamaların sayısı artsa. Oyun sunucuları, bankacılık, sigorta sektorü, realtime engine&#8217;ler&#8230; Bunların hepsi için doğru adres FP, Scala ve Erlang.</p>
<p>Teşekkürler.
</ol>
]]></content:encoded>
			<wfw:commentRss>http://fehmicans.net/blog/2012/03/15/bora-gonul-ile-fonksiyonel-programlama-dilleri-uzerine-bir-soylesi/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Play! Framework önbelleğini güncel tutmak</title>
		<link>http://fehmicans.net/blog/2012/02/29/play-framework-onbellegini-guncel-tutmak/</link>
		<comments>http://fehmicans.net/blog/2012/02/29/play-framework-onbellegini-guncel-tutmak/#comments</comments>
		<pubDate>Wed, 29 Feb 2012 00:24:10 +0000</pubDate>
		<dc:creator>canavar</dc:creator>
				<category><![CDATA[Bir player olarak canavar]]></category>

		<guid isPermaLink="false">http://fehmicans.net/blog/?p=920</guid>
		<description><![CDATA[Bu videoda veritabanı kayıtları güncellendiğinde Play! Framework önbelleğini de güncellemek adına iki farklı yöntem öneriyorum. Bu yöntemlerin ilki Model sınıfında save metodunu override etmek, diğeri ise JPA olaylarını dinleyen bir plugin yazmak. Uygulamanın kodlarına buradan erişebilirsiniz. İyi seyirler!
Güncelleme (11 Mart &#8230;<p class="read-more"><a href="http://fehmicans.net/blog/2012/02/29/play-framework-onbellegini-guncel-tutmak/">Sonraki Sayfa &#187;</a></p>]]></description>
			<content:encoded><![CDATA[<p>Bu videoda veritabanı kayıtları güncellendiğinde Play! Framework önbelleğini de güncellemek adına iki farklı yöntem öneriyorum. Bu yöntemlerin ilki Model sınıfında save metodunu override etmek, diğeri ise JPA olaylarını dinleyen bir plugin yazmak. Uygulamanın kodlarına <a href="https://github.com/canavar/kolay" title="buradan">buradan</a> erişebilirsiniz. İyi seyirler!</p>
<p><strong><em>Güncelleme (11 Mart 2011)</em></strong><br />
<a href="https://groups.google.com/d/msg/play-framework-tr/bao-hmBIuDc/CP7MtjoL4RkJ">Play! Framework Türkiye Google Grubu</a>&#8216;nda <a href="https://twitter.com/ahmetalpbalkan">Ahmet Alp Balkan</a> şöyle bir yorumda bulunmuş. Buraya da not düşmek istedim.</p>
<blockquote><p>Bir noktada serializable alan metoda kabul ettirmek icin ArrayList olarak degistirmissiniz List olan bir variable&#8217;i. Neyin gelmedigini bilmediginiz durumlarda (ornegin JPA cogu metodu List donduruyor ama tipi soylemeyebiliyor, bu yuzden ArrayList yazamayabilirsiniz bu ornekteki gibi), butun list&#8217;leri (Serializable)&#8217;a guvenle cast edebilirsiniz, tum standard API List implementasyonlari serializable oldugu icin.
</p></blockquote>
<p><center><br />
<iframe width="480" height="360" src="http://www.youtube.com/embed/ieBPw9qW8vw" frameborder="0" allowfullscreen></iframe><br />
</center></p>
]]></content:encoded>
			<wfw:commentRss>http://fehmicans.net/blog/2012/02/29/play-framework-onbellegini-guncel-tutmak/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Play! Framework ile etkin önbellek yönetimi</title>
		<link>http://fehmicans.net/blog/2012/02/26/play-framework-ile-etkin-onbellek-yonetimi/</link>
		<comments>http://fehmicans.net/blog/2012/02/26/play-framework-ile-etkin-onbellek-yonetimi/#comments</comments>
		<pubDate>Sun, 26 Feb 2012 20:28:43 +0000</pubDate>
		<dc:creator>canavar</dc:creator>
				<category><![CDATA[Bir player olarak canavar]]></category>

		<guid isPermaLink="false">http://fehmicans.net/blog/?p=910</guid>
		<description><![CDATA[Bu videoda Play! Framework önbelleğini etkin yönetebilmek adına bir yöntem öneriyorum ve veritabanı istatistiklerini 5 dakikada bir yenilenecek şekilde önbellekte tutan bir örnek veriyorum. Yöntemin eksiklerini ya da hatalarını gidermek üzere yorumlarınızı okumaktan memnun olurum. Uygulamanın kodlarına buradan erişebilirsiniz. İyi &#8230;<p class="read-more"><a href="http://fehmicans.net/blog/2012/02/26/play-framework-ile-etkin-onbellek-yonetimi/">Sonraki Sayfa &#187;</a></p>]]></description>
			<content:encoded><![CDATA[<p>Bu videoda Play! Framework önbelleğini etkin yönetebilmek adına bir yöntem öneriyorum ve veritabanı istatistiklerini 5 dakikada bir yenilenecek şekilde önbellekte tutan bir örnek veriyorum. Yöntemin eksiklerini ya da hatalarını gidermek üzere yorumlarınızı okumaktan memnun olurum. Uygulamanın kodlarına <a href="https://github.com/canavar/kolay" title="buradan">buradan</a> erişebilirsiniz. İyi seyirler!<br />
<center><br />
<iframe width="480" height="360" src="http://www.youtube.com/embed/LFoarWNQp9w" frameborder="0" allowfullscreen></iframe><br />
</center></p>
<p><a href="http://groups.google.com/group/play-framework-tr/browse_thread/thread/c6c66522c5fa1984">Play! Framework Türkiye mail listesinde</a> konuyu tartışırken CacheManager sınıfını daha da iyileştirdik. </p>
<p><script src="https://gist.github.com/1931497.js?file=CacheManager.java"></script></p>
<p>Controller içerisinden istatistiklere erişmek için aşağıdaki kod yeterli oluyor.</p>
<p><script src="https://gist.github.com/1931497.js?file=Application.java"></script></p>
]]></content:encoded>
			<wfw:commentRss>http://fehmicans.net/blog/2012/02/26/play-framework-ile-etkin-onbellek-yonetimi/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Play! Framework ile indirmeyi durdur/sürdür desteği</title>
		<link>http://fehmicans.net/blog/2012/02/09/play-framework-ile-indirmeyi-durdursurdur-destegi/</link>
		<comments>http://fehmicans.net/blog/2012/02/09/play-framework-ile-indirmeyi-durdursurdur-destegi/#comments</comments>
		<pubDate>Thu, 09 Feb 2012 19:32:43 +0000</pubDate>
		<dc:creator>canavar</dc:creator>
				<category><![CDATA[Bir player olarak canavar]]></category>

		<guid isPermaLink="false">http://fehmicans.net/blog/?p=903</guid>
		<description><![CDATA[Şu sıralar geliştirmekte olduğum bir uygulamada kullanıcıların oldukça büyük dosyaları indirebilmelerini sağlıyorum. Dosya boyutları sıklıkla 1GB&#8217;ın üzerinde olabiliyor. Her indirme isteğinden önce uygulama, kullanıcının o dosyayı indirme yetkisi olduğunu doğruluyor ve doğrulama başarılı ise indirmeye izin veriyor. Diğer bir deyişle &#8230;<p class="read-more"><a href="http://fehmicans.net/blog/2012/02/09/play-framework-ile-indirmeyi-durdursurdur-destegi/">Sonraki Sayfa &#187;</a></p>]]></description>
			<content:encoded><![CDATA[<p>Şu sıralar geliştirmekte olduğum bir uygulamada kullanıcıların oldukça büyük dosyaları indirebilmelerini sağlıyorum. Dosya boyutları sıklıkla 1GB&#8217;ın üzerinde olabiliyor. Her indirme isteğinden önce uygulama, kullanıcının o dosyayı indirme yetkisi olduğunu doğruluyor ve doğrulama başarılı ise indirmeye izin veriyor. Diğer bir deyişle dosyalar statik olarak değil aksine dinamik olarak sunuluyor. Web sunucu olarak Apache HTTP proxy arkasında çalışan ve Play! Framework 1.2.4 içerisinde gelen <a href="http://netty.io/">Netty</a> HTTP sunucuyu kullanıyorum.</p>
<p>Dosya boyutlarının oldukça fazla olduğundan bahsetmiştim. Bu durumda kullanıcıların indirme işlemine herhangi bir sebeple oluşan kesintinin ardından kaldıkları yerden devam etmeleri büyük önem kazanıyor. Flashget ya da <a href="https://addons.mozilla.org/en-US/firefox/addon/downthemall/">DownThemAll!</a> gibi indirme yöneticileri kullanıcılarına bu imkanı veriyorlar. Fakat söz konusu süreç yalnızca istemci tarafında bitmiyor. Eğer web sunucu bu desteği vermiyorsa durdur/sürdür(pause/resume) işlemi gerçekleşemiyor. Bu işlem için HTTP protokolünün <a href="http://tools.ietf.org/html/rfc2616#section-14.35">Range başlığı</a> kullanılıyor. Ayrıca sunucunun istemciye Range başlığını kabul ettiğini belirtmek için <a href="http://tools.ietf.org/html/rfc2616#section-14.5">Accept-Ranges</a> başlığını göndermesi gerekiyor. Aslında tüm bu süreç hem Apache HTTP server hem de Netty server tarafından destekleniyor. Fakat dosyaları statik sunmadığınız zaman durum ne yazık ki değişiyor.</p>
<p>Play! Framework ile gelen renderBinary() metodu binary dosyaları istemciye gönderebilmeniz için hem yalın hem de çok kullanışlı bir özellik olsa da Range başlığı desteği sunmuyor. Konu üzerinde biraz araştırma yaptığımda kuyrukta bekleyen bir <a href="https://github.com/playframework/play/pull/320">pull isteğine</a> rastladım. Söz konusu yama renderBinary metoduna Range başlığı desteği ekliyor. Ancak yama henüz kuyrukta olduğundan en erken bir sonraki Play! Framework sürümüne dahil edilecek.</p>
<p>Durum böyle olunca kendi başımın çaresine bakmak durumunda kaldım. HTTP protokolüne uygun şekilde bir gerçekleme yaptım ve DownThemAll! ile başarılı sonuç aldım. Böylece kullanıcılarım birden fazla thread ile dosya indirme ve indirmeyi durdurup sürdürme imkanına kavuştular. Gereken kodları içeren bir gist hazırladım. Aşağıda paylaşıyorum.</p>
<p><script src="https://gist.github.com/1781977.js?file=Application.java"></script></p>
<p><script src="https://gist.github.com/1781977.js?file=PartialContent.java"></script></p>
]]></content:encoded>
			<wfw:commentRss>http://fehmicans.net/blog/2012/02/09/play-framework-ile-indirmeyi-durdursurdur-destegi/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

