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

<channel>
	<title>profitto.pl</title>
	<atom:link href="http://blog.profitto.pl/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.profitto.pl</link>
	<description>Świadome finanse</description>
	<lastBuildDate>Mon, 04 Apr 2011 20:04:11 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.1.2</generator>
		<item>
		<title>MindPlace &#8211; czyli o biofeedbacku, relaksacji&#8230;</title>
		<link>http://blog.profitto.pl/2010/01/mindplace-czyli-o-biofeedbacku-relaksacji/</link>
		<comments>http://blog.profitto.pl/2010/01/mindplace-czyli-o-biofeedbacku-relaksacji/#comments</comments>
		<pubDate>Mon, 18 Jan 2010 10:49:03 +0000</pubDate>
		<dc:creator>Mikolaj Kmita</dc:creator>
				<category><![CDATA[Ogólne]]></category>

		<guid isPermaLink="false">http://blog.profitto.pl/?p=256</guid>
		<description><![CDATA[Obecnie prace nad projektem „Profitto” są zawieszone. Zapraszam za to do tworzącego się serwisu MindPlace, poświęconego biofeedbackowi, relaksacji, radzeniu sobie ze stresem. Pierwsze tematy związane są z biofeedback-iem, czyli czy można za pomocą urządzeń zmierzyć, jaki masz nastrój, jak można na to wpływać i co z tego wynika… Zapraszam http://www.mindplace.pl]]></description>
			<content:encoded><![CDATA[<p><a href="http://profi.vipserv.org/wp-content/uploads/2010/02/img_4799.jpg"><img class="size-thumbnail wp-image-269 alignleft" style="border: 1px solid black; margin-right: 10px;" title="Biofeedback" src="http://blog.profitto.pl/wp-content/uploads/2010/02/img_4799-150x150.jpg" alt="Biofeedback" width="150" height="150" /></a></p>
<p>Obecnie prace nad projektem „Profitto” są zawieszone.</p>
<p>Zapraszam za to do tworzącego się serwisu <a title="Serwis poświęcony biofeedback'owi, relaksacji, radzeniu sobie ze stresem" href="http://blog.mindplace.pl">MindPlace</a>, poświęconego biofeedbackowi, relaksacji, radzeniu sobie ze stresem. Pierwsze tematy związane są z biofeedback-iem, czyli czy można za pomocą urządzeń zmierzyć, jaki masz nastrój, jak można na to wpływać i co z tego wynika…</p>
<p>Zapraszam <img src='http://blog.profitto.pl/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p><a title="Serwis poświęcony biofeedback'owi, relaksacji, radzeniu sobie ze stresem" href="http://www.mindplace.pl">http://www.mindplace.pl</a></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.profitto.pl/2010/01/mindplace-czyli-o-biofeedbacku-relaksacji/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Beautiful Soup &#8211; parser HTML&#8217;a na (jeden) wieczór</title>
		<link>http://blog.profitto.pl/2009/02/beautiful-soup-parser-htmla-na-jeden-wieczor/</link>
		<comments>http://blog.profitto.pl/2009/02/beautiful-soup-parser-htmla-na-jeden-wieczor/#comments</comments>
		<pubDate>Sun, 08 Feb 2009 19:38:52 +0000</pubDate>
		<dc:creator>szymon</dc:creator>
				<category><![CDATA[Technologia]]></category>
		<category><![CDATA[HTML]]></category>
		<category><![CDATA[Python]]></category>

		<guid isPermaLink="false">http://blog.profitto.pl/?p=187</guid>
		<description><![CDATA[Zadanie napisania pierwszego &#8222;naszego&#8221; parsera padło na mnie. Nie będę ukrywał, że z początku uznałem to za pewne wyzwanie. Na szczęście dość szybko znalazłem to czego szukałem &#8211; czyli BeautifulSoup. Nazwa dość dziwna, ale o tym później. Wystarczyło kilka chwil (czytaj: wieczorów, gdy choć jeden domownik już śpi ), żeby przy jej użyciu, prosto i [...]]]></description>
			<content:encoded><![CDATA[<p><img class="alignright" style="border: 1px solid black; margin: 0px 10px;" src="http://www.cabcabinmoran.com/blog/wp-content/uploads/2007/04/beautifulsoup.jpg" alt="" width="336" height="219" /></p>
<p>Zadanie napisania pierwszego &#8222;naszego&#8221; parsera padło na mnie. Nie będę ukrywał, że z początku uznałem to za pewne wyzwanie. Na szczęście dość szybko znalazłem to czego szukałem &#8211; czyli <a title="BeautifulSoup" href="http://www.crummy.com/software/BeautifulSoup/" target="_blank">BeautifulSoup</a>.  Nazwa dość dziwna, ale o tym później. Wystarczyło kilka chwil (czytaj: wieczorów, gdy choć jeden domownik już śpi <img src='http://blog.profitto.pl/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' />  ), żeby przy jej użyciu, prosto i przyjemnie uzyskać to czego się chce. Nie będę tu pisał manual&#8217;a, ale pokusiłem się o prosty przykład. Załóżmy, że interesuje nas, kto komentował nasze wpisy ma blogu.  Voilà:</p>
<pre><code>
<pre class="brush: python; title: ;">
#-*- coding: UTF-8 -*-

from BeautifulSoup import BeautifulSoup
import urllib

url = &quot;http://blog.profitto.pl/2008/11/wybor-technologii&quot;
soup = BeautifulSoup(urllib.urlopen(url).read())

authors = set() # unikalność
for comment in soup('div',{'class':'cmtinfo'}):
    authors.add(comment.cite.string)

print ', '.join(authors)
</pre>
<p></code></pre>
<p><span id="more-187"></span></p>
<p>Jeśli jeszcze nie czujesz bluesa, to dodam, że BS poradzi sobie z popsutymi znacznikami i konwersją kodowania.  Poza tym mamy do dyspozycji całą moc pythona <img src='http://blog.profitto.pl/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' />  &#8211; biblioteki bardzo ułatwiają szybkie rozwiązywanie problemów z przymusem zalogowania się na stronę:</p>
<pre><code>
<pre class="brush: python; title: ;">
#-*- coding: UTF-8 -*-
# używamy słownika do wypełnienia formularza
from BeautifulSoup import BeautifulSoup
import urllib

url = &quot;http://poczta.profitto.pl&quot;
params =  urllib.urlencode( { 'login':'profitto',
                              'password':'żyrafyWchodząNaSzafy',
                              'hiddenField': 'hidden' } )
soup = BeautifulSoup(urllib.urlopen(url,params).read())
print soup.prettify()
</pre>
<p></code></pre>
<p>używania tylko najwłaściwszej przeglądarki:</p>
<pre><code>
<pre class="brush: python; title: ;">
#-*- coding: UTF-8 -*-

from BeautifulSoup import BeautifulSoup
import urllib2

url = &quot;http://www.useragent.org/&quot;
opener = urllib2.build_opener(urllib2.HTTPCookieProcessor())
opener.addheaders=[ ( 'user-agent','NCSA_Mosaic/2.0' ) ]
soup = BeautifulSoup(opener.open(url))
print soup.prettify()
</pre>
<p></code></pre>
<dl>
<dt><img class="alignleft" src="http://upload.wikimedia.org/wikipedia/commons/9/9a/Alice_par_John_Tenniel_34.png" alt="Żółwiciel opowiada" width="286" height="336" /></dt>
</dl>
<p>Na koniec dwa słowa o nazwie biblioteki. Brzmi dość dziwnie, ale jakoś przed zabraniem się za pisanie tego tekstu nie wnikałem skąd się wzięła. Nie powiem, że mnie nie natchnęła (fragment kodu: soup = kitchen.getSoup(url)  <img src='http://blog.profitto.pl/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' />  ).  Nie trzeba wiele, by odkryć (mam nadzieje, że nie tylko ja musiałem to odkrywać) &#8211; ta nazwa zainspirowana jest utworem Lewis&#8217;a Carroll&#8217;a <em>Alicja w Krainie Czarów</em>. A dokładnie jest to podmiot liryczny jednej z <a href="http://www.durrant.co.uk/alice/" target="_blank">piosenek </a>- Soup Of The Evening. Zupa na wieczór &#8211; niekoniecznie jeden.</p>
<h3>Dodatkowa literatura:</h3>
<ul>
<li><a href="http://www.rwdev.eu/articles/urllib2" target="_blank">urllib2 &#8211; zaginiony podręcznik</a></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://blog.profitto.pl/2009/02/beautiful-soup-parser-htmla-na-jeden-wieczor/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Szata graficzna</title>
		<link>http://blog.profitto.pl/2008/12/szata-graficzna/</link>
		<comments>http://blog.profitto.pl/2008/12/szata-graficzna/#comments</comments>
		<pubDate>Sun, 28 Dec 2008 10:00:42 +0000</pubDate>
		<dc:creator>Mikolaj Kmita</dc:creator>
				<category><![CDATA[Ogólne]]></category>
		<category><![CDATA[Design]]></category>

		<guid isPermaLink="false">http://blog.profitto.pl/?p=149</guid>
		<description><![CDATA[Tam gdzie to możliwe staramy się prowadzić prace równocześnie. Więc równolegle z naszymi pracami developerskimi postępowały prace nad szatą graficzną. Dzięki współpracy ze zdolnym, młodym grafikiem Michałem Parulskim możemy zaprezentować naszą stronę główną &#8211; zapraszamy więc na nią: http://www.profitto.pl. Wszelkie komentarze, uwagi, sugestie mile widziane (także te krytyczne, dzięki którym można wprowadzić poprawki ). Wydawałoby [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://profi.vipserv.org/wp-content/uploads/2008/12/mainpage.png"><img class="alignleft size-medium wp-image-150" style="border: 1px solid black; margin: 5px 10px;" title="mainpage" src="http://blog.profitto.pl/wp-content/uploads/2008/12/mainpage-300x212.png" alt="" width="300" height="212" /></a>Tam gdzie to możliwe staramy się prowadzić prace równocześnie. Więc równolegle z naszymi pracami developerskimi postępowały prace nad szatą graficzną. Dzięki współpracy ze zdolnym, młodym grafikiem <a href="http://shuma87.carbonmade.com/projects/85460">Michałem Parulskim</a> możemy zaprezentować naszą stronę główną &#8211; zapraszamy więc na nią: <a href="http://www.profitto.pl">http://www.profitto.pl</a>. Wszelkie komentarze, uwagi, sugestie mile widziane (także te krytyczne, dzięki którym można wprowadzić poprawki <img src='http://blog.profitto.pl/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' />  ).</p>
<p><a href="http://profi.vipserv.org/wp-content/uploads/2008/12/billboard.png"><img class="alignright size-medium wp-image-169" style="border: 1px solid black; margin: 5px 10px;" title="billboard" src="http://blog.profitto.pl/wp-content/uploads/2008/12/billboard-224x300.png" alt="" width="224" height="300" /></a><br />
Wydawałoby się, że prezenty gwiazdowe znajduje się tylko pod choinką. W czasie jednego ze świątecznych spacerów zauważyłem na mieście pewien intrygujący billboard &#8211; jako, że miałem ze sobą aparat uwieczniłem tą chwilę&#8230; <img src='http://blog.profitto.pl/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> </p>
]]></content:encoded>
			<wfw:commentRss>http://blog.profitto.pl/2008/12/szata-graficzna/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Association, Composition and Aggregation</title>
		<link>http://blog.profitto.pl/2008/12/association-composition-and-aggregation/</link>
		<comments>http://blog.profitto.pl/2008/12/association-composition-and-aggregation/#comments</comments>
		<pubDate>Sat, 06 Dec 2008 15:49:44 +0000</pubDate>
		<dc:creator>Mikolaj Kmita</dc:creator>
				<category><![CDATA[Technologia]]></category>
		<category><![CDATA[UML]]></category>

		<guid isPermaLink="false">http://blog.profitto.pl/?p=101</guid>
		<description><![CDATA[Dzisiaj krótszy post i to trochę filozoficznej natury. Rysując model domenowy dla naszej aplikacji w postaci UML-owego diagramu klas natknąłem się na pewną zagwozdkę. Konkretnie dylemat dotyczył różnic pomiędzy asocjacją, kompozycją a agregacją. Czytając formalne opisy, sprawa wydaje się prosta. Wątpliwości pojawiają się  w przypadku wyboru pomiędzy asocjacją, a jej bardziej specjalizowanym kuzynem &#8211; agregacją. [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://blog.profitto.pl/wp-content/uploads/2008/12/uml.jpg"><img class="size-full wp-image-107 alignleft" title="uml" src="http://blog.profitto.pl/wp-content/uploads/2008/12/uml.jpg" alt="" width="245" height="193" /></a></p>
<p>Dzisiaj krótszy post i to trochę filozoficznej <img src='http://blog.profitto.pl/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' />  natury.</p>
<p>Rysując <a title="Domain model" href="http://en.wikipedia.org/wiki/Domain_model">model domenowy</a> dla naszej aplikacji w postaci <a href="http://pl.wikipedia.org/wiki/UML">UML-owego</a> diagramu klas natknąłem się na pewną zagwozdkę. Konkretnie dylemat dotyczył różnic pomiędzy asocjacją, kompozycją a agregacją. Czytając <a href="http://en.wikipedia.org/wiki/Class_diagram#Association">formalne opisy</a>, sprawa wydaje się prosta. Wątpliwości pojawiają się  w przypadku wyboru pomiędzy asocjacją, a jej bardziej specjalizowanym kuzynem &#8211; agregacją. Agregacja zgodnie z  definicją reprezentuje asocjację typu &#8222;has a&#8221;. Jednak rysując już konkretny diagram wybór ten nie jest wcale taki oczywisty: człowiek &#8222;subskrybuje&#8221; czasopismo (asocjacja), czy też człowiek &#8222;ma subskrypcję na&#8221; czasopismo (agregacja) &#8211; przykłady i dyskusje można by mnożyć bez końca.</p>
<p><span id="more-101"></span></p>
<p>Co więcej różnica ta nie ma żadnego przełożenia na kod programu, gdyż zarówno asocjacja, jak i agregacja reprezentowane są w identyczny sposób. Gdzie więc narysować grubą czerwoną linię oddzielającą jedno pojęcie od drugiego, gdy nie dość że z <a title="Semantyka" href="http://pl.wikipedia.org/wiki/Semantyka">semantycznego</a> punktu widzenia sprawa jest mocno dyskusyjna, to dodatkowo jeszcze wybór takiego a nie innego rodzaju połączenia nie powoduje żadnego rozróżnienia w kodzie? Modelowanie nie powinno być sztuką dla sztuki i taki a nie inny model powinien mieć praktyczne odzwierciedlenie. Zdaje się, że w związku z takimi niejednoznacznościami, przez pewien czas planowano nawet <a href="http://saloon.javaranch.com/cgi-bin/ubb/ultimatebb.cgi?ubb=get_topic&amp;f=26&amp;t=005723">usunąć pojęcie &#8222;agregacji&#8221; z UML 2.0</a>, finalnie jednak tak się nie stało.</p>
<p>Z kompozycją sprawa jest już dużo prostsza, ponieważ ten rodzaj połączenia dodaje istotną informację, że pewien obiekt może istnieć wyłącznie jako część kompozycji i tym samym cykl jego życia jest zależny od cyklu życia obiektu-kontenera. W przypadku języków nie posiadających <a href="http://pl.wikipedia.org/wiki/Garbage_collection">garbage collector-a</a>, jak np. C++, będzie to oznaczało, że w trakcie niszczenia obiektu-kontenera, powinny być niszczone obiekty, które on zawiera. W przypadku nowocześniejszych języków, jak np. Java, C#, Python, itp. nie będzie to jednak już tak widoczne &#8211; ponieważ tam nie ma potrzeby &#8222;ręcznego&#8221; zwalniania pamięci.</p>
<h3>Konkluzja</h3>
<p>Pojęcie kompozycji wydaje się być dość jasno określone, co jednak z dylematem asocjacja vs agregacja? Tutaj skłaniam się ku sugestii Martina Fowler-a: <a href="http://martinfowler.com/bliki/AggregationAndComposition.html">nie używaj agregacji</a>, dopóki nie masz naprawdę dobrego uzasadnienia <img src='http://blog.profitto.pl/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' />  .</p>
<p><span style="text-decoration: underline;">Lektura uzupełniająca:</span></p>
<ul>
<li><a href="http://faq.javaranch.com/java/AssociationVsAggregationVsComposition">JavaRanch FAQ: Association Vs Aggregation Vs Composition</a></li>
<li><a href="http://faq.javaranch.com/java/AssociationVsAggregationVsComposition">Association</a><a href="http://saloon.javaranch.com/cgi-bin/ubb/ultimatebb.cgi?ubb=get_topic&amp;f=9&amp;t=001852">, Composition and </a><a href="http://faq.javaranch.com/java/AssociationVsAggregationVsComposition">Aggregation</a><a href="http://saloon.javaranch.com/cgi-bin/ubb/ultimatebb.cgi?ubb=get_topic&amp;f=9&amp;t=001852"> (OO, Patterns, UML and Refactoring forum at JavaRanch)</a></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://blog.profitto.pl/2008/12/association-composition-and-aggregation/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Wybór technologii</title>
		<link>http://blog.profitto.pl/2008/11/wybor-technologii/</link>
		<comments>http://blog.profitto.pl/2008/11/wybor-technologii/#comments</comments>
		<pubDate>Tue, 11 Nov 2008 22:54:45 +0000</pubDate>
		<dc:creator>Mikolaj Kmita</dc:creator>
				<category><![CDATA[Technologia]]></category>
		<category><![CDATA[Django]]></category>
		<category><![CDATA[Python]]></category>

		<guid isPermaLink="false">http://blog.profitto.pl/?p=30</guid>
		<description><![CDATA[Wstęp Jednym z pytań, które zazwyczaj sobie stawiamy rozpoczynając nowy projekt jest to dotyczące wyboru technologii. Nie inaczej było i tym razem &#8211;  każda technologia ma swoje plusy i minusy, swoje specyficzne smaczki, które powodują że dla pewnych zagadnień sprawdza się lepiej lub gorzej. Najlepszego języka/framework-a nie ma i być nie może, z tej prostej [...]]]></description>
			<content:encoded><![CDATA[<h1>Wstęp</h1>
<p>Jednym z pytań, które zazwyczaj sobie stawiamy rozpoczynając nowy projekt jest to dotyczące wyboru technologii. Nie inaczej było i tym razem &#8211;  każda technologia ma swoje plusy i minusy, swoje specyficzne smaczki, które powodują że dla pewnych zagadnień sprawdza się lepiej lub gorzej. Najlepszego języka/framework-a nie ma i być nie może, z tej prostej przyczyny że każdy zwraca uwagę na inne detale, co innego jest dla niego istotne, tak też framework-i skupiają się na różnych aspektach: szybkości tworzenia, elegancji, wydajności, itd. Pojawienie się idealnego języka/framework-a oznaczałoby koniec rozwoju, stagnację&#8230; na szczęście wygląda, że nam to nie grozi. Zadaniem tego postu jest pokazanie na co my zwróciliśmy uwagę i jaka decyzję finalnie podjęliśmy.</p>
<p><span id="more-30"></span></p>
<p>W zależności od naszej wiedzy, doświadczeń oraz ilości czasu jaki mamy na podjęcie takiej decyzji możemy podejść do tematu w różny sposób:</p>
<ul>
<li>Wybór podyktowany technologiami, które już znamy. Z jednej strony dzięki temu minimalizujemy czas potrzebny na poznanie nowych technologii, minimalizujemy ryzyko wszelkiego rodzaju potyczek technologicznych, bo cześć z nich już stoczyliśmy i znamy gotowe rozwiązania. Z drugiej strony możemy w ten sposób utknąć przy rozwiązaniach, które na chwilę obecną z różnych względów nie są najbardziej optymalne,</li>
<li>Rozpoznanie bojem. Jedno z bardziej ciekawych i rozwijających podejść do tematu. Wybieramy N najbardziej rokujących naszym zdaniem rozwiązań, a następnie dla każdego z nich wykonujemy mały <a title="Proof of concept" href="http://en.wikipedia.org/wiki/Proof_of_concept#In_software_development">PoC</a> (&#8222;Proof of Concept&#8221;, nie mylić z &#8222;Pirates of the Caribbean&#8221; <img src='http://blog.profitto.pl/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' />  ). Podejście to wymaga jednego założenia: mamy sporo czasu na takie prace, a z tym to już różnie bywa&#8230;,</li>
<li>Zapoznanie się z możliwie szeroką opinią innych ludzi. Możemy więc spędzić kilka wieczorów z Google-em i na podstawie tak ograniczonej ilości informacji podjąć decyzję. Z jednej strony pomysł może wydawać się ryzykowny, bo na temat każdej technologii znajdziemy zarówno psalmy pochwalne jak i posty o przeciwnym zabarwieniu (wystarczy wpisać w google-a wybrany język + sucks, np. &#8222;php sucks&#8221;). Z drugiej strony przy odpowiedniej dawce przeciwstawnych opinii i odrobinie intuicji, można podjąć naprawdę dobrą decyzję niskim kosztem.</li>
</ul>
<h1>Szranki i konkury<sup><a href="#fn1">1</a></sup></h1>
<p>Pierwszym moim podejściem było &#8222;znana technologia&#8221; &#8212; miała to być Java, jako że ostatnie kilka lat spędziłem tworząc aplikacje web-owe oparte o ten właśnie język (oczywiście plus framework-i jak <a title="Apache Struts Project" href="http://struts.apache.org/">Struts</a>, <a title="Relational Persistence for Java and .NET" href="http://www.hibernate.org/">Hibernate</a>, itp.). Rozważałem także dodanie jednego czy dwóch framework-ów, z którymi nie miałem dużych doświadczeń (jak np. <a title="Spring Application Framework " href="http://www.springframework.org/">Spring</a>), ale generalnie zamierzałem oprzeć się na znanych mi rozwiązaniach.</p>
<p>Jednak prace mimo wszystko nie posuwały się tak szybko, jakbym sobie tego życzył. Przy drugim podejściu, które nastąpiło jakiś czas później postanowiłem poddać weryfikacji swoją wcześniejszą decyzję. Jako, że na nadmiar wolnego czasu raczej nie mogę narzekać, stanęło na rozwiązaniu: &#8222;kilka wieczorów z Google-m&#8221;. Do szranków stanęły:</p>
<ul>
<li>C#</li>
<li>Java</li>
<li>PHP</li>
<li>Python</li>
<li>Perl</li>
<li>Ruby</li>
</ul>
<p>(oczywiście powyższa lista nie zawiera wszystkich dostępnych opcji, a tylko te, które w moim odczuciu były najbardziej rokujące)</p>
<p>Teoretycznie aplikację tego typu można napisać w każdym z wymienionych języków (oraz w sporej ilości niewymienionych), ale jak przychodzi już do pisania trzeba się zdecydować na ten jeden konkretny, który w naszym odczuciu do danego rodzaju aplikacji będzie najodpowiedniejszy. Na początek postanowiłem przyjrzeć się następującym kryteriom:</p>
<ul>
<li>otwartość rozwiązania, rozumiana głównie jako otwartość źródeł,</li>
<li>szybkość tworzenia kodu oraz łatwość jego późniejszego rozwoju i utrzymania,</li>
<li>popularność danego języka a tym samym łatwość późniejszego pozyskania na rynku developerów posługujących się nim,</li>
<li>szeroko rozumiana zasobo-żerność i wynikająca z niej wydajność przy określonej ilości sprzętu,</li>
<li>dostępność zewnętrznych bibliotek (najlepiej freeware-owych),</li>
<li>składnia języka,</li>
<li>dojrzałość framework-ów służących do tworzenia aplikacji web-owych w danym języku, najlepiej opartych o model <a href="http://pl.wikipedia.org/wiki/MVC">MVC.</a></li>
</ul>
<p>Mając to wszytko na uwadze rozpocząłem swoje wieczory sam na sam z Google-m. Prawdę mówiąc wybór był już dokonany (Java) i tak naprawdę chciałem tylko potwierdzić jego słuszność. Trzeba przyznać, że trochę byłem zaskoczony (tak to jest, gdy człowiek skupi się tylko na korporacyjnych rozwiązaniach), gdy już po kilku godzinach poszukiwań okazało się, że Java delikatnie mówiąc, nie jest najczęściej wybieranym rozwiązaniem &#8212; z większych serwisów wypatrzyłem tylko <a href="http://www.feedburner.com">FeedBurner</a> (który oparty jest na <a title="Interview with Traci Hailpern, FeedBurner" href="http://www.seomoz.org/web2.0/interview/feedburner/2007">Java+JS+Tomcat+MySQL</a>. Z naszego rodzimego podwórka serwis <a title="grono.net - internetowa społeczność przyjaciół" href="http://grono.net/">Grono.net</a> początkowo napisany został w oparciu o język Java, jednak po dwóch latach został on przepisany, wykorzystując tym razem <a title="Historia Grono.net" href="http://pl.wikipedia.org/wiki/Grono.net#Historia_Grono.net">Python+Django</a> &#8212; swoją drogą chętnie spytałbym się osób odpowiedzialnych za tą decyzję, co spowodowało tak poważną decyzję i co ważniejsze jak tą decyzję oceniają z perspektywy następnych kilku lat.</p>
<h2>Otwartość rozwiązania</h2>
<p>Na tym etapie odpadł C#, w zasadzie bez większego zgłębiania tematu. Język ten na pewno ma mnóstwo ciekawych rozwiązań, jednak fakt ograniczenia się do produktów Microsoft-u zadecydował o jego dyskwalifikacji. Wszystkie inne rozwiązania w mniejszym lub większym stopniu oparte są o otwarte rozwiązania.</p>
<h2>Szybkość tworzenia / łatwość utrzymania aplikacji</h2>
<p>Nie są to rzeczy łatwo mierzalne, jednak ze wszystkich znaków na niebie i ziemi (czyli dziesiątków postów) wynika że znacząco szybciej tworzy się kod przy użyciu języków interpretowanych, <a href="http://pl.wikipedia.org/wiki/Dynamiczne_typowanie">dynamicznie typowanych</a>. Jeśli chodzi o łatwość utrzymania kodu, to tak postawione pytanie jest jednym z wielu wywołujących niekończące się dyskusje w stylu: które języki są lepsze dynamicznie, czy statycznie typowane, KDE czy GNOME, Ruby czy Python, święta Bożego Narodzenia, czy Wielkanocne. Dotąd też byłem zwolennikiem języków statycznie typowanych i taki Smalltalk wydawał mi się onegdaj bardziej ciekawostką, niż językiem do tworzenia dużych systemów. Jednak wydaje się, że w przypadku serwisów internetowych języki dynamiczne lepiej się sprawdzają ze względu na zwiększenie produktywności. A wady takie jak trudniejszy refactoring, czy też możliwość, że pewne błędy zostaną wyłapane dopiero w czasie testów (a nie kompilacji) są akceptowalnym kosztem.  W swoim czasie <a href="http://pl.wikipedia.org/wiki/Bruce_Eckel">Bruce Eckel</a> (tak ten od &#8222;Thinking in Java&#8221;, &#8222;Thinking in C++&#8221;) popełnij następujący post <a href="http://mindview.net/WebLog/log-0025">Strong Typing vs. Strong Testing</a>, traktujący o tym że w dobie <a title="Test-driven development" href="http://en.wikipedia.org/wiki/Test-driven_development">TDD</a> zysk ze statycznej kontroli typów stał się znikomy.</p>
<p>W tym konkretnym konkursie postanowiłem więc przyznać punkty językom dynamicznie typowanym, tj. Perl/Python/PHP/Ruby. Jeśli kogoś zainteresowało porównanie mocnych i słabych strony języków typowanych statycznie versus dynamicznie, to odsyłam do małej prezentacji <a href="http://blog.dhananjaynene.com/2008/07/presentation-contrasting-java-and-dynamic-languages/">Contrasting java and dynamic languages</a>. Interesujące porównanie jest także tutaj <a href="http://www.dmh2000.com/cjpr/index.shtml">C++ vs Java vs Python vs Ruby</a> (i od razu oczywiście <a href="http://www.donationcoder.com/Forums/bb/index.php?topic=14231.0">krytyka takiego podejścia</a>).</p>
<h2>Popularność danego języka</h2>
<p>Jednym ze sposobów weryfikacji popularności języka może być: <a href="http://www.tiobe.com/index.php/content/paperinfo/tpci/index.html">TIOBE Programming Community Index</a> lub <a href="http://www.langpop.com/">Programming Language Popularity</a>. Innym weryfikacja na swoim ulubionym portalu z pracą, ile jest ofert związanych z określonym językiem programowania. W zależności od wyboru takiego portalu (polski/zagraniczny) wyniki mogą się trochę różnić. Wydaje się jednak że ze znalezieniem programistów Java lub PHP nie powinno być problemu. Choć w przypadku PHP należałoby pewnie zadać sobie także dodatkowe pytanie: Jak wielu z nich jest obeznanych z programowaniem obiektowym, zna i docenia zalety modeli typu MVC.</p>
<p>A może jeśli na lokalnym rynku nie ma za dużo programistów znających język, który chcemy użyć jesteśmy w stanie stworzyć odpowiednie community? Czy są blisko uczelnie informatyczne, które używają danego języka programowania w trakcie nauki studentów? Jeśli nie, to czy byłyby skłonne zacząć i jeszcze lepiej współuczestniczyć w tworzeniu community?</p>
<h2>Wydajność</h2>
<p>Dość trudno odpowiedzieć na to pytanie. Z jednej strony te same <a title="Performance Comparison - C++ / Java / Python / Ruby/ Jython / JRuby / Groovy" href="http://blog.dhananjaynene.com/2008/07/performance-comparison-c-java-python-ruby-jython-jruby-groovy/">algorytmy napisane w Java wydają się być szybsze niż ich odpowiedniki w Python/Ruby</a>. Z drugiej strony, jak się spojrzy ile pamięci potrzebuje Tomcat, aby rozsądnie działać versus np. moduł mod_python, to sprawa nie jest już taka oczywista. Można w internecie znaleźć setki takich porównań a chwilę potem tyle samo komentarzy przekonywujących czemu dany test nie ma specjalnie sensu. Przykładowe posty: <a href="http://railsforum.com/viewtopic.php?id=18547">Ruby on Rails vs. Django performance</a>, <a href="http://wiki.rubyonrails.com/rails/pages/Framework+Performance">Framework Performance</a>, <a title="The performance test of 6 leading frameworks" href="http://www.alrond.com/en/2007/jan/25/performance-test-of-6-leading-frameworks/">The performance test of 6 leading frameworks</a> (choć ten już trochę leciwy, bo z 2007 roku).</p>
<p>Osobiście byłbym skłonny dołączyć się do głosów, że 20-30% różnicy w takich testach nie jest specjalnie znaczące, a większość optymalizacji dotyczy bazy danych.</p>
<p>W kategorii tej nie został wybrany jednoznaczny zwycięzca.</p>
<h2>Zewnętrzne biblioteki</h2>
<p>Wydaje się, że wszystkie z wymienionych języków mają dość bogatą ofertę zewnętrznych bibliotek.</p>
<p>Więc także brak jednoznacznego zwycięzcy.</p>
<h2>Składnia języka</h2>
<p>Jeden język został na tym etapie zdyskwalifikowany &#8212; Perl, rozumiem, że są zadania gdzie świetnie się sprawdza, ale do mnie jego składnia nie trafia i już. Także PHP nie popisał się na tym polu, w internecie aż roi się od postów wytykających bałagan dotyczący składni, np. <a href="http://www.codinghorror.com/blog/archives/001119.html">PHP Sucks, But It Doesn&#8217;t Matter</a>.</p>
<h2>Framework-i</h2>
<p>Każde z tych rozwiązań dorobiło się już dojrzałych framework-ów. Dla PHP są to m.in. <a href="http://cakephp.org/">CakePHP</a>, <a href="http://www.symfony-project.org/">Symfony</a>, <a href="http://framework.zend.com/">Zend</a>, dla Ruby <a href="http://www.rubyonrails.org/">Ruby on Rails</a>, a także ostatnio <a href="http://merbivore.org/">Merb</a>. Dla Python-a będą to chociażby: <a href="http://www.djangoproject.com/">Django</a>, <a href="http://turbogears.org/">TurboGears</a>, <a href="http://pylonshq.com/">Pylons</a>, o Javie nie wspominając, bo ciężko byłoby je wszystkie wymienić.</p>
<p>Tak więc i w tej kategorii nie ma jednoznacznych wygranych, czy też przegranych.</p>
<h2>Podsumowanie</h2>
<p>Wybór w dużej mierze sprowadza się do zagadnienia &#8222;języki typowane statycznie versus dynamicznie&#8221;. Te drugie pozwalają szybciej kodować, oczywiście jakimś kosztem. Wydaje się jednak, że w naszym przypadku zastosowanie ich jest całkowicie uzasadnione.</p>
<h1>And the winner is&#8230;</h1>
<p>Które więc z rozwiązań PHP/Python/Perl/Ruby. Perl odpadł w związku z jego składnią. PHP jakoś mimo swojej dużej popularności do mnie nie przemawia &#8212; zresztą nie tylko do mnie (jedna z wielu <a title="Forum PHP.pl &gt; Inne &gt; Hydepark &gt; Python" href="http://forum.php.pl/index.php?showtopic=64555">dyskusji o wyższości jednego języka nad drugim</a>). Może jest to kwestia różnych korzeni &#8211; moje są obiektowe, jego nie specjalnie. Pozostają Python i Ruby &#8212; oba obiektowe, oba mające swoich zwolenników i przeciwników.</p>
<p>Schodząc na poziom framework-ów oznaczało wybór pomiędzy: Django/Pylons/TurboGears/Ruby on Rails/Merb. Tu wybór nie był już wcale oczywisty i każdy z nich prawdopodobnie świetnie by się spisał. Jednak decyzję trzeba podjąć &#8212; Merb wydaje się trochę za świeży, RoR ma trochę <a title="Rails' Ridiculous Restrictions, a Rant" href="http://discuss.joelonsoftware.com/default.asp?joel.3.309321.2">za dużo magii</a>, Pylons&amp;TurboGears z jednej strony integrują w całość najlepsze komponenty, z drugiej strony czas potrzebny na to, aby stać się produktywnym jest siłą rzeczy większy, no i ta nie najlepsza dokumentacja. Django za to sprawdził się w boju, okrzepł (ostatnio dorobił się wersji 1.0), ma doskonałą dokumentację i nawet jeśli w pewnych miejscach jest trochę słabszy &#8212; zdaje się być najlepszym wyborem dla nas. Dodatkowo Python jest jednym z trzech głównych języków używanych w firmie Google, a ichni <a href="http://code.google.com/appengine/docs/whatisgoogleappengine.html">Google App Engine</a> pozwala uruchamiać aplikacje w okrojonej wersji Django, co nawet jeśli nie zamierzamy tego wykorzystywać o czymś świadczy.</p>
<p><strong>Tak więc wybraliśmy zestaw: Python + Django.</strong></p>
<p>Jeśli ktoś ma ochotę na więcej, poniżej inne ciekawe posty w temacie wyboru technologii:</p>
<ul>
<li><a href="http://blog.zabiello.com/articles/2007/08/25/aplikacja-webowa-wybor-technologii">Aplikacja webowa &#8211; wybór technologii</a></li>
<li><a href="http://www.morizon.pl/blog/2008/04/04/dlaczego-ruby-on-rails/">Dlaczego Ruby on Rails?</a></li>
</ul>
<p>Założenia z grubsza mieliśmy podobne, jednak jak widać decyzje podjęliśmy inne. Czy któraś z nich była lepsza/gorsza? Moim zdaniem nie, po prostu są one inne. Co więcej, za pół roku mając te same założenia można by podjąć inną decyzję.</p>
<hr size="1" />
<p id="fn1"><sup>1</sup> <a href="http://merlin.pl/Kajko-i-Kokosz-Szranki-i-konkury-czesc-1_Janusz-Christa/browse/product/1,558846.html">Szranki i konkury</a> &#8211; zbieżność tytułów całkowicie przypadkowa</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.profitto.pl/2008/11/wybor-technologii/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
	</channel>
</rss>

