<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/css" href="/stylesheets/rss.css"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/">
  <channel>
    <title>Jaros&#322;aw Zabie&#322;&#322;o - BLOG: Category Java</title>
    <link>http://blog.zabiello.com/articles/category/java</link>
    <language>en-us</language>
    <ttl>40</ttl>
    <description>moje notatki, linki, komentarze</description>
    <item>
      <title>Serwery kontynuacyjne - przysz&#322;o&#347;&#263; webu</title>
      <description>&lt;p&gt;Ka&#380;dy, kto zajmowa&#322; si&#281; kiedykolwiek programowaniem stron internetowych wie, &#380;e protok&#243;&#322; &lt;span class="caps"&gt;HTTP&lt;/span&gt; jest bezstanowy. Innymi s&#322;owy, ka&#380;de prze&#322;adowanie strony  internetowej generuje kompletnie niezale&#380;ne wywo&#322;anie serwera i nie ma on mo&#380;liwo&#347;ci aby powi&#261;za&#263; wywo&#322;anie z konkretnym klientem. Aby temu zaradzi&#263;, wprowadzono prost&#261; sztuczk&#281;. Wprowadzono tzw. mechanizm cookies (dos&#322;. ciasteczek), malutkich plik&#243;w kt&#243;re serwer mo&#380;e wysy&#322;a&#263; do klienta (tam i z powrotem). Ten unikalny identyfikator (sesji)  mo&#380;na te&#380; trzyma&#263; w adresie &lt;span class="caps"&gt;URL&lt;/span&gt;, ale ta metoda jest zdecydowanie odradzana z powodu &#322;atwo&#347;ci nadu&#380;y&#263; (&#322;atwo wykra&#347;&#263; taki numer i podszy&#263; si&#281; pod autora) Od strony klienta jedynym wymaganiem jest aby nie blokowa&#322; sobie w przegl&#261;darce mechanizmu cookies.&lt;/p&gt;


	&lt;p&gt;Serwer znaj&#261;c identyfikator sesji, mo&#380;e zwi&#261;za&#263; z nim szereg danych, np. aktualn&#261; list&#281; zamawianych produkt&#243;w w&#322;o&#380;onych do koszyka w sklepie internetowym. Dane te zwykle trzyma si&#281; w bazie lub w pami&#281;ci operacyjnej. Oczywi&#347;cie czas &#380;ycia danych jest ustalany przez serwet i w normalnym wypadku s&#261; one cyklicznie kasowane. (Z tym &amp;#8220;normalnym&amp;#8221; wypadkiem to r&#243;&#380;nie bywa, bo wiele framework&#243;w tego nie zapewnia i trzeba samemu o to zadba&#263;)&lt;/p&gt;


	&lt;p&gt;Mechanizm sesji jest dosy&#263; wydajny, bo zapytania wysy&#322;ane do serwera mog&#261; by&#263; obs&#322;ugiwane &lt;strong&gt;asynchronicznie&lt;/strong&gt;, czyli bez &#380;adnych blokad w oczekiwaniu na uko&#324;czenie obs&#322;ugi zapytania. Przez lata &amp;#8220;stanowo&#347;&#263;&amp;#8221; protoko&#322;u &lt;span class="caps"&gt;HTTP&lt;/span&gt; zapewnia&#322;o si&#281; w&#322;a&#347;nie za pomoc&#261; sesji.&lt;/p&gt;


	&lt;p&gt;Ten mechanizm ma jednak swoje wady. Najwi&#281;ksz&#261; jest &lt;strong&gt;z&#322;o&#380;ono&#347;&#263;&lt;/strong&gt; jak&#261; wprowadza po stronie skrypt&#243;w na serwerze. (I to nie jest wcale taka trywialna sprawa jak to mo&#380;na by&#322;o zaobserwowa&#263; u developer&#243;w frameworka CherryPy kt&#243;rzy miesi&#261;cami nie potrafili napisa&#263; stabilnie dzia&#322;aj&#261;cego mechanizmu obs&#322;ugi sesji.)&lt;/p&gt;


	&lt;h3&gt;Kontynuacje&lt;/h3&gt;


	&lt;p&gt;Kompletnie innym podej&#347;ciem jest skorzystanie z tzw. mechanizmu kontynuacji.  Mechanizm ten podobny jest do gracza, kt&#243;ry w dowolnym momencie mo&#380;e zapisa&#263; i wczyta&#263; stan gry.  Kontynuacje zapewniaj&#261; taki mechanizm zapisu stanu programu aby w dowolnym momencie p&#243;&#378;niej go przywr&#243;ci&#263;. Niekt&#243;rzy por&#243;wnuj&#261; to do maszyny czasu, bo mo&#380;na w dowolnym momencie przywr&#243;ci&#263; wcze&#347;niejszy stan aplikacji.&lt;/p&gt;


	&lt;p&gt;Zalet z takiego podej&#347;cia jest wiele. We&#378;my np. spraw&#281; obs&#322;ugi &amp;#8220;nie&#347;miertelnego&amp;#8221; przycisku Back w przegl&#261;darce. Obs&#322;uga tego przycisku sprawia spore problemy. Programi&#347;ci najch&#281;tniej w og&#243;le by go zablokowali. W wypadku kontynuacji ten problem w og&#243;le nie istnieje. Klikn&#261;&#322; kto&#347; Back aby cofn&#261;&#263; si&#281; do poprzedniej strony? &#379;aden problem. Serwer przywr&#243;ci ca&#322;y wcze&#347;niejszy stan aplikacji bez &#380;adnego problemu. I to w spos&#243;b &lt;strong&gt;przezroczysty&lt;/strong&gt; dla programisty! Programowanie stron webowych staje si&#281; &lt;strong&gt;znacznie prostsze&lt;/strong&gt;, niczym tworzenie aplikacji desktopowej w&#322;&#261;cznie z debugowaniem krok po kroku. Wg r&#243;&#380;nych prognoz, tak b&#281;dziemy programowa&#263; serwisy internetowe za kilka lat!&lt;/p&gt;


	&lt;p&gt;Sama idea nie jest najwyra&#378;niej jeszcze powszechnie znana, skoro w rozmowie z developerami irlandzkiego Google, zaskoczy&#322;em ich informacj&#261; na ten temat. Kto wie, czy Google mocniej nie zainwestuje w Rubiego (aktualnie mocno korzysta z Pythona, kt&#243;ry jest podstaw&#261; wi&#281;kszo&#347;ci ich skrypt&#243;w).&lt;/p&gt;


	&lt;h3&gt;Smalltalk i Seaside&lt;/h3&gt;


	&lt;p&gt;Smalltalk jest bardzo starym j&#281;zykiem bo jego pocz&#261;tki si&#281;gaj&#261; lat 70-tych. Od zawsze by&#322; j&#281;zykiem w pe&#322;ni obiektowym i dynamicznym. To m.in. Smalltalk pierwszy wymy&#347;li&#322; wirtualn&#261; maszyn&#281; kt&#243;rej to ide&#281; p&#243;&#378;niej skopiowali tw&#243;rcy Javy. W Smalltalku napisano najlepszy (w chwili obecnej) na &#347;wiecie &lt;strong&gt;serwer kontynuacyjny &amp;#8211; &lt;a href="http://www.seaside.st/"&gt;Seaside&lt;/a&gt;&lt;/strong&gt;.&lt;/p&gt;


	&lt;p&gt;Czy to spowoduje renesans na Smalltalka? Osobi&#347;cie w to w&#261;tpi&#281;. G&#322;&#243;wn&#261; wad&#261; Smalltalka jest jego monolityczno&#347;&#263; i hermentyczno&#347;&#263;. Uruchamiaj&#261;c &#347;rodowisko Smalltalak uruchamia si&#281; ca&#322;y, zamkni&#281;ty &#347;wiat Smalltalka. Np. nie ma tam dost&#281;pu do plik&#243;w z zewn&#261;trz tak, jak w innych j&#281;zykach. To spowodowa&#322;o, &#380;e j&#281;zyk ten, mimo pewnych sukces&#243;w, nigdy nie zdoby&#322; sobie powszechnego uznania. I moim zdanie, nigdy ju&#380; nie zdob&#281;dzie, bo w mi&#281;dzyczasie wyros&#322;a mu m&#322;oda, obiecuj&#261;ca konkurencja.&lt;/p&gt;


	&lt;h3&gt;Ruby&lt;/h3&gt;


	&lt;p&gt;Ruby jest j&#281;zykiem relatywnie m&#322;odym. Tzn. zosta&#322; po raz pierwszy udost&#281;pniony publicznie w tym samym roku co Java &amp;#8211; 1995. Ale przez wi&#281;kszo&#347;&#263; lat by&#322; ma&#322;o znany poza Japoni&#261; (sk&#261;d pochodzi jego tw&#243;rca).  Ruby jest tak&#380;e  jednym z tych nielicznych j&#281;zyk&#243;w, kt&#243;re (podobnie jak Smalltalk) posiadaj&#261; wbudowan&#261; obs&#322;ug&#281; kontynuacji. Istniej&#261; co prawda r&#243;&#380;ne pr&#243;by implementacji tego mechanizmu w Javie&lt;sup&gt;&lt;a href="#fn1"&gt;1&lt;/a&gt;&lt;/sup&gt;, ale tylko Ruby posiada ten mechanizm jako co&#347; naturalnego i nie trzeba stosowa&#263; &#380;adnych specjalnych sztuczek aby go emulowa&#263;. Z tego co pami&#281;tam, Seaside pierwotnie by&#322; tworzony w Ruby, ale w tamtym okresie, kontynuacje w Ruby by&#322;y jeszcze niedojrza&#322;e, wi&#281;c tw&#243;rcy przerzucili si&#281; na Smalltalka. Ruby jednak szybko si&#281; rozwija, nabiera dojrza&#322;o&#347;ci i moim zdaniem, ma bardzo du&#380;e szanse, aby wyprzedzi&#263; pozosta&#322;e j&#281;zyki przy tworzeniu serwis&#243;w internetowych nowej generacji, serwis&#243;w opartych na kontynuacjach.&lt;/p&gt;


	&lt;h3&gt;Przyk&#322;ad kontynuacji.&lt;/h3&gt;


	&lt;p&gt;Poni&#380;szy przyk&#322;ad&lt;sup&gt;&lt;a href="#fn2"&gt;2&lt;/a&gt;&lt;/sup&gt; pokazuje implementacj&#281; generatora za pomoc&#261; kontynuacji.&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;&lt;span class="keyword"&gt;class &lt;/span&gt;&lt;span class="class"&gt;Generator&lt;/span&gt;

  &lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;initialize&lt;/span&gt;
    &lt;span class="ident"&gt;do_generation&lt;/span&gt;
  &lt;span class="keyword"&gt;end&lt;/span&gt;

  &lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;next&lt;/span&gt;
    &lt;span class="ident"&gt;callcc&lt;/span&gt; &lt;span class="keyword"&gt;do&lt;/span&gt; &lt;span class="punct"&gt;|&lt;/span&gt;&lt;span class="ident"&gt;here&lt;/span&gt;&lt;span class="punct"&gt;|&lt;/span&gt;
      &lt;span class="attribute"&gt;@main_context&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="ident"&gt;here&lt;/span&gt;&lt;span class="punct"&gt;;&lt;/span&gt;
       &lt;span class="attribute"&gt;@generator_context&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;call&lt;/span&gt;
    &lt;span class="keyword"&gt;end&lt;/span&gt;
  &lt;span class="keyword"&gt;end&lt;/span&gt;

   &lt;span class="ident"&gt;private&lt;/span&gt;

   &lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;do_generation&lt;/span&gt;
     &lt;span class="ident"&gt;callcc&lt;/span&gt; &lt;span class="keyword"&gt;do&lt;/span&gt; &lt;span class="punct"&gt;|&lt;/span&gt;&lt;span class="ident"&gt;context&lt;/span&gt;&lt;span class="punct"&gt;|&lt;/span&gt;
       &lt;span class="attribute"&gt;@generator_context&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="ident"&gt;context&lt;/span&gt;&lt;span class="punct"&gt;;&lt;/span&gt;
       &lt;span class="keyword"&gt;return&lt;/span&gt;
     &lt;span class="keyword"&gt;end&lt;/span&gt;
     &lt;span class="ident"&gt;generating_loop&lt;/span&gt;
   &lt;span class="keyword"&gt;end&lt;/span&gt;

   &lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;generate&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;value&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
     &lt;span class="ident"&gt;callcc&lt;/span&gt; &lt;span class="keyword"&gt;do&lt;/span&gt; &lt;span class="punct"&gt;|&lt;/span&gt;&lt;span class="ident"&gt;context&lt;/span&gt;&lt;span class="punct"&gt;|&lt;/span&gt;
       &lt;span class="attribute"&gt;@generator_context&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="ident"&gt;context&lt;/span&gt;&lt;span class="punct"&gt;;&lt;/span&gt;
       &lt;span class="attribute"&gt;@main_context&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;call&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;value&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
     &lt;span class="keyword"&gt;end&lt;/span&gt;
   &lt;span class="keyword"&gt;end&lt;/span&gt;
&lt;span class="keyword"&gt;end&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;A oto oparty na nim generator ci&#261;gu liczb Fibbonacciego:&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;&lt;span class="keyword"&gt;class &lt;/span&gt;&lt;span class="class"&gt;FibGenerator&lt;/span&gt; &lt;span class="punct"&gt;&amp;lt;&lt;/span&gt; &lt;span class="constant"&gt;Generator&lt;/span&gt;
  &lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;generating_loop&lt;/span&gt;
    &lt;span class="ident"&gt;generate&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="number"&gt;1&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
    &lt;span class="ident"&gt;a&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="ident"&gt;b&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="number"&gt;1&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="number"&gt;1&lt;/span&gt;
    &lt;span class="ident"&gt;loop&lt;/span&gt; &lt;span class="keyword"&gt;do&lt;/span&gt;
      &lt;span class="ident"&gt;generate&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;b&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
      &lt;span class="ident"&gt;a&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="ident"&gt;b&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="ident"&gt;b&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="ident"&gt;a&lt;/span&gt;&lt;span class="punct"&gt;+&lt;/span&gt;&lt;span class="ident"&gt;b&lt;/span&gt;
    &lt;span class="keyword"&gt;end&lt;/span&gt;
  &lt;span class="keyword"&gt;end&lt;/span&gt;
&lt;span class="keyword"&gt;end&lt;/span&gt;

&lt;span class="ident"&gt;fib&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="constant"&gt;FibGenerator&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;new&lt;/span&gt;
&lt;span class="number"&gt;15&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;times&lt;/span&gt; &lt;span class="punct"&gt;{&lt;/span&gt; &lt;span class="ident"&gt;print&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;&lt;span class="expr"&gt;#{fib.next}&lt;/span&gt; &lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt; &lt;span class="punct"&gt;}&lt;/span&gt;
&lt;span class="comment"&gt;#wynik: 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 &lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p id="fn1"&gt;&lt;sup&gt;1&lt;/sup&gt; Np. &lt;a href="http://rifers.org/"&gt;Riff&lt;/a&gt; lub &lt;a href="http://jetty.mortbay.org/jetty/"&gt;Jetty 6&lt;/a&gt;.&lt;/p&gt;


	&lt;p id="fn2"&gt;&lt;sup&gt;2&lt;/sup&gt; Przyk&#322;ad z ksi&#261;&#380;ki &amp;#8220;The Ruby Way&amp;#8221;, 1ed.&lt;/p&gt;</description>
      <pubDate>Wed, 22 Nov 2006 02:26:00 +0100</pubDate>
      <guid isPermaLink="false">urn:uuid:c15ba4a7-3852-452b-af70-9f5ea30a4702</guid>
      <author>Jaros&#322;aw Zabie&#322;&#322;o</author>
      <link>http://blog.zabiello.com/articles/2006/11/22/serwery-kontynuacyjne-przysz%C5%82o%C5%9B%C4%87-webu</link>
      <category>Ruby</category>
      <category>Java</category>
      <category>SmallTalk</category>
      <category>ruby</category>
      <category>smalltalk</category>
      <category>java</category>
      <category>continuations</category>
    </item>
    <item>
      <title>Sun zatrudni&#322; programist&#243;w JRuby</title>
      <description>&lt;p&gt;W &#347;rodowisku javowc&#243;w &lt;a href="http://ruby-lang.org/"&gt;Ruby&lt;/a&gt; jest j&#281;zykiem kt&#243;ry robi troch&#281; zamieszania (jako&#347; tak si&#281; sk&#322;ada, &#380;e Ruby bardziej przemawia do programist&#243;w Javy ni&#380; &lt;a href="http://python.org"&gt;Python&lt;/a&gt;).  Cieszy zatem, &#380;e firma Sun podj&#281;&#322;a decyzj&#281; o wsparciu projektu &lt;a href="http://jruby.codehaus.org/"&gt;JRuby&lt;/a&gt; &lt;a href="http://www.tbray.org/ongoing/When/200x/2006/09/07/JRuby-guys"&gt;zatrudniaj&#261;c&lt;/a&gt; jego czo&#322;owych developer&#243;w.  Powinno to znacznie przy&#347;pieszy&#263; prace nad tym projektem podobnie jak sta&#322;o si&#281; z &lt;a href="http://www.codeplex.com/Wiki/View.aspx?ProjectName=IronPython"&gt;IronPythonem&lt;/a&gt;, gdy Microsoft zatrudni&#322; jego tw&#243;rc&#281;.&lt;/p&gt;


	&lt;p&gt;Jestem ciekaw jak d&#322;ugo programi&#347;ci zachowaj&#261; entuzjazm dla swego j&#281;zyka, gdy b&#281;dzie mo&#380;na generowa&#263; taki sam bytecode Javy lecz w niezr&#243;wnanie prostszy spos&#243;b. :)&lt;/p&gt;


	&lt;p&gt;Przyk&#322;adowy kod Javy:&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_java "&gt;public class Filter {
  public static void main(String[] args) {
    List list = new java.util.ArrayList();
    list.add(&amp;quot;Tim&amp;quot;); list.add(&amp;quot;Ike&amp;quot;); list.add(&amp;quot;Tina&amp;quot;);
    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() &amp;lt;= length) { result.add( item ); }
    }
    return result;
  }
}&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;A oto odpowiadaj&#261;cy mu kod  w Ruby:&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;&lt;span class="ident"&gt;list&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="punct"&gt;['&lt;/span&gt;&lt;span class="string"&gt;Tim&lt;/span&gt;&lt;span class="punct"&gt;',&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;Ike&lt;/span&gt;&lt;span class="punct"&gt;',&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;Tina&lt;/span&gt;&lt;span class="punct"&gt;']&lt;/span&gt;
&lt;span class="ident"&gt;list&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;select&lt;/span&gt; &lt;span class="punct"&gt;{|&lt;/span&gt;&lt;span class="ident"&gt;n&lt;/span&gt;&lt;span class="punct"&gt;|&lt;/span&gt; &lt;span class="ident"&gt;n&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;length&lt;/span&gt; &lt;span class="punct"&gt;&amp;gt;&lt;/span&gt; &lt;span class="number"&gt;3&lt;/span&gt;&lt;span class="punct"&gt;}.&lt;/span&gt;&lt;span class="ident"&gt;each&lt;/span&gt; &lt;span class="punct"&gt;{|&lt;/span&gt;&lt;span class="ident"&gt;n&lt;/span&gt;&lt;span class="punct"&gt;|&lt;/span&gt; &lt;span class="ident"&gt;puts&lt;/span&gt; &lt;span class="ident"&gt;n&lt;/span&gt;&lt;span class="punct"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;Oczywi&#347;cie to nie wszystko. Dzi&#281;ki JRuby mo&#380;na uzyska&#263; efekty kompletnie nieosi&#261;galne w standardowej Javie &amp;#8211; np. mo&#380;na pracowa&#263; z bibliotek&#261; Swing w spos&#243;b &lt;strong&gt;interaktywny&lt;/strong&gt;, z poziomu interpretera zmieniaj&#261;c na &#380;ywo jej obiekty.&lt;/p&gt;


	&lt;p&gt;Wkr&#243;tce ma tak&#380;e by&#263; gotowa &lt;strong&gt;wersja Rails&#243;w dzia&#322;aj&#261;ca z  JRuby&lt;/strong&gt; (Zobacz prezentacj&#281; w &lt;a href="http://dist.codehaus.org/jruby/jruby_presentation_may06.ppt"&gt;PowerPoint&lt;/a&gt;).  Tym samym odesz&#322;yby wszelkie uwagi co do wydajno&#347;ci Rails&#243;w, bo wsp&#243;&#322;czesna wirtualna maszyna Javy jest tak silnie zoptymalizowna &#380;e dor&#243;wnuje j&#281;zykowi C++. Oczywi&#347;cie model w&#261;tkowy JRuby jest zgodny z wydajnym i dojrza&#322;ym modelem w&#261;tkowym Javy &amp;#8211; po prostu z niego korzysta.&lt;/p&gt;</description>
      <pubDate>Fri, 08 Sep 2006 10:33:00 +0200</pubDate>
      <guid isPermaLink="false">urn:uuid:d35f513c-939f-4f71-9392-e4d9f95c11ee</guid>
      <author>Jaros&#322;aw Zabie&#322;&#322;o</author>
      <link>http://blog.zabiello.com/articles/2006/09/08/sun-zatrudni%C5%82-programist%C3%B3w-jruby</link>
      <category>Ruby</category>
      <category>Java</category>
      <category>ruby</category>
      <category>java</category>
      <category>jruby</category>
    </item>
    <item>
      <title>Akcesory w Javie, Pythonie, Ruby i PHP5</title>
      <description>&lt;p&gt;Java, j&#281;zyk kt&#243;ry doby&#322; sobie siln&#261; pozycj&#281; na rynku korporacyjnym, jest od jakiego&#347; czasu pod obstrza&#322;em krytyki z r&#243;&#380;nych stron. Wysz&#322;a ca&#322;a seria ksi&#261;&#380;ek krytykuj&#261;cych model obiektowy oraz  metodologie promowane przez Jav&#281; (od najs&#322;ynniejszej &lt;a href="http://www.amazon.com/gp/product/0596100949/"&gt;&lt;strong&gt;Beyond Java&lt;/strong&gt;&lt;/a&gt; po &lt;a href="http://www.manning.com/books/tate"&gt;Bitter Java&lt;/a&gt;, &lt;a href="http://www.manning.com/books/tate2"&gt;Bitter &lt;span class="caps"&gt;EJB&lt;/span&gt;&lt;/a&gt;, czy inne)&lt;/p&gt;


	&lt;p&gt;Nie umniejszaj&#261;c zalet Javy, jej krytycy wytykaj&#261; jej niepotrzebn&#261; nadmiarowo&#347;&#263; kodu, oci&#281;&#380;a&#322;o&#347;&#263; i ma&#322;&#261; zwrotno&#347;&#263;, kt&#243;ra powoduje &#380;e j&#281;zyk ten s&#322;abo nadaje si&#281; do modnej ostatnio metodologii _&lt;a href="http://agilemanifesto.org/"&gt;agile programming&lt;/a&gt;. _ Aby lepiej ten problem zobaczy&#263;, przyjrzyjmy si&#281; typowej praktyce programist&#243;w Javy. Tekst ten zainspirowany jest &lt;a href="http://jdn.pl/node/520"&gt;niedawn&#261; dyskusj&#261;&lt;/a&gt; jaka mia&#322;a miejsce w jednym z blog&#243;w mojego kolegi.&lt;/p&gt;


	&lt;h3&gt;Czym s&#261; akcesory?&lt;/h3&gt;


	&lt;p&gt;Akcesory (lub inaczej: gettery i settery) to slangowe okreslenie metod jakie u&#380;ywa obiekt do odczytu i modyfikacji swoich atrybut&#243;w. S&#261; one tak nagminnie u&#380;ywane przez programist&#243;w Javy, &#380;e niekt&#243;re edytory (np. Eclipse) zosta&#322;y nawet wyposa&#380;one w makra do automatycznego ich generowania.&lt;/p&gt;


	&lt;h3&gt;Dorzucanie nieu&#380;ywanego kodu &amp;#8220;na wszelki wypadek&amp;#8221;...&lt;/h3&gt;


	&lt;p&gt;Nagminna (w&#347;r&#243;d programist&#243;w Javy) praktyka dodawania akcesor&#243;w do atrybut&#243;w klasy pachnie jakim&#347; &lt;a href="http://en.wikipedia.org/wiki/Antipattern"&gt;antipatternem&lt;/a&gt;  i s&#261; g&#322;osy, kt&#243;re u&#380;ywanie akcesor&#243;w nazwyaj&#261; wprost &lt;a href="http://www.javaworld.com/javaworld/jw-09-2003/jw-0905-toolbox.html"&gt;z&#322;&#261; praktyk&#261;&lt;/a&gt; . Jest w tym troch&#281; racji. Ale, jak to poni&#380;ej wyka&#380;&#281;, jest to pewnego rodzaju kompromis w zwi&#261;zku ze s&#322;abym modelem obiektowy Javy.&lt;/p&gt;


	&lt;p&gt;Dlaczego programi&#347;ci Javy generuj&#261; akcesory dla ka&#380;dego atrybutu nawet, jak nie przewiduj&#261; potrzeby ich u&#380;ywania? Ot&#243;&#380; czyni&#261; to &amp;#8220;na wszelki wypadek&amp;#8221; bo nie wiedz&#261;, czy w przysz&#322;o&#347;ci nie b&#281;dzie im to potrzebne&amp;#8230;&lt;/p&gt;


	&lt;p&gt;We&#378;my np. taki kod (z powodu kolejnego ograniczenia Javy nie mo&#380;na w jednym pliku trzyma&#263; wi&#281;cej, ni&#380; jednej klasy; tu dla kr&#243;tko&#347;ci umieszczam kod z obu plik&#243;w razem)&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_java "&gt;public class First {
  public String msg = &amp;quot;hello&amp;quot;;
}

public class Second extends First {
  public static void main(String[] args) {
    First obj = new First();        
    System.out.println(obj.msg);
  }
}&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;Jak wida&#263;, w Javie mo&#380;na si&#281;ga&#263; do atrybutu w spos&#243;b bezpo&#347;redni.&lt;/p&gt;


	&lt;p&gt;Wyobra&#378;my sobie jednak, &#380;e projekt nam si&#281; rozr&#243;s&#322; i mamy ju&#380; ca&#322;kiem sporo kodu oraz sporo plik&#243;w (pomna&#380;anych wydatnie przez javowe ograniczenia co do ilo&#347;ci klas mog&#261;cych wyst&#261;pi&#263; w pliku). Teraz przychodzi polecenie aby w momencie odczytu i zapisu atrybutu co&#347; dodatkowego wykona&#263;. (Np. niech to b&#281;dzie logowanie informacji o takim zdarzeniu, albo zablokowanie mo&#380;liwo&#347;ci modyfikacji tre&#347;ci atrybutu. Wszystko jedno co)&lt;/p&gt;


	&lt;p&gt;Mamy zatem pierwszy problem. Trzeba w tych wszystkich milionach miejsc, gdzie odwo&#322;ywali&#347;my si&#281; bezpo&#347;rednio do atrybut&#243;w, wymieni&#263; kod&amp;#8230;&lt;/p&gt;


	&lt;p&gt;W&#322;a&#347;nie dlatego, aby takich niespodzianek unikn&#261;&#263; w przysz&#322;o&#347;ci, programi&#347;ci Javy dorzucaj&#261; dodatkowe metody opakowuj&#261;ce odczyt i zapis atrybut&#243;w. Eclipse upraszcza ten proces zwalniaj&#261;c programist&#281; od r&#281;cznego wpisywania tego kodu.&lt;/p&gt;


	&lt;p&gt;Klasa First po zmianie:&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_java "&gt;public class First {
  public String msg = &amp;quot;hello&amp;quot;;
  public String getMsg() {
    return msg;
  }
  public void setMsg(String msg) {
    this.msg = msg;
  }
}&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;Wydaje si&#281;, &#380;e problem jest rozwi&#261;zany. Ale to dopiero pocz&#261;tek innych problem&#243;w.&lt;/p&gt;


	&lt;p&gt;Je&#347;li  bowiem, automatycznie dorzucamy te metody do wszystkich tysi&#281;cy atrybut&#243;w nowo tworzonych klas, to pierwsz&#261; rzecz&#261; kt&#243;r&#261; zauwa&#380;amy, jest nag&#322;e &amp;#8220;spuchni&#281;cie kodu&amp;#8221;. &lt;em&gt;Mamy kup&#281; nieu&#380;ywanych linii kodu, z kt&#243;rych prawdopodobnie wi&#281;kszo&#347;&#263; nie b&#281;dzie nigdy u&#380;ywana!&lt;/em&gt;&lt;/p&gt;


	&lt;p&gt;Ale to nie wszystko. Za&#322;&#243;&#380;my, &#380;e stajemy przed potrzeb&#261; &lt;em&gt;zmiany nazwy atrybutu&lt;/em&gt;. Oczywi&#347;cie, mo&#380;emy to zmieni&#263; w jednym miejscu (w ciele akcesora), ale wtedy wprowadzamy chaos w pozosta&#322;ej cz&#281;&#347;ci odno&#347;nie&amp;#8230; nazw (atrybut &amp;#8220;msg&amp;#8221; zmieniony na &amp;#8220;title&amp;#8221; troch&#281; g&#322;upio wygl&#261;da z akcesorami o nazwie &amp;#8220;getMsg&amp;#8221; i &amp;#8220;setMsg&amp;#8221;) Musimy przekopa&#263; si&#281; przez miliony miejsc w kodzie i pozmienia&#263; nazwy starym wywo&#322;aniom.&lt;/p&gt;


	&lt;p&gt;Zobaczmy jak ta sytuacja wygl&#261;da w j&#281;zykach dynamicznych.&lt;/p&gt;


	&lt;h3&gt;Python&lt;/h3&gt;


	&lt;p&gt;Python (podobnie jak Java) pozwala na bezpo&#347;redni dost&#281;p do atrybut&#243;w klasy. A co w sytuacji kiedy chcemy opakowa&#263; atrybut akcesorami? Nic prostszego. &lt;em&gt;Python pozwala na dodanie akcesor&#243;w wtedy, i tylko wtedy, kiedy s&#261; potrzebne. Na dodatek czyni to w spos&#243;b ca&#322;kowicie przezroczysty dla pozosta&#322;ej cz&#281;&#347;ci kodu.&lt;/em&gt; Programista Javy mo&#380;e sobie o tym tylko pomarzy&#263;.&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;&lt;span class="keyword"&gt;class &lt;/span&gt;&lt;span class="class"&gt;X(object):&lt;/span&gt;
  &lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;get_msg&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="constant"&gt;self&lt;/span&gt;&lt;span class="punct"&gt;):&lt;/span&gt;
    &lt;span class="keyword"&gt;return&lt;/span&gt; &lt;span class="constant"&gt;self&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;__msg&lt;/span&gt;
  &lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;set_msg&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="constant"&gt;self&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="ident"&gt;val&lt;/span&gt;&lt;span class="punct"&gt;):&lt;/span&gt;
    &lt;span class="constant"&gt;self&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;__msg&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="ident"&gt;val&lt;/span&gt;
  &lt;span class="ident"&gt;msg&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="ident"&gt;property&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;get_msg&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="ident"&gt;set_msg&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;

&lt;span class="ident"&gt;obj&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="constant"&gt;X&lt;/span&gt;&lt;span class="punct"&gt;()&lt;/span&gt;
&lt;span class="ident"&gt;obj&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;msg&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;hello&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;
&lt;span class="ident"&gt;print&lt;/span&gt; &lt;span class="ident"&gt;obj&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;msg&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;Python pozwala tak&#380;e zwi&#261;za&#263; z dowoln&#261; metod&#261;, atrybutem, klas&#261; czy modu&#322;em &lt;em&gt;docstring&lt;/em&gt;, czyli tekst z dokumentacj&#261;, obja&#347;nieniem itp. To jedna z genialnych cech Pythona specjalnie pomy&#347;lana dla leniwych programist&#243;w, kt&#243;rym nie chce si&#281; pisa&#263; dokumentacji. ;)&lt;/p&gt;


	&lt;h3&gt;Ruby&lt;/h3&gt;


	&lt;p&gt;W j&#281;zyku Ruby z definicji nie ma &#380;adnej mo&#380;liwo&#347;ci dost&#281;pu do atrubut&#243;w klasy inaczej jak przez akcesory. Odpada wi&#281;c problem zapominania aby je doda&#263;. Ruby jednak narzuca nazwy dla akcesor&#243;w (maj&#261; nazw&#281; tak&#261; jak atrybut!) i ca&#322;o&#347;&#263; wygl&#261;da tak, jakby operowano bezpo&#347;rednio na atrybucie.&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;&lt;span class="keyword"&gt;class &lt;/span&gt;&lt;span class="class"&gt;X&lt;/span&gt;
  &lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;msg&lt;/span&gt;
    &lt;span class="attribute"&gt;@msg&lt;/span&gt;
  &lt;span class="keyword"&gt;end&lt;/span&gt;
  &lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;msg=&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;val&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
    &lt;span class="attribute"&gt;@msg&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="ident"&gt;val&lt;/span&gt;
  &lt;span class="keyword"&gt;end&lt;/span&gt;
&lt;span class="keyword"&gt;end&lt;/span&gt;

&lt;span class="ident"&gt;obj&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="constant"&gt;X&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;new&lt;/span&gt;
&lt;span class="ident"&gt;obj&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;msg&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;hello&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;
&lt;span class="ident"&gt;puts&lt;/span&gt; &lt;span class="ident"&gt;obj&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;msg&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

Dla os&#243;b, kt&#243;re nie lubi&#261; za du&#380;o pisa&#263;, Ruby ma wygodne skr&#243;ty. Powy&#380;sz&#261; definicj&#281; klasy mo&#380;na zapisa&#263; tak&#380;e w ten spos&#243;b:
&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;&lt;span class="keyword"&gt;class &lt;/span&gt;&lt;span class="class"&gt;X&lt;/span&gt;
  &lt;span class="ident"&gt;attr_accessor&lt;/span&gt; &lt;span class="symbol"&gt;:msg&lt;/span&gt;
&lt;span class="keyword"&gt;end&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;Istniej&#261; tak&#380;e oddzielne skr&#243;ty dla getter&#243;w i setter&#243;w. No i mo&#380;na po przecinku doda&#263; akcesory dla ca&#322;ej grupy atrybut&#243;w.&lt;/p&gt;


	&lt;h3&gt;&lt;span class="caps"&gt;PHP5&lt;/span&gt;&lt;/h3&gt;


	&lt;p&gt;&lt;span class="caps"&gt;PHP&lt;/span&gt; w wersji 5 ma przebudowany model obiektowy od podstaw. Tw&#243;rcy j&#281;zyka &lt;span class="caps"&gt;PHP&lt;/span&gt; nie starali si&#281; poprawia&#263; modelu obiektowego &lt;span class="caps"&gt;PHP4&lt;/span&gt; (by&#322; on tak z&#322;y, &#380;e pro&#347;ciej by&#322;o im napisa&#263; go od nowa). W nowym &lt;span class="caps"&gt;PHP5&lt;/span&gt; mamy ju&#380; mo&#380;liwo&#347;&#263; przezroczystego dodania akcesora.&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_php "&gt;&amp;lt;?php
class X {
  private $attributes = array('msg'=&amp;gt;null);
  private function __get($attrname) {
    return $this-&amp;gt;attributes[$attrname];
  }
  private function __set($attrname, $val) {
    $this-&amp;gt;attributes[$attrname] = $val;
  }
}

$obj = new X();
$obj-&amp;gt;msg = &amp;quot;hello&amp;quot;;
print $obj-&amp;gt;msg;
?&amp;gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;Sk&#322;adnia mo&#380;e nie jest tak prosta jak w Ruby, ale (przynajmniej w tym miejscu), &lt;span class="caps"&gt;PHP5&lt;/span&gt; zachowuje si&#281; tu sensownie i unika dylemat&#243;w Javy.&lt;/p&gt;</description>
      <pubDate>Tue, 07 Feb 2006 23:25:00 +0100</pubDate>
      <guid isPermaLink="false">urn:uuid:3c61a0f6-2070-4178-b4fb-4db526cb572e</guid>
      <author>Jaros&#322;aw Zabie&#322;&#322;o</author>
      <link>http://blog.zabiello.com/articles/2006/02/07/akcesory-w-javie-pythonie-ruby-i-php5</link>
      <category>Python</category>
      <category>Ruby</category>
      <category>Java</category>
      <category>java</category>
      <category>php</category>
      <category>python</category>
      <category>ruby</category>
    </item>
  </channel>
</rss>
