Ruby 1.9 (YARV) vs. Python, Lua & PHP

Opublikowane przez Jarosław Zabiełło Mon, 01 Jan 2007 18:36:00 GMT

Korzystając z tego, że niedawno do repozytorium Rubiego został dodany YARV (wirtualna maszyna Rubiego) pokusiłem się o małe porównanie wydajności. Jako test użyłem prostego programu jaki pojawił się na liście pl.comp.lang.pyhon (musiałem tylko trochę zwiększyć pętle do 10 milionów iteracji, aby były widoczne jakieś wyniki) Użyty sprzęt: Athlon64 3700+, 64bit Ubuntu 6.0.6.

Sprawdziłem też z ciekawości PHP 5.2 na tym samym sprzęcie. Dla tak prostego testu powinien móc dać z siebie wszystko. Jest jednak wolniejszy od Rubiego 1.9.

Kod dla Pythona:

import time
t=time.time()
a=0
for i in xrange(10000000):
    a += i
print a
print time.time() - t
Kod dla Lua:
t = os.clock()
a = 0
for i = 1,10000000 do
    a=a+i
end
print(a)
print(os.clock() - t)

Kod dla Rubiego:

t = Time.now
a = 0
for i in 1..10_000_000
  a = a+i
end
puts a
puts Time.now - t

Kod dla PHP:

<?php
function microtime_float() {
 $time = microtime();
 return (double)substr($time, 11) + (double)substr($time, 0, 8);
}
$t =  microtime_float();
$a = 0;
for ($i = 0; $i < 10000000; $i++) {
  $a += $i;
}
print "$a\n";
print  microtime_float()- $t;
?>

Wyniki:

  1. Lua: 1.14 s
  2. Ruby 1.9: 1.49 s
  3. PHP 5.2: 1.74 s
  4. Python 2.5: 2.64 s
  5. Python 2.4.3: 2.72 s
  6. Ruby 1.8.5: 3.83 s.

Drugie podejście

Tym razem wynik uśredniam dla 10 prób. Zwiększyłem ilość iteracji do 20 mln. No i… Ruby 1.9 pobił wszystko. Zarówno Pythona jak i Lua! (PHP 5.2 po 30 sek. zgłosił timeout. Musiałem więc uśrednić po 5 wynikach.)

PYTHON

import time
def bench():
    a, t = 0, time.time()
    for i in xrange(20000000):
        a+=i
    return time.time()-t
result = 0
for i in range(10):
  result += bench()
print result / 10.0

RUBY

def bench
  a, t = 0, Time.now
  20_000_000.times { |i| a += i }
  Time.now - t
end
result = 0
10.times { |i| result += bench }
puts result / 10

LUA

function bench()
  a = 0
  t = os.time()
  for i = 1, 20000000 do
    a = a + i
  end
  return os.time() - t
end
result = 0
for x = 1,10 do
  result = result + bench()
end
print(result/10)

PHP

<?php
function bench() {
  $a = 0;
  $t =  time();
  for ($i = 0; $i < 20000000; $i++) $a += $i;
  return time() - $t;
}
$result = 0;
for ($x = 1; $x <= 5; $x++) $result += bench();
print $result / 5.0;
?>

Wyniki

  1. Ruby 1.9: 2.0953268 s.
  2. Lua 5.1: 2.4 s.
  3. Python 2.5: 2.49481592178 s.
  4. Python 2.4.3: 2.71687791348 s.
  5. PHP 5.2: 4.2 s.
  6. Ruby 1.8.5: 9.0153751 s.

Jestem ciekaw kiedy wyjdzie Rails dostosowany do Ruby 1.9. Zapowiada się bardzo obiecująco!

Posted in , ,  | Tagi , , , , ,  | 19 comments

Skype3 i polski czat dla Railsów, Django i Pylonsa

Opublikowane przez Jarosław Zabiełło Thu, 14 Dec 2006 23:48:00 GMT

Nowy Skype 3 wprowadza małą rewolucję w stos. do poprzedniej wersji. Można nie tylko rozmawiać, ale pograć w szachy, kółko i krzyżyk i inne gry (są b. ładnie zrobione we Flashu 9). Można nagrywać rozmowy na dysk. Można tworzyć publiczne czaty. I właśnie w tej sprawie piszę ten tekst bo stworzyłem polski czat dla miłośników frameworków Ruby on Rails, Django i Pylons. Wygodniej jest czasem skonsultować coś w czasie rzeczywistym niż na grupie czy forum dyskusyjnym.

Posted in , , , , ,  | Tagi , ,  | 17 comments

PickAxe2 po polsku

Opublikowane przez Jarosław Zabiełło Fri, 01 Dec 2006 00:47:00 GMT

Mimo że o języku Ruby mówi się szerzej raczej od niedawna, ilość książek i dokumentacji dostępnej do Rubiego zdążyły już pobić to, co zostało napisane dla języka Python i stale się powiększa. Trudno aby taką sytuację nie wykorzystały polskie firmy wydawnicze.

Jeszcze w grudniu 2006 powinna pojawić się w księgarniach polska wersja kultowej książki na temat Rubiego – tzw. PickAxe21 czyli Programming Ruby: The Pragmatic Programmers. Pierwsze wydanie tej książki przyczyniło się w znacznej mierze do popularyzacji języka poza Japonią. Jest ono dostępne darmo w internecie. Część druga, poza tym, że jest znacznie obszerniejsza, i uwzględnia nowości w języku w stos. do starego wydania z 1993 roku.

1 Nazwa PickAxe pochodzi od charakterystycznej okładki z kilofem (ang. pick axe) Dwójka oznacza drugie wydanie.

Posted in  | Tagi  | 1 comment

Serwery kontynuacyjne - przyszłość webu

Opublikowane przez Jarosław Zabiełło Wed, 22 Nov 2006 01:26:00 GMT

Każdy, kto zajmował się kiedykolwiek programowaniem stron internetowych wie, że protokół HTTP jest bezstanowy. Innymi słowy, każde przeładowanie strony internetowej generuje kompletnie niezależne wywołanie serwera i nie ma on możliwości aby powiązać wywołanie z konkretnym klientem. Aby temu zaradzić, wprowadzono prostą sztuczkę. Wprowadzono tzw. mechanizm cookies (dosł. ciasteczek), malutkich plików które serwer może wysyłać do klienta (tam i z powrotem). Ten unikalny identyfikator (sesji) można też trzymać w adresie URL, ale ta metoda jest zdecydowanie odradzana z powodu łatwości nadużyć (łatwo wykraść taki numer i podszyć się pod autora) Od strony klienta jedynym wymaganiem jest aby nie blokował sobie w przeglądarce mechanizmu cookies.

Serwer znając identyfikator sesji, może związać z nim szereg danych, np. aktualną listę zamawianych produktów włożonych do koszyka w sklepie internetowym. Dane te zwykle trzyma się w bazie lub w pamięci operacyjnej. Oczywiście czas życia danych jest ustalany przez serwet i w normalnym wypadku są one cyklicznie kasowane. (Z tym “normalnym” wypadkiem to różnie bywa, bo wiele frameworków tego nie zapewnia i trzeba samemu o to zadbać)

Mechanizm sesji jest dosyć wydajny, bo zapytania wysyłane do serwera mogą być obsługiwane asynchronicznie, czyli bez żadnych blokad w oczekiwaniu na ukończenie obsługi zapytania. Przez lata “stanowość” protokołu HTTP zapewniało się właśnie za pomocą sesji.

Ten mechanizm ma jednak swoje wady. Największą jest złożoność jaką wprowadza po stronie skryptów na serwerze. (I to nie jest wcale taka trywialna sprawa jak to można było zaobserwować u developerów frameworka CherryPy którzy miesiącami nie potrafili napisać stabilnie działającego mechanizmu obsługi sesji.)

Kontynuacje

Kompletnie innym podejściem jest skorzystanie z tzw. mechanizmu kontynuacji. Mechanizm ten podobny jest do gracza, który w dowolnym momencie może zapisać i wczytać stan gry. Kontynuacje zapewniają taki mechanizm zapisu stanu programu aby w dowolnym momencie później go przywrócić. Niektórzy porównują to do maszyny czasu, bo można w dowolnym momencie przywrócić wcześniejszy stan aplikacji.

Zalet z takiego podejścia jest wiele. Weźmy np. sprawę obsługi “nieśmiertelnego” przycisku Back w przeglądarce. Obsługa tego przycisku sprawia spore problemy. Programiści najchętniej w ogóle by go zablokowali. W wypadku kontynuacji ten problem w ogóle nie istnieje. Kliknął ktoś Back aby cofnąć się do poprzedniej strony? Żaden problem. Serwer przywróci cały wcześniejszy stan aplikacji bez żadnego problemu. I to w sposób przezroczysty dla programisty! Programowanie stron webowych staje się znacznie prostsze, niczym tworzenie aplikacji desktopowej włącznie z debugowaniem krok po kroku. Wg różnych prognoz, tak będziemy programować serwisy internetowe za kilka lat!

Sama idea nie jest najwyraźniej jeszcze powszechnie znana, skoro w rozmowie z developerami irlandzkiego Google, zaskoczyłem ich informacją na ten temat. Kto wie, czy Google mocniej nie zainwestuje w Rubiego (aktualnie mocno korzysta z Pythona, który jest podstawą większości ich skryptów).

Smalltalk i Seaside

Smalltalk jest bardzo starym językiem bo jego początki sięgają lat 70-tych. Od zawsze był językiem w pełni obiektowym i dynamicznym. To m.in. Smalltalk pierwszy wymyślił wirtualną maszynę której to ideę później skopiowali twórcy Javy. W Smalltalku napisano najlepszy (w chwili obecnej) na świecie serwer kontynuacyjny – Seaside.

Czy to spowoduje renesans na Smalltalka? Osobiście w to wątpię. Główną wadą Smalltalka jest jego monolityczność i hermentyczność. Uruchamiając środowisko Smalltalak uruchamia się cały, zamknięty świat Smalltalka. Np. nie ma tam dostępu do plików z zewnątrz tak, jak w innych językach. To spowodowało, że język ten, mimo pewnych sukcesów, nigdy nie zdobył sobie powszechnego uznania. I moim zdanie, nigdy już nie zdobędzie, bo w międzyczasie wyrosła mu młoda, obiecująca konkurencja.

Ruby

Ruby jest językiem relatywnie młodym. Tzn. został po raz pierwszy udostępniony publicznie w tym samym roku co Java – 1995. Ale przez większość lat był mało znany poza Japonią (skąd pochodzi jego twórca). Ruby jest także jednym z tych nielicznych języków, które (podobnie jak Smalltalk) posiadają wbudowaną obsługę kontynuacji. Istnieją co prawda różne próby implementacji tego mechanizmu w Javie1, ale tylko Ruby posiada ten mechanizm jako coś naturalnego i nie trzeba stosować żadnych specjalnych sztuczek aby go emulować. Z tego co pamiętam, Seaside pierwotnie był tworzony w Ruby, ale w tamtym okresie, kontynuacje w Ruby były jeszcze niedojrzałe, więc twórcy przerzucili się na Smalltalka. Ruby jednak szybko się rozwija, nabiera dojrzałości i moim zdaniem, ma bardzo duże szanse, aby wyprzedzić pozostałe języki przy tworzeniu serwisów internetowych nowej generacji, serwisów opartych na kontynuacjach.

Przykład kontynuacji.

Poniższy przykład2 pokazuje implementację generatora za pomocą kontynuacji.

class Generator

  def initialize
    do_generation
  end

  def next
    callcc do |here|
      @main_context = here;
       @generator_context.call
    end
  end

   private

   def do_generation
     callcc do |context|
       @generator_context = context;
       return
     end
     generating_loop
   end

   def generate(value)
     callcc do |context|
       @generator_context = context;
       @main_context.call(value)
     end
   end
end

A oto oparty na nim generator ciągu liczb Fibbonacciego:

class FibGenerator < Generator
  def generating_loop
    generate(1)
    a, b = 1, 1
    loop do
      generate(b)
      a, b = b, a+b
    end
  end
end

fib = FibGenerator.new
15.times { print "#{fib.next} " }
#wynik: 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 

1 Np. Riff lub Jetty 6.

2 Przykład z książki “The Ruby Way”, 1ed.

Posted in , ,  | Tagi , , ,  | 23 comments

Społeczność Rubiego rośnie w siłę

Opublikowane przez Jarosław Zabiełło Tue, 07 Nov 2006 23:34:00 GMT

Społeczność Rubiego jest może mniejsza niż Pythona, ale jest jakaś bardziej aktywna i zorganizowana (przynajmniej tak to widać w Polsce). Nie tylko trwają prace nad tłumaczeniem strony domowej Rubiego na język polski, ale także coraz częściej są organizowane spotkania miłośników tego języka.

Najbliższe spotkanie jest planowane na 15 listopada 2006 w Warszawie. Niedługo później, 18 listopada jest organizowane spotkanie w Krakowie.

Od niedawna też oficjalna strona języka Ruby http://ruby-lang.org zgłasza się po polsku (w wypadku przegłądarki ustawionej na jęz. polski). Inni też mogą wejść na stronę polską, która jest bezpośrednio dostępna spod adresu: http://www.ruby-lang.org/pl/.

Co ciekawe, zaczyna się pojawiać coraz więcej ofert pracy dla programistów Rubiego. Oczywiście siłą napędową języka jest wciąż Rails. :)

Posted in  | Tagi ,  | brak comments

RadRails i snippety TextMate

Opublikowane przez Jarosław Zabiełło Tue, 07 Nov 2006 23:13:00 GMT

RadRails, zintegrowany edytor dla Rubiego i Railsów zaczyna coraz bardziej niwelować wcześniejsze zachwyty nad komercyjnym edytorem TextMate. Nie dość, że jest darmowy i działa na Windows, MacOS-X i Linuksie (TextMate tylko na MacOS-X), to na dodatek uzyskał to, co do tej pory było główną atrakcją TextMate – makra przyśpieszające pisanie kodu, czyli tzw. snippety. RadRaila ma już przygotowanych 199 snippetów do Rubiego i 50 do RHTML!

Do tego wystarczy dorzucić kolorowanie kodu a’la TextMate i RadRails ma już wszystko (no może do pełni doskonałości brakuje mu uzupełniania kodu tak, jak to robi komercyjny edytor Komodo)

Posted in ,  | Tagi , , ,  | brak comments

Polski kanał IRC dla RoR

Opublikowane przez Jarosław Zabiełło Thu, 12 Oct 2006 14:55:31 GMT

Poza polskim forum mamyod niedawna kanał #rubyonrails.pl na serwerze irc.freenode.net gdzie można bardziej interaktywnie wymieniać się doświadczeniem na temat Rubiego i/lub Railsów. Na razie nie ma wiele osób, ale może się bardziej rozkręci.

Posted in ,  | 5 comments

Subversion /etc/init.d script

Opublikowane przez Jarosław Zabiełło Sat, 07 Oct 2006 00:57:00 GMT

Postanowiłem troszkę poprawić napisany wcześniej skrypt startowy do Subversion. Dorzuciłem też wersję w Pythonie.

#!/usr/bin/env ruby

VERBOSE = true
USER = "nobody"
APP = "/usr/bin/svnserve"
DIR = "/home/svn-repository"
PID = "/var/run/svnserve.pid"

def script action
  def start
    unless File.exists?(PID)
      system %Q|su -c "#{APP} -d -r #{DIR}" #{USER}|
      system "echo `pidof -o %PPID #{APP}` > #{PID}"
    end
  end
  def stop
    return false unless File.exists?(PID)
    system "/bin/kill -TERM #{File.read(PID)}"
    system "/bin/rm -f #{PID}"
    true
  end
  puts "#{APP} #{action}"  if VERBOSE
  $defout.flush # unbuffered output
  case action
    when :start
      start
    when :stop
      puts "#{File.basename(APP)} cannot be stopped because it cannot find #{PID}" unless stop
    when :restart
      stop
      start
  end
end

if %w{start stop restart}.include? ARGV.first
  script ARGV.first.to_sym
else
  puts "Usage: sudo #{__FILE__} {start|stop|restart}"
end

Ten sam skrypt w Pythonie:

#!/usr/bin/env python

import os, sys

VERBOSE = True
USER = "nobody"
APP = "/usr/bin/svnserve"
DIR = "/home/svn-repository"
PID = "/var/run/svnserve.pid"

def script(action):
  def start():
    if not os.path.exists(PID):
      os.system('su -c "%s -d -r %s" %s' % (APP, DIR, USER))
      os.system('echo `pidof -o %%PPID %s` > %s' % (APP, PID))
  def stop():
    if not os.path.exists(PID): return False
    os.system('/bin/kill -TERM %s' % file(PID).read())
    return True
  if VERBOSE: print "%s %s" % (APP, action),
  if action == 'start':
    start()
  elif action == 'stop':
    if not stop():
      print "%s cannot be stopped because it cannot find %s" % (os.path.basename(APP), PID)
  elif action == 'restart':
    stop()
    start()

if len(sys.argv) == 2 and sys.argv[1] in ('start', 'stop', 'restart'):
  script(sys.argv[1])
else:
  if VERBOSE:  print "Usage: sudo %s {start|stop|restart}" % sys.argv[0]

Posted in ,  | Tagi , ,  | 2 comments

Ruby i skrypt startowy do SVN

Opublikowane przez Jarosław Zabiełło Thu, 05 Oct 2006 14:37:00 GMT

Subversion to świetny, darmowy system wersjonowania kodu. Jest znacznie lepszy od starego CVS’a. Niestety, nigdzie nie mogłem się doszukać skryptu startującego do serwera. Co gorsze, skrytp svnserve w ogóle nie ma opcji zapisu numeru swojego procesu co utrudnia pisanie kodu który go “zabije”. Na szczęście Linux posiada komendę pidof. Poniżej gotowy skrypt napisany w Ruby. Należy go umieścić w /etc/init.d, dodać atrybuty wykonywalności (chmod a+x subversion.rb) i dodać linki symboliczne aby startowała utomatycznie razem ze startem serwera (pod Debianem/Ubuntu robi to komenda update-rc.d -f subversion.rb defaults, pod RedHatem/CentOS/Fedorą jest do tego komenda chkconfig)

#!/usr/bin/env ruby

$USER = "nobody"
$APP = "/usr/bin/svnserve"
$DIR = "/home/SVN"
$PID = "/var/run/svnserve.pid"

def script action
  def start 
    system(%Q|su -c "#{$APP} -d -r #{$DIR}" #{$USER}|)
    system(%Q|echo `pidof -o %PPID #{$APP}` > #{$PID}|)
  end
  def stop
    return false if not File.exists?($PID)
    system(%Q|/bin/kill -TERM #{File.read($PID)}|)
    true
  end
  print "#{$APP} #{action}..."
  $defout.flush # unbuffered output
  case action 
    when :start 
      start()
      puts "done"
    when :stop
      if not stop()
        puts "#{File.basename($APP)} cannot be stopped because it cannot find #{$PID}"
      else
        puts "done"
      end 
    when :restart
      stop()
      start()
      puts "done"
  end
end

case ARGV.first
  when "start": script :start
  when "stop": script :stop
  when "restart": script :restart
end

unless %w{start stop restart}.include? ARGV.first
  puts "Usage: sudo #{__FILE__} {start|stop|restart}"
  exit
end

Posted in  | Tagi , ,  | 2 comments

Uniksowy skrypt /etc/init.d w Ruby

Opublikowane przez Jarosław Zabiełło Fri, 29 Sep 2006 12:04:00 GMT

Ruby całkiem dobrze nadaje się do pisania skryptów systemowych. W sumie nie wiem dlaczego do tej pory pisałem skrypty tego typu w uniksowym bash’u. :)

#!/usr/bin/env ruby

MONGREL = "/usr/bin/mongrel_rails"
PROJECT = "/home/httpd/somedomain.com/rails_project"

def execute(action, project)
  Dir.chdir(project)
  print "#{MONGREL} #{action}..."
  $defout.flush # unbuffered output
  `#{MONGREL} cluster::#{action}`
  puts 'done'
end

case ARGV.first
  when 'start': execute 'start', PROJECT
  when 'stop': execute 'stop', PROJECT
  when 'restart': execute 'restart', PROJECT
end

unless %w{start stop restart}.include? ARGV.first
  puts "Usage: sudo #{__FILE__} {start|stop|restart}"
  exit
end

Posted in  | Tagi , ,  | 1 comment

Nowa strona Rubiego

Opublikowane przez Jarosław Zabiełło Tue, 12 Sep 2006 07:42:00 GMT

Strona domowa Rubiego zmieniała swój wygląd. Jest znacznie lepiej. :)

Posted in  | Tagi  | 5 comments

Sun zatrudnił programistów JRuby

Opublikowane przez Jarosław Zabiełło Fri, 08 Sep 2006 08:33:00 GMT

W środowisku javowców Ruby jest językiem który robi trochę zamieszania (jakoś tak się składa, że Ruby bardziej przemawia do programistów Javy niż Python). Cieszy zatem, że firma Sun podjęła decyzję o wsparciu projektu JRuby zatrudniając jego czołowych developerów. Powinno to znacznie przyśpieszyć prace nad tym projektem podobnie jak stało się z IronPythonem, gdy Microsoft zatrudnił jego twórcę.

Jestem ciekaw jak długo programiści zachowają entuzjazm dla swego języka, gdy będzie można generować taki sam bytecode Javy lecz w niezrównanie prostszy sposób. :)

Przykładowy kod Javy:

public class Filter {
  public static void main(String[] args) {
    List list = new java.util.ArrayList();
    list.add("Tim"); list.add("Ike"); list.add("Tina");
    Filter filter = new Filter();
    for (String item : filter.filterLongerThan(list, 3)) { 
      System.out.println( item ); 
    }
  }
  public List filterLongerThan(List list, int length) {
    List result = new ArrayList();
    for (String item : list) {
      if (item.length() <= length) { result.add( item ); }
    }
    return result;
  }
}

A oto odpowiadający mu kod w Ruby:

list = ['Tim', 'Ike', 'Tina']
list.select {|n| n.length > 3}.each {|n| puts n}

Oczywiście to nie wszystko. Dzięki JRuby można uzyskać efekty kompletnie nieosiągalne w standardowej Javie – np. można pracować z biblioteką Swing w sposób interaktywny, z poziomu interpretera zmieniając na żywo jej obiekty.

Wkrótce ma także być gotowa wersja Railsów działająca z JRuby (Zobacz prezentację w PowerPoint). Tym samym odeszłyby wszelkie uwagi co do wydajności Railsów, bo współczesna wirtualna maszyna Javy jest tak silnie zoptymalizowna że dorównuje językowi C++. Oczywiście model wątkowy JRuby jest zgodny z wydajnym i dojrzałym modelem wątkowym Javy – po prostu z niego korzysta.

Posted in ,  | Tagi , ,  | 32 comments

Mamy pl.comp.lang.ruby!

Opublikowane przez Jarosław Zabiełło Fri, 23 Jun 2006 07:13:00 GMT

Są już oficjalne wyniki głosowania na rzecz stworzenia grupy dyskusyjnej pl.comp.lang.ruby. 96 głosów za, 4 wstrzymujące się i 6 nieważnych. Nowa grupa powinna być wkrótce dostępna na serwerach usenetowych.

Posted in ,  | Tagi  | 3 comments

pl.comp.lang.ruby - głosowanie rozpoczęte!

Opublikowane przez Jarosław Zabiełło Sat, 03 Jun 2006 14:03:00 GMT

Po długim okresie oczekiwań w końcu doczekaliśmy się rozpoczęcia głosowania nad stworzeniem grupy pl.comp.lang.ruby. Oczywistą zaletą grupy newsowej jest m.in. to, że jest indeksowana i archiwizowana przez Google oraz jest bardziej odporna na “pady” serwera, bo posty są replikowane po wielu serwerach. Formalna treść ogłoszenia (wraz z informacją o sposobie głosowania) jest dostępna tutaj…

Posted in ,  | Tagi  | brak comments

JEdit i Rails

Opublikowane przez Jarosław Zabiełło Sun, 28 May 2006 01:46:00 GMT

RadRails ma silną konkurencję. Edytor JEdit jest nie tylko szybszy i mniej zabiera zasobów komputera, to na dodatek, przy dodaniu odpowiednich pluginów doskonale nadaje się do pracy z Railsami. Wygląda to bardzo dobrze, wystarczy rzucić okiem na tę stronę.

Posted in ,  | Tagi ,  | 3 comments

Arachno IDE 0.6.11

Opublikowane przez Jarosław Zabiełło Wed, 24 May 2006 14:48:00 GMT

Udostępniono kolejną wersję beta świetnego edytora Arachno IDE dedykowanego do Ruby i Railsów. Poprawiono sporo błędów. Dodano parę nowych możliwości. Arachno IDE ewoluuje w kierunku edytora łatwego do rozbudowy o nowe funkcje. Jeszcze to nie jest w pełni gotowe. Ale do programu został dodany zagnieżdżony interpreter Pythona…

Posted in ,  | Tagi ,  | 1 comment

RadRails 0.6.3 - dużo lepiej

Opublikowane przez Jarosław Zabiełło Mon, 15 May 2006 09:21:00 GMT

Wyszła kolejna wersja edytora RaiRails (0.6.3). Poprawiono denerwujące (dla uzytkowników windozy) błędy. Działa całkiem dobrze. Na dodatek dodano zintegrowaną obsługę pluginów. Można je instalować zdalnie prosto z RaidRails.

Posted in ,  | Tagi ,  | 1 comment

JRuby on Rails - ruszył

Opublikowane przez Jarosław Zabiełło Sun, 14 May 2006 18:21:00 GMT

JRuby – projekt będący implementacją Rubiego w języku Java został przyśpieszony w związku z konferencją JavaOne. Developerom udało się w końcu uruchomić pełną aplikację Railsów działającą na wirtualnej maszynie Javy. Na razie jeszcze nie ma informacji o jakimś znaczącym przyśpieszeniu działania, ale pierwszy krok został dokonany. Zobacz więcej…

Zobacz też listę języków potrafiących pracować w javowskiej JVM – jest ich całkiem sporo. Kto by pomyślał, że nawet napisano assembler generujący klasy Javy. :)

Posted in ,  | Tagi ,  | brak comments

JRuby on Rails - ruszył

Opublikowane przez Jarosław Zabiełło Sun, 14 May 2006 18:21:00 GMT

JRuby – projekt będący implementacją Rubiego w języku Java został przyśpieszony w związku z konferencją JavaOne. Developerom udało się w końcu uruchomić pełną aplikację Railsów działającą na wirtualnej maszynie Javy. Na razie jeszcze nie ma informacji o jakimś znaczącym przyśpieszeniu działania, ale pierwszy krok został dokonany. Zobacz więcej…

Zobacz też listę języków potrafiących pracować w javowskiej JVM – jest ich całkiem sporo. Kto by pomyślał, że nawet napisano assembler generujący klasy Javy. :)

Posted in ,  | Tagi ,  | brak comments

Dlaczego Ruby on Rails jest wyjątkowy?

Opublikowane przez Jarosław Zabiełło Sun, 14 May 2006 04:22:00 GMT

Niektórym osobom stykającym się z po raz pierwszy z Railsami wydaje się, że jest to tylko jakieś kolejne, tradycyjne środowisko developerskie pracujące wg wzorca projektowego MVC (model-widok-kontroler). Przywiązani do swoich języków i frameworków czasami się dziwią, dlaczego temat Railsów wywołuje od jakiegoś czasu tyle emocji i komentarzy. Na pewno po częsci jest tak pewnie dlatego, że RoR jest bardzo dobrze wypromowany. Dobra strona główna, dobra dokumentacja, książki, filmy, bardzo aktywna społeczność – nic tylko naśladować. Z drugiej strony, trzeba też przyznać, że jest to środowisko świetnie zaprojektowane – w Railsach sie pracuje po prostu komfortowo.

Nie dziwią więc ciągłe próby naśladowania Railsów w innych językach (PHP, Python, Java, C# itp) Jednakże między nimi a Railsami będzie ciągle pewna, trudna do osiągnięcia, jeśli nie w ogóle niemożliwa – bariera. Railsy posiadają nie tylko wszystko, co potrzeba do bardzo produktywnego tworzenia aplikacji internetowych, ale są przy tym równocześnie bardzo eleganckie i czytelne. Eleganckie i czytelne czyli łatwe do nauki. Tak, nauka Rubiego nie jest przeszkodą. Przekona się o tym każdy, kto trochę bliżej przyjrzy się jak działa RoR.

Miałem okazję porównywać ze sobą kilka różnych frameworków. Gdy chciałem przekonać się do któregoś z nich, zawsze ostatecznie wracałem z powrotem do RoR. Po prostu żaden z nich nie jest jak elegancki i prosty w użyciu1. Co jest główną przyczyną takiego wrażenia? Twórca Railsów, David Heinemeier Hansson powiedział kiedyś, że gdyby nie Ruby to nie powstałby Ruby on Rails. Powiedział także, że uważa iż w żadnym innym języku nie da się napisać tak eleganckiego i pięknego kodu. Zatem można powiedzieć, że prawdziwą siłą Railsów jest Ruby. Razem tworzą nierozłączną parę i ta łączność nie dotyczy bynajmniej tylko nazwy. ;) Ruby posiada bowiem pewne unikalne cechy, które pozwoliły stworzyć RoR w postaci, która jest raczej mało nieosiągalna dla innych języków. Już to wyjaśniam.

Panuje powszechnie mniemanie, że Ruby to połączenie cech Pythona i Perla. Ruby (podobnie jak Perl) posiada np. wbudowaną w składnię obsługe wyrażeń regularnych. Posiada także (podobnie jak Python) pełną obiektowość i bardzo elegancką, czytelną (choć nie taką samą) składnię. Pewnym odkryciem było dla mnie to, że językie, do którego Ruby ma najwięcej podobieństw to innego języka – Smalltalk. Lektura cech, filozofii (i nawet do pewnego stopnia składni) Smalltalka pokazuje zdumiewające podobieństwo do Rubiego. Można wręcz odnieść wrażenie, że Ruby to swego rodzaju przeróbka Smalltalka2. Podobieństw jest bardzo wiele. Od słów kluczowych po symbole, sposób tworzenia instancji klas, bloki kodu (ang. closures), kontynuacje3 itp. Jak ktoś jeszcze nie rozumie filozofii Rubiego, jego modelu obiektowego i powodu istnienia otwartych klas, powinien poczytać sobie trochę o Smalltalku.

Ruby jak i Smalltalk posiadają bardzo podobny model obiektowy. Wszystkie obiekty (na drodze dziedziczenia) wywodzą się z jednej, ostateczniej klasy Object. Oba języki mają zaimplementowaną pełną obiektowość. Nie ma (tak ja w Javie) podziału na prymitywy i typy referencyjne. Wszystko jest obiektem i wszystko posiada metody. Dotyczy to nie tylko liczb i napisów ale także obiektu nil, true czy false. Każdy obiekt można przeciążyć i/lub zmodyfikować wewnetrznie (dynamicznie dodając lub usuwając jego metody w trakcie pracy programu)

Z tego wynika, że właściwie to można modyfikować sam język. Daje to możliwości zupełnie nieosiągalne nawet dla tak dobrego i obiektowego języka jakim jest Python. Ruby pozwala na łatwe dodawanie nowych metod do liczb czy napisów. Pozwala na taką modyfikację samego siebie, aby optymalnie nadawał się do realizacji pewnych, specyficznych zadań. Ruby umożliwia zatem tworzenie tego, co się określa mianem języków domenowych (Domain-specific Programming Languages). Są to języki, które w przeciwieństwie do języków ogólnego zastostosowania, zostały zaprojektowane do wykonywania specyficznego zadania/zadań. Zarówno Smalltalk jak i Ruby pozwalają na tworzenie języków domenowych.

Ruby on Rails to nic innego jak framework napisany za pomocą Rubiego zmodyfikowanego w celu uzyskania wysoce produktywnego środowiska do tworzenia nowoczesnych aplikacji internetowych.

Przykładowe helpery dostępne w Rails, które korzystają z nowych metod nie będących standardową częścią Rubiego. Poniższe przykłady pochodzą z 1-g wydania książki Agile Web Development in Rails.

puts 20.bytes #=> 20
puts 20.kilobytes #=> 20480
puts 20.megabytes #=> 20971520
puts 20.gigabytes #=> 21474836480
puts 20.terabytes #=> 21990232555520
puts 20.minutes.ago #=> Tue May 10 16:43:43 CDT 2005
puts 20.hours.from_now #=> Wed May 11 13:03:43 CDT 2005
puts 20.weeks.from_now #=> Tue Sep 27 17:03:43 CDT 2005
puts 20.months.ago #=> Thu Sep 18 17:03:43 CDT 2003
now = Time.now
puts now #=> Tue May 10 17:15:59 CDT 2005
puts now.ago(3600) #=> Tue May 10 16:15:59 CDT 2005
puts now.at_beginning_of_day #=> Tue May 10 00:00:00 CDT 2005
puts now.at_beginning_of_month #=> Sun May 01 00:00:00 CDT 2005
puts now.at_beginning_of_week #=> Mon May 09 00:00:00 CDT 2005
puts now.at_beginning_of_year #=> Sat Jan 01 00:00:00 CST 2005
puts now.at_midnight #=> Tue May 10 00:00:00 CDT 2005
puts now.change(:hour => 13) #=> Tue May 10 13:00:00 CDT 2005
puts now.last_month #=> Sun Apr 10 17:15:59 CDT 2005
puts now.last_year #=> Mon May 10 17:15:59 CDT 2004
puts now.midnight #=> Tue May 10 00:00:00 CDT 2005
puts now.monday #=> Mon May 09 00:00:00 CDT 2005
puts now.months_ago(2) #=> Thu Mar 10 17:15:59 CST 2005
puts now.months_since(2) #=> Sun Jul 10 17:15:59 CDT 2005
puts now.next_week #=> Mon May 16 00:00:00 CDT 2005
puts now.next_year #=> Wed May 10 17:15:59 CDT 2006
puts now.seconds_since_midnight #=> 62159.215938
puts now.since(7200) #=> Tue May 10 19:15:59 CDT 2005
puts now.tomorrow #=> Wed May 11 17:15:59 CDT 2005
puts now.years_ago(2) #=> Sat May 10 17:15:59 CDT 2003
puts now.years_since(2) #=> Thu May 10 17:15:59 CDT 2007
puts now.yesterday #=> Mon May 09 17:15:59 CDT 2005
puts "cat".pluralize #=> cats
puts "cats".pluralize #=> cats
puts "erratum".pluralize #=> errata
puts "cats".singularize #=> cat
puts "errata".singularize #=> erratum

Z racji tego, że Railsy zmodyfikowały Rubiego do realizacji swoich zadań, uważam, że próba sklonowania tego środowiska w jakimś innym języku (poza Smalltalkiem), jest z góry skazana na niepowodzenie. Po prostu nigdy to nie będzie tak piękny kod jak Ruby dla Railsów. Na otarcie łez dla pythonistas, mogę powiedzieć, że przy wszystkich zaletach Rubiego, nadal uważam że Python (jako język) jest nie tylko łatwiejszy do opanowania ale także bardziej produktywny. Ale jeśli chodzi o frameworki, to Rails jest nie do pobicia jeśli chodzi o komfort, możliwości i DRY[4].

1 Zupełnie identyczne wrażenia prostoty jak z Railsami miałem w przypadku szukania dobrego systemu CMS’a. Taki np. pythonowy Plone w porównaniu do ezPublish i całej masy innych, pehapowych rozwiązań jest nie tylko poteżniejszy ale także niezrównanie prostszy i wygodny (po 5 minutach od instalacji, praktycznie bez czytania dokumentacji i bez znajomości Pythona, można stworzyć prosty serwis o całkiem przyzwoitej, podstawowej funkcjonalności)

2 Smalltalk posiada tylko 5 słów kluczowych i proste zasady: wszystko jest obiektem, wszystkie operacje polegają na przesyłaniu metod (nazywanych tu: wiadomościami) między obiektami. Moim zdaniem Smalltalk trochę przesadził z tą zasadą, bo nawet bo zamiast do sterowania kontrolą kodu używane są także wiadomości. Może jest jest spójne, ale trochę dziwnie wygląda. Osobiście bardziej podobają mi się możliwości Smalltalka ale wyrażone w składni …Rubiego. :) Zobacz też Ruby Instead of Smalltalk

3 Kontynuacje są jedną z wbudowanych cech Rubiego o której może być za jakiś czas głośno. Umożliwiają bowiem budowanie tzw. internetowych serwerów kontynuacyjnych, które w pełni zachowują stan pomiędzy requestami i ogromnie upraszczają prace programistów. W tej chwili najlepiej opracowanym frameworkiem tego typu jest smalltalkowy Seaside.

4 DRY to skrót od ang. Dont’t Repeat Yourself. Railsy zostały napisane z wręcz obsesyjną ;) cechą unikania powtarzania kodu. Mniej powtórzeń to nie tylko mniej niepotrzebnej, dodatkowej pracy ale także mniejsze ryzyko popełniania błędu.

Posted in , ,  | Tagi , ,  | 32 comments

Starsze wpisy: 1 2