<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/atom10full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><feed xmlns="http://www.w3.org/2005/Atom" xmlns:openSearch="http://a9.com/-/spec/opensearch/1.1/" xmlns:georss="http://www.georss.org/georss" xmlns:gd="http://schemas.google.com/g/2005" xmlns:thr="http://purl.org/syndication/thread/1.0" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" gd:etag="W/&quot;DkEDQH48fip7ImA9WhRaGEQ.&quot;"><id>tag:blogger.com,1999:blog-3992064681062004055</id><updated>2012-02-22T08:11:11.076+01:00</updated><category term="SOLID" /><category term="Domain Driven Design (DDD)" /><category term="TestNG" /><category term="JPA" /><category term="LJUG" /><category term="Erlang Ant Library" /><category term="PL/SQL" /><category term="Hibernate" /><category term="OOD" /><category term="hamcrect" /><category term="Software Craftsmanship" /><category term="Clojure" /><category term="SCJP" /><category term="Lisp" /><category term="Oracle DB" /><category term="szacowanie" /><category term="NetBeans Platform" /><category term="Firefox plugins" /><category term="JRuby" /><category term="typy generyczne" /><category term="DWR" /><category term="iBATIS" /><category term="Eclipse plugins" /><category term="Property" /><category term="warsztat dewelopera" /><category term="JUnit" /><category term="Spring" /><category term="Commons Configuration" /><category term="testy jednostkowe" /><category term="konfiguracja" /><category term="JBoss" /><category term="quick and dirty" /><category term="zawód programista" /><category term="MySQL" /><category term="OSGi" /><category term="Java EE" /><category term="XStream" /><category term="hamcrest" /><category term="java4people" /><category term="Narzędzia" /><category term="XML" /><category term="wzorce" /><category term="Java" /><category term="EJB 3.0" /><category term="Cobertura" /><category term="log4j" /><category term="SCRUM" /><category term="Tomcat" /><category term="Domain Specific Languages (DSL)" /><category term="Komentarze" /><category term="domknięcia" /><category term="Agile" /><category term="Ruby" /><category term="Maven" /><category term="Commons Logging" /><category term="OOP" /><category term="Konferencje" /><category term="książki" /><category term="Meta Programming Systems (MPS)" /><category term="Wiki" /><category term="JavaScript" /><category term="plugins" /><category term="certyfikaty" /><category term="Ant" /><category term="mapowanie obiektowo-relacyjne" /><category term="Struts 2" /><category term="Erlang" /><title>IT Researches</title><subtitle type="html">Some thoughts on casting spells, writing scrolls, studying magic ... and other software development activities.</subtitle><link rel="http://schemas.google.com/g/2005#feed" type="application/atom+xml" href="http://it-researches.blogspot.com/feeds/posts/default" /><link rel="alternate" type="text/html" href="http://it-researches.blogspot.com/" /><link rel="next" type="application/atom+xml" href="http://www.blogger.com/feeds/3992064681062004055/posts/default?start-index=26&amp;max-results=25&amp;redirect=false&amp;v=2" /><author><name>Piotr Paradzinski</name><uri>http://www.blogger.com/profile/07915292026695759953</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="25" height="32" src="http://4.bp.blogspot.com/_cGW9IpdChVc/SYRCu49W5lI/AAAAAAAAADE/eZPPGD0JW_Q/S220/PiotrParadzinski.jpg" /></author><generator version="7.00" uri="http://www.blogger.com">Blogger</generator><openSearch:totalResults>112</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/atom+xml" href="http://feeds.feedburner.com/ItResearches" /><feedburner:info uri="itresearches" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><entry gd:etag="W/&quot;Ck4MR3ozfyp7ImA9Wx5UGUo.&quot;"><id>tag:blogger.com,1999:blog-3992064681062004055.post-2894027970379957421</id><published>2010-10-25T03:43:00.000+02:00</published><updated>2010-10-25T03:43:06.487+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-10-25T03:43:06.487+02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Java" /><category scheme="http://www.blogger.com/atom/ns#" term="Konferencje" /><category scheme="http://www.blogger.com/atom/ns#" term="Clojure" /><title>Konferencja Warsjava 2010</title><content type="html">Konferencję &lt;a href="http://github.com/warszawajug/warsjawa2010/wiki/Konferencja-Warsjawa-2010"&gt;Warsjava&lt;/a&gt; uważam za udaną. Ponowne spotkanie ludzi których pamiętam z java4people i pierwszej edycji COOLuarów. Dające do myślenia prelekcje i dyskusje po nich.&lt;br /&gt;
&lt;br /&gt;
Niestety spóźniłem się. Trafiłem dopiero na 2 wystąpienie &lt;a href="http://sprawnainzynieriaoprogramowania.blogspot.com/"&gt;Pawła Lipińskiego&lt;/a&gt;. Gdy spytałem sąsiadów o temat, zyskałem beztroskie wzruszenie ramionami. Fakt, student ma inne rzeczy na głowie, gdy dostaje test za rozwiązanie którego można wygrać koszulkę czy też PlayStation :)&lt;br /&gt;
&lt;br /&gt;
Jedna z koncepcji przedstawiona przez prelegenta nie daje mi spokoju: &lt;b&gt;robienie jednej rzeczy jest lepsze niż wielu jednocześnie&lt;/b&gt;. Sam podczas rozwiązywania problemów staram się robić 2 rzeczy. Gdy zatnę się na jednej, ruszam z drugą. Pozwalam przetwarzać moim neuronom pierwszy problem w tle. &lt;br /&gt;
&lt;br /&gt;
Czasami po prostu wiem, że kolejne zadanie spowoduje długie czekanie (na pobranie połowy netu przez Maven'a lub kolejny krok instalacji Oracle) więc staram się zrobić kilka drobnych rzeczy po drodze.&lt;br /&gt;
&lt;br /&gt;
Zasada równoległej realizacji niezależnych zadań świetnie sprawdza się w zarządzaniu projektem i przetwarzaniu danych przez automaty. Tylko czy działa to na poziomie indywidualnej organizacji zadań?&lt;br /&gt;
&lt;br /&gt;
Ileż to razy robiłem podwójny update bo spodziewając się że chwilkę zajmie - przełączałem się na struganie skryptu w oknie obok. Po powrocie do pierwotnego kodu nie pamiętałem czy zrobiłem ten update czy tylko chciałem go zrobić - więc dla pewności ... :)&lt;br /&gt;
&lt;br /&gt;
Ileż razy musiałem ponownie zainstalować Oracle bo zapomniałem zaznaczyć jakieś ważnej opcji lub usunąć któregoś wpisu w rejestrze przy poprzednim odinstalowaniu Oracle :)&lt;br /&gt;
&lt;br /&gt;
Więc może jednak warto spróbować z jedną rzeczą na raz.&lt;br /&gt;
&lt;br /&gt;
&lt;a href="http://luksza.org/"&gt;Dariusz Łuksza&lt;/a&gt; swoją prezentacja o narzędziach do Git: &lt;a href="http://www.eclipse.org/egit/"&gt;egit&lt;/a&gt; (plugin do Eclipse), &lt;a href="http://eagain.net/gitweb/?p=gitosis.git"&gt;gitosis&lt;/a&gt; (serwer do utrzymywania repozytorium) &lt;a href="https://git.wiki.kernel.org/index.php/Gitweb"&gt;gitweb&lt;/a&gt; (udostępnianie zawartości przez www), &lt;a href="http://code.google.com/p/gerrit/"&gt;gerrit&lt;/a&gt; (system wspierający rewizje kodu) przypomniał mi, że miałem rozpoznać ten system kontroli wersji i jeszcze się za to nie zabrałem ... od 1,5 roku :)&lt;br /&gt;
&lt;br /&gt;
Obserwowanie dobrego specjalisty, który potrafi wycisnąć ze swoich narzędzi 100% jest naprawdę rewelacyjnym doświadczeniem. Porównywalnym z czytaniem eleganckiego rozwiązania w kodzie.&lt;br /&gt;
&lt;br /&gt;
&lt;a href="http://www.clojureblog.pl/"&gt;Marcin Rzewucki&lt;/a&gt; oraz &lt;a href="http://jan.rychter.com/"&gt;Jan Rychter&lt;/a&gt; przedstawili Clojure. Skoro są ludzie, którzy używają tego języka komercyjnie i istnieją narzędzia wspierające budowanie &lt;a href="http://github.com/technomancy/leiningen"&gt;Leiningen&lt;/a&gt; może nadszedł czas odświeżenie i pogłębienie swojej wiedzy na ten temat.&lt;br /&gt;
&lt;br /&gt;
Prezentacja Adama Michalika na temat czytania i pisania bytecode była zaskakująca. Sceptycznie do niej podszedłem ale zostałem mile zaskoczony. Jeśli ktoś potrudzi się, by za pomocą &lt;a href="http://download.oracle.com/javase/1.5.0/docs/tooldocs/windows/javap.html"&gt;javap&lt;/a&gt; przeanalizować przykłady bytecode dla:&lt;br /&gt;
- klas implementujących covariant return types, &lt;br /&gt;
- konkatanacji String'ów&lt;br /&gt;
- traktowania wartości boolean, byte, short i int&lt;br /&gt;
- klas wewnętrznych&lt;br /&gt;
wówczas nie spojrzy już tak samo na kod źródłowy. Zastanawia mnie tylko, czy powszechna znajomość &lt;a href="http://jasmin.sourceforge.net/xt.html"&gt;Jasmin&lt;/a&gt; wśród fanów przedwczesnej optymalizacji nie przyniesie nam chaosu i zniszczenia :)&lt;br /&gt;
&lt;br /&gt;
&lt;a href="http://rrusin.blogspot.com/"&gt;Rafał Rusin&lt;/a&gt; przedstawił implementację standardu WS HumanTask przez projekty Apache HISE i Apache Camel. Ciekaw jestem w jakim zakresie te narzędzia znajdą zastosowanie.&lt;br /&gt;
&lt;br /&gt;
Organizacja przebiegła sprawnie. Brakuje mi tylko eventu na LinkedIn :)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3992064681062004055-2894027970379957421?l=it-researches.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/ItResearches/~4/jielQ2bk0MA" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://it-researches.blogspot.com/feeds/2894027970379957421/comments/default" title="Komentarze do posta" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=3992064681062004055&amp;postID=2894027970379957421&amp;isPopup=true" title="Komentarze (3)" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3992064681062004055/posts/default/2894027970379957421?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3992064681062004055/posts/default/2894027970379957421?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/ItResearches/~3/jielQ2bk0MA/konferencja-warsjava-2010.html" title="Konferencja Warsjava 2010" /><author><name>Piotr Paradzinski</name><uri>http://www.blogger.com/profile/07915292026695759953</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="25" height="32" src="http://4.bp.blogspot.com/_cGW9IpdChVc/SYRCu49W5lI/AAAAAAAAADE/eZPPGD0JW_Q/S220/PiotrParadzinski.jpg" /></author><thr:total>3</thr:total><feedburner:origLink>http://it-researches.blogspot.com/2010/10/konferencja-warsjava-2010.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DE8MQXwzcSp7ImA9Wx5REUU.&quot;"><id>tag:blogger.com,1999:blog-3992064681062004055.post-3758867031633010007</id><published>2010-08-19T05:01:00.000+02:00</published><updated>2010-08-19T05:01:20.289+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-08-19T05:01:20.289+02:00</app:edited><title>APM boost</title><content type="html">&lt;b&gt;Better OS&lt;/b&gt;&lt;br /&gt;
------------&lt;br /&gt;
Till last weak I was using Windows XP as the base for my development effort (Try Vista, try Windows 7 - user friendly means too difficult to find tools under the annoying effects). But after a few experiences with different Linux distros (Ubuntu, Centos, Fedora) I've finally chosen most suitable for me.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Basic knowledge&lt;/b&gt;&lt;br /&gt;
It take some time to run computer with Linux instead of walking it ;) but it's worth the effort. I remember pushing to the limits regexp in Notepad++ and Eclipse diff to be close to  desired result on Win. In the Linux world it's just standard option in grep, find, sed or awk (and it's not close to result - it's simple and accurate solution).&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Keyboard&lt;/b&gt;&lt;br /&gt;
Microsoft Comfort Curve Keyboard 2000 is my current choice. It is slim and more ergonomic than classic keyboard. And big enough to use on armchair :D&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Short cuts&lt;/b&gt;&lt;br /&gt;
A little learning about short cuts in Terminal, multiple workspaces, Firefox and some customization.  &lt;br /&gt;
&lt;br /&gt;
Finally great boost in &lt;a href="http://en.wikipedia.org/wiki/Actions_per_minute"&gt;APM&lt;/a&gt;'s is finally mine. It's probably not the greatest idea to use keyboard to do precise pointing (play cRPG without mouse if you don't believe). Using mouse to do things that can be done by shortcut is even more painful (try playing cRPG without keyboard).&lt;br /&gt;
&lt;br /&gt;
The reason is not because the time saving by using immediate short cut vs mouse point, choose and click but the time spend to distract you from whats on your mind currently. That's why I don't agree that &lt;a href="http://arekborek.blogspot.com/2010/01/httpupdatemousefeedcom.html"&gt;mousefeed isn't decent plugin&lt;/a&gt; (well I would not agree if it didn't crash old Eclipse versions).&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3992064681062004055-3758867031633010007?l=it-researches.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/ItResearches/~4/EpaNpTLfoC8" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://it-researches.blogspot.com/feeds/3758867031633010007/comments/default" title="Komentarze do posta" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=3992064681062004055&amp;postID=3758867031633010007&amp;isPopup=true" title="Komentarze (2)" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3992064681062004055/posts/default/3758867031633010007?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3992064681062004055/posts/default/3758867031633010007?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/ItResearches/~3/EpaNpTLfoC8/apm-boost.html" title="APM boost" /><author><name>Piotr Paradzinski</name><uri>http://www.blogger.com/profile/07915292026695759953</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="25" height="32" src="http://4.bp.blogspot.com/_cGW9IpdChVc/SYRCu49W5lI/AAAAAAAAADE/eZPPGD0JW_Q/S220/PiotrParadzinski.jpg" /></author><thr:total>2</thr:total><feedburner:origLink>http://it-researches.blogspot.com/2010/08/apm-boost.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CUQMQnw8cCp7ImA9Wx5REUU.&quot;"><id>tag:blogger.com,1999:blog-3992064681062004055.post-8874157640059255768</id><published>2010-08-19T04:03:00.000+02:00</published><updated>2010-08-19T04:03:03.278+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-08-19T04:03:03.278+02:00</app:edited><title>Brave new world</title><content type="html">&lt;b&gt;Why in english?&lt;/b&gt;&lt;br /&gt;
---------------&lt;br /&gt;
I wanna learn as many different things as possible. I have heard that it's one of the key things to achieve 100+ lifespan :) So I'm writing in my sloppy english. Hopefully some French, German, Spanish or Japanese posts will occur ;)&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Why new world?&lt;/b&gt;&lt;br /&gt;
--------------&lt;br /&gt;
The time when a was working for the current company very soon will end. And a new challenging events will follow (I hope).&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Why brave?&lt;/b&gt;&lt;br /&gt;
----------&lt;br /&gt;
It only took me 1 day off work and suddenly plethora of crazy, impossible, revolutionary, amazing, a little scary, innovative and eventually profitable ideas come to my mind. &lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;First Step&lt;/b&gt;&lt;br /&gt;
----------&lt;br /&gt;
The most crazy, impossible and terrifying one was to clean up my living space. After 5+ years of cleanup-by-putting-unnecessary-stuff-to-rarely-accessed-place introducing order take some time. Sorting notes from university, high school, and random notes gave me opportunity to watch some videos on InfoQ and YoutTube. Here are the ones I find interesting:&lt;br /&gt;
&lt;br /&gt;
On TDD&lt;br /&gt;
&lt;a href="http://www.infoq.com/presentations/tdd-ten-years-later"&gt;Test Driven Development: Ten Years Later&lt;/a&gt;&lt;br /&gt;
&lt;a href="http://www.infoq.com/presentations/TDD-Managers-Nicolette-Scotland"&gt;Manager's Introduction to Test-Driven Development&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
On TDD by Misko Hevery&lt;br /&gt;
&lt;a href="http://www.youtube.com/watch?v=RlfLCWKxHJ0&amp;feature=channel"&gt;The Clean Code Talks - Don't Look For Things!&lt;/a&gt; &lt;br /&gt;
&lt;a href="http://www.youtube.com/watch?v=4F72VULWFvc&amp;feature=channel"&gt;The Clean Code Talks -- Inheritance, Polymorphism, &amp; Testing &lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
On Agile Metrics&lt;br /&gt;
&lt;a href="http://www.infoq.com/presentations/agile-project-metrics"&gt;Agile Project Metrics&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
On iterative development and testing&lt;br /&gt;
&lt;a href="http://www.infoq.com/interviews/jeffries-running-tested-features"&gt;Interview: Ron Jeffries on Running Tested Features&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
On Architecture&lt;br /&gt;
&lt;a href="http://www.infoq.com/presentations/Learning-from-Five-Years-Skype"&gt;Learning from Five Years as a Skype Architect&lt;/a&gt; &lt;br /&gt;
&lt;br /&gt;
By Joshua Kerievsky &lt;br /&gt;
&lt;a href="http://www.infoq.com/author/Joshua-Kerievsky"&gt;all presentations and interviews are very interesting&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
And looking at the great pile of papers - I'll probably watch quiet a few more :)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3992064681062004055-8874157640059255768?l=it-researches.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/ItResearches/~4/b3T-hheIVE8" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://it-researches.blogspot.com/feeds/8874157640059255768/comments/default" title="Komentarze do posta" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=3992064681062004055&amp;postID=8874157640059255768&amp;isPopup=true" title="Komentarze (1)" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3992064681062004055/posts/default/8874157640059255768?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3992064681062004055/posts/default/8874157640059255768?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/ItResearches/~3/b3T-hheIVE8/brave-new-world.html" title="Brave new world" /><author><name>Piotr Paradzinski</name><uri>http://www.blogger.com/profile/07915292026695759953</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="25" height="32" src="http://4.bp.blogspot.com/_cGW9IpdChVc/SYRCu49W5lI/AAAAAAAAADE/eZPPGD0JW_Q/S220/PiotrParadzinski.jpg" /></author><thr:total>1</thr:total><feedburner:origLink>http://it-researches.blogspot.com/2010/08/brave-new-world.html</feedburner:origLink></entry><entry gd:etag="W/&quot;D0UMQH05fCp7ImA9WxFQFkQ.&quot;"><id>tag:blogger.com,1999:blog-3992064681062004055.post-4062368165618302692</id><published>2010-05-12T21:09:00.002+02:00</published><updated>2010-05-12T22:14:41.324+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-05-12T22:14:41.324+02:00</app:edited><title>break;</title><content type="html">Jakiś etap mojego funkcjonowania się zakończył. Powoli &lt;a href="http://groups.google.com/group/lublin-jug/browse_thread/thread/97883d5ebfd1eea8#"&gt;wycofuję się z bycia leaderem Lublin JUG&lt;/a&gt; - są ludzie o lepszych kwalifikacjach organizacyjnych i programistycznych.

Od jakiegoś czasu nie piszę postów. Z &lt;a href="http://it-researches.blogspot.com/2008/06/komentarze-vs-testy-jednostkowe-dobry.html"&gt;wieloma zaprezentowanymi tu opiniami się nie zgadzam&lt;/a&gt;. Niektóre były niepotrzebnym &lt;a href="http://it-researches.blogspot.com/2010/01/manifest-blogowania-w-jezyku-polskim.html"&gt;rozrywaniem sobie koszulki&lt;/a&gt; lub &lt;a href="http://it-researches.blogspot.com/2009/04/warstwa-dao-przetrwa-atak-jpa-dzieki.html"&gt;wymądrzaniem się&lt;/a&gt;. Droga do bycia dobrym programistą nie jest prosta i bezstresowa a że głośno myślałem na blogu ... :)

Niemniej &lt;a href="http://it-researches.blogspot.com/2008/04/wzorce-projektowe-i-architektoniczne.html"&gt;z niektórych postów jestem po prostu dumny&lt;/a&gt;. Słyszałem, że &lt;a href="http://it-researches.blogspot.com/2009/05/dodatkowe-ograniczenia-typow.html"&gt;niektóre przydały się innym&lt;/a&gt; jeszcze &lt;a href="http://it-researches.blogspot.com/2009/12/ruby-quick-dirty-linki.html"&gt;inne przydały się mi&lt;/a&gt; :P

Jak przychodzę do domu, to już nie odpalam kompa, żeby sprawdzić co nowego w 20+ grupach dyskusyjnych IT, albo poeksperymentować z jakimś dziwnym feature'm na który natknąłem się gdzieś przypadkiem. 

Pędziłem szybko, biorąc na siebie obowiązki, angażując się w różne aspekty funkcjonowania - wszystko po to, by zostawić coś daleko za sobą. Praktyka pokazuje, iż nie wychodzi mi to. Trudno niech sobie tak będzie. Ja się zasapałem, więc teraz sobie odpocznę.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3992064681062004055-4062368165618302692?l=it-researches.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/ItResearches/~4/iqFPc_zsv0A" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://it-researches.blogspot.com/feeds/4062368165618302692/comments/default" title="Komentarze do posta" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=3992064681062004055&amp;postID=4062368165618302692&amp;isPopup=true" title="Komentarze (4)" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3992064681062004055/posts/default/4062368165618302692?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3992064681062004055/posts/default/4062368165618302692?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/ItResearches/~3/iqFPc_zsv0A/break.html" title="break;" /><author><name>Piotr Paradzinski</name><uri>http://www.blogger.com/profile/07915292026695759953</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="25" height="32" src="http://4.bp.blogspot.com/_cGW9IpdChVc/SYRCu49W5lI/AAAAAAAAADE/eZPPGD0JW_Q/S220/PiotrParadzinski.jpg" /></author><thr:total>4</thr:total><feedburner:origLink>http://it-researches.blogspot.com/2010/05/break.html</feedburner:origLink></entry><entry gd:etag="W/&quot;D0MHQHozeip7ImA9WxFSE0s.&quot;"><id>tag:blogger.com,1999:blog-3992064681062004055.post-3768879161288900693</id><published>2010-04-15T21:32:00.005+02:00</published><updated>2010-04-15T23:03:51.482+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-04-15T23:03:51.482+02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Lisp" /><title>Czyżby zmiana kierunku (z Lisp'em w tle)</title><content type="html">Wysłuchałem dziś &lt;a href="http://www.se-radio.net/podcast/2008-01/episode-84-dick-gabriel-lisp"&gt;wywiadu w SE Radio na temat języka Lisp&lt;/a&gt;. Jestem pod silnym wrażeniem. Opowieść o historii powstania pierwszego kompilatora Lisp'a rzuciła mnie na kolana. Na tyle, że po powrocie do domu nie siadłem do &lt;a href="http://iitv.info/stargate--atlantis/s05e01-search-and-rescue.html"&gt;5 sezonu Stargate Atlantis&lt;/a&gt;.

Opowieść o tym, jak kilka osób ze świata Lisp'a próbowało zrozumieć o co chodzi w programowaniu obiektowym pogłębiła efekt. Niektóre fragmenty są naprawdę zabawne.

Niemniej, podczas słuchania, nie mogłem oprzeć się od myśli, iż programowanie obiektowe jest tylko trywialnym przypadkiem programowania funkcyjnego. Takim dla małych dzieci. Żeby sobie kuku nie zrobiły :)

...

Dziedziczenie wielo-bazowe jawi się, jako przykład tego, jak te małe dzieci próbując rozbudowywać swoje zabawki poszły w jakimś dziwnym kierunku. &lt;a href="http://en.wikipedia.org/wiki/Diamond_problem"&gt;Wypaczając&lt;/a&gt; ciekawą i dosyć naturalną ideę rozszerzania mixin'ów.

...

Mam wrażenie, iż w dziedzinie tworzenia oprogramowania rozwój nie polega na wpadaniu na nowe koncepcje, przełomowe idee. Polega on na wygrzebywaniu starych, dużo lepiej rozwiniętych koncepcji w bardziej łopatologiczny i uproszczony sposób. Ubrany w lepsze marketingowo słowa.

...

Od jakiegoś czasu noszę się z zamiarem zmiany kierunku moich riserczów. Może trochę trzeba odpocząć? A może zamiast podniecać się nowymi cieszącymi oko łeb-frejmłorkami i prze-ficzerami z bibliotek FOSS, lepiej dogłębnie poznać i zrozumieć podstawowe narzędzie każdego programisty - języki programowania (&lt;a href="http://en.wikipedia.org/wiki/Scheme_%28programming_language%29"&gt;Scheme&lt;/a&gt;, &lt;a href="http://en.wikipedia.org/wiki/Forth_%28programming_language%29"&gt;Forth&lt;/a&gt;). Sprawdzić co, już dawno temu, zostało odkryte.

...

A może zmienić kierunek zainteresowań jeszcze bardziej?&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3992064681062004055-3768879161288900693?l=it-researches.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/ItResearches/~4/JHTl_uB-7Ug" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://it-researches.blogspot.com/feeds/3768879161288900693/comments/default" title="Komentarze do posta" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=3992064681062004055&amp;postID=3768879161288900693&amp;isPopup=true" title="Komentarze (1)" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3992064681062004055/posts/default/3768879161288900693?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3992064681062004055/posts/default/3768879161288900693?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/ItResearches/~3/JHTl_uB-7Ug/czyzby-zmiana-kierunku-z-lispem-w-tle.html" title="Czyżby zmiana kierunku (z Lisp'em w tle)" /><author><name>Piotr Paradzinski</name><uri>http://www.blogger.com/profile/07915292026695759953</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="25" height="32" src="http://4.bp.blogspot.com/_cGW9IpdChVc/SYRCu49W5lI/AAAAAAAAADE/eZPPGD0JW_Q/S220/PiotrParadzinski.jpg" /></author><thr:total>1</thr:total><feedburner:origLink>http://it-researches.blogspot.com/2010/04/czyzby-zmiana-kierunku-z-lispem-w-tle.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CkQHR3czeSp7ImA9WxBbEUo.&quot;"><id>tag:blogger.com,1999:blog-3992064681062004055.post-4720398966612409241</id><published>2010-03-09T22:07:00.003+01:00</published><updated>2010-03-09T22:32:16.981+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-03-09T22:32:16.981+01:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="LJUG" /><category scheme="http://www.blogger.com/atom/ns#" term="Java" /><title>Wyrażenia lambda na Lublin JUG</title><content type="html">Dziś Wojciech Gomoła na spotkaniu &lt;a href="http://groups.google.com/group/lublin-jug"&gt;Lublin JUG&lt;/a&gt; wywołał niezłą dyskusję :) Widać wyraźnie, iż Java jest głęboko za .NET jeśli chodzi o wprowadzanie rozszerzeń języka. Spora część dzisiejszych uczestników LJUG'a widziała w prezentowanych wyrażeniach lambda, nową metodę na pisanie marnego kodu.

Z &lt;a href="http://java.sun.com/javase/7/webnotes/index.html"&gt;oficjalnej informacji na temat nowości w Java 7&lt;/a&gt; wynika, iż wprowadzenie czegoś podobnego do wyrażeń lambda, jest konsekwencją &lt;a href="http://java.sun.com/javase/7/docs/technotes/guides/vm/mulitple-language-support.html"&gt;ułatwienia implementacji języków dynamicznie typowanych&lt;/a&gt;.

Warto się chyba przyjrzeć nowym feature'om z pakietu &lt;a href="http://java.sun.com/javase/7/webnotes/index.html"&gt;java.dyn&lt;/a&gt;. Skoro będą w standardzie napewno będą używane i nadużywane.

Na spotkaniu pokazana była biblioteka &lt;a href="http://code.google.com/p/google-collections/"&gt;Google Collection&lt;/a&gt;. Na mnie zrobiła spore wrażenie. Wydaje mi się, że dało by się ją sensownie wykorzystać.

Trzeba będzie dorzucić ją do skrzynki z narzędziami.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3992064681062004055-4720398966612409241?l=it-researches.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/ItResearches/~4/STTl2FoBd00" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://it-researches.blogspot.com/feeds/4720398966612409241/comments/default" title="Komentarze do posta" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=3992064681062004055&amp;postID=4720398966612409241&amp;isPopup=true" title="Komentarze (0)" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3992064681062004055/posts/default/4720398966612409241?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3992064681062004055/posts/default/4720398966612409241?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/ItResearches/~3/STTl2FoBd00/wyrazenia-lambda-na-lublin-jug.html" title="Wyrażenia lambda na Lublin JUG" /><author><name>Piotr Paradzinski</name><uri>http://www.blogger.com/profile/07915292026695759953</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="25" height="32" src="http://4.bp.blogspot.com/_cGW9IpdChVc/SYRCu49W5lI/AAAAAAAAADE/eZPPGD0JW_Q/S220/PiotrParadzinski.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://it-researches.blogspot.com/2010/03/wyrazenia-lambda-na-lublin-jug.html</feedburner:origLink></entry><entry gd:etag="W/&quot;Dk4MRXozfip7ImA9WxBUGUs.&quot;"><id>tag:blogger.com,1999:blog-3992064681062004055.post-5736089911191958258</id><published>2010-03-07T10:35:00.005+01:00</published><updated>2010-03-07T13:29:44.486+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-03-07T13:29:44.486+01:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="hamcrest" /><title>hamcrest - matchery</title><content type="html">W podstawowej bibliotece hamcrest &lt;code&gt;hamcrest-core.jar&lt;/code&gt; dostępne są różne matchery, które można podzielić na kilka grup.

&lt;h3&gt;Dopasowanie napisów&lt;/h3&gt;
&lt;table border="1"&gt;&lt;tr&gt;&lt;td&gt;startsWith(substr)&lt;/td&gt;&lt;td&gt;testItem.startsWith(substr)&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;endsWith(substr)&lt;/td&gt;&lt;td&gt;testItem.endsWith(substr)&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;containsString(substr)&lt;/td&gt;&lt;td&gt;testItem.indexOf(substr) &amp;gt;= 0&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;

Na przykład:

&lt;pre&gt;&lt;font color="#0000ff"&gt;&lt;strong&gt;import static org.hamcrest.core.StringContains.containsString;&lt;/strong&gt;&lt;/font&gt;
&lt;font color="#0000ff"&gt;&lt;strong&gt;import org.hamcrest.Matcher;&lt;/strong&gt;&lt;/font&gt;

&lt;font color="#444444"&gt;// ...&lt;/font&gt;

&lt;font color="#2040a0"&gt;Matcher&lt;/font&gt;&lt;font color="#4444ff"&gt;&amp;lt;&lt;/font&gt;&lt;font color="#2040a0"&gt;String&lt;/font&gt;&lt;font color="#4444ff"&gt;&amp;gt;&lt;/font&gt; &lt;font color="#2040a0"&gt;matcher&lt;/font&gt; &lt;font color="#4444ff"&gt;=&lt;/font&gt; &lt;font color="#2040a0"&gt;containsString&lt;/font&gt;&lt;font color="#4444ff"&gt;&lt;strong&gt;(&lt;/strong&gt;&lt;/font&gt;&lt;font color="#008000"&gt;"ma"&lt;/font&gt;&lt;font color="#4444ff"&gt;&lt;strong&gt;)&lt;/strong&gt;&lt;/font&gt;&lt;font color="#4444ff"&gt;;&lt;/font&gt;
&lt;strong&gt;boolean&lt;/strong&gt; &lt;font color="#2040a0"&gt;match&lt;/font&gt; &lt;font color="#4444ff"&gt;=&lt;/font&gt; &lt;font color="#2040a0"&gt;matcher&lt;/font&gt;.&lt;font color="#2040a0"&gt;matches&lt;/font&gt;&lt;font color="#4444ff"&gt;&lt;strong&gt;(&lt;/strong&gt;&lt;/font&gt;&lt;font color="#008000"&gt;"ala ma kota"&lt;/font&gt;&lt;font color="#4444ff"&gt;&lt;strong&gt;)&lt;/strong&gt;&lt;/font&gt;&lt;font color="#4444ff"&gt;;&lt;/font&gt; &lt;font color="#444444"&gt;// true&lt;/font&gt;
&lt;/pre&gt;

&lt;h3&gt;Sprawdzenie równości obiektów, null, typu&lt;/h3&gt;
&lt;table border="1"&gt;
&lt;tr&gt;&lt;td&gt;sameInstance(object)&lt;/td&gt;&lt;td&gt;testItem == object&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;equalTo(operand)&lt;/td&gt;&lt;td&gt;testItem.equals(operand)&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;notNullValue()&lt;/td&gt;&lt;td&gt;testItem != null&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;nullValue()&lt;/td&gt;&lt;td&gt;testItem == null&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;instanceOf(type)&lt;/td&gt;&lt;td&gt;testItem instanceOf type&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;

Na przykład:

&lt;pre&gt;&lt;font color="#0000ff"&gt;&lt;strong&gt;import static org.hamcrest.core.IsEqual.equalTo;&lt;/strong&gt;&lt;/font&gt;
&lt;font color="#0000ff"&gt;&lt;strong&gt;import static org.hamcrest.core.IsInstanceOf.instanceOf;&lt;/strong&gt;&lt;/font&gt;
&lt;font color="#0000ff"&gt;&lt;strong&gt;import static org.hamcrest.core.IsNull.notNullValue;&lt;/strong&gt;&lt;/font&gt;
&lt;font color="#0000ff"&gt;&lt;strong&gt;import static org.hamcrest.core.IsNull.nullValue;&lt;/strong&gt;&lt;/font&gt;
&lt;font color="#0000ff"&gt;&lt;strong&gt;import static org.hamcrest.core.IsSame.sameInstance;&lt;/strong&gt;&lt;/font&gt;

&lt;font color="#0000ff"&gt;&lt;strong&gt;import org.hamcrest.Matcher;&lt;/strong&gt;&lt;/font&gt;

&lt;font color="#444444"&gt;//...&lt;/font&gt;

&lt;font color="#2040a0"&gt;Matcher&lt;/font&gt;&lt;font color="#4444ff"&gt;&amp;lt;&lt;/font&gt;&lt;font color="#2040a0"&gt;Integer&lt;/font&gt;&lt;font color="#4444ff"&gt;&amp;gt;&lt;/font&gt; &lt;font color="#2040a0"&gt;mSameObject&lt;/font&gt; &lt;font color="#4444ff"&gt;=&lt;/font&gt; &lt;font color="#2040a0"&gt;sameInstance&lt;/font&gt;&lt;font color="#4444ff"&gt;&lt;strong&gt;(&lt;/strong&gt;&lt;/font&gt; &lt;strong&gt;new&lt;/strong&gt; &lt;font color="#2040a0"&gt;Integer&lt;/font&gt;&lt;font color="#4444ff"&gt;&lt;strong&gt;(&lt;/strong&gt;&lt;/font&gt;&lt;font color="#ff0000"&gt;0&lt;/font&gt;&lt;font color="#4444ff"&gt;&lt;strong&gt;)&lt;/strong&gt;&lt;/font&gt; &lt;font color="#4444ff"&gt;&lt;strong&gt;)&lt;/strong&gt;&lt;/font&gt;&lt;font color="#4444ff"&gt;;&lt;/font&gt;
&lt;strong&gt;boolean&lt;/strong&gt; &lt;font color="#2040a0"&gt;isSameObject&lt;/font&gt; &lt;font color="#4444ff"&gt;=&lt;/font&gt; &lt;font color="#2040a0"&gt;mSameObject&lt;/font&gt;.&lt;font color="#2040a0"&gt;matches&lt;/font&gt;&lt;font color="#4444ff"&gt;&lt;strong&gt;(&lt;/strong&gt;&lt;/font&gt; &lt;strong&gt;new&lt;/strong&gt; &lt;font color="#2040a0"&gt;Integer&lt;/font&gt;&lt;font color="#4444ff"&gt;&lt;strong&gt;(&lt;/strong&gt;&lt;/font&gt;&lt;font color="#ff0000"&gt;0&lt;/font&gt;&lt;font color="#4444ff"&gt;&lt;strong&gt;)&lt;/strong&gt;&lt;/font&gt; &lt;font color="#4444ff"&gt;&lt;strong&gt;)&lt;/strong&gt;&lt;/font&gt;&lt;font color="#4444ff"&gt;;&lt;/font&gt; &lt;font color="#444444"&gt;// false&lt;/font&gt;

&lt;font color="#2040a0"&gt;Matcher&lt;/font&gt;&lt;font color="#4444ff"&gt;&amp;lt;&lt;/font&gt;? &lt;strong&gt;super&lt;/strong&gt; &lt;font color="#2040a0"&gt;Integer&lt;/font&gt;&lt;font color="#4444ff"&gt;&amp;gt;&lt;/font&gt; &lt;font color="#2040a0"&gt;mEquals&lt;/font&gt; &lt;font color="#4444ff"&gt;=&lt;/font&gt; &lt;font color="#2040a0"&gt;equalTo&lt;/font&gt;&lt;font color="#4444ff"&gt;&lt;strong&gt;(&lt;/strong&gt;&lt;/font&gt; &lt;strong&gt;new&lt;/strong&gt; &lt;font color="#2040a0"&gt;Integer&lt;/font&gt;&lt;font color="#4444ff"&gt;&lt;strong&gt;(&lt;/strong&gt;&lt;/font&gt;&lt;font color="#ff0000"&gt;0&lt;/font&gt;&lt;font color="#4444ff"&gt;&lt;strong&gt;)&lt;/strong&gt;&lt;/font&gt; &lt;font color="#4444ff"&gt;&lt;strong&gt;)&lt;/strong&gt;&lt;/font&gt;&lt;font color="#4444ff"&gt;;&lt;/font&gt;
&lt;strong&gt;boolean&lt;/strong&gt; &lt;font color="#2040a0"&gt;isEquals&lt;/font&gt; &lt;font color="#4444ff"&gt;=&lt;/font&gt; &lt;font color="#2040a0"&gt;mEquals&lt;/font&gt;.&lt;font color="#2040a0"&gt;matches&lt;/font&gt;&lt;font color="#4444ff"&gt;&lt;strong&gt;(&lt;/strong&gt;&lt;/font&gt; &lt;strong&gt;new&lt;/strong&gt; &lt;font color="#2040a0"&gt;Integer&lt;/font&gt;&lt;font color="#4444ff"&gt;&lt;strong&gt;(&lt;/strong&gt;&lt;/font&gt;&lt;font color="#ff0000"&gt;0&lt;/font&gt;&lt;font color="#4444ff"&gt;&lt;strong&gt;)&lt;/strong&gt;&lt;/font&gt; &lt;font color="#4444ff"&gt;&lt;strong&gt;)&lt;/strong&gt;&lt;/font&gt;&lt;font color="#4444ff"&gt;;&lt;/font&gt; &lt;font color="#444444"&gt;// true&lt;/font&gt;

&lt;font color="#2040a0"&gt;Matcher&lt;/font&gt;&lt;font color="#4444ff"&gt;&amp;lt;&lt;/font&gt;&lt;font color="#2040a0"&gt;Bar&lt;/font&gt;&lt;font color="#4444ff"&gt;&amp;gt;&lt;/font&gt; &lt;font color="#2040a0"&gt;mNull&lt;/font&gt; &lt;font color="#4444ff"&gt;=&lt;/font&gt; &lt;font color="#2040a0"&gt;nullValue&lt;/font&gt;&lt;font color="#4444ff"&gt;&lt;strong&gt;(&lt;/strong&gt;&lt;/font&gt;&lt;font color="#4444ff"&gt;&lt;strong&gt;)&lt;/strong&gt;&lt;/font&gt;&lt;font color="#4444ff"&gt;;&lt;/font&gt;
&lt;strong&gt;boolean&lt;/strong&gt; &lt;font color="#2040a0"&gt;isNull&lt;/font&gt; &lt;font color="#4444ff"&gt;=&lt;/font&gt; &lt;font color="#2040a0"&gt;mNull&lt;/font&gt;.&lt;font color="#2040a0"&gt;matches&lt;/font&gt;&lt;font color="#4444ff"&gt;&lt;strong&gt;(&lt;/strong&gt;&lt;/font&gt; &lt;strong&gt;new&lt;/strong&gt; &lt;font color="#2040a0"&gt;Bar&lt;/font&gt;&lt;font color="#4444ff"&gt;&lt;strong&gt;(&lt;/strong&gt;&lt;/font&gt;&lt;font color="#4444ff"&gt;&lt;strong&gt;)&lt;/strong&gt;&lt;/font&gt; &lt;font color="#4444ff"&gt;&lt;strong&gt;)&lt;/strong&gt;&lt;/font&gt;&lt;font color="#4444ff"&gt;;&lt;/font&gt; &lt;font color="#444444"&gt;// false&lt;/font&gt;

&lt;font color="#2040a0"&gt;Matcher&lt;/font&gt;&lt;font color="#4444ff"&gt;&amp;lt;&lt;/font&gt;&lt;font color="#2040a0"&gt;Integer&lt;/font&gt;&lt;font color="#4444ff"&gt;&amp;gt;&lt;/font&gt; &lt;font color="#2040a0"&gt;mNotNull&lt;/font&gt; &lt;font color="#4444ff"&gt;=&lt;/font&gt; &lt;font color="#2040a0"&gt;notNullValue&lt;/font&gt;&lt;font color="#4444ff"&gt;&lt;strong&gt;(&lt;/strong&gt;&lt;/font&gt;&lt;font color="#4444ff"&gt;&lt;strong&gt;)&lt;/strong&gt;&lt;/font&gt;&lt;font color="#4444ff"&gt;;&lt;/font&gt;
&lt;strong&gt;boolean&lt;/strong&gt; &lt;font color="#2040a0"&gt;isNotNull&lt;/font&gt; &lt;font color="#4444ff"&gt;=&lt;/font&gt; &lt;font color="#2040a0"&gt;mNotNull&lt;/font&gt;.&lt;font color="#2040a0"&gt;matches&lt;/font&gt;&lt;font color="#4444ff"&gt;&lt;strong&gt;(&lt;/strong&gt;&lt;/font&gt; &lt;strong&gt;new&lt;/strong&gt; &lt;font color="#2040a0"&gt;Integer&lt;/font&gt;&lt;font color="#4444ff"&gt;&lt;strong&gt;(&lt;/strong&gt;&lt;/font&gt;&lt;font color="#ff0000"&gt;0&lt;/font&gt;&lt;font color="#4444ff"&gt;&lt;strong&gt;)&lt;/strong&gt;&lt;/font&gt; &lt;font color="#4444ff"&gt;&lt;strong&gt;)&lt;/strong&gt;&lt;/font&gt;&lt;font color="#4444ff"&gt;;&lt;/font&gt; &lt;font color="#444444"&gt;// true&lt;/font&gt;

&lt;font color="#444444"&gt;// ...&lt;/font&gt;

&lt;strong&gt;interface&lt;/strong&gt; &lt;font color="#2040a0"&gt;Foo&lt;/font&gt; &lt;font color="#4444ff"&gt;&lt;strong&gt;{&lt;/strong&gt;&lt;/font&gt;&lt;font color="#4444ff"&gt;&lt;strong&gt;}&lt;/strong&gt;&lt;/font&gt;
&lt;strong&gt;class&lt;/strong&gt; &lt;font color="#2040a0"&gt;Bar&lt;/font&gt; &lt;strong&gt;implements&lt;/strong&gt; &lt;font color="#2040a0"&gt;Foo&lt;/font&gt; &lt;font color="#4444ff"&gt;&lt;strong&gt;{&lt;/strong&gt;&lt;/font&gt;&lt;font color="#4444ff"&gt;&lt;strong&gt;}&lt;/strong&gt;&lt;/font&gt; 

&lt;font color="#2040a0"&gt;Matcher&lt;/font&gt;&lt;font color="#4444ff"&gt;&amp;lt;&lt;/font&gt;&lt;font color="#2040a0"&gt;Foo&lt;/font&gt;&lt;font color="#4444ff"&gt;&amp;gt;&lt;/font&gt; &lt;font color="#2040a0"&gt;mInstanceOf&lt;/font&gt; &lt;font color="#4444ff"&gt;=&lt;/font&gt; &lt;font color="#2040a0"&gt;instanceOf&lt;/font&gt;&lt;font color="#4444ff"&gt;&lt;strong&gt;(&lt;/strong&gt;&lt;/font&gt; &lt;font color="#2040a0"&gt;Foo&lt;/font&gt;.&lt;strong&gt;class&lt;/strong&gt; &lt;font color="#4444ff"&gt;&lt;strong&gt;)&lt;/strong&gt;&lt;/font&gt;&lt;font color="#4444ff"&gt;;&lt;/font&gt;
&lt;strong&gt;boolean&lt;/strong&gt; &lt;font color="#2040a0"&gt;isInstanceOf&lt;/font&gt; &lt;font color="#4444ff"&gt;=&lt;/font&gt; &lt;font color="#2040a0"&gt;mInstanceOf&lt;/font&gt;.&lt;font color="#2040a0"&gt;matches&lt;/font&gt;&lt;font color="#4444ff"&gt;&lt;strong&gt;(&lt;/strong&gt;&lt;/font&gt; &lt;strong&gt;new&lt;/strong&gt; &lt;font color="#2040a0"&gt;Bar&lt;/font&gt;&lt;font color="#4444ff"&gt;&lt;strong&gt;(&lt;/strong&gt;&lt;/font&gt;&lt;font color="#4444ff"&gt;&lt;strong&gt;)&lt;/strong&gt;&lt;/font&gt; &lt;font color="#4444ff"&gt;&lt;strong&gt;)&lt;/strong&gt;&lt;/font&gt;&lt;font color="#4444ff"&gt;;&lt;/font&gt; &lt;font color="#444444"&gt;// true&lt;/font&gt;&lt;/pre&gt;

&lt;h3&gt;Łączenie warunków, itp&lt;/h3&gt;
&lt;table border="1"&gt;&lt;tr&gt;&lt;td&gt;anything()&lt;/td&gt;&lt;td&gt;true&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;anyOf(Matcher... matchers)&lt;/td&gt;&lt;td&gt;matcher1 || matcher2 || ...&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;allOf(Matcher... matchers)&lt;/td&gt;&lt;td&gt;mathcer1 &amp;&amp; matcher2 &amp;&amp; ...&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;not(matcher)&lt;/td&gt;&lt;td&gt;! matcher1&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;

i trochę lukru składniowego:

&lt;table border="1"&gt;&lt;tr&gt;&lt;td&gt;is(matcher)&lt;/td&gt;&lt;td&gt;matcher&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;both(matcher1).and(matcher2)&lt;/td&gt;&lt;td&gt;matcher1 &amp;&amp; matcher2&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;either(matcher1).or(matcher2)&lt;/td&gt;&lt;td&gt;matcher1 || matcher2&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;

&lt;h3&gt;Przeglądanie kolekcji&lt;/h3&gt;
Najlepsze na koniec:

&lt;ul&gt;&lt;li&gt;everyItem(elementMatcher)&lt;/li&gt;&lt;li&gt;hasItem(elementMatcher)&lt;/li&gt;&lt;li&gt;hasItems(Matcher&lt;? super T&gt;... elementMatchers)&lt;/li&gt;&lt;/ul&gt;

Na przykład: 

&lt;pre&gt;&lt;font color="#0000ff"&gt;&lt;strong&gt;import static org.hamcrest.core.Every.everyItem;&lt;/strong&gt;&lt;/font&gt;
&lt;font color="#0000ff"&gt;&lt;strong&gt;import static org.hamcrest.core.IsCollectionContaining.hasItem;&lt;/strong&gt;&lt;/font&gt;
&lt;font color="#0000ff"&gt;&lt;strong&gt;import static org.hamcrest.core.IsCollectionContaining.hasItems;&lt;/strong&gt;&lt;/font&gt;
&lt;font color="#0000ff"&gt;&lt;strong&gt;import static org.hamcrest.core.IsEqual.equalTo;&lt;/strong&gt;&lt;/font&gt;

&lt;font color="#0000ff"&gt;&lt;strong&gt;import org.hamcrest.Matcher;&lt;/strong&gt;&lt;/font&gt;

&lt;font color="#444444"&gt;// ...&lt;/font&gt;

&lt;font color="#2040a0"&gt;List&lt;/font&gt;&lt;font color="#4444ff"&gt;&amp;lt;&lt;/font&gt;&lt;font color="#2040a0"&gt;String&lt;/font&gt;&lt;font color="#4444ff"&gt;&amp;gt;&lt;/font&gt; &lt;font color="#2040a0"&gt;stringList&lt;/font&gt; &lt;font color="#4444ff"&gt;=&lt;/font&gt; &lt;font color="#2040a0"&gt;Arrays&lt;/font&gt;.&lt;font color="#2040a0"&gt;asList&lt;/font&gt;&lt;font color="#4444ff"&gt;&lt;strong&gt;(&lt;/strong&gt;&lt;/font&gt;&lt;font color="#008000"&gt;"eggs"&lt;/font&gt;, &lt;font color="#008000"&gt;"spam"&lt;/font&gt;&lt;font color="#4444ff"&gt;&lt;strong&gt;)&lt;/strong&gt;&lt;/font&gt;&lt;font color="#4444ff"&gt;;&lt;/font&gt;

&lt;font color="#2040a0"&gt;Matcher&lt;/font&gt;&lt;font color="#4444ff"&gt;&amp;lt;&lt;/font&gt;?&lt;font color="#4444ff"&gt;&amp;gt;&lt;/font&gt; &lt;font color="#2040a0"&gt;mEveryItem&lt;/font&gt; &lt;font color="#4444ff"&gt;=&lt;/font&gt; &lt;font color="#2040a0"&gt;everyItem&lt;/font&gt;&lt;font color="#4444ff"&gt;&lt;strong&gt;(&lt;/strong&gt;&lt;/font&gt;&lt;font color="#2040a0"&gt;equalTo&lt;/font&gt;&lt;font color="#4444ff"&gt;&lt;strong&gt;(&lt;/strong&gt;&lt;/font&gt;&lt;font color="#008000"&gt;"eggs"&lt;/font&gt;&lt;font color="#4444ff"&gt;&lt;strong&gt;)&lt;/strong&gt;&lt;/font&gt;&lt;font color="#4444ff"&gt;&lt;strong&gt;)&lt;/strong&gt;&lt;/font&gt;&lt;font color="#4444ff"&gt;;&lt;/font&gt;
&lt;strong&gt;boolean&lt;/strong&gt; &lt;font color="#2040a0"&gt;isEveryItem&lt;/font&gt; &lt;font color="#4444ff"&gt;=&lt;/font&gt; &lt;font color="#2040a0"&gt;mEveryItem&lt;/font&gt;.&lt;font color="#2040a0"&gt;matches&lt;/font&gt;&lt;font color="#4444ff"&gt;&lt;strong&gt;(&lt;/strong&gt;&lt;/font&gt;&lt;font color="#2040a0"&gt;stringList&lt;/font&gt;&lt;font color="#4444ff"&gt;&lt;strong&gt;)&lt;/strong&gt;&lt;/font&gt;&lt;font color="#4444ff"&gt;;&lt;/font&gt; &lt;font color="#444444"&gt;// false&lt;/font&gt;

&lt;font color="#2040a0"&gt;Matcher&lt;/font&gt;&lt;font color="#4444ff"&gt;&amp;lt;&lt;/font&gt;&lt;font color="#2040a0"&gt;Iterable&lt;/font&gt;&lt;font color="#4444ff"&gt;&amp;lt;&lt;/font&gt;? &lt;strong&gt;super&lt;/strong&gt; &lt;font color="#2040a0"&gt;String&lt;/font&gt;&lt;font color="#4444ff"&gt;&amp;gt;&lt;/font&gt;&lt;font color="#4444ff"&gt;&amp;gt;&lt;/font&gt; &lt;font color="#2040a0"&gt;mHasItem1&lt;/font&gt; &lt;font color="#4444ff"&gt;=&lt;/font&gt; &lt;font color="#2040a0"&gt;hasItem&lt;/font&gt;&lt;font color="#4444ff"&gt;&lt;strong&gt;(&lt;/strong&gt;&lt;/font&gt;&lt;font color="#2040a0"&gt;equalTo&lt;/font&gt;&lt;font color="#4444ff"&gt;&lt;strong&gt;(&lt;/strong&gt;&lt;/font&gt;&lt;font color="#008000"&gt;"eggs"&lt;/font&gt;&lt;font color="#4444ff"&gt;&lt;strong&gt;)&lt;/strong&gt;&lt;/font&gt;&lt;font color="#4444ff"&gt;&lt;strong&gt;)&lt;/strong&gt;&lt;/font&gt;&lt;font color="#4444ff"&gt;;&lt;/font&gt;
&lt;strong&gt;boolean&lt;/strong&gt; &lt;font color="#2040a0"&gt;hasItem1&lt;/font&gt; &lt;font color="#4444ff"&gt;=&lt;/font&gt; &lt;font color="#2040a0"&gt;mHasItem1&lt;/font&gt;.&lt;font color="#2040a0"&gt;matches&lt;/font&gt;&lt;font color="#4444ff"&gt;&lt;strong&gt;(&lt;/strong&gt;&lt;/font&gt;&lt;font color="#2040a0"&gt;stringList&lt;/font&gt;&lt;font color="#4444ff"&gt;&lt;strong&gt;)&lt;/strong&gt;&lt;/font&gt;&lt;font color="#4444ff"&gt;;&lt;/font&gt; &lt;font color="#444444"&gt;// true&lt;/font&gt;

@&lt;font color="#2040a0"&gt;SuppressWarnings&lt;/font&gt;&lt;font color="#4444ff"&gt;&lt;strong&gt;(&lt;/strong&gt;&lt;/font&gt;&lt;font color="#008000"&gt;"unchecked"&lt;/font&gt;&lt;font color="#4444ff"&gt;&lt;strong&gt;)&lt;/strong&gt;&lt;/font&gt;
&lt;font color="#2040a0"&gt;Matcher&lt;/font&gt;&lt;font color="#4444ff"&gt;&amp;lt;&lt;/font&gt;&lt;font color="#2040a0"&gt;Iterable&lt;/font&gt;&lt;font color="#4444ff"&gt;&amp;lt;&lt;/font&gt;&lt;font color="#2040a0"&gt;String&lt;/font&gt;&lt;font color="#4444ff"&gt;&amp;gt;&lt;/font&gt;&lt;font color="#4444ff"&gt;&amp;gt;&lt;/font&gt; &lt;font color="#2040a0"&gt;mHasItems1&lt;/font&gt; &lt;font color="#4444ff"&gt;=&lt;/font&gt; &lt;font color="#2040a0"&gt;hasItems&lt;/font&gt;&lt;font color="#4444ff"&gt;&lt;strong&gt;(&lt;/strong&gt;&lt;/font&gt;
   &lt;font color="#2040a0"&gt;equalTo&lt;/font&gt;&lt;font color="#4444ff"&gt;&lt;strong&gt;(&lt;/strong&gt;&lt;/font&gt;&lt;font color="#008000"&gt;"eggs"&lt;/font&gt;&lt;font color="#4444ff"&gt;&lt;strong&gt;)&lt;/strong&gt;&lt;/font&gt;, &lt;font color="#2040a0"&gt;equalTo&lt;/font&gt;&lt;font color="#4444ff"&gt;&lt;strong&gt;(&lt;/strong&gt;&lt;/font&gt;&lt;font color="#008000"&gt;"spam"&lt;/font&gt;&lt;font color="#4444ff"&gt;&lt;strong&gt;)&lt;/strong&gt;&lt;/font&gt; &lt;font color="#4444ff"&gt;&lt;strong&gt;)&lt;/strong&gt;&lt;/font&gt;&lt;font color="#4444ff"&gt;;&lt;/font&gt;
&lt;strong&gt;boolean&lt;/strong&gt; &lt;font color="#2040a0"&gt;hasItems1&lt;/font&gt; &lt;font color="#4444ff"&gt;=&lt;/font&gt; &lt;font color="#2040a0"&gt;mHasItems1&lt;/font&gt;.&lt;font color="#2040a0"&gt;matches&lt;/font&gt;&lt;font color="#4444ff"&gt;&lt;strong&gt;(&lt;/strong&gt;&lt;/font&gt;&lt;font color="#2040a0"&gt;stringList&lt;/font&gt;&lt;font color="#4444ff"&gt;&lt;strong&gt;)&lt;/strong&gt;&lt;/font&gt;&lt;font color="#4444ff"&gt;;&lt;/font&gt; &lt;font color="#444444"&gt;// true&lt;/font&gt;&lt;/pre&gt;

Dodatkowo jeśli sprawdzamy czy obiekt w kolekcji jest równy dnemu, możemy pominąć &lt;code&gt;equalTo()&lt;/code&gt;

&lt;ul&gt;&lt;li&gt;hasItem(T element)&lt;/li&gt;&lt;li&gt;hasItem(elementMatcher)&lt;/li&gt;&lt;li&gt;hasItems(T... elements)&lt;/li&gt;&lt;/ul&gt;

Na przykład:

&lt;pre&gt;&lt;font color="#0000ff"&gt;&lt;strong&gt;import static org.hamcrest.core.IsCollectionContaining.hasItem;&lt;/strong&gt;&lt;/font&gt;
&lt;font color="#0000ff"&gt;&lt;strong&gt;import static org.hamcrest.core.IsCollectionContaining.hasItems;&lt;/strong&gt;&lt;/font&gt;
&lt;font color="#0000ff"&gt;&lt;strong&gt;import static org.hamcrest.core.IsEqual.equalTo;&lt;/strong&gt;&lt;/font&gt;

&lt;font color="#0000ff"&gt;&lt;strong&gt;import org.hamcrest.Matcher;&lt;/strong&gt;&lt;/font&gt;

&lt;font color="#444444"&gt;// ...&lt;/font&gt;

&lt;font color="#2040a0"&gt;List&lt;/font&gt;&lt;font color="#4444ff"&gt;&amp;lt;&lt;/font&gt;&lt;font color="#2040a0"&gt;String&lt;/font&gt;&lt;font color="#4444ff"&gt;&amp;gt;&lt;/font&gt; &lt;font color="#2040a0"&gt;stringList&lt;/font&gt; &lt;font color="#4444ff"&gt;=&lt;/font&gt; &lt;font color="#2040a0"&gt;Arrays&lt;/font&gt;.&lt;font color="#2040a0"&gt;asList&lt;/font&gt;&lt;font color="#4444ff"&gt;&lt;strong&gt;(&lt;/strong&gt;&lt;/font&gt;&lt;font color="#008000"&gt;"eggs"&lt;/font&gt;, &lt;font color="#008000"&gt;"spam"&lt;/font&gt;&lt;font color="#4444ff"&gt;&lt;strong&gt;)&lt;/strong&gt;&lt;/font&gt;&lt;font color="#4444ff"&gt;;&lt;/font&gt;

&lt;font color="#2040a0"&gt;Matcher&lt;/font&gt;&lt;font color="#4444ff"&gt;&amp;lt;&lt;/font&gt;&lt;font color="#2040a0"&gt;Iterable&lt;/font&gt;&lt;font color="#4444ff"&gt;&amp;lt;&lt;/font&gt;? &lt;strong&gt;super&lt;/strong&gt; &lt;font color="#2040a0"&gt;String&lt;/font&gt;&lt;font color="#4444ff"&gt;&amp;gt;&lt;/font&gt;&lt;font color="#4444ff"&gt;&amp;gt;&lt;/font&gt; &lt;font color="#2040a0"&gt;mHasItem2&lt;/font&gt; &lt;font color="#4444ff"&gt;=&lt;/font&gt; &lt;font color="#2040a0"&gt;hasItem&lt;/font&gt;&lt;font color="#4444ff"&gt;&lt;strong&gt;(&lt;/strong&gt;&lt;/font&gt;&lt;font color="#008000"&gt;"eggs"&lt;/font&gt;&lt;font color="#4444ff"&gt;&lt;strong&gt;)&lt;/strong&gt;&lt;/font&gt;&lt;font color="#4444ff"&gt;;&lt;/font&gt;

&lt;strong&gt;boolean&lt;/strong&gt; &lt;font color="#2040a0"&gt;hasItem2&lt;/font&gt; &lt;font color="#4444ff"&gt;=&lt;/font&gt; &lt;font color="#2040a0"&gt;mHasItem2&lt;/font&gt;.&lt;font color="#2040a0"&gt;matches&lt;/font&gt;&lt;font color="#4444ff"&gt;&lt;strong&gt;(&lt;/strong&gt;&lt;/font&gt;&lt;font color="#2040a0"&gt;stringList&lt;/font&gt;&lt;font color="#4444ff"&gt;&lt;strong&gt;)&lt;/strong&gt;&lt;/font&gt;&lt;font color="#4444ff"&gt;;&lt;/font&gt; &lt;font color="#444444"&gt;// true&lt;/font&gt;
&lt;font color="#2040a0"&gt;System&lt;/font&gt;.&lt;font color="#2040a0"&gt;out&lt;/font&gt;.&lt;font color="#2040a0"&gt;println&lt;/font&gt;&lt;font color="#4444ff"&gt;&lt;strong&gt;(&lt;/strong&gt;&lt;/font&gt;&lt;font color="#2040a0"&gt;hasItem2&lt;/font&gt;&lt;font color="#4444ff"&gt;&lt;strong&gt;)&lt;/strong&gt;&lt;/font&gt;&lt;font color="#4444ff"&gt;;&lt;/font&gt;

&lt;font color="#2040a0"&gt;Matcher&lt;/font&gt;&lt;font color="#4444ff"&gt;&amp;lt;&lt;/font&gt;&lt;font color="#2040a0"&gt;Iterable&lt;/font&gt;&lt;font color="#4444ff"&gt;&amp;lt;&lt;/font&gt;&lt;font color="#2040a0"&gt;String&lt;/font&gt;&lt;font color="#4444ff"&gt;&amp;gt;&lt;/font&gt;&lt;font color="#4444ff"&gt;&amp;gt;&lt;/font&gt; &lt;font color="#2040a0"&gt;mHasItems2&lt;/font&gt; &lt;font color="#4444ff"&gt;=&lt;/font&gt; &lt;font color="#2040a0"&gt;hasItems&lt;/font&gt;&lt;font color="#4444ff"&gt;&lt;strong&gt;(&lt;/strong&gt;&lt;/font&gt;&lt;font color="#008000"&gt;"eggs"&lt;/font&gt;, &lt;font color="#008000"&gt;"spam"&lt;/font&gt;&lt;font color="#4444ff"&gt;&lt;strong&gt;)&lt;/strong&gt;&lt;/font&gt;&lt;font color="#4444ff"&gt;;&lt;/font&gt;

&lt;strong&gt;boolean&lt;/strong&gt; &lt;font color="#2040a0"&gt;hasItems2&lt;/font&gt; &lt;font color="#4444ff"&gt;=&lt;/font&gt; &lt;font color="#2040a0"&gt;mHasItems2&lt;/font&gt;.&lt;font color="#2040a0"&gt;matches&lt;/font&gt;&lt;font color="#4444ff"&gt;&lt;strong&gt;(&lt;/strong&gt;&lt;/font&gt;&lt;font color="#2040a0"&gt;stringList&lt;/font&gt;&lt;font color="#4444ff"&gt;&lt;strong&gt;)&lt;/strong&gt;&lt;/font&gt;&lt;font color="#4444ff"&gt;;&lt;/font&gt; &lt;font color="#444444"&gt;// true&lt;/font&gt;
&lt;font color="#2040a0"&gt;System&lt;/font&gt;.&lt;font color="#2040a0"&gt;out&lt;/font&gt;.&lt;font color="#2040a0"&gt;println&lt;/font&gt;&lt;font color="#4444ff"&gt;&lt;strong&gt;(&lt;/strong&gt;&lt;/font&gt;&lt;font color="#2040a0"&gt;hasItems2&lt;/font&gt;&lt;font color="#4444ff"&gt;&lt;strong&gt;)&lt;/strong&gt;&lt;/font&gt;&lt;font color="#4444ff"&gt;;&lt;/font&gt;&lt;/pre&gt;

&lt;h3&gt;Dodatkowe matchery&lt;/h3&gt;
W archiwum &lt;code&gt;hamcrest-library.jar&lt;/code&gt; znajdują się matchery realizujące: &lt;ul&gt;&lt;li&gt;porównywanie liczb (w tym z daną dokładnością),&lt;/li&gt; &lt;li&gt;porównywanie napisów bez uwzględniania wielkości liter lub białych znaków,&lt;/li&gt; &lt;li&gt;czy napis jest pusty,&lt;/li&gt; &lt;li&gt;czy tablica lub kolekcja ma określony rozmiar lub czy mapa zawiera określony klucz lub wartość&lt;/li&gt;&lt;li&gt;testowanie występowania określonej ścieżki XPath&lt;/li&gt;&lt;/ul&gt;

&lt;h3&gt;Zastosowanie&lt;/h3&gt;
Oficjalna strona wymienia &lt;a href="http://code.google.com/p/hamcrest/wiki/UsesOfHamcrest"&gt;produkty wykorzystujące hamcrest&lt;/a&gt;. Najbardziej znane to weryfikacja w testach JUnit oraz tworzenie moków w Mockito.

Wydaje mi się, iż pomija się tu jedną ciekawą cechę matcherów, która jest oczywista dla każdego, kto otarł się o języki funkcyjne. Matcher'y są tak naprawdę metodą na zapamiętanie funkcji. Zatem tak zapamiętaną funkcję nie tylko można przekazać jako parametr metody, aby wywołać ją od razu (assertThath() w JUnit) lub po jakimś czasie (thenReturn() w Mockito) lecz &lt;b&gt;można zapamiętać warunek i (re)używać&lt;/b&gt;.

Dlaczego, nie zapamiętać skonstruowanego matcher'a i wykorzystać w kilku różnych funkcjach?&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3992064681062004055-5736089911191958258?l=it-researches.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/ItResearches/~4/T683kCaJn_4" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://it-researches.blogspot.com/feeds/5736089911191958258/comments/default" title="Komentarze do posta" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=3992064681062004055&amp;postID=5736089911191958258&amp;isPopup=true" title="Komentarze (2)" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3992064681062004055/posts/default/5736089911191958258?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3992064681062004055/posts/default/5736089911191958258?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/ItResearches/~3/T683kCaJn_4/hamcrest-matchery.html" title="hamcrest - matchery" /><author><name>Piotr Paradzinski</name><uri>http://www.blogger.com/profile/07915292026695759953</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="25" height="32" src="http://4.bp.blogspot.com/_cGW9IpdChVc/SYRCu49W5lI/AAAAAAAAADE/eZPPGD0JW_Q/S220/PiotrParadzinski.jpg" /></author><thr:total>2</thr:total><feedburner:origLink>http://it-researches.blogspot.com/2010/03/hamcrest-matchery.html</feedburner:origLink></entry><entry gd:etag="W/&quot;C0EGSHg9eip7ImA9WxBUGUg.&quot;"><id>tag:blogger.com,1999:blog-3992064681062004055.post-4984943798613971596</id><published>2010-03-07T08:58:00.003+01:00</published><updated>2010-03-07T09:47:09.662+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-03-07T09:47:09.662+01:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="hamcrect" /><title>hamcrest - podstawowe koncepcje</title><content type="html">Wspomniałem już o bólu przegryzania się przez bibliotekę hamcrest. Poniżej przegląd podstawowych elementów składowych hamcrest. Zawarte są w &lt;code&gt;hamcrest-core.jar&lt;/code&gt;.

&lt;h3&gt;Matcher&lt;/h3&gt;
Podstawowy typ klocków jakimi bawimy się w hamcrest to &lt;b&gt;matcher&lt;/b&gt;. Reprezentuje on warunek opakowany w obiekt. Dzięki temu warunek ten możemy zapamiętać a następnie sprawdzać czy różne obiekty spełniają ten warunek.

Każdy matcher rozszerza klasę &lt;code&gt;org.hamcrest.BaseMatcher&lt;/code&gt; implementującej interfejs &lt;code&gt;org.hamcrest.Matcher&lt;/code&gt;

Oto hello world wykorzystujący hamcrest. Pokazuje on w jaki sposób działają matcher'y:

&lt;pre&gt;&lt;a name="line1"&gt;1&lt;/a&gt; &lt;font color="#2040a0"&gt;Matcher&lt;/font&gt;&lt;font color="#4444ff"&gt;&amp;lt;&lt;/font&gt;&lt;font color="#2040a0"&gt;String&lt;/font&gt;&lt;font color="#4444ff"&gt;&amp;gt;&lt;/font&gt; &lt;font color="#2040a0"&gt;condition&lt;/font&gt; &lt;font color="#4444ff"&gt;=&lt;/font&gt; &lt;font color="#2040a0"&gt;endsWith&lt;/font&gt;&lt;font color="#4444ff"&gt;&lt;strong&gt;(&lt;/strong&gt;&lt;/font&gt; &lt;font color="#008000"&gt;"bar"&lt;/font&gt; &lt;font color="#4444ff"&gt;&lt;strong&gt;)&lt;/strong&gt;&lt;/font&gt;&lt;font color="#4444ff"&gt;;&lt;/font&gt;
&lt;a name="line2"&gt;2&lt;/a&gt; 
&lt;a name="line3"&gt;3&lt;/a&gt; &lt;strong&gt;if&lt;/strong&gt; &lt;font color="#4444ff"&gt;&lt;strong&gt;(&lt;/strong&gt;&lt;/font&gt; &lt;font color="#2040a0"&gt;condition&lt;/font&gt;.&lt;font color="#2040a0"&gt;matches&lt;/font&gt;&lt;font color="#4444ff"&gt;&lt;strong&gt;(&lt;/strong&gt;&lt;/font&gt; &lt;font color="#008000"&gt;"foobar"&lt;/font&gt;&lt;font color="#4444ff"&gt;&lt;strong&gt;)&lt;/strong&gt;&lt;/font&gt; &lt;font color="#4444ff"&gt;&lt;strong&gt;)&lt;/strong&gt;&lt;/font&gt; &lt;font color="#4444ff"&gt;&lt;strong&gt;{&lt;/strong&gt;&lt;/font&gt;
&lt;a name="line4"&gt;4&lt;/a&gt;    &lt;font color="#2040a0"&gt;System&lt;/font&gt;.&lt;font color="#2040a0"&gt;out&lt;/font&gt;.&lt;font color="#2040a0"&gt;println&lt;/font&gt;&lt;font color="#4444ff"&gt;&lt;strong&gt;(&lt;/strong&gt;&lt;/font&gt; &lt;font color="#008000"&gt;"hello world"&lt;/font&gt; &lt;font color="#4444ff"&gt;&lt;strong&gt;)&lt;/strong&gt;&lt;/font&gt;&lt;font color="#4444ff"&gt;;&lt;/font&gt;
&lt;a name="line5"&gt;5&lt;/a&gt; &lt;font color="#4444ff"&gt;&lt;strong&gt;}&lt;/strong&gt;&lt;/font&gt; &lt;strong&gt;else&lt;/strong&gt; &lt;font color="#4444ff"&gt;&lt;strong&gt;{&lt;/strong&gt;&lt;/font&gt;
&lt;a name="line6"&gt;6&lt;/a&gt;    &lt;font color="#2040a0"&gt;System&lt;/font&gt;.&lt;font color="#2040a0"&gt;out&lt;/font&gt;.&lt;font color="#2040a0"&gt;println&lt;/font&gt;&lt;font color="#4444ff"&gt;&lt;strong&gt;(&lt;/strong&gt;&lt;/font&gt; &lt;font color="#008000"&gt;"not this time"&lt;/font&gt; &lt;font color="#4444ff"&gt;&lt;strong&gt;)&lt;/strong&gt;&lt;/font&gt;&lt;font color="#4444ff"&gt;;&lt;/font&gt;
&lt;a name="line7"&gt;7&lt;/a&gt; &lt;font color="#4444ff"&gt;&lt;strong&gt;}&lt;/strong&gt;&lt;/font&gt;&lt;/pre&gt;

W linii 1, za pomocą metody statycznej &lt;code&gt;endsWith&lt;/code&gt;, tworzymy matcher reprezentujący warunek "napis kończący się na bar".

Następnie w linii 3 sprawdzamy czy napis "foobar" spełnia ten warunek.

&lt;h3&gt;Description&lt;/h3&gt;
Kolejny podstawowy element hamcrest to Description (&lt;code&gt;org.hamcrest.Description&lt;/code&gt;). Czyli obiekt reprezentujący opis matcher'a albo przeprowadzonej próby dopasowania. Opis jest ogólną koncepcją. W hamcrest core znajdują się 2 implementacje: opis tekstowy: &lt;code&gt;StringDescription&lt;/code&gt; i nic nie robiący opis NullDescription. Oto identyczny warunek ale nieco bardziej gadatliwy:

&lt;pre&gt;&lt;a name="line1"&gt; 1&lt;/a&gt; &lt;font color="#2040a0"&gt;String&lt;/font&gt; &lt;font color="#2040a0"&gt;expectedSuffix&lt;/font&gt; &lt;font color="#4444ff"&gt;=&lt;/font&gt; &lt;font color="#008000"&gt;"bar"&lt;/font&gt;&lt;font color="#4444ff"&gt;;&lt;/font&gt;
&lt;a name="line2"&gt; 2&lt;/a&gt; &lt;font color="#2040a0"&gt;String&lt;/font&gt; &lt;font color="#2040a0"&gt;testedItem&lt;/font&gt; &lt;font color="#4444ff"&gt;=&lt;/font&gt; &lt;font color="#008000"&gt;"foobarbaz"&lt;/font&gt;&lt;font color="#4444ff"&gt;;&lt;/font&gt;
&lt;a name="line3"&gt; 3&lt;/a&gt; 
&lt;a name="line4"&gt; 4&lt;/a&gt; &lt;font color="#2040a0"&gt;Matcher&lt;/font&gt;&lt;font color="#4444ff"&gt;&amp;lt;&lt;/font&gt;&lt;font color="#2040a0"&gt;String&lt;/font&gt;&lt;font color="#4444ff"&gt;&amp;gt;&lt;/font&gt; &lt;font color="#2040a0"&gt;matcher&lt;/font&gt; &lt;font color="#4444ff"&gt;=&lt;/font&gt; &lt;font color="#2040a0"&gt;endsWith&lt;/font&gt;&lt;font color="#4444ff"&gt;&lt;strong&gt;(&lt;/strong&gt;&lt;/font&gt; &lt;font color="#2040a0"&gt;expectedSuffix&lt;/font&gt; &lt;font color="#4444ff"&gt;&lt;strong&gt;)&lt;/strong&gt;&lt;/font&gt;&lt;font color="#4444ff"&gt;;&lt;/font&gt;
&lt;a name="line5"&gt; 5&lt;/a&gt; 
&lt;a name="line6"&gt; 6&lt;/a&gt; &lt;font color="#2040a0"&gt;Description&lt;/font&gt; &lt;font color="#2040a0"&gt;properBehaviourDes&lt;/font&gt; &lt;font color="#4444ff"&gt;=&lt;/font&gt; &lt;strong&gt;new&lt;/strong&gt; &lt;font color="#2040a0"&gt;StringDescription&lt;/font&gt;&lt;font color="#4444ff"&gt;&lt;strong&gt;(&lt;/strong&gt;&lt;/font&gt;&lt;font color="#4444ff"&gt;&lt;strong&gt;)&lt;/strong&gt;&lt;/font&gt;&lt;font color="#4444ff"&gt;;&lt;/font&gt;
&lt;a name="line7"&gt; 7&lt;/a&gt; &lt;font color="#2040a0"&gt;matcher&lt;/font&gt;.&lt;font color="#2040a0"&gt;describeTo&lt;/font&gt;&lt;font color="#4444ff"&gt;&lt;strong&gt;(&lt;/strong&gt;&lt;/font&gt; &lt;font color="#2040a0"&gt;properBehaviourDes&lt;/font&gt; &lt;font color="#4444ff"&gt;&lt;strong&gt;)&lt;/strong&gt;&lt;/font&gt;&lt;font color="#4444ff"&gt;;&lt;/font&gt;
&lt;a name="line8"&gt; 8&lt;/a&gt; 
&lt;a name="line9"&gt; 9&lt;/a&gt; &lt;strong&gt;if&lt;/strong&gt; &lt;font color="#4444ff"&gt;&lt;strong&gt;(&lt;/strong&gt;&lt;/font&gt; &lt;font color="#2040a0"&gt;matcher&lt;/font&gt;.&lt;font color="#2040a0"&gt;matches&lt;/font&gt;&lt;font color="#4444ff"&gt;&lt;strong&gt;(&lt;/strong&gt;&lt;/font&gt; &lt;font color="#2040a0"&gt;testedItem&lt;/font&gt; &lt;font color="#4444ff"&gt;&lt;strong&gt;)&lt;/strong&gt;&lt;/font&gt; &lt;font color="#4444ff"&gt;&lt;strong&gt;)&lt;/strong&gt;&lt;/font&gt; &lt;font color="#4444ff"&gt;&lt;strong&gt;{&lt;/strong&gt;&lt;/font&gt;
&lt;a name="line10"&gt;10&lt;/a&gt;    &lt;font color="#2040a0"&gt;System&lt;/font&gt;.&lt;font color="#2040a0"&gt;out&lt;/font&gt;.&lt;font color="#2040a0"&gt;println&lt;/font&gt;&lt;font color="#4444ff"&gt;&lt;strong&gt;(&lt;/strong&gt;&lt;/font&gt; &lt;font color="#008000"&gt;"I wish "&lt;/font&gt; &lt;font color="#4444ff"&gt;+&lt;/font&gt; &lt;font color="#2040a0"&gt;properBehaviourDes&lt;/font&gt; &lt;font color="#4444ff"&gt;&lt;strong&gt;)&lt;/strong&gt;&lt;/font&gt;&lt;font color="#4444ff"&gt;;&lt;/font&gt; 
&lt;a name="line11"&gt;11&lt;/a&gt;    &lt;font color="#2040a0"&gt;System&lt;/font&gt;.&lt;font color="#2040a0"&gt;out&lt;/font&gt;.&lt;font color="#2040a0"&gt;println&lt;/font&gt;&lt;font color="#4444ff"&gt;&lt;strong&gt;(&lt;/strong&gt;&lt;/font&gt; &lt;font color="#008000"&gt;"and my dream come true"&lt;/font&gt; &lt;font color="#4444ff"&gt;&lt;strong&gt;)&lt;/strong&gt;&lt;/font&gt;&lt;font color="#4444ff"&gt;;&lt;/font&gt;
&lt;a name="line12"&gt;12&lt;/a&gt; &lt;font color="#4444ff"&gt;&lt;strong&gt;}&lt;/strong&gt;&lt;/font&gt; &lt;strong&gt;else&lt;/strong&gt; &lt;font color="#4444ff"&gt;&lt;strong&gt;{&lt;/strong&gt;&lt;/font&gt;
&lt;a name="line13"&gt;13&lt;/a&gt;    &lt;font color="#2040a0"&gt;Description&lt;/font&gt; &lt;font color="#2040a0"&gt;invalidBehaviourDesc&lt;/font&gt; &lt;font color="#4444ff"&gt;=&lt;/font&gt; &lt;strong&gt;new&lt;/strong&gt; &lt;font color="#2040a0"&gt;StringDescription&lt;/font&gt;&lt;font color="#4444ff"&gt;&lt;strong&gt;(&lt;/strong&gt;&lt;/font&gt;&lt;font color="#4444ff"&gt;&lt;strong&gt;)&lt;/strong&gt;&lt;/font&gt;&lt;font color="#4444ff"&gt;;&lt;/font&gt;
&lt;a name="line14"&gt;14&lt;/a&gt;    &lt;font color="#2040a0"&gt;matcher&lt;/font&gt;.&lt;font color="#2040a0"&gt;describeMismatch&lt;/font&gt;&lt;font color="#4444ff"&gt;&lt;strong&gt;(&lt;/strong&gt;&lt;/font&gt; &lt;font color="#2040a0"&gt;testedItem&lt;/font&gt;, &lt;font color="#2040a0"&gt;invalidBehaviourDesc&lt;/font&gt; &lt;font color="#4444ff"&gt;&lt;strong&gt;)&lt;/strong&gt;&lt;/font&gt;&lt;font color="#4444ff"&gt;;&lt;/font&gt;
&lt;a name="line15"&gt;15&lt;/a&gt; 
&lt;a name="line16"&gt;16&lt;/a&gt;    &lt;font color="#2040a0"&gt;System&lt;/font&gt;.&lt;font color="#2040a0"&gt;out&lt;/font&gt;.&lt;font color="#2040a0"&gt;println&lt;/font&gt;&lt;font color="#4444ff"&gt;&lt;strong&gt;(&lt;/strong&gt;&lt;/font&gt; &lt;font color="#008000"&gt;"I wish "&lt;/font&gt; &lt;font color="#4444ff"&gt;+&lt;/font&gt; &lt;font color="#2040a0"&gt;properBehaviourDes&lt;/font&gt; &lt;font color="#4444ff"&gt;&lt;strong&gt;)&lt;/strong&gt;&lt;/font&gt;&lt;font color="#4444ff"&gt;;&lt;/font&gt; 
&lt;a name="line17"&gt;17&lt;/a&gt;    &lt;font color="#2040a0"&gt;System&lt;/font&gt;.&lt;font color="#2040a0"&gt;out&lt;/font&gt;.&lt;font color="#2040a0"&gt;println&lt;/font&gt;&lt;font color="#4444ff"&gt;&lt;strong&gt;(&lt;/strong&gt;&lt;/font&gt; &lt;font color="#008000"&gt;"but "&lt;/font&gt; &lt;font color="#4444ff"&gt;+&lt;/font&gt; &lt;font color="#2040a0"&gt;invalidBehaviourDesc&lt;/font&gt; &lt;font color="#4444ff"&gt;&lt;strong&gt;)&lt;/strong&gt;&lt;/font&gt;&lt;font color="#4444ff"&gt;;&lt;/font&gt;
&lt;a name="line18"&gt;18&lt;/a&gt; &lt;font color="#4444ff"&gt;&lt;strong&gt;}&lt;/strong&gt;&lt;/font&gt;&lt;/pre&gt;

Wynik działania programu:&lt;pre&gt;I wish a string ending with "bar"
but was "foobarbaz"&lt;/pre&gt;

W liniach 6-7 jest tworzony opis dla warunku. Wyświetlany w 10 i 16 przy użyciu metody &lt;code&gt;toString()&lt;/code&gt;.

W liniach 13-14 tworzymy opis dla sprawdzenia czy obiekt spełnia warunek. Wyświetlany jest w linii 17.

&lt;h3&gt;Factory&lt;/h3&gt;
Ostatni element to adnotacja wykorzystywana do oznaczenia metod, tworzących matchery. Jest to &lt;code&gt;org.hamcrest.Factory&lt;/code&gt;. Dzięki niemu można stosunkowo łatwo wyszukać dostępne metody tworzące matchery.

Przyznaję, eleganckie rozwiązanie :)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3992064681062004055-4984943798613971596?l=it-researches.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/ItResearches/~4/T49HnweQSNI" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://it-researches.blogspot.com/feeds/4984943798613971596/comments/default" title="Komentarze do posta" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=3992064681062004055&amp;postID=4984943798613971596&amp;isPopup=true" title="Komentarze (2)" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3992064681062004055/posts/default/4984943798613971596?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3992064681062004055/posts/default/4984943798613971596?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/ItResearches/~3/T49HnweQSNI/hamcrest-podstawowe-koncepcje.html" title="hamcrest - podstawowe koncepcje" /><author><name>Piotr Paradzinski</name><uri>http://www.blogger.com/profile/07915292026695759953</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="25" height="32" src="http://4.bp.blogspot.com/_cGW9IpdChVc/SYRCu49W5lI/AAAAAAAAADE/eZPPGD0JW_Q/S220/PiotrParadzinski.jpg" /></author><thr:total>2</thr:total><feedburner:origLink>http://it-researches.blogspot.com/2010/03/hamcrest-podstawowe-koncepcje.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CEYMSH89fCp7ImA9WxBUGUg.&quot;"><id>tag:blogger.com,1999:blog-3992064681062004055.post-8849701267796649174</id><published>2010-03-07T08:11:00.006+01:00</published><updated>2010-03-07T09:56:29.164+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-03-07T09:56:29.164+01:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="hamcrect" /><title>hamcrest - deficyt informacyjny</title><content type="html">Ostatnio, gdy po ciekawemu zastosowaniu wzorca strategii chciałem przetestować jego działanie, napotkałem ponownie problem sprawdzenia czy w kolekcji jest napis coś tam zawierający.

Po przygodach z Ruby pomyślałem sobie to powinno być proste! Po co muszę pisać pętlę, zabezpieczać się przed NPE, wprowadzać jakąś boolowską flagę dla sprawdzania wyniku i wrzucić do &lt;code&gt;assertTrue()&lt;/code&gt;.

I wtedy przypomniałem sobie o jakimś przykładzie w &lt;a href="http://www.junit.org/"&gt;JUnit 4&lt;/a&gt; z &lt;code&gt;assertThat()&lt;/code&gt; i biblioteką &lt;a href="http://code.google.com/p/hamcrest/"&gt;hamcrest&lt;/a&gt;.

Niestety przykład nie pasował dokładnie do moich potrzeb, szukam online API lub online Javadoc ... nie ma!

Sięgam do kodów źródłowych, żeby zobaczyć jakieś dobre komentarze, które mi wyjaśnią o co chodzi ... no bieda niesamowita (na w każdym razie nie jest to javadoc jaki jest np w JUnit 4 gdzie czytasz opis klasy i widzisz snippet)!

Sięgam do &lt;a href="http://code.google.com/p/hamcrest/wiki/Tutorial"&gt;oficjalnego tutoriala hamcrest&lt;/a&gt; a tu opis hello world oraz jak rozszerzać hamcrest'a ... ech.

No nawet na &lt;a href="http://en.wikipedia.org/wiki/Hamcrest"&gt;wpis o hamcrest na Wiki angielskiej&lt;/a&gt; jest co najmniej lakoniczny.

Zdesperowany przeszukuję czytnik blogów ... tylko wzmianka że jest.


Oczywiście API hamcrest nie jest specjalnie ciężkie, więc metodą prób i błędów coś tam się udało zrobić (choć nie aż tak oczywiste, jak np w Mockito), ...


... zaś brak dla jednych jest przygnębiającym i rozczarowującym faktem, dla innych - wyzwaniem i &lt;a href="http://it-researches.blogspot.com/2010/03/hamcrest-podstawowe-koncepcje.html"&gt;sytuacją rodzącą ciekawe możliwości&lt;/a&gt; :D&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3992064681062004055-8849701267796649174?l=it-researches.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/ItResearches/~4/U2N5XHBYdvc" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://it-researches.blogspot.com/feeds/8849701267796649174/comments/default" title="Komentarze do posta" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=3992064681062004055&amp;postID=8849701267796649174&amp;isPopup=true" title="Komentarze (0)" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3992064681062004055/posts/default/8849701267796649174?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3992064681062004055/posts/default/8849701267796649174?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/ItResearches/~3/U2N5XHBYdvc/hamcrest-deficyt-informacyjny.html" title="hamcrest - deficyt informacyjny" /><author><name>Piotr Paradzinski</name><uri>http://www.blogger.com/profile/07915292026695759953</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="25" height="32" src="http://4.bp.blogspot.com/_cGW9IpdChVc/SYRCu49W5lI/AAAAAAAAADE/eZPPGD0JW_Q/S220/PiotrParadzinski.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://it-researches.blogspot.com/2010/03/hamcrest-deficyt-informacyjny.html</feedburner:origLink></entry><entry gd:etag="W/&quot;C04FQXk9cSp7ImA9WxBVE00.&quot;"><id>tag:blogger.com,1999:blog-3992064681062004055.post-4816058389138183928</id><published>2010-02-14T22:29:00.005+01:00</published><updated>2010-02-16T07:31:50.769+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-02-16T07:31:50.769+01:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Clojure" /><title>Clojure pierwszy nieśmiały kroczek</title><content type="html">W ten weekend niewiele udało mi się zrobić z Clojure. Byłem trochę zajęty: wygoliłem sobie irokeza na głowie, po drodze do sklepu zapisaniem się na kurs prawa jazdy i trochę imprezowałem na wyjeździe i w domu :D 

Ale jednak wystartowałem:

&lt;h3&gt;Ogólne info&lt;/h3&gt;&lt;dl&gt;&lt;dt&gt;Twórca&lt;/dt&gt;&lt;dd&gt;Rich Hickey&lt;/dd&gt;&lt;dt&gt;Nazwa&lt;/dt&gt;&lt;dd&gt;od closure zastąpiono s przez j&lt;/dd&gt;&lt;dt&gt;Licencja&lt;/dt&gt;&lt;dd&gt;&lt;a href="http://www.eclipse.org/legal/epl-v10.html"&gt;Eclipse Public License&lt;/a&gt;&lt;/dd&gt;&lt;dt&gt;składnia&lt;/dt&gt;&lt;dd&gt;Jest to dialekt Lisp (wiec chyba kasiazki do Lisp moga sie przydac :)&lt;/dd&gt;&lt;dt&gt;Prawdopodobne zastosowanie&lt;/dt&gt;&lt;dd&gt;łączenie z kodem w Java do uzyskania wielowątkowego kodu (ciekawe czy aż tak wydajnie i niezawodnie jak w Erlang'u)&lt;/dd&gt;&lt;dt&gt;Pojawienie się języka&lt;/dt&gt;&lt;dd&gt;2007&lt;/dd&gt;&lt;dt&gt;Pojawienie się stabilnej wersji&lt;/dt&gt;&lt;dd&gt;maj 2009 (czyli niestety bardzo młody ... a może jednak stety)&lt;/dd&gt;&lt;/dl&gt;

&lt;h3&gt;Ważne linki&lt;/h3&gt;
Z oficjalnej strony: &lt;ul&gt;&lt;li&gt;&lt;a href="http://clojure.org/rationale"&gt;Uzasadnienie powstania&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://clojure.org/features"&gt;Przegląd funkcjonalności&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://richhickey.github.com/clojure/"&gt;API&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://clojure.org/Reference"&gt;Konstrukcje języka&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://code.google.com/p/clojure/wiki/FAQ"&gt;FAQ&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://en.wikibooks.org/wiki/Clojure_Programming"&gt;Clojure Programming (wikibooks)&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://clojure.blogspot.com/"&gt;Oficjalny blog&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;

Prezentacje i wideo: &lt;ul&gt;&lt;li&gt;&lt;a href="http://www.infoq.com/interviews/hickey-clojure"&gt;Rich Hickey on Clojure's Features and Implementation&lt;/a&gt;&lt;/li&gt;&lt;li&gt;Clojure for Java Programmers &lt;a href="http://blip.tv/file/982823"&gt;część 1&lt;/a&gt; i&lt;a href="http://blip.tv/file/982957"&gt; część 2&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://parleys.com/#st=5&amp;id=1518"&gt;Clojure: Functional Concurrency for JVM&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;

&lt;h3&gt;Instalacja i uruchomienie interpretera&lt;/h3&gt;
Praca z interpreterem nazywana bywa REPL - read-eval-print loop. Pobieramy &lt;a href="http://code.google.com/p/clojure/downloads/list"&gt;zip'a z Clojure&lt;/a&gt;. W środku powinna być biblioteka clojure.jar. 

Interpreter Clojure uruchamiamy poleceniem: &lt;pre&gt;java -cp clojure.jar clojure.main&lt;/pre&gt;

Warto zrobić sobie skrypt uruchamiający. Np na MS Windows zrobiłem tak:

1) zdefiniowałem zmienna środowiskowa CLOJURE_HOME wskazująca na katalog do którego rozpakowałem Clojure.

2) Dedalem na końcu do Ptah &lt;code&gt;;%CLOJURE_HOME%&lt;/code&gt;

3) Utworzyłem w katalogu CLOJURE_HOME plik clj.bat zawierajacy: &lt;pre&gt;java -cp %CLOJURE_HOME%/clojure.jar clojure.main %1&lt;/pre&gt;

Teraz skrypty w clojure można uruchamiać w postaci:
&lt;pre&gt;clj my_clojure_script.clj&lt;/pre&gt;

Zaś sam interpreter: &lt;pre&gt;clj&lt;/pre&gt;

&lt;h3&gt;Hello World&lt;/h3&gt;
Tworzymy plik hello_World.clj zawierający

(println "Hello world")

&lt;h3&gt;Integracja z Java&lt;/h3&gt;
No właśnie, Clojure byłby niczym więcej, niż tylko (n-1)-szym&lt;sup&gt;[1]&lt;/sup&gt;, bardzo młodym dialektem Lisp'a ... gdyby nie mały szczegół - integracja z Java.

Z poziomu kodu w Clojure można wywołać kod Java za pomocą składni: &lt;pre&gt;(. nazwa_klasy_java (nazwa_metody arg1 arg2 arg3))&lt;/pre&gt; Na przykład &lt;pre&gt;(. Integer (parseInt "12"))&lt;/pre&gt; Tu trafiło mi się pytanie na które nie znam jeszcze odpowiedzi: jak wywołać metodę z publicznego pola - czyli zrobić System.out.println?

W drugą stronę wygląda to również dosyć prosto. Niestety nie znam jeszcze konstrukcji Clojure wykorzystanych do tego, więc zostawiam tylko &lt;a href="http://clojure.org/compilation"&gt;linkę&lt;/a&gt;.

Jak się zbiorą i uformują moje notatki, dot. składni, w sensowną całość to umieszczę w kolejnym poście.

&lt;hr /&gt;
&lt;sup&gt;1 Tak tu powinno być n+1 ale ponieważ n-1 jest świetną miarą ilości flaszek na n-osobową imprezę, więc jest n-1 :)&lt;/sup&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3992064681062004055-4816058389138183928?l=it-researches.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/ItResearches/~4/Z2qm0jTwPUw" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://it-researches.blogspot.com/feeds/4816058389138183928/comments/default" title="Komentarze do posta" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=3992064681062004055&amp;postID=4816058389138183928&amp;isPopup=true" title="Komentarze (1)" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3992064681062004055/posts/default/4816058389138183928?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3992064681062004055/posts/default/4816058389138183928?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/ItResearches/~3/Z2qm0jTwPUw/clojure-pierwszy-niesmiay-kroczek.html" title="Clojure pierwszy nieśmiały kroczek" /><author><name>Piotr Paradzinski</name><uri>http://www.blogger.com/profile/07915292026695759953</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="25" height="32" src="http://4.bp.blogspot.com/_cGW9IpdChVc/SYRCu49W5lI/AAAAAAAAADE/eZPPGD0JW_Q/S220/PiotrParadzinski.jpg" /></author><thr:total>1</thr:total><feedburner:origLink>http://it-researches.blogspot.com/2010/02/clojure-pierwszy-niesmiay-kroczek.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DEMGSHY5cCp7ImA9WxBUGUo.&quot;"><id>tag:blogger.com,1999:blog-3992064681062004055.post-876721598271979497</id><published>2010-02-12T23:24:00.005+01:00</published><updated>2010-03-07T16:40:29.828+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-03-07T16:40:29.828+01:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="warsztat dewelopera" /><category scheme="http://www.blogger.com/atom/ns#" term="Ruby" /><category scheme="http://www.blogger.com/atom/ns#" term="Clojure" /><title>Ruby dodany do skrzynki z narzędziami</title><content type="html">Popełniłem mój pierwszy skrycik w języku Ruby w celach komercyjnych. Ku mojemu niemałemu zaskoczeniu, sporo mi pomogły &lt;a href="http://it-researches.blogspot.com/2009/12/ruby-quick-dirty-linki.html"&gt;moje własne linki o Ruby&lt;/a&gt;.

Rozwiązywałem problem bardziej administracyjno-wdrożeniowy niż programistyczny - niemniej czuję, jakbym w dziedzinie programowania osiągnął kolejny stopień wtajemniczenia :D

Sympatycznie jest przypomnieć sobie, że usunięcie duplikatów z napisu nie wymaga pętli tylko małego regexpa: &lt;center&gt;&lt;pre&gt;&lt;font color="#008000"&gt;'aaababbzzzzccjkk'&lt;/font&gt;.gsub&lt;font color="4444FF"&gt;&lt;strong&gt;(&lt;/strong&gt;&lt;/font&gt;&lt;font color="b000d0"&gt;/(.)\1+/&lt;/font&gt;,&lt;font color="#008000"&gt;'&lt;font color="#77dd77"&gt;\1&lt;/font&gt;'&lt;/font&gt;&lt;font color="4444FF"&gt;&lt;strong&gt;)&lt;/strong&gt;&lt;/font&gt;&lt;/pre&gt;&lt;/center&gt;


Z &lt;a href="http://it-researches.blogspot.com/2008/05/nauka-jzykw-programowaniaparadygmatw.html"&gt;wcześniej wymienionej listy języków i podejść jakie chciałbym dodać do mojej skrzynki z narzędziami developerskimi&lt;/a&gt; dodałem 2 pozycje: język skryptowy oraz Ruby.

Nie zamierzam zostawić tej wiedzy na obecnym poziomie. Niemniej wypadało by rozejrzeć się za jakimś godnym przeciwnikiem.

Najlepiej jakby dało się ten język integrować z JVM, aby można było jakoś z tego skorzystać w razie napotkania odpowiedniej klasy problemu. Z drugiej strony, język ten powinien wnosić jak najwięcej świeżości do mojego warsztatu.

Zastanawiam się nad językami: &lt;a href="http://www.scala-lang.org/"&gt;Scala&lt;/a&gt; i &lt;a href="http://clojure.org/"&gt;Clojure&lt;/a&gt;. &lt;a href="http://groovy.codehaus.org/"&gt;Groovy&lt;/a&gt; jest zbyt ... webowy (trudno o bardziej miażdżący w swej sile i głęboko merytoryczny powód :). Przez googlowe okularki można znaleźć &lt;a href="http://www.tutkiun.com/2009/11/scala-groovy-jruby-clojure-comparision.html"&gt;ciekawe porównanie różnych języków JVM&lt;/a&gt;

Wprawdzie Scala ma bardzo dobry PR i ciekawe &lt;a href="http://www.artima.com/scalazine/articles/twitter_on_scala.html"&gt;przykłady zastosowań, typu Twitter&lt;/a&gt;, jednak najprawdopodobniej będzie to Clojure: &lt;ul&gt;&lt;li&gt;nadrobię zaległości w zakresie programowania współbieżnego (owszem, miałem to załatwić przy pomocy Erlang'a, niemniej nie zanosi się na to aby podbijał on rynek IT)&lt;/li&gt;&lt;li&gt;to jest jakaś forma Lisp'a, a więc będzie to kontynuacja moich nieśmiałych prób z początku kariery&lt;/li&gt;&lt;li&gt;skoro jest to Lisp-owaty język więc może jakiś zakręt w kierunku sztucznej inteligencji?&lt;/li&gt;&lt;li&gt;czysto funkcyjny język ... kto wie może uda mi się znaleźć jakiś produktywny sposób wykorzystania tego podejścia do tworzenia dużych systemów&lt;/li&gt;&lt;/ul&gt;

Niestety nie będzie tak łatwo zacząć jak z Ruby. Tutorial do Ruby leży w co drugiej skrzyni. (Tak mi powiedział, z okrutnym uśmiechem, pewien gracz M&amp;M VII o mieczach +5, gdy zdobyłem, po kilku podejściach &lt;a href="http://crpg.iml.pl/baldurs-gate-2/katany/1705a"&gt;Furię Niebios&lt;/a&gt;.)

Może uda się (&lt;a href="http://grok-code.com/367/learning-clojure-with-project-euler/"&gt;za radą z tego blogu&lt;/a&gt;) wykorzystać &lt;a href="http://projecteuler.net/"&gt;projekt Euler&lt;/a&gt; jako źródło problemów (liczę na perm buff +5 do algorytmiki i tymczasowo +20 do satysfakcji z rozwiązywanych problemów).

Jak mawia stare porzekadło, jak się trochę porozglądasz po świecie to i czapka dla &lt;a href="http://elderscrolls.phx.pl/index.php?option=com_content&amp;task=view&amp;id=60&amp;Itemid=134"&gt;Arogranina&lt;/a&gt; się znajdzie ... czy tam &lt;a href="http://java.ociweb.com/mark/clojure/article.html"&gt;tutorial dla Clojure&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3992064681062004055-876721598271979497?l=it-researches.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/ItResearches/~4/WS9wQOejEKA" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://it-researches.blogspot.com/feeds/876721598271979497/comments/default" title="Komentarze do posta" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=3992064681062004055&amp;postID=876721598271979497&amp;isPopup=true" title="Komentarze (4)" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3992064681062004055/posts/default/876721598271979497?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3992064681062004055/posts/default/876721598271979497?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/ItResearches/~3/WS9wQOejEKA/ruby-dodany-do-skrzynki-z-narzedziami.html" title="Ruby dodany do skrzynki z narzędziami" /><author><name>Piotr Paradzinski</name><uri>http://www.blogger.com/profile/07915292026695759953</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="25" height="32" src="http://4.bp.blogspot.com/_cGW9IpdChVc/SYRCu49W5lI/AAAAAAAAADE/eZPPGD0JW_Q/S220/PiotrParadzinski.jpg" /></author><thr:total>4</thr:total><feedburner:origLink>http://it-researches.blogspot.com/2010/02/ruby-dodany-do-skrzynki-z-narzedziami.html</feedburner:origLink></entry><entry gd:etag="W/&quot;C0UAQ309eyp7ImA9WxBQGU4.&quot;"><id>tag:blogger.com,1999:blog-3992064681062004055.post-8636997764735634571</id><published>2010-01-19T19:53:00.006+01:00</published><updated>2010-01-19T21:00:42.363+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-01-19T21:00:42.363+01:00</app:edited><title>SCJP zdany i co z tym fantem?</title><content type="html">Dzięki uprzejmości &lt;a href="http://www.betacom.com.pl/"&gt;mojej firmy&lt;/a&gt; w poniedziałek 18 stycznia 2010 przespacerowałem się po pierwszej &lt;a href="http://www.sun.com/training/certification/java/index.xml"&gt;ścieżce certyfikacyjnej Sun&lt;/a&gt; :)

Rozgrzewka była solidna. Drugie czytanie &lt;a href="http://www.amazon.com/SCJP-Certified-Programmer-Java-310-065/dp/0071591060"&gt;SCJP Sun Certified Programmer for Java 6 Study Guide&lt;/a&gt; zajęło mi, mniej więcej, półtora tygodnia (pierwsze czytanie szło prawie rok bo między akapitami był WoW). 

Prawie 3 dni męczenia się nad zadaniami, z ww dzieła (wiadomo przerwy pół dniowe na oglądanie filmów). I ...

O K!@#$ tylko 20% ja p!@@#$%. 

Zaczęło się. Kawa lub inne nośniki kofeiny, witaminy b12 i magnezu. Ciężka muzyka ewentualnie inne wyzwalacze adrenaliny. No i oczywiście ultra szybkie wertowanie snippetów oraz ociekających tłuszczem, fragmentów świetnie napisanej prozy Javowej.

Skupiłem się na błędach z zadań oraz temu co przy 3 czytaniu mnie zaskakiwało. Notatki z tego czasu (niedziela wieczorem i w nocy) wystarczyły by do codziennego blogowania w 2010 :D

Późne godziny nocne - testy, mocki, symulatory etc. Trochę snu. Zgodnie ze złotą zasadą iż, umysł jest najbardziej chłonny &lt;b&gt;TUŻ PRZED EGZAMINEM&lt;/b&gt; sprawdzałem czym która metoda lubi sobie cisnąć, i jakie sformułowania wywołują grymasy kompilatora. Lektura mnie uśpiła ale udało się wchłonąć gorący lecz mały (by organizm nie tracił energii na trawienie) posiłek. Kofeina, batony czekoladowe, głębokie oddychanie (dla dotlenienie krwi), szybkie chodzenie (dla lepszego ukrwienia) i podnoszenie adrenaliny do ostatnich minut egzaminu rozważaniami nad tym jak powiedzieć szefowi, że się nie udało. I ...

... 96%!!! Układającym pytania udało się zatem znaleźć tylko 2 haki na mnie :) No nie-najgorzej :D

Niestety, dzień po egzaminie, uświadomiłem sobie smutną sprawę. Mamy nową specyfikację Java EE, z &lt;a href="http://www.sun.com/training/upcoming_java_ee_6.html"&gt;nowymi ciekawymi egzaminami&lt;/a&gt; np egzamin z JSF. Egzaminy niestety jeszcze w przygotowaniu. Książek przygotowujących do nich nie ma i pewnie nie będzie szybko. Do tego jest ich teraz 5 a nie 3. Wygląda też na to, iż trzeba będzie zdawać nowe wersje, żeby uzyskać tytułu na poziomie master.

No i mój &lt;a href="http://it-researches.blogspot.com/2009/05/czas-na-nowe-hobby-certyfikaty-it.html"&gt;harmonogram kolekcjonowania certyfikatów&lt;/a&gt; nieco się opóźnia :)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3992064681062004055-8636997764735634571?l=it-researches.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/ItResearches/~4/PJn819Gim1U" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://it-researches.blogspot.com/feeds/8636997764735634571/comments/default" title="Komentarze do posta" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=3992064681062004055&amp;postID=8636997764735634571&amp;isPopup=true" title="Komentarze (4)" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3992064681062004055/posts/default/8636997764735634571?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3992064681062004055/posts/default/8636997764735634571?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/ItResearches/~3/PJn819Gim1U/scjp-zdany-i-co-z-tym-fantem.html" title="SCJP zdany i co z tym fantem?" /><author><name>Piotr Paradzinski</name><uri>http://www.blogger.com/profile/07915292026695759953</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="25" height="32" src="http://4.bp.blogspot.com/_cGW9IpdChVc/SYRCu49W5lI/AAAAAAAAADE/eZPPGD0JW_Q/S220/PiotrParadzinski.jpg" /></author><thr:total>4</thr:total><feedburner:origLink>http://it-researches.blogspot.com/2010/01/scjp-zdany-i-co-z-tym-fantem.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CUYDRn84eSp7ImA9WxBQF04.&quot;"><id>tag:blogger.com,1999:blog-3992064681062004055.post-2259306233173636536</id><published>2010-01-17T12:48:00.004+01:00</published><updated>2010-01-17T13:59:37.131+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-01-17T13:59:37.131+01:00</app:edited><title>Jak pisać kod?</title><content type="html">Poszukiwałem informacji na temat tego jak należy tworzyć kod. Nie mogłem jakoś pogodzić ze sobą dwóch idei.

Pierwsza sprowadza się do tworzenia prostych, rozwiązań bez jakichkolwiek upiększeń - czyli &lt;a href="http://c2.com/cgi/wiki?KeepItSimpleStupid"&gt;KISS&lt;/a&gt; oraz &lt;a href="http://c2.com/xp/YouArentGonnaNeedIt.html"&gt;YAGNI&lt;/a&gt;. 

Druga, kładzie nacisk na tworzenie elastycznego kodu, łatwego do modyfikacji, rozszerzalnego akcentując różne zasady np DRY lub ich zestawy zasad np &lt;a href="http://c2.com/cgi/wiki?PrinciplesOfObjectOrientedDesign"&gt;SOLID&lt;/a&gt;, &lt;a href="http://en.wikipedia.org/wiki/GRASP_%28Object_Oriented_Design%29"&gt;GRASP&lt;/a&gt;.

Nie można odmówić racji i jednemu i drugiemu podejściu. Lecz nie trudno zauważyć, iż dążenie do elastyczności, rozszerzalności itp może prowadzić do komplikacji kodu - czyli naruszenia YAGNI. Różni ludzie, z którymi zdarzyło mi się dyskutować, kładli nacisk albo na 1 albo na 2 podejście lub udzielali mi odpowiedzi 44.

Dodatkowo dyskusje na ten temat, albo są teoretyczne, albo praktyczne z dokładnością do dobranych przykładów, albo dotyczą nieco wyższego poziomu abstrakcji - czyli projektowania. Nie mogłem jednym słowem znaleźć "&lt;a href="http://www.youtube.com/watch?v=ff-XVdiepTo"&gt;mojej racji, która była by była najmojsza&lt;/a&gt;" ;)

Ostatnio zacząłem czytać &lt;a href="http://www.amazon.com/Implementation-Patterns-Kent-Beck/dp/0321413091"&gt;Implementation Patterns&lt;/a&gt; Kent'a Beck'a. W końcu doczekałem się swojego &lt;a href="http://c2.com/cgi/wiki?AhHa"&gt;Aha!&lt;/a&gt; Ale nie przedstawię tu moich wniosków. Sięgnijcie do Kenta Becka - dokadniej do początkowych rozdziałów :)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3992064681062004055-2259306233173636536?l=it-researches.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/ItResearches/~4/jMetsJAypkA" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://it-researches.blogspot.com/feeds/2259306233173636536/comments/default" title="Komentarze do posta" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=3992064681062004055&amp;postID=2259306233173636536&amp;isPopup=true" title="Komentarze (8)" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3992064681062004055/posts/default/2259306233173636536?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3992064681062004055/posts/default/2259306233173636536?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/ItResearches/~3/jMetsJAypkA/jak-pisac-kod.html" title="Jak pisać kod?" /><author><name>Piotr Paradzinski</name><uri>http://www.blogger.com/profile/07915292026695759953</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="25" height="32" src="http://4.bp.blogspot.com/_cGW9IpdChVc/SYRCu49W5lI/AAAAAAAAADE/eZPPGD0JW_Q/S220/PiotrParadzinski.jpg" /></author><thr:total>8</thr:total><feedburner:origLink>http://it-researches.blogspot.com/2010/01/jak-pisac-kod.html</feedburner:origLink></entry><entry gd:etag="W/&quot;Ak8NQXw9fip7ImA9WxBQF08.&quot;"><id>tag:blogger.com,1999:blog-3992064681062004055.post-2210794391654523259</id><published>2010-01-17T12:13:00.005+01:00</published><updated>2010-01-17T12:48:10.266+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-01-17T12:48:10.266+01:00</app:edited><title>Generowanie kodu brzydkim zapachem?</title><content type="html">Zdarzyło mi się napisać &lt;a href="http://it-researches.blogspot.com/2009/11/generowanie-kodu.html"&gt;post o generowaniu kodu&lt;/a&gt;. Na c2.com znalazłem ciekawą dyskusję o tym, czy generowanie kodu jest oznaką kiepskiego rozwiązania: &lt;a href="http://c2.com/cgi/wiki?CodeGenerationIsaDesignSmell"&gt;Code Generation Isa Design Smell&lt;/a&gt;. W ramach tego samego serwisu jeszcze &lt;a href="http://c2.com/cgi/wiki?HowToDoCodeGenerationWell"&gt;How To Do Code Generation Well&lt;/a&gt;.

IMHO ciekawe.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3992064681062004055-2210794391654523259?l=it-researches.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/ItResearches/~4/I1LepLJo0J4" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://it-researches.blogspot.com/feeds/2210794391654523259/comments/default" title="Komentarze do posta" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=3992064681062004055&amp;postID=2210794391654523259&amp;isPopup=true" title="Komentarze (0)" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3992064681062004055/posts/default/2210794391654523259?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3992064681062004055/posts/default/2210794391654523259?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/ItResearches/~3/I1LepLJo0J4/generowanie-kodu-brzydkim-zapachem.html" title="Generowanie kodu brzydkim zapachem?" /><author><name>Piotr Paradzinski</name><uri>http://www.blogger.com/profile/07915292026695759953</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="25" height="32" src="http://4.bp.blogspot.com/_cGW9IpdChVc/SYRCu49W5lI/AAAAAAAAADE/eZPPGD0JW_Q/S220/PiotrParadzinski.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://it-researches.blogspot.com/2010/01/generowanie-kodu-brzydkim-zapachem.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DUENQ3k9eCp7ImA9WxBQEUg.&quot;"><id>tag:blogger.com,1999:blog-3992064681062004055.post-1538584234244221780</id><published>2010-01-10T13:47:00.010+01:00</published><updated>2010-01-10T22:08:12.760+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-01-10T22:08:12.760+01:00</app:edited><title>Manifest blogowania w języku polskim</title><content type="html">W społeczności blogów IT, zajmującej się językiem Java, widać tendencję do zmiany języka na angielski.

Przykłady: &lt;ul&gt;&lt;li&gt;Paweł Stawicki, &lt;a href="http://pawelstawicki.blogspot.com/"&gt;Java, the Programming, and Everything&lt;/a&gt; od wpisu &lt;a href="http://pawelstawicki.blogspot.com/2009/05/english-from-now-on.html"&gt;English from now on&lt;/a&gt;,&lt;/li&gt;&lt;li&gt;Paweł Badeński, &lt;a href="http://pbadenski.blogspot.com/"&gt;Pawel Badenski's IT Realms&lt;/a&gt; od wpisu &lt;a href="http://pbadenski.blogspot.com/2009/03/keywords-vs-api-continued.html"&gt;Keywords vs API, continued&lt;/a&gt;,&lt;/li&gt;&lt;li&gt;Paweł Szulc, &lt;a href="http://paulszulc.blogspot.com/"&gt;Whatever, we all gonna die anyway&lt;/a&gt; od wpisu &lt;a href="http://paulszulc.blogspot.com/2009/05/svn-merge-r531.html"&gt;svn merge -r:53:1&lt;/a&gt;&lt;/ul&gt; 

Nie mogę odmówić słuszności twierdzeniom: &lt;ul&gt;&lt;li&gt;chyba każdy programista Java, umie czytać w języku angielskim&lt;/li&gt;&lt;li&gt;większość, szukając rozwiązania używa Google i pisze słowa kluczowe w j.ang. nawet jeśli komunikat z błędem, problem jest ujęty w języku polskim&lt;/li&gt;&lt;li&gt;wypowiadając się w bardziej międzynarodowym gronie, lepiej jest wybrać język angielski&lt;/li&gt;&lt;li&gt;angielska terminologia dotycząca IT jest często czytelniejsza i bardziej zrozumiała niż w języku narodowym.&lt;/li&gt;&lt;/ul&gt; 

Jednak nie zamierzam przechodzić na język angielski.

Nie będę w ten sposób protestować przeciwko pozbawianiu różnorodności, spłycaniu, pozbawianiu smaku i wrażliwości wielu obszarów związanych z kulturą i rozrywką, przez komercyjne produkty ze stanów i ich kopie. Mimo iż dostrzegam ten proces. To jednak nie ludzie z IT za to odpowiadają :)

&lt;h3&gt;Eric Raymond - zgadzam się, o ile dobrze rozumiem&lt;/h3&gt;
Za migracje na angielski jest odpowiedzialny post na blogu Jeff'a Atwooda &lt;a href="http://www.codinghorror.com/blog/archives/001248.html"&gt;The Ugly American Programmer&lt;/a&gt;. Odniosę się, na początek, do obszernego cytatu z &lt;a href="catb.org/~esr/faqs/hacker-howto.html"&gt;How To Become A Hacker&lt;/a&gt; (Eric Raymond, 2001, link nie działa oto &lt;a href="http://209.85.129.132/search?q=cache:SyzMkm6XQH8J:catb.org/~esr/faqs/hacker-howto.html+How+To+Become+A+Hacker&amp;cd=1&amp;hl=pl&amp;ct=clnk&amp;gl=pl"&gt;kopia w archiwach Google&lt;/a&gt;).

&lt;cite&gt;Being a native English-speaker does not guarantee that you have language skills good enough to function as a hacker. If your writing is semi-literate, ungrammatical, and riddled with misspellings, many hackers (including myself) will tend to ignore you. While sloppy writing does not invariably mean sloppy thinking, we've generally found the correlation to be strong — and we have no use for sloppy thinkers. If you can't yet write competently, learn to.&lt;/cite&gt;

Według mnie fragment, mówi iż, nie powinno się używać języka angielskiego niezgodnie z jego ortografią i gramatyką. Wcześniej Eric Raymond pisze, iż znajomość języka angielskiego jest wymagana do funkcjonowania w środowisku hakerskiem:

&lt;cite&gt;As an American and native English-speaker myself, I have previously been reluctant to suggest this, lest it be taken as a sort of cultural imperialism. But several native speakers of other languages have urged me to point out that English is the working language of the hacker culture and the Internet, and that you will need to know it to function in the hacker community.&lt;/cite&gt;

W porządku. Posługiwanie się, językiem angielskim jest bardzo wskazane w projektach międzynarodowych: 

&lt;cite&gt;Linus Torvalds, a Finn, comments his code in English (it apparently never occurred to him to do otherwise). His fluency in English has been an important factor in his ability to recruit a worldwide community of developers for Linux. It's an example worth following.&lt;/cite&gt;

To bardzo dobry zwyczaj, by używać języka zrozumiałego dla postronnego słuchacza, nawet gdy się rozmawia z rodakiem:

&lt;cite&gt;Back around 1991 I learned that many hackers who have English as a second language use it in technical discussions even when they share a birth tongue; it was reported to me at the time that English has a richer technical vocabulary than any other language and is therefore simply a better tool for the job.&lt;/cite&gt;

Wg. mnie przesłanie autora &lt;i&gt;How To Become A Hacker&lt;/i&gt; brzmi: "Naucz się poprawnie posługiwać się językiem angielskim."

&lt;h3&gt;Jeff Atwood - nie zgadzam się&lt;/h3&gt;
Nie zgadzam się z tezą, Jeff'a Atwooda w &lt;a href="http://www.codinghorror.com/blog/archives/001248.html"&gt;The Ugly American Programmer&lt;/a&gt;

&lt;cite&gt;Advocating the adoption of English as the de-facto standard language of software development is simple pragmatism, the most virtuous of all hacker traits. If that makes me an ugly American programmer, so be it. &lt;/cite&gt;

Co oznacza przyjęcie języka angielskiego jako standardu w tworzeniu oprogramowania? Dla mnie oznacza to, zmuszenie do używania go. Wszędzie, gdzie mamy do czynienia z tworzeniem oprogramowania i komunikowania się na ten temat.

Czy to znaczy, że mam przetłumaczyć moje posty na język angielski i jeśli już pisać, to w języku angielskim? Pal licho mój blog - są popularniejsze. 

Zresztą nie chodzi tylko o blogi. Co z grupami dyskusyjnymi, publikacjami akademickimi, książkami, czasopismami. Kończymy z tłumaczeniami? Zamykamy etap rozwoju języka polskiego w obszarze IT?

Językiem wykładowców i studentów informatyki jest od dziś amerykański?

Kolegów w pracy też mam po angielsku pytać o technologie, styl komentowania, co sądzą o danym rozwiązaniu projektowym?

&lt;h3&gt;Różnorodność, w tym języka, jest ważna&lt;/h3&gt;
Literatura naukowa powstaje w różnych językach. Język, którym się posługujemy wpływa na nasz sposób opisywania, nazywania, wyodrębniania a zatem i postrzegania rzeczywistości. Więc niech będzie bogaty i różnorodny. Nie zamykajmy sobie kierunków rozwoju. Nie wybierajmy jednej właściwej słusznej drogi. I to tylko dlatego że popularnemu bloggerowi wydaje się, że ziemia jest płaska ;)

&lt;h3&gt;Automatyczne tłumaczenie&lt;/h3&gt;
Myślę, że w miarę rozgarnięty użytkownik internetu użyje sobie narzędzia w stylu: &lt;a href="http://babelfish.yahoo.com/"&gt;Babelfish&lt;/a&gt; lub &lt;a href="http://translate.google.com/"&gt;Google Translate&lt;/a&gt;. I uda mu się przetłumaczyć wypowiedzi na swój język. Będą niezgrabne ale kod zapewne da się przeczytać.

&lt;h3&gt;Jakość literatury&lt;/h3&gt;
Techniczne słownictwo w języku angielskim jest zapewne najbogatsze. Czy to jednak oznacza, iż nie należy starać się wypracować dobrych odpowiedników i zaadoptować to co jest nie daje się dobrze przetłumaczyć?

Jeśli się spojrzy na tłumaczenia niektórych książek na język polski (np. &lt;a href="http://www.wnt.com.pl/product.php?action=0&amp;prod_id=986"&gt;Wzorce projektowe&lt;/a&gt;), to sposób tłumaczenia terminologii programistycznej, nie zawsze zachwyca. Jednak chyba sytuacja się poprawia - np: &lt;a href="http://helion.pl/ksiazki/refawp.htm"&gt;Refaktoryzacja do wzorców&lt;/a&gt;.

Jednak tłumaczenia nie będą zwiększały swojej jakości, dzięki temu, iż wszystko będzie napisane w języku angielskim. Łącznie z blogami.

Zapewne grupa dyskusyjna &lt;a href="http://groups.google.pl/group/pl.comp.tlumaczenia/topics"&gt;pl.comp.tlumaczenia&lt;/a&gt; ma na to większy wpływ, ale wszystko się liczy.

&lt;h3&gt;Co pikantniejsze komentarze&lt;/h3&gt;
Post Jeff'a Atwood'a doczekał się ogromnej liczby komentarzy. Większość w stylu "dobrze gada dać mu wódki". Ale są też nieco inne.

Trochę ad personam, lecz wg. mnie trafny:

&lt;cite&gt;My question is, if the world becomes a different place in the future, are you ok with someone telling you that functional Hindi is required in order to be a true hacker?&lt;/cite&gt;

Sam chciałem tak skomentować:

&lt;cite&gt;But you completely missed the point. What I'm saying is that there is a LOT of non-english programming sites, but YOU don't read them, and you didn't post IN THEM such discussion, so you don't get their feedback.&lt;/cite&gt;

Naprawdę rozbrajający:

&lt;cite&gt;I predict in 200-300 years software developers are required to learn a dead language (English) so that they can maintain the legacy systems that run our technology infrastructure.&lt;/cite&gt;

&lt;h3&gt;Najważniejsze dla mnie&lt;/h3&gt;
No właśnie. Dla mnie pisanie po polsku jest zgodne z ... byciem sobą, tym jak siebie postrzegam.

&lt;h3&gt;Wniosek&lt;/h3&gt;
Obecnie poprzestaję na języku polskim. Niemniej będę w miarę możliwości śledził też polską myśl deweloperską "na obczyźnie" :) Nie można zaprzeczyć, iż stanie się ona częściej wygoogliwana.

Postaram się również, zwrócić pilniejszą uwagę na język moich wypowiedzi. Na gramatykę, stylistykę i interpunkcję. Jeśli coś, gdzieś zrobię niezgodnie ze sztuką, proszę o informacje. Postaram się poprawić. Dziękuję &lt;a href="http://agsik.blogspot.com/"&gt;AGS&lt;/a&gt; za zwrócenie mi na to uwagi.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3992064681062004055-1538584234244221780?l=it-researches.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/ItResearches/~4/AbnXwTuq8DI" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://it-researches.blogspot.com/feeds/1538584234244221780/comments/default" title="Komentarze do posta" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=3992064681062004055&amp;postID=1538584234244221780&amp;isPopup=true" title="Komentarze (2)" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3992064681062004055/posts/default/1538584234244221780?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3992064681062004055/posts/default/1538584234244221780?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/ItResearches/~3/AbnXwTuq8DI/manifest-blogowania-w-jezyku-polskim.html" title="Manifest blogowania w języku polskim" /><author><name>Piotr Paradzinski</name><uri>http://www.blogger.com/profile/07915292026695759953</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="25" height="32" src="http://4.bp.blogspot.com/_cGW9IpdChVc/SYRCu49W5lI/AAAAAAAAADE/eZPPGD0JW_Q/S220/PiotrParadzinski.jpg" /></author><thr:total>2</thr:total><feedburner:origLink>http://it-researches.blogspot.com/2010/01/manifest-blogowania-w-jezyku-polskim.html</feedburner:origLink></entry><entry gd:etag="W/&quot;D0YMQXc8eip7ImA9WxBQEU8.&quot;"><id>tag:blogger.com,1999:blog-3992064681062004055.post-8388771439789181435</id><published>2010-01-08T10:16:00.005+01:00</published><updated>2010-01-10T13:06:20.972+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-01-10T13:06:20.972+01:00</app:edited><title>Piotrze, zapoznaj się z tym!</title><content type="html">Te linki chcę mieć w jednym miejscu. Prowadzą one do informacji, które zamierzam w najbliższym czasie poznać, zrozumieć i przemyśleć. W przeciwieństwie do większości innych treści, które wystarczy pobieżnie przejrzeć lub co najwyżej raz przeczytać.

&lt;ul&gt;&lt;li&gt;&lt;a href="http://martinfowler.com/articles.html"&gt;Martin Fowler: Articles&lt;/a&gt;&lt;/li&gt;&lt;li&gt;Object Mentor &lt;a href="http://www.objectmentor.com/resources/publishedArticles.html"&gt;artykuły&lt;/a&gt; i &lt;a href="http://www.objectmentor.com/resources/otherMedia.html"&gt;nagrania audio i wideo&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://butunclebob.com/ArticleS.UncleBob.PrinciplesOfOod"&gt;Principles of OOD - Robert Martin (Uncle Bob)&lt;/a&gt;, oraz ciekawy zbiór odnośników o &lt;a href="http://arekborek.blogspot.com/2009/09/solid.html"&gt;SOLID na blogu arek.borek&lt;/a&gt;&lt;/li&gt;&lt;li&gt;c2.com wiki, przeglądanie można zacząć np tu: &lt;a href="http://c2.com/cgi/wiki?DontRepeatYourself"&gt;DRY&lt;/a&gt;, &lt;a href="http://c2.com/cgi/wiki?KeepItSimpleStupid"&gt;KISS&lt;/a&gt;, &lt;a href="http://c2.com/xp/CodeSmell.html"&gt;Code Smell&lt;/a&gt;, &lt;a href="http://c2.com/cgi/wiki?AntiPatternsCatalog"&gt;Anti-Patterns - lista&lt;/a&gt;, &lt;a href="http://c2.com/cgi/wiki?CategoryPattern"&gt;Design Patterns - w podziale na kategorie&lt;/a&gt;, &lt;a href="http://c2.com/cgi/wiki?CategoryTesting"&gt;testing&lt;/a&gt;, &lt;a href="http://c2.com/cgi/wiki?YouArentGonnaNeedIt"&gt;YAGNI&lt;/a&gt;, &lt;a href="http://c2.com/cgi/wiki?OoDesignPrinciples"&gt;OO Design Principles&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://misko.hevery.com/"&gt;Blog Misko Hevery&lt;/a&gt; - bardzo ciekawe koncepcje i słownictwo związane z tworzenie łatwego do testowania kodu&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.threeriversinstitute.org/blog/"&gt;blog Kent'a Beck'a&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;

Jeszcze 2 ciekawe prezentacje na InfoQ o projektowaniu. 

&lt;a href="http://www.infoq.com/presentations/responsive-design"&gt;Kent Beck - Responsive Design&lt;/a&gt;, w którym Kent Beck porusza sporo kwestii m.in. rekomenduje 2 książki (&lt;a href="http://www.amazon.com/Implementation-Patterns-Kent-Beck/dp/0321413091"&gt;Implementation patterns&lt;/a&gt; oraz &lt;a href="http://www.amazon.com/Structured-Design-Fundamentals-Discipline-Computer/dp/0138544719/ref=sr_1_1?ie=UTF8&amp;s=books&amp;qid=1263049577&amp;sr=1-1"&gt;Structured design&lt;/a&gt;), podaje ciekawą definicję projektowania oprogramowania, opisuje co różni jego decyzje projektowe od decyzji ludzi z którymi projektował i tworzył kod, systematyzuje różnice podając 4 wzorce czy raczej tendencje a dalej nie wiem bo padłem koło 2 w nocy :)

&lt;a href="http://www.infoq.com/presentations/What-Drives-Design-Rebecca-Wirfs-Brock"&gt;What Drives Design?&lt;/a&gt;. Rebecca Wirtfs-Brock opowiada o *DD w tym ciekawie przedstawia na czym skupiają się poszczególne podejścia i jak to jest z ich łączeniem. Szerzej opisuje Responsibility Driven Design.

I na koniec coś z czym kilka razy się spotkałem ale sceptycznie podchodziłem do tej teorii: &lt;a href="http://en.wikipedia.org/wiki/Dreyfus_model_of_skill_acquisition"&gt;model braci Dreyfus - poziomów umiejętności&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3992064681062004055-8388771439789181435?l=it-researches.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/ItResearches/~4/q3jBRq6VWMY" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://it-researches.blogspot.com/feeds/8388771439789181435/comments/default" title="Komentarze do posta" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=3992064681062004055&amp;postID=8388771439789181435&amp;isPopup=true" title="Komentarze (0)" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3992064681062004055/posts/default/8388771439789181435?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3992064681062004055/posts/default/8388771439789181435?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/ItResearches/~3/q3jBRq6VWMY/piotr-zapoznaj-sie-z-tym.html" title="Piotrze, zapoznaj się z tym!" /><author><name>Piotr Paradzinski</name><uri>http://www.blogger.com/profile/07915292026695759953</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="25" height="32" src="http://4.bp.blogspot.com/_cGW9IpdChVc/SYRCu49W5lI/AAAAAAAAADE/eZPPGD0JW_Q/S220/PiotrParadzinski.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://it-researches.blogspot.com/2010/01/piotr-zapoznaj-sie-z-tym.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DEEMSH44eip7ImA9WxBRF08.&quot;"><id>tag:blogger.com,1999:blog-3992064681062004055.post-6356893841780439286</id><published>2010-01-05T21:56:00.003+01:00</published><updated>2010-01-05T22:24:49.032+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-01-05T22:24:49.032+01:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="JRuby" /><category scheme="http://www.blogger.com/atom/ns#" term="zawód programista" /><title>JRuby praktycznie</title><content type="html">Dzięki komentarzom do &lt;a href="http://it-researches.blogspot.com/2010/01/dlaczego-ruby.html"&gt;posta Dlaczego Ruby&lt;/a&gt; osoby ukrywającej się pod pseudonimem lopex (być może &lt;a href="http://svnsearch.org/svnsearch/repos/JRUBY/search?author=lopex"&gt;jeden z komiterów JRuby&lt;/a&gt;) dowiedziałem się, iż nowo powstające języki czy też, jak w tym przypadku, implementacje istniejącego od jakiegoś czasu języka - czyli JRuby są wykorzystywane w praktyce.

Stosunkowo łatwo można wyszukać info o &lt;a href="http://kenai.com/projects/jruby/pages/SuccessStories"&gt;projektach, które wykorzystują JRuby&lt;/a&gt; czy nawet dzielą się swoimi doświadczeniami w &lt;a href="http://kenai.com/projects/jruby/pages/CaseStudies"&gt;używaniu tej implementacji&lt;/a&gt;. Nie było by to warte nowego posta gdyby nie &lt;a href="http://kenai.com/projects/jruby/pages/InYourRegion"&gt;3 ciekawa strona&lt;/a&gt;. Mamy na niej długą listę obszarów w USA gdzie jest JRuby wykorzystywany, krótszą z różnymi krajami europejskimi a tu nagle ... POLSKA !!!

Dacie wiarę :)

Czujecie jak wasze uczucia patriotyczne zostały mile połechtane? Ba można by rzec iż wbrew silnym tendencjom na rynku by pozostawać przy starych sprawdzonych rozwiązaniach (np CVS, Ant, edytor tekstu zamiast IDE, itp) są projekty w których stosuje się innowacyjne podejścia.

Mi się łezka zakręciła w oku nie tylko z powodu dumy narodowej i obserwacji dążenia do rozwoju technologicznego lecz ... ze względu na pewne przemyślenia natury ... hmmm ekonomicznej ... lub powiedzmy to w końcu wprost - marketingowej :)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3992064681062004055-6356893841780439286?l=it-researches.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/ItResearches/~4/sbKVZVKWRMc" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://it-researches.blogspot.com/feeds/6356893841780439286/comments/default" title="Komentarze do posta" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=3992064681062004055&amp;postID=6356893841780439286&amp;isPopup=true" title="Komentarze (1)" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3992064681062004055/posts/default/6356893841780439286?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3992064681062004055/posts/default/6356893841780439286?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/ItResearches/~3/sbKVZVKWRMc/jruby-praktycznie.html" title="JRuby praktycznie" /><author><name>Piotr Paradzinski</name><uri>http://www.blogger.com/profile/07915292026695759953</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="25" height="32" src="http://4.bp.blogspot.com/_cGW9IpdChVc/SYRCu49W5lI/AAAAAAAAADE/eZPPGD0JW_Q/S220/PiotrParadzinski.jpg" /></author><thr:total>1</thr:total><feedburner:origLink>http://it-researches.blogspot.com/2010/01/jruby-praktycznie.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CUUDRno-eyp7ImA9WxBRFkw.&quot;"><id>tag:blogger.com,1999:blog-3992064681062004055.post-8290388818571192674</id><published>2010-01-04T13:02:00.005+01:00</published><updated>2010-01-04T14:54:37.453+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-01-04T14:54:37.453+01:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="testy jednostkowe" /><title>Blog Miško Hevery - polecam</title><content type="html">Polecam &lt;a href="http://misko.hevery.com/"&gt;blog pana Miško Hevery&lt;/a&gt;, dotyczący przede wszystkim tworzenia kodu łatwego do testowania (przynajmniej do drugiej połowy 2008 roku bo dotąd doczytałem). O blogu usłyszałem na prezentacji Pawła Szulca &lt;a href="http://paulszulc.blogspot.com/"&gt;[1]&lt;/a&gt; &lt;a href="http://paulszulc.blogspot.com/"&gt;[2]&lt;/a&gt; na konferencji &lt;a href="http://www.java4people.com/"&gt;java4people&lt;/a&gt; (Szczecin 2009).

Wg. mnie warto zacząć od obejrzenie nagrania wideo &lt;a href="http://misko.hevery.com/2008/11/04/clean-code-talks-unit-testing/"&gt;Clean Code Talk - Unit Testing&lt;/a&gt;. 

A czemu akurat ten blog? Proste autor jest trenerem (czyli wie jak opowiadać) tworzenia testów i testowanego kodu w Google (czyli kwalifikacje odpowiednie ma).

Większość osób pisząc o testach jednostkowych robi to mniej więcej tak. Pisanie testów jednostkowych jest piękne, łatwe i przyjemne. Każdy kto tego nie robi jest co najmniej dziwny. Kto choć hello world zrobił w junit (lub testng) nigdy nie będzie chciał zacząć implementacji nowych funkcji bez testu. Brzmi znajomo :)

Możliwe nawet że tak faktycznie jest, jeśli tworzy się kod w ramach dobrze zaprojektowanego, dobrze zaimplementowanego, przetestowanego, udokumentowanego projektu bez presji terminów. Ciągle brzmi znajomo :P

Miško Hevery bardzo realistycznie przedstawia w jak wielkiej d... jest deweloper który zaczyna pisać testy do własnego, nietrywialnego kodu bez przygotowania. Dlaczego? 

Bo każdy ma wrodzoną, często przez długi czas rozwijaną, umiejętność pisania trudnego do testowania kodu. I nie dosyć że, zapewne, nie zdaje sobie z tego sprawy to jeszcze nawet nie wie w czym tkwi problem.

&lt;b&gt;Trudne w testach jednostkowych nie jest samo pisanie testów, tylko tworzenie łatwego do przetestowania kodu&lt;/b&gt;.

Sporo jest informacji o pisaniu zgodnie z prawem Demeter, wstrzykiwaniu zależności, rozdzielaniu konstrukcji obiektów od ich użycia. 

Zapewne każdy wie że wzorzec Singleton, stan globalny i metody statyczne to zło. Ale czy każdy wie dlaczego? A nawet jeśli zna krótką odpowiedź to czy zna uzasadnienie? A jeśli nawet wie to wszystko to czy wie kiedy te złe rzeczy powodują problemy a kiedy nie?

Lektura naprawdę poszerza horyzonty. W każdym razie moje :)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3992064681062004055-8290388818571192674?l=it-researches.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/ItResearches/~4/e6r4u1XdSig" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://it-researches.blogspot.com/feeds/8290388818571192674/comments/default" title="Komentarze do posta" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=3992064681062004055&amp;postID=8290388818571192674&amp;isPopup=true" title="Komentarze (1)" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3992064681062004055/posts/default/8290388818571192674?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3992064681062004055/posts/default/8290388818571192674?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/ItResearches/~3/e6r4u1XdSig/blog-misko-havery-polecam.html" title="Blog Miško Hevery - polecam" /><author><name>Piotr Paradzinski</name><uri>http://www.blogger.com/profile/07915292026695759953</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="25" height="32" src="http://4.bp.blogspot.com/_cGW9IpdChVc/SYRCu49W5lI/AAAAAAAAADE/eZPPGD0JW_Q/S220/PiotrParadzinski.jpg" /></author><thr:total>1</thr:total><feedburner:origLink>http://it-researches.blogspot.com/2010/01/blog-misko-havery-polecam.html</feedburner:origLink></entry><entry gd:etag="W/&quot;D0cBR3o8fip7ImA9WxBRFUo.&quot;"><id>tag:blogger.com,1999:blog-3992064681062004055.post-7856086506342701432</id><published>2010-01-03T23:47:00.008+01:00</published><updated>2010-01-04T04:17:36.476+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-01-04T04:17:36.476+01:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Maven" /><category scheme="http://www.blogger.com/atom/ns#" term="Cobertura" /><category scheme="http://www.blogger.com/atom/ns#" term="TestNG" /><title>Eclipse + Maven2 + TestNG + Cobertura</title><content type="html">&lt;h3&gt;Eclipse konfiguracja Maven2&lt;/h3&gt;

W Eclipse wystarczy dodać plugin do obsługi Maven2 z update site &lt;a href="http://beust.com/eclipse"&gt;http://beust.com/eclipse&lt;/a&gt;. Resztę narzędzi typu TestNG, Cobertura integruje się z Maven'em.

&lt;b&gt;Maven2 - podstawowe zmiany&lt;/b&gt;

Ustawienie poziomu kompilacji na 1.6 w pom.xml: &lt;pre&gt;&amp;lt;project&amp;gt;
  &amp;lt;!-- ... --&amp;gt;
  &amp;lt;build&amp;gt;
    &amp;lt;!-- ... --&amp;gt;
    &amp;lt;plugins&amp;gt;
          
      &amp;lt;plugin&amp;gt;
        &amp;lt;groupId&amp;gt;org.apache.maven.plugins&amp;lt;/groupId&amp;gt;
        &amp;lt;artifactId&amp;gt;maven-compiler-plugin&amp;lt;/artifactId&amp;gt;
        &amp;lt;configuration&amp;gt;
          &amp;lt;source&amp;gt;1.6&amp;lt;/source&amp;gt;
          &amp;lt;target&amp;gt;1.6&amp;lt;/target&amp;gt;
        &amp;lt;/configuration&amp;gt;
      &amp;lt;/plugin&amp;gt;

      &amp;lt;!-- ... --&amp;gt;
    &amp;lt;/plugins&amp;gt;
  &amp;lt;/build&amp;gt;
  &amp;lt;!-- ... --&amp;gt;
&amp;lt;/project&amp;gt;&lt;/pre&gt; Lub jeszcze lepiej przez zdefiniowanie zmiennej (&lt;a href="http://maven.apache.org/pom.html#Properties"&gt;więcej o propertis&lt;/a&gt;): &lt;pre&gt;&amp;lt;project&amp;gt;
  &amp;lt;!-- ... --&amp;gt;     
  &amp;lt;properties&amp;gt;
   &amp;lt;source-level&amp;gt;1.6&amp;lt;/source-level&amp;gt;
  &amp;lt;/properties&amp;gt;

  &amp;lt;!-- ... --&amp;gt;
  &amp;lt;build&amp;gt;
    &amp;lt;!-- ... --&amp;gt;
    &amp;lt;plugins&amp;gt;
      &amp;lt;!-- ... --&amp;gt;
    
      &amp;lt;plugin&amp;gt;
        &amp;lt;groupId&amp;gt;org.apache.maven.plugins&amp;lt;/groupId&amp;gt;
        &amp;lt;artifactId&amp;gt;maven-compiler-plugin&amp;lt;/artifactId&amp;gt;
        &amp;lt;configuration&amp;gt;
          &amp;lt;source&amp;gt;${source-level}&amp;lt;/source&amp;gt;
          &amp;lt;target&amp;gt;${source-level}&amp;lt;/target&amp;gt;
        &amp;lt;/configuration&amp;gt;
      &amp;lt;/plugin&amp;gt;
  
      &amp;lt;!-- ... --&amp;gt;
    &amp;lt;plugins&amp;gt;  
    &amp;lt;!-- ... --&amp;gt;
  &amp;lt;/build&amp;gt;    
&amp;lt;!-- ... --&amp;gt;
&amp;lt;/project&amp;gt; &lt;/pre&gt; Ustawienie kodowania plików z zasobami na UTF-8 w pom.xml (&lt;a href="http://maven.apache.org/plugins/maven-resources-plugin/examples/encoding.html"&gt;na podstawie&lt;/a&gt;): &lt;pre&gt;&amp;lt;project&amp;gt;
  &amp;lt;!-- ... --&amp;gt;
  &amp;lt;build&amp;gt;
    &amp;lt;!-- ... --&amp;gt;
    &amp;lt;plugins&amp;gt;
          
      &amp;lt;plugin&amp;gt;
        &amp;lt;groupId&amp;gt;org.apache.maven.plugins&amp;lt;/groupId&amp;gt;
        &amp;lt;artifactId&amp;gt;maven-resources-plugin&amp;lt;/artifactId&amp;gt;
        &amp;lt;configuration&amp;gt;
          &amp;lt;encoding&amp;gt;UTF-8&amp;lt;/encoding&amp;gt;
        &amp;lt;/configuration&amp;gt;
      &amp;lt;/plugin&amp;gt;

      &amp;lt;!-- ... --&amp;gt;
    &amp;lt;/plugins&amp;gt;
  &amp;lt;/build&amp;gt;
  &amp;lt;!-- ... --&amp;gt;
&amp;lt;/project&amp;gt;&lt;/pre&gt;

&lt;b&gt;TestNG konfiguracja pod Maven2&lt;/b&gt;

Dodanie biblioteki TestNG do pom.xml: &lt;pre&gt;&amp;lt;/project&amp;gt;
  &amp;lt;!-- ... --&amp;gt;
  &amp;lt;/dependencies&amp;gt;
  &amp;lt;!-- ... --&amp;gt;

     &amp;lt;dependency&amp;gt;
       &amp;lt;groupId&amp;gt;org.testng&amp;lt;/groupId&amp;gt;
       &amp;lt;artifactId&amp;gt;testng&amp;lt;/artifactId&amp;gt;
       &amp;lt;version&amp;gt;5.11&amp;lt;/version&amp;gt;
       &amp;lt;scope&amp;gt;test&amp;lt;/scope&amp;gt;
       &amp;lt;classifier&amp;gt;jdk15&amp;lt;/classifier&amp;gt;
     &amp;lt;/dependency&amp;gt;

    &amp;lt;!-- ... --&amp;gt;   
  &amp;lt;/dependencies&amp;gt;
  &amp;lt;!-- ... --&amp;gt; 
&amp;lt;/project&amp;gt;&lt;/pre&gt; Instalacja biblioteki TestNG w repo Mavena (sprawdzałem bez instalacji z poprzednimi wersjami też były problemy). &lt;pre&gt;C:\Documents and Settings\piter&gt;mvn install:install-file 
  -DgroupId=org.testng 
  -DartifactId=testng 
  -Dversion=5.11 
  -Dclassifier=jdk15 
  -Dpackaging=jar 
  -Dfile=LOKALIZACJA_TEST_NG\testng-5.11\testng-5.11-jdk15.jar&lt;/pre&gt; Wskazanie ścieżki do pliku konfiguracyjnego dla TestNG (testng.xml) w pom.xml (można dodać &lt;a href="http://maven.apache.org/plugins/maven-surefire-report-plugin/report-only-mojo.html"&gt;konwersję wyników do html&lt;/a&gt;): &lt;pre&gt;&amp;lt;project&amp;gt;
  &amp;lt;!-- ... --&amp;gt;
  &amp;lt;build&amp;gt;
    &amp;lt;!-- ... --&amp;gt;
    &amp;lt;plugins&amp;gt;
          
      &amp;lt;plugin&amp;gt;
        &amp;lt;groupId&amp;gt;org.apache.maven.plugins&amp;lt;/groupId&amp;gt;
        &amp;lt;artifactId&amp;gt;maven-surefire-plugin&amp;lt;/artifactId&amp;gt;
        &amp;lt;configuration&amp;gt;
          &amp;lt;suiteXmlFiles&amp;gt;
            &amp;lt;suiteXmlFile&amp;gt;${basedir}/src/test/resources/testng.xml&amp;lt;/suiteXmlFile&amp;gt;
          &amp;lt;/suiteXmlFiles&amp;gt;
        &amp;lt;/configuration&amp;gt;
      &amp;lt;/plugin&amp;gt;

      &amp;lt;!-- ... --&amp;gt;
    &amp;lt;/plugins&amp;gt;
  &amp;lt;/build&amp;gt;
  &amp;lt;!-- ... --&amp;gt;
&amp;lt;/project&amp;gt;&lt;/pre&gt; Przykładowy plik konfiguracyjny dla TestNG: 
&lt;pre&gt;&amp;lt;!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd" &amp;gt;
  
&amp;lt;suite name="suite-all" verbose="1" &amp;gt;

  &amp;lt;test name="TestClient" &amp;gt;
    &amp;lt;classes&amp;gt;
       &amp;lt;class name="com.blogspot.itresearches.moj.pakiet.TestClient" /&amp;gt;
    &amp;lt;/classes&amp;gt;
  &amp;lt;/test&amp;gt;
 
  &amp;lt;test name="all-package"&amp;gt;
    &amp;lt;packages&amp;gt;
      &amp;lt;package name="com.blogspot.itresearches.moj.pakiet" /&amp;gt;
   &amp;lt;/packages&amp;gt;
  &amp;lt;/test&amp;gt;
&amp;lt;/suite&amp;gt;&lt;/pre&gt; Więcej o &lt;a href="http://testng.org/doc/documentation-main.html#testng-xml"&gt;konfiguracji TestNG&lt;/a&gt; oraz &lt;a href="http://maven.apache.org/plugins/maven-surefire-plugin/examples/testng.html"&gt;konfiguracji TestNG w Maven2&lt;/a&gt;. 

Uruchomienie: &lt;pre&gt;mvn test&lt;/pre&gt;

&lt;b&gt;Cobertura konfiguracja pod Maven2&lt;/b&gt;

Modyfikacja w pom.xml (&lt;a href="http://mojo.codehaus.org/cobertura-maven-plugin/"&gt;więcej o konfigu Cobertury w Maven&lt;/a&gt;): &lt;pre&gt;&amp;lt;/project&amp;gt;
  &amp;lt;!-- ... --&amp;gt;
  &amp;lt;reporting&amp;gt;
   &amp;lt;!-- ... --&amp;gt;
 
    &amp;lt;plugins&amp;gt;
      &amp;lt;plugin&amp;gt;
        &amp;lt;groupId&amp;gt;org.codehaus.mojo&amp;lt;/groupId&amp;gt;
        &amp;lt;artifactId&amp;gt;cobertura-maven-plugin&amp;lt;/artifactId&amp;gt;
  &amp;lt;configuration&amp;gt;
         &amp;lt;outputDirectory&amp;gt;${basedir}/target/test-coverage-report&amp;lt;/outputDirectory&amp;gt;
        &amp;lt;/configuration&amp;gt;
      &amp;lt;/plugin&amp;gt;
    &amp;lt;/plugins&amp;gt;

    &amp;lt;!-- ... --&amp;gt;
  &amp;lt;/reporting&amp;gt;   
  &amp;lt;!-- ... --&amp;gt;  
&amp;lt;/project&amp;gt;&lt;/pre&gt; Uruchomienie: &lt;pre&gt;mvn cobertura:cobertura&lt;/pre&gt; Dzięki zmianie ścieżki output nie trafia tam gdzie reszta danych przy generowaniu site tylko w &lt;code&gt;target/test-coverage-report&lt;/code&gt;.

&lt;h3&gt;Pozostałe narzędzia do analizy kodu&lt;/h3&gt;
Jeszcze się nie bawiłem, ale pewnie warto sprawdzić: &lt;a href="http://mojo.codehaus.org/findbugs-maven-plugin/"&gt;Findbugs&lt;/a&gt;, &lt;a href="http://maven.apache.org/plugins/maven-pmd-plugin/"&gt;PMD&lt;/a&gt;, &lt;a href="http://maven.apache.org/plugins/maven-checkstyle-plugin/"&gt;Checkstyle&lt;/a&gt;, &lt;a href="http://mojo.codehaus.org/jdepend-maven-plugin/"&gt;JDepend&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3992064681062004055-7856086506342701432?l=it-researches.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/ItResearches/~4/4ZJhEThlVCA" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://it-researches.blogspot.com/feeds/7856086506342701432/comments/default" title="Komentarze do posta" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=3992064681062004055&amp;postID=7856086506342701432&amp;isPopup=true" title="Komentarze (1)" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3992064681062004055/posts/default/7856086506342701432?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3992064681062004055/posts/default/7856086506342701432?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/ItResearches/~3/4ZJhEThlVCA/eclipse-maven2-testng-cobertura.html" title="Eclipse + Maven2 + TestNG + Cobertura" /><author><name>Piotr Paradzinski</name><uri>http://www.blogger.com/profile/07915292026695759953</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="25" height="32" src="http://4.bp.blogspot.com/_cGW9IpdChVc/SYRCu49W5lI/AAAAAAAAADE/eZPPGD0JW_Q/S220/PiotrParadzinski.jpg" /></author><thr:total>1</thr:total><feedburner:origLink>http://it-researches.blogspot.com/2010/01/eclipse-maven2-testng-cobertura.html</feedburner:origLink></entry><entry gd:etag="W/&quot;Dk8CQXgzcCp7ImA9WxBRFEo.&quot;"><id>tag:blogger.com,1999:blog-3992064681062004055.post-2330002402375441783</id><published>2010-01-03T00:16:00.006+01:00</published><updated>2010-01-03T00:27:40.688+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-01-03T00:27:40.688+01:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Wiki" /><category scheme="http://www.blogger.com/atom/ns#" term="OOD" /><title>Prawo Demeter na polskiej Wiki</title><content type="html">Pomyślałem a co anglojęzyczni mają być lepsi? No i tak oto dorzuciłem kolejną cegiełkę do budowy świata - czyli wpis na polskiej Wikipedi o &lt;a href="http://pl.wikipedia.org/wiki/Prawo_Demeter"&gt;prawie Demeter&lt;/a&gt;.

Przy okazji natrafiłem na ujmujące &lt;a href="http://www.digipedia.pl/def/302823-law-of-Demeter.html"&gt;tłumaczenie Law of Demeter na digipedia&lt;/a&gt;: prawo Demetera. Prawda że ujmujące :)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3992064681062004055-2330002402375441783?l=it-researches.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/ItResearches/~4/T8o303VHe14" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://it-researches.blogspot.com/feeds/2330002402375441783/comments/default" title="Komentarze do posta" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=3992064681062004055&amp;postID=2330002402375441783&amp;isPopup=true" title="Komentarze (0)" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3992064681062004055/posts/default/2330002402375441783?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3992064681062004055/posts/default/2330002402375441783?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/ItResearches/~3/T8o303VHe14/pomyslaem-co-anglojezyczni-maja-byc.html" title="Prawo Demeter na polskiej Wiki" /><author><name>Piotr Paradzinski</name><uri>http://www.blogger.com/profile/07915292026695759953</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="25" height="32" src="http://4.bp.blogspot.com/_cGW9IpdChVc/SYRCu49W5lI/AAAAAAAAADE/eZPPGD0JW_Q/S220/PiotrParadzinski.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://it-researches.blogspot.com/2010/01/pomyslaem-co-anglojezyczni-maja-byc.html</feedburner:origLink></entry><entry gd:etag="W/&quot;C0UGQXg5eip7ImA9WxBRE0U.&quot;"><id>tag:blogger.com,1999:blog-3992064681062004055.post-4088975845630257433</id><published>2010-01-01T21:03:00.004+01:00</published><updated>2010-01-01T22:27:00.622+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-01-01T22:27:00.622+01:00</app:edited><title>Rozwiązania quick and dirty ... do właściwych problemów</title><content type="html">I znowu odpowiedź na komentarz tym razem &lt;a href="http://bottega.com.pl/"&gt;właściciela filmy Bottega Pracownia IT&lt;/a&gt;.

Co mam na myśli mówiąc język do rozwiązań quick and dirty? Mam na myśli język w którym zamierzam &lt;b&gt;automatyzować&lt;/b&gt; czynności, które zdarza mi się wykonywać więcej niż 2 - 3 razy. Czasem jest to czynność którą wykonujemy raz lecz składa się ona z 400 podobnych ruchów :)

Przykłady?

Weźmy dla przykładu prostą operację. Tworzymy sobie system. Wszystko jest fajnie i zabawnie. Dodajemy funkcjonalności. Testujemy je dodając testowe dane. Wszystko bryka pięknie.

Ale załóżmy, że tworzymy jakieś raporty z ciekawymi diagramami pokazującymi dynamikę zmian zróżnicowanie sprzedaży produktów z podziałem na kategorie cenowe i jakieś tam inne na przestrzeni pewnego czasu.

No nie głupio by było wklepać powiedzmy 
12 (liczba miesięcy w badanym okresie rozliczeniowym) 
* 2 (dynamika czyli porównujemy dane z 2 kolejnych lat)
* 5 (kategorie produktów)
* 3 (kategorie cenowe)
* 1 + random(10) (aby pojawiły się sumy a nie pojedyncze wartości sprzedaży)
czyli od 360 do 3600 ... np wpisów bazodanowych.

Jeśli jeszcze damy odważne założenie że w systemie jest więcej niż jedna tabela powiązana jakimiś konstraintami to wygląda, że do zobaczenia tych wykresów w aplikacji trzeba by tak na miesiąc zatrudnić kilku bardzo-szybko-nap!@#$cych-w-klawiaturę-gości lub uzyskać dane od klienta :)

Zapewne problem ten dało by się jakoś chytrze rozwiązać (usunąć konstrainty, wbić dane w pętlach korzystając z zapewne już zaimplementowanej funkcjonalności zapisywania danych w systemie, itp). Ale proszę się nie czepiać wymyśliłem przykład na poczekaniu.

Więc dosyć dobrym rozwiązaniem było by na poczekaniu strzelić jakiś mały program, który wygenerował by nam takie dane o pożądanych właściwościach. Ba może spodobały by nam się coś tam jeszcze zmienić w tych danych, żeby zobaczyć specyficzne zachowanie np brak prezentacji danych których wartość sprzedaży nie przekracza jakiegoś progu itp. No i fajnie by było, gdyby jednak nie trzeba było armi klepaczy ponownie zatrudniać do każdego wariantu :)

Do tego typu problemów język Java nie nadaje się najlepiej. Za dużo trzeba się opisać, ale nie tylko. Wiele cech mainstreamowych języków wykorzystywanych do tworzenia softu jest tak skonstruowanych aby bronić programisty przed zrobieniem sobie kuku (zasada iż lepiej zgłosić błąd na poziomie kompilacji a nie w czasie uruchamiania itp). Dodatkowo zapewniają mechanizmy typu bezpieczeństwo, przenośność, czytelność itp itd. które nie są z punktu widzenia rozważanej klasy problemów istotne.

Ale przecież my tu potrzebujemy prostego skryptu który uruchomimy tylko raz! Więc nie potrzebujemy tego.

Więc załóżmy, iż nie wiemy nic o wyłączaniu konstraintów a dane nie pochodzą z naszego systemu i nie ma możliwości ich zapisania. 

Jakie cechy zatem powinien posiadać język w którym napiszemy nasz program generujący dane: &lt;ul&gt;&lt;li&gt;zwięzły - więc niech ma te wszystkie sprytne metody machania listami, hash, string'ami, fajne operatory umożliwiające pominięcie kilku warunków i pętli, zapamiętywanie wyników przeprowadzonych operacji, itd&lt;/li&gt;&lt;li&gt;dynamicznie typowany - czasem do &lt;code&gt;pi&lt;/code&gt; chcę sobie przypisać 3,14 a czasem "Produkcja Internetowa" a czasem new ProductInfo(Info.SPAM, new Product("egg")) &lt;/li&gt;&lt;li&gt;interpretowany - nie potrzebuję kompilacji&lt;/li&gt;&lt;li&gt;prosta, intuicyjna składnia&lt;/li&gt;&lt;li&gt;łatwy w nauce&lt;/li&gt;&lt;/ul&gt; oraz a może raczej przede wszystkim solidna (prosta, łatwa w użyciu, wymagająca małej ilości kodu) obsługa takich zagadnień: &lt;ul&gt;&lt;li&gt;wyrażenie regularne&lt;/li&gt;&lt;li&gt;operacje na napisach&lt;/li&gt;&lt;li&gt;tworzenie, usuwanie, kopiowanie, edycja plików tekstowych i katalogów&lt;/li&gt;&lt;li&gt;obsługa sieci ale nie jakieś generowanie HTML czy tworzenie serwera do obsługi komunikacji na wskazanym porcie lecz wczytywanie zawartości i nagłówków stron HTML czyli wygodna obsługa HTTP&lt;/li&gt;&lt;li&gt;łatwe uruchamianie innych programów&lt;/li&gt;&lt;/ul&gt;

Być może jeszcze dobrze by było mieć możliwość podpięcia się do popularnych (dowolnej) baz danych, obsługa FTP i XML, kompresja ale to już trochę przesadzam.

W takim języku proste powtarzalne problemy się łatwo wykonuje. Alternatywa to opanować do perfekcji inne narzędzia np menadżer plików, program archiwizujący, przeglądarka WWW, programistyczne edytory tekstu, wyszukiwarkę systemową, komendy linii poleceń OS.

Wbrew pozorom takie problemy pojawiają się dosyć często. Może to być, np generowanie jakichś xml, czy dodanie do naszego ulubionego ORM'a funkcji generującej dodatkowe artefakty bo tak wg. nas powinno to wyglądać. 

Inna sprawa iż zwykle pojawiają się nie w ramach programowania. Głównym narzędziem programisty jest język programowania który dzięki np OOP pozwala przy mniejszym lub większym nakładzie pracy osiągnąć DRY. Ale nie w każdym języku da się to osiągnąć. Np dosyć często kuleje pod tym względem SQL. Raczej jest do zmora testerów, wdrożeniowców, administratorów, tzw computer power users itd. Niemniej czasem przytrafia się też ludziom, którzy poza tworzeniem kodu są też odpowiedzialni za jego działanie i jakość a czasem po prostu programistom.

Fakt, definicja quick-and-dirty podawana przez wiki: 

&lt;cite&gt;crude solution or programming implementation that is imperfect, inelegant, or otherwise inadequate, but which solves or masks the problem at hand, and is generally faster and easier to put in place than a proper solution&lt;/cite&gt;

Rozwiązania każdego typu problemów w ten sposób to zaciąganie kredytu - ktoś będzie musiał za to zapłacić i to z odsetkami. Idea rozwiązania tymczasowego jest taka, iż łata ono dziurę ale w tym miejscu gdzie widać. Prędzej czy później ktoś jednak spojrzy też na te miejsca gdzie jednak tymczasowe rozwiązanie nie zakrywa dziury. I zwykle stanie się to podczas prezentacji u klienta.

Jednak szybkie rozwiązanie jest dokładnie tym czego potrzebujemy, gdy chcemy wygenerować jakieś dane. W końcu nie ma sensu do każdego problemu pisać fajnego frameworku, który rozwiązuje problem elegancko i pozwala jeszcze dodać interfejs w kilku językach :)

Nie twierdzę też, że język który nadaje się do pisania szybkich programików automatyzujących nie pozwala na czytelnie lub wręcz eleganckie tworzenie kodu. Mi konstrukcje z Ruby wydaję się bardzo potężne i jasne zarazem.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3992064681062004055-4088975845630257433?l=it-researches.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/ItResearches/~4/t23Mykh83uE" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://it-researches.blogspot.com/feeds/4088975845630257433/comments/default" title="Komentarze do posta" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=3992064681062004055&amp;postID=4088975845630257433&amp;isPopup=true" title="Komentarze (1)" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3992064681062004055/posts/default/4088975845630257433?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3992064681062004055/posts/default/4088975845630257433?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/ItResearches/~3/t23Mykh83uE/rozwiazania-quick-and-dirty-do.html" title="Rozwiązania quick and dirty ... do właściwych problemów" /><author><name>Piotr Paradzinski</name><uri>http://www.blogger.com/profile/07915292026695759953</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="25" height="32" src="http://4.bp.blogspot.com/_cGW9IpdChVc/SYRCu49W5lI/AAAAAAAAADE/eZPPGD0JW_Q/S220/PiotrParadzinski.jpg" /></author><thr:total>1</thr:total><feedburner:origLink>http://it-researches.blogspot.com/2010/01/rozwiazania-quick-and-dirty-do.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DEMHQ3c-fip7ImA9WxBRF08.&quot;"><id>tag:blogger.com,1999:blog-3992064681062004055.post-4939215431288728574</id><published>2010-01-01T16:03:00.004+01:00</published><updated>2010-01-05T22:20:32.956+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-01-05T22:20:32.956+01:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Ruby" /><title>Dlaczego Ruby?</title><content type="html">Skoro &lt;a href="http://www.jaceklaskowski.pl/"&gt;najbardziej znany blogger polskiej sceny Java'owej&lt;/a&gt; zadał mi pytanie w komentarzu do &lt;a href="http://it-researches.blogspot.com/2009/07/ruby-instalacja.html"&gt;posta o instalacji Ruby&lt;/a&gt; warto by na nie udzielić odpowiedzi.

&lt;cite&gt;Ni z gruszki, ni z pietruszki pojawia się wpis o Ruby?! I jak tu człowiek ma się rozeznać, po co mu to?&lt;/cite&gt;

Według mnie Ruby ma kilka ciekawych cech: &lt;ol&gt;&lt;li&gt;Nadaje się do tworzenia programów typu &lt;a href="http://en.wikipedia.org/wiki/Quick-and-dirty"&gt;quick and dirty&lt;/a&gt; (nie będzie mu łatwo się przebić, gdyż opanowałem Notepad++, Excel i kilka innych narzędzi ułatwiających automatyzację powtarzalnych czynności dosyć dobrze)&lt;/li&gt;&lt;li&gt;Jest wykorzystywany w grach jako język osadzony - chyba bardziej popularna jest Lua ale jeśli Lua to pewnie skończył bym grając w WoW ... tego kierunku chciałbym uniknąć&lt;/li&gt;&lt;li&gt;Ruby on Rails - chyba warto poznać u źródeł ideę jedno-kliknięciowego tworzenia przeglądarek do bazy danych&lt;/li&gt;&lt;li&gt;Jest m.in. językiem funkcyjnym więc rozwinę mój warsztat o nowe idee, pomysły, techniki&lt;/li&gt;&lt;li&gt;Filozofia tworzenia kodu: krótko za pomocą potężnych konstrukcji ale w miarę możliwości czytelnie. W Perl'u poza zwięzłością zapisu ceniona jest oryginalność&lt;sup&gt;1&lt;/sup&gt; co jest mocno skorelowane z nieczytelnością. W Python'e zaś chyba za bardzo skupiono się na przejrzystości kodu&lt;sup&gt;2&lt;/sup&gt;. To ważna lecz drugorzędna cecha języka do zastosowań quick and dirty.&lt;/li&gt;&lt;li&gt;W Ruby dosyć łatwo tworzy się DSL.&lt;/li&gt;&lt;/ol&gt; Wszystkie te przymioty przekonują mnie, iż w Ruby może być dla mnie przydatny w praktyce i dać mi możliwość poszerzyć moje horyzonty w IT.

Ale może lepiej zobaczyć jak wygląda &lt;a href="http://martinfowler.com/articles/rubyAtThoughtWorks.html#WasRubyTheRightChoice"&gt;opinia o Rubym przedstawiana przez firmę ThoughtWorks&lt;/a&gt;, która miała z nim sporo doświadczeń.

&lt;cite&gt;Sądziłbym, że z jruby będzie Ci łatwiej i bliżej, a tu czyste Ruby.&lt;/cite&gt;

Nie wybrałem jruby czy innych takich wynalazków biegających pod JVM ponieważ obecnie nikt tego nie używa w praktyce. Poza oczywiście twórcami blogów, prelegentami konferencji, autorami samej technologii oraz grupą zapaleńców piszących kod do szuflady (czy tam do własnego dysku twardego) ... oraz ludźmi którzy faktycznie piszą w nich oprogramowanie i to zupełnie na poważnie :D

&lt;hr /&gt; UPDATE 5 stycznia 2010 !!!
Istnieją projekty wykorzystujące tak niepochlebnie opisywane przeze mnie języki J*.

W poprzedniej wersji tego posta krzywdząco wypowiedziałem się, jakbym soft w JRuby pisany był do dysku twardego. Przepraszam wszelkie osoby, które poczuły się przez to sformułowanie obrażone lub wprowadzone w błąd.

Dziękuję osobie ukrywającej się pod pseudonimem lopex za wyprowadzenie mnie z błędu :)
END OF UPDATE 5 styczna 2010 &lt;hr /&gt;

I co ważniejsze: nie ma nic wspólnego z Java. A to spora zaleta jeśli się człowiek przez 8+ h namorduje z czymś to potrzebuje odmiany.

Na zakończenie argument za językami J*. Wg. mnie zastosowanie wielu języków programowania, kompilowanych do wspólnej postaci niskopoziomowej to przyszłość tworzenia softu. Zresztą przejawia się to nie tylko w tym, iż istnieje wiele języków które działają na JVM czy na .NET Framework to tylko jeden przejaw tego trendu. Inny to tworzenie DSL, &lt;a href="http://en.wikipedia.org/wiki/Language-oriented_programming"&gt;language oriented programming&lt;/a&gt;. Zresztą powstają już narzędzia do tego np &lt;a href="http://www.jetbrains.com/mps/index.html"&gt;MPS&lt;/a&gt;.
&lt;hr /&gt;
&lt;sup&gt;1&lt;/sup&gt; &lt;small&gt;Oryginalność nie wynika dosłownie z filozofi Perla. Ale zwróćmy uwagę na oficjalnie akceptowany przez użytkowników Perl'a koncepcję &lt;a href="http://en.wikipedia.org/wiki/There%27s_more_than_one_way_to_do_it"&gt;Tim Toady&lt;/a&gt;. Dodajmy do tego jeszcze żart mówiący o tym jak powstała składnia języka: kot Larrego Wall'a przeszedł się po klawiaturze. Coś tam na ekranie się pojawiły jakieś dziwne znaczki i ciągi znaków. Larry: nie wiem co to jest ale fajnie by było gdyby dało się zrobić język programowania w którym miało by to sens. W Perlu trochę programowałem i rozmawiałem z fanami tego języka.&lt;/small&gt;

&lt;sup&gt;2&lt;/sup&gt; &lt;small&gt;Kilka osób, które zna Pythona i stosuje chwali sobie ten język. jednak mnie odrzuca pomysł stosowania wcięć do określenia bloków, granic funkcji itp dla programów quick and dirty. Chociaż w innych zastosowaniach czemu nie.&lt;/small&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3992064681062004055-4939215431288728574?l=it-researches.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/ItResearches/~4/lSWgfXzTMwQ" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://it-researches.blogspot.com/feeds/4939215431288728574/comments/default" title="Komentarze do posta" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=3992064681062004055&amp;postID=4939215431288728574&amp;isPopup=true" title="Komentarze (6)" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3992064681062004055/posts/default/4939215431288728574?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3992064681062004055/posts/default/4939215431288728574?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/ItResearches/~3/lSWgfXzTMwQ/dlaczego-ruby.html" title="Dlaczego Ruby?" /><author><name>Piotr Paradzinski</name><uri>http://www.blogger.com/profile/07915292026695759953</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="25" height="32" src="http://4.bp.blogspot.com/_cGW9IpdChVc/SYRCu49W5lI/AAAAAAAAADE/eZPPGD0JW_Q/S220/PiotrParadzinski.jpg" /></author><thr:total>6</thr:total><feedburner:origLink>http://it-researches.blogspot.com/2010/01/dlaczego-ruby.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CEQARHw4eSp7ImA9WxBREko.&quot;"><id>tag:blogger.com,1999:blog-3992064681062004055.post-5784636459844445407</id><published>2009-12-31T15:16:00.005+01:00</published><updated>2009-12-31T16:12:25.231+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-12-31T16:12:25.231+01:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="zawód programista" /><title>Jak być programistą dobrym a może lepszym?</title><content type="html">Swego czasu podpytywałem, nieśmiało, ludzi tworzących soft &lt;b&gt;jaki powinien być dobry programista&lt;/b&gt;: &lt;a href="http://it-researches.blogspot.com/2009/11/cechy-dobrego-programisty-wywiad.html"&gt;[1]&lt;/a&gt;, &lt;a href="http://it-researches.blogspot.com/2009/11/cechy-dobrego-programisty-wywiad-2.html"&gt;[2]&lt;/a&gt;. To było ciekawe doświadczenie. Jeszcze ciekawszym pytaniem na jakie chciałem znaleźć odpowiedź to, &lt;b&gt;co robić aby być lepszym programistą&lt;/b&gt;. 

Można znaleźć sporo &lt;a href="http://www.google.pl/#hl=pl&amp;q=better+programmer+site%3Awww.codinghorror.com%2Fblog%2F&amp;lr=&amp;aq=f&amp;oq=better+programmer+site%3Awww.codinghorror.com%2Fblog%2F&amp;fp=ecc07ad2dc80c3a1"&gt;postów na ten temat na blogu Jeff'a Atwooda&lt;/a&gt;. Na przykład &lt;a href="http://www.codinghorror.com/blog/archives/000543.html"&gt;How To Become a Better Programmer by Not Programming&lt;/a&gt; traktuje wprawdzie na nieco inny temat, ale komentarze do niego są naprawdę niezłe.

Drugie dobre źródło ciekawych wypowiedzi to &lt;a href="http://www.google.pl/#hl=pl&amp;q=better+programmer+site%3Astackoverflow.com%2Fquestions&amp;lr=&amp;aq=f&amp;oq=better+programmer+site%3Astackoverflow.com%2Fquestions&amp;fp=ecc07ad2dc80c3a1"&gt;Stackoverflow&lt;/a&gt;. W szczególności spodobały mi się odpowiedzi do pytania&lt;a href="http://stackoverflow.com/questions/1546135/roadmap-to-a-better-programmer"&gt;Roadmap to a better programmer&lt;/a&gt;.

W serwisie The Server Side spotkałem się z 2 ciekawymi pozycjami: &lt;ul&gt;&lt;a href="http://www.theserverside.net/news/thread.tss?thread_id=44431"&gt;TSS.NET asks: What makes a "good" software developer?&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.theserverside.net/blogs/thread.tss?thread_id=40575"&gt;Damien Katz asks: Are you a bad programmer?&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt; Pierwszy nawiązuje do wspomnianego posta J. Atwooda. Drugi odnosi się do artykułu &lt;a href="http://damienkatz.net/2006/05/signs_youre_a_c.html"&gt;Signs You're a Crappy Programmer (and don't know it)&lt;/a&gt; Damien'a Katza.

No koniec pisania drętwych postów w tym roku: Wszystkiego dobrego w 2010 :)

PS
Cytowany w TSS oraz CodingHorror, &lt;a href="http://dobbscodetalk.com/index.php?option=com_myblog&amp;show=I-Miss-Bill.-Do-You-.html&amp;Itemid=29"&gt;wywiad z Bill'em Gates'en znalazłem w Dr. Dobbs Journal&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3992064681062004055-5784636459844445407?l=it-researches.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/ItResearches/~4/V028wA1nf9s" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://it-researches.blogspot.com/feeds/5784636459844445407/comments/default" title="Komentarze do posta" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=3992064681062004055&amp;postID=5784636459844445407&amp;isPopup=true" title="Komentarze (0)" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3992064681062004055/posts/default/5784636459844445407?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3992064681062004055/posts/default/5784636459844445407?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/ItResearches/~3/V028wA1nf9s/jak-byc-programista-dobrym-moze-lepszym.html" title="Jak być programistą dobrym a może lepszym?" /><author><name>Piotr Paradzinski</name><uri>http://www.blogger.com/profile/07915292026695759953</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="25" height="32" src="http://4.bp.blogspot.com/_cGW9IpdChVc/SYRCu49W5lI/AAAAAAAAADE/eZPPGD0JW_Q/S220/PiotrParadzinski.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://it-researches.blogspot.com/2009/12/jak-byc-programista-dobrym-moze-lepszym.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DEcEQ3Y_eip7ImA9WxBREEw.&quot;"><id>tag:blogger.com,1999:blog-3992064681062004055.post-906822724927091792</id><published>2009-12-28T13:08:00.003+01:00</published><updated>2009-12-28T17:00:02.842+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-12-28T17:00:02.842+01:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Ruby" /><category scheme="http://www.blogger.com/atom/ns#" term="quick and dirty" /><title>Ruby - quick &amp; dirty - linki</title><content type="html">Wygrzebane linki dot. korzystania z Ruby w kontekście szybkiego i niekoniecznie eleganckiego rozwiązywania problemów.

Najlepsze źródła: &lt;ul&gt;&lt;li&gt;&lt;a href="http://www.ruby-doc.org/docs/ProgrammingRuby/"&gt;Programming Ruby - The Pragmatic Programmer's Guide&lt;/a&gt; online 1 wydanie książki, b. dobry indeks w lewym dolnym rogu&lt;/li&gt;&lt;li&gt;&lt;a href="http://ruby-doc.org/ruby-1.9/index.html"&gt;Ruby Documentation 1.9&lt;/a&gt; opis całego API&lt;/li&gt;&lt;/ul&gt;

Miejsca w RDoc przydatne do Quick &amp; Dirty&lt;ul&gt;&lt;li&gt;wyrażenia regularne: &lt;a href="http://ruby-doc.org/ruby-1.9/classes/Regexp.html"&gt;Regexp&lt;/a&gt; i &lt;a href="http://ruby-doc.org/ruby-1.9/classes/MatchData.html"&gt;MatchData&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://ruby-doc.org/ruby-1.9/classes/String.html"&gt;napisy&lt;/a&gt;, &lt;a href="http://ruby-doc.org/ruby-1.9/classes/Array.html"&gt;tablice&lt;/a&gt;, &lt;a href="http://ruby-doc.org/ruby-1.9/classes/Hash.html"&gt;hash&lt;/a&gt;&lt;/li&gt;&lt;li&gt;pobieranie przez sieć &lt;a href="http://ruby-doc.org/ruby-1.9/classes/OpenURI.html"&gt;OpenURI&lt;/a&gt;&lt;/li&gt;&lt;li&gt;operacje na systemie plików: &lt;a href="http://ruby-doc.org/ruby-1.9/classes/File.html"&gt;File&lt;/a&gt;, &lt;a href="http://ruby-doc.org/ruby-1.9/classes/Dir.html"&gt;Dir&lt;/a&gt;&lt;/li&gt;&lt;li&gt;kompresja: &lt;a href="http://ruby-doc.org/ruby-1.9/classes/Zlib/GzipReader.html"&gt;GzipReader&lt;/a&gt;, &lt;a href="http://ruby-doc.org/ruby-1.9/classes/Zlib/GzipWriter.html"&gt;GzipWriter&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;

Tutoriale: &lt;ul&gt;&lt;li&gt;&lt;a href="http://ruby-doc.org/docs/"&gt;http://ruby-doc.org/docs/&lt;/a&gt; linki do tutoriali &lt;/li&gt;&lt;li&gt;&lt;a href="http://rubylearning.com/satishtalim/tutorial.html"&gt;Tutorial na Learning Ruby&lt;/a&gt; tutorial, sporo przykładów&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.troubleshooters.com/codecorn/ruby/basictutorial.htm"&gt;Ruby Basic Tutorial&lt;/a&gt; wygooglany, z tego się uczyłem&lt;/li&gt;&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3992064681062004055-906822724927091792?l=it-researches.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/ItResearches/~4/5wD1nh6UuzA" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://it-researches.blogspot.com/feeds/906822724927091792/comments/default" title="Komentarze do posta" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=3992064681062004055&amp;postID=906822724927091792&amp;isPopup=true" title="Komentarze (0)" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3992064681062004055/posts/default/906822724927091792?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3992064681062004055/posts/default/906822724927091792?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/ItResearches/~3/5wD1nh6UuzA/ruby-quick-dirty-linki.html" title="Ruby - quick &amp; dirty - linki" /><author><name>Piotr Paradzinski</name><uri>http://www.blogger.com/profile/07915292026695759953</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="25" height="32" src="http://4.bp.blogspot.com/_cGW9IpdChVc/SYRCu49W5lI/AAAAAAAAADE/eZPPGD0JW_Q/S220/PiotrParadzinski.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://it-researches.blogspot.com/2009/12/ruby-quick-dirty-linki.html</feedburner:origLink></entry><entry gd:etag="W/&quot;C08HR3k9cSp7ImA9WxBREE0.&quot;"><id>tag:blogger.com,1999:blog-3992064681062004055.post-5900441375234992763</id><published>2009-12-27T23:18:00.006+01:00</published><updated>2009-12-28T13:03:56.769+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-12-28T13:03:56.769+01:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="domknięcia" /><category scheme="http://www.blogger.com/atom/ns#" term="Ruby" /><title>Ruby - clousure, proc, lambda, block</title><content type="html">Domknięcie to tajemnicza czarna magia, której ujarzmieniem szczycą się języki funkcyjne, języki skryptowe (typu &lt;a href="http://www.python.org/"&gt;Python&lt;/a&gt;, &lt;a href="http://www.ruby-lang.org/"&gt;Ruby&lt;/a&gt;), różne języki biegające po JVM (&lt;a href="http://clojure.org/"&gt;Clojure&lt;/a&gt;, &lt;a href="http://www.scala-lang.org/"&gt;Scala&lt;/a&gt;, &lt;a href="http://groovy.codehaus.org/"&gt;Groovy&lt;/a&gt;).

Próbowałem wzbogacić swój warsztat o tę technikę przy okazji nauki &lt;a href="http://www.erlang.org/"&gt;Erlang&lt;/a&gt;'a a jeszcze wcześniej &lt;a href="http://en.wikipedia.org/wiki/Lisp_%28programming_language%29"&gt;Lisp&lt;/a&gt;'a. W końcu udało się ale w Ruby 1.9 ... A wszystko dlatego, że słabo mi idzie nauka do SCJP :)

Do rzeczy póki, jeszcze pamiętam o co w tym chodzi:

&lt;h3&gt;Bloki i iteratory w Ruby&lt;/h3&gt; Iteratory i bloki w Ruby pozwalają na łatwe przechodzenie po tablicy i wykonywanie jakichś operacji na jej elementach.

Tablicę w Ruby &lt;pre&gt;tab = ["first", "second", "third"]&lt;/pre&gt; można wyświetlić klasycznie w pętli: &lt;pre&gt;for i in 0...tab.length
   puts tab[i];
end
&lt;/pre&gt; lub krótko: &lt;pre&gt;print tab&lt;/pre&gt; Można też użyć do tego iteratora each, do którego przekazujemy blok &lt;pre&gt;tab.each do |elem|
   puts elem;
end&lt;/pre&gt; Generalnie blok można przekazać nie tylko do iteratora ale również do dowolnej funkcji poprzez umieszczenie za jej wywołaniem tego bloku: &lt;pre&gt;#definiujemy funkcje
def my_fun()
   puts "In function"
end

# wywolujemy ja przekazujac jej blok
my_fun() do
   puts "In block passed to function"
end&lt;/pre&gt; Wynik działania programu &lt;pre&gt;In function&lt;/pre&gt; wskazuje, iż mimo przekazania do funkcji myFun bloku nie została wykonana instrukcja zawarta w bloku.

Aby blok, przekazany do metody, został wykonany w niej, należy wywołać metodę &lt;b&gt;yield&lt;/b&gt;.

&lt;pre&gt;#definiujemy funkcje
def my_fun()
   yield
   puts "In function"
   yield
end

# wywolujemy ja przekazujac jej blok
my_fun() do
   puts "In block passed to function"
end&lt;/pre&gt; Wynik działania programu mówi sam za siebie: &lt;pre&gt;In block passed to function
In function
In block passed to function&lt;/pre&gt;

Blok może posiadać argumenty, których wartości określamy wywołując go w yield: &lt;pre&gt;#definiujemy funkcje
def my_fun()
   yield "BEFORE" 
   puts "In function"
   yield "AFTER"
end

# wywolujemy ja przekazujac jej blok
my_fun() do |a|
   puts "In block passed to function " &lt;&lt; a
end&lt;/pre&gt; Co powoduje pokazanie się na konsoli: &lt;pre&gt;In block passed to function BEFORE
In function
In block passed to function AFTER&lt;/pre&gt; Dodatkowo z bloku przekazanego do funkcji mozna zwracać wartości podobnie jak w zwykłych funkcjach.

Można by zatem stwierdzić, iż blok jest takim dziwnym tworem przypominającym funkcję. Z tym, że nie ma nazwy, co skutkuje specyficznym sposobem "deklarowania" parametrów w bloku i niezwykłym mechanizmem jego &lt;b&gt;przekazania i wywoływania z poziomu innej funkcji&lt;/b&gt;. Bardziej formalnie: jest to grupa instrukcji, którą wiążemy z wywołaniem danej funkcji. W ramach tej funkcji, można wspomnianą grupę instrukcji wykonać przez wywołanie yield.

Iterator natomiast jest funkcją, która przechodzi po elementach kolekcji (niesamowite nieprawdaż) i wywołuje w określony sposób przekazany jej blok.

Poza ciekawą składnią nic niezwykłego.

&lt;h3&gt;Proc.new&lt;/h3&gt; Bloku nie można bezpośrednio zapamiętać w zmiennej i sobie go uruchomić byle gdzie. (Trzeba go zdefiniować przy wywołaniu jakiejś funkcji a funkcja musi wiedzieć, że ma go uruchomić.) Można jednak blok skonwertować do obiektu Proc. Wówczas możemy go zapamiętać w zmiennej: &lt;pre&gt;rememberedBlock = Proc.new do
   answer_to_life_the_universe_and_everything = 42
   puts answer_to_life_the_universe_and_everything
end&lt;/pre&gt; a następnie wywołać w stosownym momencie: &lt;pre&gt;rememberedBlock.call()&lt;/pre&gt;

Blok skonwertowany do obiektu Proc można przekazać jako argument funkcji &lt;pre&gt;def funExecProc(the_proc)
   puts "fun in here"
   the_proc.call();
end

myProc = Proc.new do puts "in block" end;

funExecProc(myProc);&lt;/pre&gt; Można również zwrócić go jako wynik funkcji: &lt;pre&gt;def get_fun_add()
   newFun = Proc.new do |n| n + 3 end
   return newFun;
end

# utworz funkcje
my_fun = get_fun_add();

# wywolanie
puts my_fun.call(1);&lt;/pre&gt;

&lt;h3&gt;clousure (domknięcie)&lt;/h3&gt; Ciekawe w tym jest to, iż w momencie konwersji bloku do obiektu Proc następuje zapamiętanie stanu środowiska w jakim ono było w trakcie konwersji. Zobaczmy to na przykładzie. Oto funkcja, która inne funkcje (bloki konwertowane na Proc) dodające pewną wartość do argumentu: &lt;pre&gt;def make_fun_add(how_much)
   # nowa funkcja, ktora dla argumentu n zwraca
   # ten argument zwiekszony o wartosc how_much
   newFun = Proc.new do |n| n + how_much end
   return newFun;
end

# utworz funkcje w ktorej how_much = 3
add3 = make_fun_add(3)
# utworz funkcje w ktorej how_much = 5
add5 = make_fun_add(5)

# kilka wywolan
puts add3.call(1)

puts add5.call(5)
puts add5.call(10)&lt;/pre&gt; Funkcja &lt;code&gt;make_fun_add&lt;/code&gt; zwraca nowo utworzoną funkcję newFun. Zobaczmy, iż w momencie wywołania &lt;code&gt;add3 = make_fun_add(3)&lt;/code&gt; zmienna how_much w funkcji make_fun_add przybrała wartość 3. Ta wartość jest zapamiętana, dzięki czemu wywołania funkcji add3 powodują dodanie 3 do argumentu. Bardziej formalnie: dla Proc add3 zmienna how_much została powiązana z wartością 3.

Podobnie została zapamiętana wartość 5 przy wywołaniu &lt;code&gt;add5 = make_fun_add(5)&lt;/code&gt;.

Wartości jakie zostały przypisane do zmiennych, można odczytać za pomocą metody &lt;code&gt;eval&lt;/code&gt; przekazując jej nazwę parametru oraz obiekt reprezentujący powiązania zwracany przez binding: &lt;pre&gt;def make_fun(arg)
   return Proc.new do end
end

fun1 = make_fun(12);
fun2 = make_fun("foo");

puts eval("arg", fun1.binding); # 12
puts eval("arg", fun2.binding); # foo&lt;/pre&gt;

No i w końcu dochodzimy do sedna sprawy.

&lt;b&gt;Blok skonwertowany na obiekt Proc, w którym zapamiętano stan środowiska w momencie definiowania tego bloku jest nazywany &lt;a href="http://pl.wikipedia.org/wiki/Domkni%C4%99cie_%28programowanie%29"&gt;domknięciem&lt;/a&gt; (ang. &lt;i&gt;clousure&lt;/i&gt;).&lt;/b&gt;

Warto dodać, iż funkcja, która przyjmuje jako argument lub zwraca inną funkcję nazywana jest &lt;a href="http://pl.wikipedia.org/wiki/Funkcja_wy%C5%BCszego_rz%C4%99du"&gt;funkcją wyższego rzędu&lt;/a&gt;

Tyle w kwestii definicji.

&lt;h3&gt;lambda vs proc&lt;/h3&gt; Istnieje jeszcze jeden nie tak znowu drobny szczegół. Załóżmy, iż mamy funkcję generującą Proc, który wyświetla argumenty. Można to zrobić za pomocą Proc.new podobnie jak w przykładzie z dodawaniem, lecz można zamiast tego użyć funkcji &lt;code&gt;lambda&lt;/code&gt; lub funkcji &lt;code&gt;proc&lt;/code&gt;. Zobaczmy &lt;pre&gt;def make_fun_show_new()
   return Proc.new do |n, m| print n, " ", m, "\n" end;
end

def make_fun_show_lambda()
   return lambda do |n, m| print n, " ", m, "\n" end;
end

def make_fun_show_proc()
   return proc do |n, m| print n, " ", m, "\n" end;
end

pn = make_fun_show_new();
pl = make_fun_show_lambda();
pp = make_fun_show_proc();

pl.call(2,3);
pn.call(2,3);
pp.call(2,3);&lt;/pre&gt; Wyniki wywołania &lt;pre&gt;2 3
2 3
2 3&lt;/pre&gt; funkcji zdefiniowanych za pomocą Proc.new, proc i lambda niczym się nie różnią ... dla prawidłowej liczby argumentów.

Zobaczmy jednak co się stanie, gdy spróbujemy przekazać za mało lub za dużo argumentów. Dla Proc.new i proc: &lt;pre&gt;puts "Dla Proc.new do end"
pn.call(10);
pn.call(1,2,3);

puts "Dla proc do end"
pp.call(10);
pp.call(1,2,3);&lt;/pre&gt; dostajemy: &lt;pre&gt;Dla Proc.new do end
10
1 2
Dla proc do end
10
1 2&lt;/pre&gt; Natomiast dla funkcji zdefiniowanej przez &lt;code&gt;lambda do end&lt;/code&gt; próba wywołania z mniejszą liczbą argumentów: &lt;pre&gt;puts pl.call(10);&lt;/pre&gt; kończy się błędem: &lt;pre&gt;wrong number of arguments (1 for 2) (ArgumentError)&lt;/pre&gt; dal odmiany zaś, próba wywołania z większą &lt;pre&gt;puts pl.call(1,2,3);&lt;/pre&gt; zaskakuje nas tak: &lt;pre&gt;wrong number of arguments (3 for 2) (ArgumentError)&lt;/pre&gt;

Jak widać Proc utworzony za pomocą Proc.new oraz proc zachowuje się identycznie i umie sobie radzić z błędną liczbą argumentów. Natomiast Proc utworzony za pomocą lambda jest mniej ogarnięty i w razie problemów poddaje się.

&lt;h3&gt;lambda?&lt;/h3&gt; O tym czy Proc do którego odnosi się zmienna jest typu lambda czy typu proc można stwierdzić za pomocą metody lambda? Wywołanie &lt;pre&gt;print "Proc.new is lambda ", pn.lambda?, "\n"
print "proc     is lambda ", pp.lambda?, "\n"
print "lambda   is lambda ", pl.lambda?, "\n"&lt;/pre&gt; pokazuje na konsoli: &lt;pre&gt;Proc.new is lambda false
proc     is lambda false
lambda   is lambda true&lt;/pre&gt;

&lt;h3&gt;arity&lt;/h3&gt; Skoro bloki opakowane w obiekty Proc za pomocą lambda są tak wrażliwe na ilość argumentów nie od rzeczy było by odpytać się obiekt Proc'a o to ile argumentów by sobie, życzył: &lt;pre&gt;proc0 = Proc.new do || end
puts proc0.arity # 0

proc1 = Proc.new do |x| puts x end
puts proc1.arity # 1

proc2 = Proc.new do |x,y| puts x + y end
puts proc2.arity # 2&lt;/pre&gt; Niestety w mniej trywialnych przypadkach &lt;a href="http://ruby-doc.org/ruby-1.9/classes/Proc.html#M001168"&gt;funkcja arity może zwrócić wartości ujemne&lt;/a&gt;.

&lt;h3&gt;Powrót do teraźniejszości&lt;/h3&gt; Miałem zamiar rozgryźć i opisać funkcję curring oraz popełnić niezwykle popisowy, wycierający podłogę czytelnikami, kopiący po jajkach i w ogóle przykład z generowaniem Proc reprezentującego jednomian ... ale chyba lepsze do tego jest programowanie obiektowe ... zresztą trzeba wracać do SCJP :(&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3992064681062004055-5900441375234992763?l=it-researches.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/ItResearches/~4/Pv5OM9CtfGI" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://it-researches.blogspot.com/feeds/5900441375234992763/comments/default" title="Komentarze do posta" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=3992064681062004055&amp;postID=5900441375234992763&amp;isPopup=true" title="Komentarze (4)" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3992064681062004055/posts/default/5900441375234992763?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3992064681062004055/posts/default/5900441375234992763?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/ItResearches/~3/Pv5OM9CtfGI/ruby-clousure-proc-lambda-block.html" title="Ruby - clousure, proc, lambda, block" /><author><name>Piotr Paradzinski</name><uri>http://www.blogger.com/profile/07915292026695759953</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="25" height="32" src="http://4.bp.blogspot.com/_cGW9IpdChVc/SYRCu49W5lI/AAAAAAAAADE/eZPPGD0JW_Q/S220/PiotrParadzinski.jpg" /></author><thr:total>4</thr:total><feedburner:origLink>http://it-researches.blogspot.com/2009/12/ruby-clousure-proc-lambda-block.html</feedburner:origLink></entry></feed>

