Rails için jetty_rails güncellemesi

Merhabalar,

Bir önceki yazımızda rails için jruby kullanımından ve windows üzerinde rails uygulamalarının servis edilmesi hakkında bir yazı yazmıştık. Bu yazıda jetty_rails’in sürümünün biraz eski olduğundan (son güncelleme tarihi 2009-07-08 20:28) bazı problemle karşılaştığımı yazmıştım.

Bu yazıda sizlere bu problemleri nasıl ortadan kaldıracağımızı anlatmak istiyorum.

1. Öncelikle jetty-rails’i standart gem yöntemleriyle yüklüyoruz.

jruby -S gem install jetty-rails

(daha fazla…)

Rails için yazılım geliştirme ortamı

Merhabalar,

Ne zamandır arkadaşlarım rails için yazılım geliştirme ortamı sorup duruyorlar, aslında ortada çok fazla alternatif olduğu için kafa karışıklığına neden olabiliyor.

Son (bir windows sunucu da host etmek zorunda olduğumuz) projem de redcar + jruby 1.6.3 + rails 3.0.9 + mysql >5 (arabirim olarak mysql workbench) ortamında yazılım geliştirme gerçekleştirdim.

Neden redcar;

  • Netbeans Build-in debugger’ı code-complete özelliği ile tam bir editör ama 6.9.1′den sonra desteği yok.
  • Redcar’ın kısa yolları ve “snippet” lerine alışırsanız oldukça hızlı ve efektif şekilde uygulamanızı geliştirebilirsiniz.
  • Diğerlerini denemeyin bile :)

Neden MRI değil de jruby kullandığımı soracak olursanız, cevabı yukarıdaki parantez içerisinde yazdığım küçük cümlecikte saklı. Evet malesef rails için windows üzerinde yüksek TPS değerlerine erişebilecek bir sistem kurmak oldukça zor ve problemli. Bu nedenle jruby ile java‘nın bu getirilerinden faydalanmak istedim.

JRuby’nin bu gücünü kullanmak içinde bazı çalışmalarım oldu. GlassFish, Tomcat :) hatta IIS üzerinde koşturup, performans değerlerini inceledim. Tomcat ve IIS için pek olumlu konuşamayacağım, belki de ayarlarını tam yapamadığım için olabilir ama GlassFish gerçekten iyi bir performans grafiği çizdi. GlassFish’in tek kötü yanı çok büyük ve gereksiz birçok bileşen içermesi ama elbette bazı projelerin bu bileşenlere ihtiyacı olabilir, bu durumda tercih edilebilecek bir sunum ortamı olabilir.

Benim tercihim ise jetty oldu. jetty_rails adlı bir eklenti ile işler kolaylaşıyor fakat ne yazık ki eklenti oldukça eski bir sürüme ait bu nedenle bazı ufak tefek düzeltmeler yapmamız gerekiyor. Lafı çok uzattık bu düzeltmeleri daha sonra sizlerle paylaşırım.

Son söz olarak, rails uygulamanızı yazarken aşağıdaki maddeleri göz önüne almanızı tavsiye ederim;

  • Rails uygulamanızı kendiniz host etmeyin.
  • Rails uygulamanızı gerçekten kendiniz host etmeyin.
  • Rails uygulamanızı Linux bir sunucuda host edin. Linux için zilyon tane başarılı alternatifi deneyebilirsiniz.
  • Rails uygulamanızı Windows sunucuda host etmeyin.
  • Rails uygulamanızı Windows sunucuda host etmeyin, gerçekten.
  • Rails uygulamanızı Windows üzerinde host etmek istiyorsanız, jruby uyumlu olmasına özen gösterin. Host etmek istediğiniz zaman duruma göre glassFish veya jetty kullanabilirsiniz.

Kolay gelsin :)

Ruby ile Kyoto Cabinet – 5

Merhabalar,

Birkaç arkadaşım yazıları okuduktan sonra Kyoto Cabinet’in sorgu performansını merak etmiş. Bunun üzerine küçük bir çalışma ile sorgulama performanslarını sizlerle paylaşmak isterim.

Hemen sonuçları yazmakta fayda görüyorum :)

MySQL üzerinden daha önceki yazılarımda yer alan konfigurasyon ile (engine: Innodb, primary key üzerinden sorgulama yapılıyor.) 100 thread ile 1.000.000 kayit 48.56 sn’de sorgulanmıştır.

KyotoCabinet üzerinden daha önceki yazılarımda yer alan konfigurasyon ile (engine: Hash, ek parametreler DB::OCREATE | DB::GCONCURRENT ve key üzerinden sorgulama yapılmıştır) 100 thread ile 1.000.000 kayit 4.54 sn’de sorgulanmıştır.

Şaka değil gerçek.
(daha fazla…)

Ruby ile KyotoCabinet – 4

Merhabalar,

Bir KyotoCabinet yazısına daha hoşgeldiniz. Bugün sizlerle MySql’in 100 thread üzerinden “insert” yetenekleri ile kyoto cabinet’inkileri birbirleriyle karşılaştıracağız. Peki bunu neden yapıyoruz, çünkü bir önceki yazımızda tek thread üzerinden kyoto cabinet üzerine veri yazma işlemi mysql’a göre ~10 kat daha hızlı olduğunu gördük.

Bu durum, tüm transactional tablolarımızı kyoto cabinet’e taşımamıza neden olmasa bile, yazılım geliştirirken kullandığımız bir çok “log” tablolarını taşımamızın kapısını aralar diye düşünüyorum. Yazılım geliştirirken bu kayıtları için bir log tablosuna veya dosyaya yazarız. Fakat dosyaya attığımız kayıtları tekrar okumak veya istediğimiz kayıda erişmek istediğimizde problemlerle karşılaştığımız için genelde “log” tablolarını tercih ederiz. İşte bu tercihlerimizde, eğer bu testten de başarı ile geçerse, log işlemleri için (hatta belki daha fazlası için) mysql yerine kullanılabilir.

Veya tecrübe ile sabit, web sistemlerinin session yönetimi ve loglaması için kullanılabilir. Aklınıza bir soru gelebilir, çünkü session tablosunda sorgu atmak için kullandığımız tek alan SessionId’dir. Yani ID üzerinden yapacağımız tüm işlemlerde bu veri tabanı yapılarının klasik veri tabanı yapılarına göre çok daha hızlı olduğunu unutmayalım.
(daha fazla…)

Ruby ile KyotoCabinet – 3

Merhabalar,

Bir önceki yazımızda Ruby üzerinden KyotoCabinet’e 1.000.000 (1 milyon) veri girişini çok kısa bir sürede tamamlamıştık. Daha sonra içime bir kurt düştü, acaba mysql’de durum nasıldı? Yani aynı koşullar altında mysql veri tabanına 1.000.000 kayıdı kaç sn içerisinde yazabilecektim?

Makinanın özelliklerini bir önceki yazımızda vermiştim.

Bu işlemin testi için öncelikle kendimize oldukça hızlı olduğuna inandığım, KyotoCabinet’in Ruby arabiriminde olduğu gibi C dili ile yazılmış MySQL/Ruby bir arabirim kütüphanesi buldum ve 2.8.2 versiyonunu kurdum. Bununla beraber MySQLClient versiyonunun 5.1.41 olduğunu söylemeliyim.

Daha sonra key, value tutacağımız bir veri tabanı oluşturdum. Öncelikle MyISAM motorunu kullanan bir tablo oluşturdum ve testlerimi bu tablo üzerinde yaptım.

CREATE TABLE `kyoto_cabinet`.`simple_table` (
  `key` CHAR(12) UNICODE NOT NULL,
  `value` CHAR(12) UNICODE NOT NULL,
  PRIMARY KEY (`key`)
)
ENGINE = MyISAM
CHARACTER SET utf8 COLLATE utf8_turkish_ci;

(daha fazla…)

Ruby ile KyotoCabinet – 2

Merhabalar,

Bir önceki yazımıza kaldığımız yerden devam ediyoruz. Bu sefer Kyoto Cabinet’in insert (kayıt ekleme) performansını inceleyeceğiz.

Öncelikle bu bir performans çalışması olduğu için makinamın özelliklerini verelim;
- 2 x AMD Athlon x64 3800+
- 2 G Ram
- Ubuntu 10.04 LTS
- FileSystem ext4
- Ruby 1.8.7 (2010-01-10 patchlevel 249)
- KyotoCabinet 1.2.2
- KyotoCabinet ruby kütüphanesi 1.14

En azından bu özelliklerle yapılan bir test sizleri kodu kendi makinanıza alıp denemeniz için cezbedebilir. Sonuçta bir önceki yazıdan kurulum işlemleri uygulayıp sonrasında aşağıda belirteceğim kod parçasını uygulayacaksınız. Sonuçları benimle paylaşabilirsiniz.

require 'kyotocabinet'
include KyotoCabinet

DB::process('subscribers.kch') { |db|
  # resmi sitede yer alan örneklerde set_encoding olarak gösteriliyor fakat aslında tune_encoding olmalı.
  db.tune_encoding('utf-8')

  # Telco sektöründe çalıştığımız için, numara bir MSISDN'e benziyor degil mi :)
  start_number = 905000000000

  start_time = Time.now
  puts "sira;gecen_sure;toplam_gecen_sure"
  100.times { |index|
    first_loop_start_time = Time.now
    10000.times {
      start_number += 1

      # Evet alt satirda KyotoCabinet üzerinde "Insert" islemi yapıyoruz.
      db[start_number] = start_number
    }
    loop_elapsed = Time.now.to_f - first_loop_start_time.to_f
    total_elapsed = Time.now.to_f - start_time.to_f
    puts index.to_s + ";" + loop_elapsed.to_s + ";" + total_elapsed.to_s
  }

  puts "1.000.000 kayit eklenmistir. Toplam süre: " + (Time.now.to_f - start_time.to_f).to_s
}

ruby kyoto_test01.rb > output.csv ile çalıştırırsanız çıktı dosyasını bir office programında açar ve performans analizinizi daha hızlı yapabilirsiniz. Unutmadan uygulamayı Netbeans veya Scite gibi editörlerin üzerinden çalıştırmayın toplamda benim makinamda 3 sn gibi fazlalıklara neden oldular.

İşte benim makinam üzerindeki sonuçların bir özeti;
(daha fazla…)

Ruby ile KyotoCabinet

Merhabalar,

Uzun bir aradan sonra kendimde tekrar yazı yazabilecek enerjiyi bulabildim. Nasıl mı? Aslında ben de bilmiyorum. Yeni doğan kızım Nil (evet, artık benim bir kızım var, kendisi daha 22 günlük :) ) nedeniyle evde çok neşeli bir telaşımız var ama yine de bir cumartesi akşamı ben bu yazıyı yazabiliyorum.

Ayrıca bugünün cumartesi olması ve şu saatlerin de akşam olması ve artık bir kızımın olması nedeniyle ilk kez akşam gezintileri için “benden geçmiş” demek zorunda hissettim kendimi. :)

Neyse konumuza dönelim, konumuz Kyoto Cabinet‘in ruby’de kullanılması olacak. Öncelikle

Kyoto Cabinet nedir;
Aslında bilenler var ise Kyoto Cabinet, Tokyo Cabinet gibi, Memcache gibi yüksek performanslı non-relational (türkçe çevirisi için ‘ilişkisiz’ den daha iyi fikri olan söylesin) veri tabanı sistemidir. Limitleri oldukça yüksektir ve performans konusunda gerçekten dudaklarınızıda uçuklatabilir. Kesinlikle oracle, mysql veya postgre gibi relational (ilişkili) veri tabanı sistemleri ile kıyaslanmamadır. Bu elma ile armut kıyaslanması gibi olur.

Kyoto Cabinet aslında “Key” ve “Value” ikilisini bir veri tabanında (bir dosyada) tutmak ve yönetmek için yapılandırılmış bir kütüphanedir. Bir dosya üzerinde yer alan Key ve Value alanları farklı uzunluklara sahip ve farklı tiplere sahip olabilir. Ayrıca bu kayıtları B-Tree veya Hash olarak tutabilmektedir.

Peki hemen aklınıza bir soru gelebilir. Nedir bu B-Tree ve Hash denen arkadaşlar? Sayfaları ziyaret edin, kullanın öğnenin diyorum başka da birşey demiyorum. Yaptığınız işe göre, kullanmanız gereken algoritmaya göre seçeceğiniz yapı yazılım performasını etkileyen en büyük unsur olacaktır. Ve malesef bunların bir tanesi hepsini dövmüyor/dövemiyor.

Hadi Kyoto Cabinet kuralım
0- Linux’da çalışıyor. Benim kullandığım ubuntu üzerinden kurulumu anlatacağım.
(daha fazla…)

Diziler (Uzmanlar için)

Merhabalar,

Uzun süredir herhangi bir yazı yazmıyordum, arkadaşlar arasında konuşurken “neden yazmıyorsun” gibi sorulara maruz kaldım, “eee dedim yazacak pek bir şey kalmadıki, ben ruby veya yazılım ile ilgili konularda yazıyorum” dedim. “eğer herhangi bir konuda istek gelir ise o konuda yazarım ama, şimdilik böyle bir konu yok” dedim. Dedim de hemen cevabı yapıştırdılar suratımın orta yerine.. “Ruby dizileri gerçekten basit tutmuş, herhalde hız için.. Lisp veya fonksiyonel programlama dileri kadar esnek değil” dediler.. “Eneee” dedim :) bana yazı yazacak konu çıktı.

Şimdi öncelikle biraz konu ile ilgili kendimizi motive edelim; Neden dizi işlemleri bu kadar önemli ? Ya da diğer işlerden farkı ne olabilir ki ?

Öncelikle bir konuya açıklık getirmek gerekir, günümüzde yazılan programlar içerisinde pek çok durumda dinamik veya durağan veri kümeleri ile işlemler yapılıyor. Bu işlemler, yazdığımız programlar içerisinde performansı etkileyen en önemli etken olarak karşımıza çıkıyor. Ve günümüzdeki daha fazla veri üzerinden daha doğru bilgi edinme anlayışı nedeni ile dizilerin boyutları gün geçtikce artıyor ve üzerlerinde yapılan işlemler gün geçtik fazlalaşıyor, bu performans etkeni daha da önemli hale geliyor. Yanlış anlaşılma olmasın, burada bahsettiğim performans Şişirme Veri Girişi adlı yazıda bahsettiğim veri yoğunluğunun artması ile beraber ortaya çıkan performans kötüleşmesi.

Diziler üzerinde yapılacak işlemlerde öncelikle iki ana başlıkta değerlendirilmelidir;
1- Kolay kullanım,
2- En iyi algoritmanın kullanılması.

İkinci maddenin neden gerekli olduğu konusunda fazla söze gerek yok ama, birinci maddenin neden gerekli olduğu konusunda aklınızda sorular olabilir, bu soruları ortadan kaldırmak için şu şekilde bir açıklama yapabilirim. “Diziler üzerinde yaptığınız optimizasyonlar, algoritma seçimleri veya memory optimizasyonları” gerçekten zor ve uygulanması oldukça tartışmalı olabilir. Örneğin google’ın java dili için çıkardığı “Google Collections Library” buna örnek olarak gösterilebilir. Kolay kullanım ve entegrasyon yazılımcılar tarafından her zaman tercih edilir.

Peki Ruby tüm bunların karşısında bize güzel silahlar veriyor. Aslında tüm Ruby işlemlerinde olduğu gibi performans basitliğin gerisinde kalmış, yüzlerce kez söylediğim gibi “yazılımın çalışma hızı sonsuza giderken, geliştirme süresi sıfıra gitmeli” felsefesine ters değil.

data = [1,2,4,8,12,5,7,3,0,13,10,11,3]

# For..In
data.each { |x| puts "x=#{x}" }

# data içerisindeki tüm elemanları tek tek verilen
# blok içerisindeki işlemden geçirir ve sonuçlardan yeni bir dizi üretir.
puts data.collect { |x| x + x }

# For..In :) ile indexleri verir.. :) pek çok programlama dilinde
# karşılığı bulunmaz.
data.each_with_index { |x, index| puts "#{index}. eleman = #{x}" }

# 5'den büyük ilk kayıdı bulur.
puts data.detect { |x| x > 5 }

# 5'den küçük olanları true_data değişkenine,
# diğerlerini false_data değişkenine dizi olarak atar.
true_data, false_data = data.partition { |x| x < 5 }
puts true_data
puts false_data

# 5'den küçük olanları diziden çıkartır ve geri döner.
puts data.reject { |x| x < 5 }

# Varsayılan sıralama işlemi
puts data.sort

# Belirlenmiş kritere göre sıralama işlemi (string olarak sıralama)
puts data.sort_by { |x| x.to_s }
# veya
puts data.sort_by { |x| (x+5)/x }

Kolay gelsin.. :)

Regular Expression

Merhabalar,

Bugün yeni gelen bilgisayar masamın şerefine bir yazı yazmak istiyordum ama öyle boşu boşuna yazı yazamayacağım için arada sizlere regular expression’dan bahsetmek istiyorum :)

Öncelikle sizlerin de yazılım hayatınıza başlayalı 5~10 yılı geçtiyse artık etraf koddan geçilmez hale gelir. Her yerde başka kodlar, hepsinize siz yazmışsınızdır ama.. “kardeşim ne yazmışım yaa, bu kadar da olmaz ki”.. dersiniz. Daha sonrasında kendinizi birşeyler araken ve en önemlisi bulumazken bulacaksınız.. “ahh nereye koymuştum bunu salak şeyi..” dersiniz.. tekrar dersiniz.. ama bunu söylemenin bir etkisi yoktur, gene bulamazsınız.. gene bulamazsınız.

Ya da size bir iş verirler. RegEx (Regular Expression) kullanmanız gerekir.. Gerekir gerekir gerekmez demeyin. Örnek vermek gerekir ise, geçen gün Zodazone Türkiye’de belirli bir tabloda yer alan açıklama bilgilerini değiştirilmesi istendi üstlerden bir yerlerden (ne biliyim muhasebeden falan işte..).

Bize bir ofis dökümanı içerisinde tekil kod bilgisini ve yanında yeni açıklamasını gönderdiler.. Onlar oturmuş kasmış… hatta uğraşmış sabahlara kadar 150 civarındaki açıklamayı kafa patlatmışlar, düşünmüşler, taşınmışlar.. ve değiştirmişler.. Tabii ne zennetiniz sadece bunun için maaş alan adamlar bile mevcut.

Ehh tabii bu Tankut kardeşiniz oturup, 150 tane açıklama alanını tek tek yapacak hali yok. Deli miyim ben :) söz meclisten dışarı efenim :) Neyse şimdi bu dökümanı gönderdiler ya içerisinde sadece açıklama bilgisi bulunmuyor ki, kim bilir hangi düzenle yazdılar bu dökümanı diye bir düşünün bakalım.. Regular Expression olmadan adım atamazsın adım….

Neyse öncelikle güzel güzel açıklayalım bu RegEx nedir, ne değildir ?
RegEx, karakter yığınları içerisinde özel belirtilen karakter veya karakter kümelerini bulmak, diğerlerinden ayırmak için kullanılan oldukça gelişmiş bir kütüphanedir. Kullanımı biraz zordur, hemen kısa sürede alışmanız zor olabilir.

Öncelikle RegEx tanımlarını ve anahtar kelimelerini tanıyalım; (Kitap yazmıyoruz burada ona göre.. tüm özelliklerini yazmıyorum sadece çok kullandıklarımı)

Anahtar kelimeler:
^ : Satır başını ifade eder.
\n : Enter karakteri için kullanılır.
\t : Tab karakteri için kullanılır
[...] : Örnek: [aeıioöuü] sadece sesli harfleri bulunur. ‘[]‘ karakterleri içerisinde yer alan herhangi bir karaktere uyanları getirir.
[^...] : Örnek: [^aeıioöuü] sadece sessiz harfleri bulunur. ‘[^]‘ karakterleri içerisinde yer alan herhangi bir karaktere uymayanları getirir.
. : Yeni satır (\n) karakteri hariç herhangi bir karakteri ifade eder. Tek karakteri
\w : Herhangi bir alfanumeric veya numeric karakteri işaret eder. a..z, A..Z, 0..9
\W : \w’nin tersidir.
\d : \d herhangi numeric karakter.
\D : \d’nin tersi.
\ : bir sonraki karakter özel bir anlam ifade ediyorsa, bu özelliği iptal eder.

Destekleyiciler
? : Bir önceki karakterden bir tane var ise bulur.
+ : Bir önceki karakterden bir ve birden fazla var ise.
* : Bir önceki karakterden 0 ve birden fazla var ise.
{n} : Bir önceki karakterden n adet olanları bulur.
(…) : Gruplama işlemi yapar. ‘()’ içerisine yazılanlar grup olarak değerlendirilir.
| : ‘OR’ işlemi için kullanılır, 2 farklı RegEx bu şekilde bağlanabilir.

Opsiyonlar:
i : Büyük küçük harfe duyarlı olmaz.
m : Karakter katarını birden çok satırmış gibi düşünür.
s : Karakter katarını tek satırmış gibi düşünür.

Kolay gelsin.. :)

Hpricot Örneği

Merhabalar,

Geçmiş zaman olurki bir proje için internette yayınlanan videoların kaç kez görüntülendiğini öğrenmek isteyen arkadaşlar ile tanıştım, çok ısrar ettiler yaptım. Bazı siteler için süper basit ve hızlı olurken bazıları için uzun sürdü ama 5 site için görüntüleme bilgilerini 2 saat gibi uzun bir sürede yapmayı başardım. Öff bee çok uzun sürmüş harbiden… şimdi yazınca daha da uzun geldi… aman aman bir daha yapmam valla… bu nedenle sizler de tekrar tekrar uğraşmayın diye bu Tankut kulunuz bu yazıyı yazıyor. Sırf sizler için, reklamları tıklamanız için değil, adımı ağzınızda sakız yapmanız için değil.. sadece siz uğraşmayın diye.. heyttt bee hizmet etmeye geldik diye siyasi bir yaklaşım içerisinde bulunan ve hiç birşey yapmayanlar utansın..

Öfff öff gene gereksiz yazdım işte örnekler :)

Öncelikle bulduğumuz gösterim sayılarını (view count) html veya “,” gibi karakterler ayırmak için bir methoda ihtiyacımız var. İşte ‘remove_char’ methodu tam bu noktada isteklerimizi karşılıyor.

def remove_char(number)
  ret = ''
  number.to_s.split(//).each do |char|
    ret += char if char.to_i.to_s == char
  end
  ret
end

Öncelik google kardeşimizin olsun, google kardeşimiz video url’i aslında frame’lerden oluşuyor. Ve gösterim sayısının (video view count) bulunduğu frame’i üstün araştırmalarımın sonucunda buldum… :) url’de ‘videoplay’ yerine ‘videohosted’ yazıyorsunuz oldu bitti maşallah :).

require 'open-uri'
require 'hipricot'

# Sassy Girl (Chun-Hyang) Episode 5
video_url = 'http://video.google.com/videoplay?docid=1197987351381288347'
google_video = Hpricot(open(video_url.gsub('videoplay','videohosted')))
temp = google_video.search("//table[@id='statsshowmore']")
google_video_view = Hpricot(temp.innerHTML).search("//td")
view_count = remove_char(google_video_view[0]).to_i
puts view_count

Sonraki örneğimiz myspace’den olsun…

# Internet People!
require 'open-uri'
require 'hipricot'

video_url = 'http://vids.myspace.com/index.cfm?fuseaction=vids.individual&VideoID=2057681175'
myspace_video = Hpricot(open(video_url))
temp = myspace_video.search("//div[@class='userinfo']")
myspace_video_view = Hpricot(temp.innerHTML).search("//span")
view_count = remove_char(myspace_video_view[2]).to_i
puts view_count

Vur patlasın çal yahoo’dan gelsin örnek..!

# Eastern Promises
require 'open-uri'
require 'hipricot'

video_url = 'http://video.yahoo.com/video/play?vid=1145798&fr=&cache=1'
yahoo_video = Hpricot(open(video_site.url))
temp = yahoo_video.search("//div[@class='vd']")
yahoo_video_view = Hpricot(temp.innerHTML).search("//span[@class='bold']").inner_text
view_count = remove_char(yahoo_video_view).to_i
puts view_count

En son youtube kardeşe bakalım; ama bir saniye youtube kardeşle uğraşmaya gerek yok.. :)
“gem install youtube” yazın evinize gelsin :)

require 'youtube'

Kolay gelsin..

** Düzeltme kodlar muhtemelen artık çalışmıyordur. Sadece örnek olması açısından değerlendirin lütfen.

Dosya İşlemleri (Karşılaştırma)

Merhabalar,

Öncelikle karşılaştırma derken, nasıl bir karşılaştırma yapacağımızı anlatmalıyım. Performans işlemleri karşılaştırma kriterlerim içerisinde bulunmuyor, bundan hiç bahsetmeyeceğim. Ama kodun okunabilirliği, hızlı yazılması, hatalara karşı ne kadar duyarlı olduğu ve tabii ki en önemlisi tekrar kullanabilirliği.

Aslında bu son nokta yani ‘tekrar kullanılabilirlik’ başlı başına bir yazı konusu ama buna şimdilik pek değinmeyeceğim. Başlıkta yazdığı gibi dosya işlemlerini karşılaştıracağım.

Arşılaştırmayı sadece VBScript, JScript ve Ruby arasında yapacağım, neden mi ? hali hazırda yapmıştım da ondan.. bu yazıyı yazacağım diye oturup program yazmadım. Önce programları yazdım, sonra yazıyı yazmak aklıma geldi. Bu nedenle neden diye sormayın. :)

Ama belki daha sonraki zamanlarda Java ve C# versiyonlarının karşılaştırmalarını da eklerim.

Öncelikle sizlere problemden bahsedeyim.

Belirli bir server üzerinde ps ve txt (post script ve text) dosyaları online bir uygulama tarafından oluşturuluyor, daha sonrasında online uygulama üzerinden kullanıcı bu dosyaları temizlemeyi unutuyor ve dosya sisteminin şişmesi ile beraber performans problemleri ortaya çıkıyor. Bu nedenle dosyaların gün bazında ömürlerinin olmasına ve ömrünü doldurmuş olan dosyalarında sistem tarafından silinmesine, silme işlemi esnasında log almasını ve bu loglarında aynı ömür kuralına tabii olmasını istiyoruz… işte bu program bu işi yapacak.. günde bir kez çalışacak ve bu işlemi yapacak. Microsoft Windows sistemde çalışmasını istediğimiz için VBScript ve JScript’de (JavaScript’in bire bir aynı klonu) ve platform bağımsız olan Ruby’de yazıldı. İşte Ruby örneği;
(daha fazla…)

Ruby’de Mesajlaşma ve Methodlar

Merhabalar,

Bu yazımı aslında takip ettiğim bir kaç sitede yayınlanan blogları gördükten sonra yazma gereği duydum. Bahsettiğim bloglarda yer alan yazılar aslında basit anlamda Ruby’nin temel özelliklerinden bahsediyorlarda fakat bu yazılara çok farklı tepkiler geldi. Bu tepkiler içerisinde çok şaşıranlar.. hadi ya ben bunu bilmiyordum diyenler.. yaa demek böyle birşey varmış ama bu kötü vs..vs.. Ben de bu yorumları inceledikten sonra bu yazıyı yazmaya karar verdim.

Aslında konumuz Ruby’de sınıfların yapısı, özellikleri ile Ruby’nin sınıfları, kütüphaneleri ve bizim Component dediğimiz şeyleri nasıl gördüğüdür.

Öncelikle OO (Object Oriented) tüm dillerde olduğu gibi Ruby’nin sınıf tanımı Java’nın veya C#’ın sınıf tanımı ile aynıdır. Peki o zaman farklılık nerede :) ayrıntılarda.. şeytanın gizli olduğu yerde :)

public class HelloWorld extends ExampleSupport {

    private String execute() throws Exception {
        setMessage(getText(MESSAGE));
        return SUCCESS;
    }
}

Yukarıda belirtilen örnekte olduğu gibi execute isimli methodumuz private tanımlanmış, yani sadece HelloWorld sınıfı içerisinden kullanılabilir. Neden çünkü private…

peki bir de bunun benzerini Ruby’de gerçekleştirelim;

class HelloWorld < ActiveSupport
    private
    def execute
        SetMessage(GetText(MESSAGE))
        return SUCCESS;
    end
end

Yukarıdaki iki örnek birbirlerinin aynısı. Ama diyorum ya şeytan bu ayrıntılarda gizli elbetteki.. :) Tahmin ettiğiniz gibi Java dilinde herhangi bir esneklik yok tabiki.. private tanımladın.. private.. yok öyle yanar döner method tanımlama olayları...

Peki ya Ruby'de private olarak tanımlanmış bir methodu public yapabilirmiyiz.. elbette yaparsınız; private yerine public yazarsınız.. taaa taa oldu.. :) Diğer bir yöntem;

Parçalı sınıf (Partial Class) yönetimi ile yapılabilir.

class HelloWorld
    public
    def execute_public
        execute
    end
end

peki başka nasıl olur bu iş.. mesajlaşma ile olur.. şöyleki aslında bir methodu çağırmanın tek yöntemi o methodu direkt olarak çağırmak değildir. Ayrıca Reflection dediğimiz kavram ile de çağrılabilir (Java dünyasında da oldukça kullanılır).

helloWorld = HelloWorld.new
helloWorld.execute # Hata üretir.. execute halen private bir methodtur...
helloWorld.execute_public # Çalışır :)
helloWorld.send("execute") # Çalışır.. problem çıkarmaz.. Sınıfa execute adlı bir method çalıştırmasını söyler.
helloWorld.instance_eval("execute") # Çalışır.. problem çıkarmaz..

Görüldüğü gibi.. yazılımcıdır tüm kodların hakimi.. yoktur programlama dilinin mecburiyetleri.. :P

En son olarak benim tercih ettiğim yöntem; tabii private yerine public yazmak yerine.. :)

class HelloWorld
    public :execute
end

Yukarıda belirtilen bu yordam ile.. execute methodu artık public olmuştur.. hayırlı uğurlu olsun.. :D

Kolay gelsin..!

Ruby Değişken Özellikleri

Merhabalar,

Öncelikle bu kadar uzun bir süre yazı yazmak ilginç oluyor. Bir aydan fazla bir süredir, nokta koymadığım bu günlüğe birşeyler yazmak biraz yabancı geldi açıkcası.

Bu yazıyı yazmam için beni birazcıkta olsa gaza getiren sevgili Mehmet DURAN kardeşime buradan teşekkür etmek isterim.. şak şakk şakk şakk.. javaayyyyy diyorum sana Mehmet.. :)

Öncelikle bu yazıdaki konumuzu belirteyim; Ruby programlama dilinde değişkenlerin nasıl tanımlandığı ve değişkenler üzerinde tip dönüşümlerinin nasıl olduğu.

Ruby’de değişkenler tanımlanırken herhangi bir şekilde tip belirtmenize gerek yoktur. İsterseniz Java veya C#’da yaptığınız gibi yapabilirsiniz ama o zaman biraz ayıp olur.. yuhananırsınız.. ohaa artık diyenler olabilir. Şöyledir yani;

intValue = 5
strValue = 'Hobaaa'
arrValue = []
hashValue = {}
regValue = \.*\
classValue = MyClass.new

Öncelikle programlama dillerinde değişken tiplerinin dönüşümü ve bu tiplerin ele alınmasını iki soru altında toplanabiliriz; Bu sorular
1. Tipler arasındaki dönüşüm nasıl gerçekleşir?
2. Değişken üzerinde işlem yaparken tip önemlimidir?

Öncelikle 1. soruyu ele alalım; “1. Tipler arasındaki dönüşüm nasıl gerçekleşir?”
El cevap: Eğer değişkeninizi bir tipten öteki tipe hödöö hödöö diye gönderiyorsanız, kullandığınız dil dinamik tip dönüşümüne sahiptir demektir. Eğer hödö hödöö diye değil de, daha efendi bir şekilde (örnek: ‘String.valueOf(55)’) yapıyorsanız durağan tip dönüşümüne sahipsiniz demektir. Değişkenlerinizi bir tipten öteki tipe değiştiremiyorsanız, ohaaa sizin o kullandığınız şey programa dili değil çin işkencesi demektir.

Programlama dillerine göre dinamik ve durağan tip dönüşümüne sahip olan diller;
Dinamik: Ruby, Python..vb.
Durağan: Java(yyyy), C#….vb.

İkinci soruyu ele alırsak; “2. Değişken üzerinde işlem yaparken tip önemlimidir?”
El cevap: Eğer siz bir karakter ile sayiyi toplamak isterseniz veya benim bir değerim var ama inan ben bile bilmiyorum ne olduğunu öyle yanar dönerli birşey işte.. (Basic’den Variant, C’den void) diyebiliyor iseniz, sizin için değişkenin tipi pekde önemli değildir. Yani değişkenler ile değişken tipleri arasındaki bağlantı ‘zayıf’tır. Her değişkenin veya her işlemin tipi olmasına gerek yoktur, diyebilirsiniz. Ama dersenizki ‘hadeee canım, tipsiz tipsiz değişkenmi olur, tipli adamın tipsiz değişkeni olmaz’ derseniz, tüm değişkenleriniz ile değişken tipleri arasında ‘güçlü’ bir bağlantınız var demektir.

Güçlü: Ruby, Java(yyyy), C#, C++…vb.
Zayıf: C, Basic, Java(yyy)Script….vb.

Peki Ruby’de bunlar nasıl oluyor da oluryor diyeceksiniz şimdi; İşte böyle oluyor..;

intValue = 5
puts 5 + intValue # problem yok.
puts "5" + intValue # büüürrrstt nereye biraderr..
puts "5" * "5" # bürrsttt yok daha neler..
# bir string(a) ile numarayı(b) çarptığınızda, ruby sizin a'yi b kez tekrarlamak istediğinizi zanneder.
puts "5" * intValue # Olur, bunun ruby'de karşılığı vardır.

Kolay gelsin..!

JRuby 1.0 RC3

Merhabalar arkadaşlar,

Küçük bir yazı olacak, sadece sizlere JRuby’nin 1.0 Release Candidate 3 sürümünü duyurmak için bu yazıyı yazıyorum. Evet doğru duydunuz, JRuby takımı Microsoft’tan daha hızlı davranarak (yarış halen bitmedi, gerçi ortada bir yarış var mı onu da bilmiyorum ama :) ) RC3′de olsa 1.0 sürümünü dünyaya *nihayet* duyurdu.

Şimdi aklınızda soru işaretleri olabilir, Hemen sizlere JRuby’nin ne olduğunu anlatmaya çalışayım. Aslında sizler normal Ruby uygulamalarınızı yazıyorsunuz, çalıştırıyorsunuz..vs..vs. Fakat sonra canınız sıkılıyor, neden sıkılıyor bilmiyorum ama birden Ruby’de yazdığınız kodların Ruby’nin doğal ortamında değil de, Java Virtual Machine (JVM) üzerinde çalışmasını istiyorsunuz, nedenleriz şunlar olabilir;
- Performans amaçlı olabilir (bu konu tartışılır)
- Ruby’nin çalışmadığı fakat java’nın çalıştığı bir ortamda çalıştırmak için (Hangi ortam o ?? belki vardır, bilen varsa yazsın…)
- Müşterinizi ‘ben programı Java’da yazdım’ diye kandırmak için :)

galiba en geçerli neden bu sonuncusu :).

Ama sonuçta güzel, hoş ve desteklenmesi gereken bir olay. Ruby dili çok güzel ve akıcı bir yapıya sahip neden JVM’yi kullanmak istiyenler bu güzel dili kullanmaktan mahrum kalsınlar ki.. ciddiyim, espiri falan yapmıyorum, tamamiyle destekliyorum.

Rails kullanıcılarına önemli bir not, RoR altyapısı tamamiyle Ruby’de yazıldığı için JRuby yoluyla JVM üzerinde de dolayısı ile Java Application Server’lar üzerinde çalışabilir hale gelmiştir. Özellikle sağlam veri tabanı özelliklerini kullanan uygulamalarda bu sayede hız artışı sağlanabilir. (Henüz 1.0 RC3′ü inceleyemedim ama bazı kısıtlardan bahsediliyor fakat kesin bir şey söyleyemiyorum.)

Kolay gelsin…

Ruby ile Struct

Merhaba arkadaşlar,

Bugünkü yazımızda Struct ve OpenStruct yapılarından bahsedeceğiz. “Bu yapılara neden ihtiyacımız var ?”, “Var olan ‘class’ yapısı veya bu işlemlere benzer olan ‘Array’ ve ‘Hash’ yapılarını neden kullanmıyoruz ?”, “Bu kadar fazla öğrenmemiz gereken sınıf, yapı ve işlev varken neden bir de başımıza bu ikisi çıktı ?”, ve son olarak “Ne işimiz var kardeşim Struct ile falan, bunlar boş iş.. ne yapacan öğrenip de..!?” gibi soruları cevaplamak gerekir. Ama tüm bu sorulardan önce ben neden bu yazıyı yazıyorum onu anlatmalıyım sanırım. Bu yazıyı bu linkte yer alan bir yazıyı gördükten sonra yazmaya karar verdim. Bu yazıda blog sahibi arkadaş Ruby on Rails’de ActionMailler kullanımı sırasında kullanmış, çok da güzel kullanmış. Ben de kendi kendime ‘Ben de bunu bizimkilerle paylaşayım’ dedim. İyi ettim di mi ? ettim ettim.. :)

Hatta ve hatta çok da güzel bir snippet’da mevcut. Bir göz atmanızı tavsiye ederim.

‘Struct’ ruby içerisinde yer alan ‘Class’ benzeri bir yapı, aslında Class’dan türemiş farklı bir yapı. Şöyleki normalde yeni bir ‘class’ yaratmak istediğimiz de

class YeniSinif
attr_reader ...
attr_writer ...
attr_accessor ...

def ...
end

...
end

şeklinde ‘YeniSinif’ı yaratır ve bu sınıftan nesneler üretmeye başlayabiliriz. Struct, sadece veri taşımak için tasarlandığı için şu şekilde bir tanımlamaya ihtiyaç duyar;

# Temel Struct tanımı...
Adres = Struct.new(:posta_kodu, :sehir, :ilce, :semt, :mahalle, :apt_no, :apt_isim, :daire)

anlaşılacağı üzere, herhangi bir şekilde erişim belirleyicisi tanımlanamaz (private, protected, public gibi) tüm üyeler public’dir. Önemle belirtmem gerekirki, bu yeni oluşturduğum ‘Adres’ bir nesne değildir, bir sınıftır yani yeni bir türdür(type). Peki biz neden ruby içerisinde yeni bir tür(type) yaratmak istedik ? Örnekten de anlaşılacağı gibi, normal hayatta adres bilgisinde posta kodu, şehir, ilçe…vb bilgiler birbirlerinden ayrılamazlar ve mantıksal anlamda da bir birliktelikleri vardır. Elbette kullanmazsak programlarımızda çok büyük problemler çıkmaz ama bazı durumlarda bize çok büyük kolaylıklar sağlayabilir; örnek vermek gerekir ise; Struct kullanmadan adres yapısının kopyalanması;

yeni_posta_kodu = posta_kodu
yeni_sehir = sehir
yeni_ilce = ilce
yeni_semt = semt
...
...

peki Adres diye bir tür kullansaydık ve işlemleri bu tür üzerinden yürütseydik;

yeni_adres = adres.clone # Bu kadar.. :)

şeklinde küçücük bir kod parçası ile bu işlemi yapabilirdik. Peki hemen aklınıza gelebilir, zaten sınıf(class) yapısı mevcut ben struct yerine class kullanamazmıyım ? Elbette kullanabilirsin, class, struct’ın yapabileceği tüm özelliklere sahip temel ve en genel yapıdır. Struct sadece verileri tutmak için yapılmış ve bu iş üzerine yönelmiş class’ın alt sınıfıdır. Yukarıda da bahsettiğim snippet incelenecek olursa, bu konu daha rahat anlaşılır diye tahmin ediyorum.

Peki “Struct sadece verileri tutmak için yapılmış ve bu iş üzerine yönelmiş class’ın alt sınıfıdır” dedik, bu veri tutma işinde bizlere hangi özellikleri vermektedir. Struct, class’lardan farklı olarak bizlere bir Array veya Hash nesnesine erişir gibi içerisinde yer alan özelliklere erişimimizi sağlayabilir. Şöyleki;

adres = Adres.new()
# veya
# adres = Adres.new(34300, "İstanbul", "Fatih", "Cerrahpaşa", "ZZZZ ZZZ ZZZZ ZZ", 1, "Gonca", 18)
adres.posta_kodu = 34300
adres.sehir = "İstanbul"
puts adres[:posta_kodu] # 34300
puts adres["sehir"] # İstanbul
puts adres[1] # İstanbul
puts adres.members # üyelerin isimlerini verir.
puts adres.values # üyelerin değerlerini verir.

adres.each_pair do |key,value|
	puts key.to_s + ":" + value.to_s
end

Bir sonraki yazımda OpenStruct’u anlatmaya çalışacağım… :)

Kolay gelsin :)