<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-5197374494377847819</id><updated>2012-01-24T12:09:25.236+01:00</updated><category term='Integracja'/><category term='Domain Driven Design'/><category term='JPA'/><category term='Research'/><category term='JUG'/><category term='Craftsmanship'/><category term='Seam'/><category term='Dependency Injection'/><category term='Hibernate'/><category term='OOD'/><category term='Command Query Separation'/><category term='Data Context Interaction'/><category term='EJB'/><category term='edukacja'/><category term='wzorce projektowe'/><category term='TDD'/><category term='GRASP'/><category term='ORM'/><category term='command design pattern'/><category term='wzorce architektoniczne'/><category term='z dystansu'/><category term='Domain Specific Language'/><category term='Spring'/><category term='konferencja'/><category term='usability'/><category term='linki'/><category term='post gościnny'/><category term='recenzja'/><category term='Qi'/><category term='Distributed Domain Driven Design'/><category term='paranoja'/><category term='śmieszne'/><category term='Unified Process'/><category term='Lazy loading'/><category term='frameworki'/><category term='UP-DDD in Action'/><category term='prezentacja'/><category term='metodyki'/><category term='UML'/><category term='kognitywistyka'/><category term='Inversion of Control'/><category term='Behaviour-Driven Development'/><category term='cloud'/><category term='Java'/><category term='Composite Oriented Programming'/><category term='CqRS'/><category term='gui'/><category term='Rozwój'/><category term='anty-wzorce'/><category term='Leaven'/><category term='samodoskonalenie'/><category term='Architektura'/><category term='Agile'/><category term='Homo sum...'/><category term='OOP'/><category term='Hardware'/><category term='JSF'/><category term='Saga'/><category term='OOA'/><category term='artykuł'/><category term='management'/><title type='text'>Holistycznie o inżynierii oprogramowania</title><subtitle type='html'>Inżynieria oprogramowania w ujęciu systemowym.
Zintegrowane podejście do metodyk,&lt;br&gt; technologii (głównie Java EE), architektury, designu i rozwoju osobistego.</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://art-of-software.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5197374494377847819/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://art-of-software.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><link rel='next' type='application/atom+xml' href='http://www.blogger.com/feeds/5197374494377847819/posts/default?start-index=101&amp;max-results=100'/><author><name>Sławek Sobótka</name><uri>http://www.blogger.com/profile/15082577671795313109</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='30' height='32' src='http://3.bp.blogspot.com/-tmFOhJC48_E/TkQ0G2DxrqI/AAAAAAAAAz8/WVGBaaS5a_Y/s220/zdjecie2.png'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>117</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-5197374494377847819.post-5563511856707720758</id><published>2012-01-03T22:05:00.000+01:00</published><updated>2012-01-03T22:05:37.906+01:00</updated><title type='text'>Dopamina Driven Development</title><content type='html'>Jaki wpływ na tworzenie kodu mogą mieć wytryski &lt;a href="http://pl.wikipedia.org/wiki/Dopamina"&gt;dopaminy&lt;/a&gt;?&lt;br&gt;Co wspólnego ma nikotyna z TDD?&lt;br&gt;Dowiecie się w 22. minucie i 30. sekundzie prezentacji &lt;a href="http://www.infoq.com/presentations/Things-I-Wish-I-d-Known"&gt;Things I Wish I'd Known&lt;/a&gt; od samego twórcy Springa - Roda Johnsona:)&lt;br&gt;&lt;br&gt;&lt;br&gt;//======================&lt;br&gt;&lt;br&gt;Generalnie bardzo polecam obejrzenie całej prezentacji, ale uprzedzam - nie ma w niej ani linijki kodu:)&lt;br&gt;&lt;br&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5197374494377847819-5563511856707720758?l=art-of-software.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://art-of-software.blogspot.com/feeds/5563511856707720758/comments/default' title='Komentarze do posta'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5197374494377847819&amp;postID=5563511856707720758' title='Komentarze (0)'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5197374494377847819/posts/default/5563511856707720758'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5197374494377847819/posts/default/5563511856707720758'/><link rel='alternate' type='text/html' href='http://art-of-software.blogspot.com/2012/01/dopamina-driven-development.html' title='Dopamina Driven Development'/><author><name>Sławek Sobótka</name><uri>http://www.blogger.com/profile/15082577671795313109</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='30' height='32' src='http://3.bp.blogspot.com/-tmFOhJC48_E/TkQ0G2DxrqI/AAAAAAAAAz8/WVGBaaS5a_Y/s220/zdjecie2.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5197374494377847819.post-3297311326990916488</id><published>2011-12-16T02:16:00.000+01:00</published><updated>2011-12-16T03:10:31.844+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Hardware'/><title type='text'>Skręt kości promieniowej i łokciowej, czyli rzecz o myszkach</title><content type='html'>Awaria mojej głównej myszki (czyli tej której używam do codziennej pracy, w odróżnieniu od specjalnej do gry ze znajomymi w CoD) skłoniła mnie do napisania kolejnego posta na temat &lt;a href="http://art-of-software.blogspot.com/search/label/Hardware"&gt;Sprzętu&lt;/a&gt;.&lt;br&gt;&lt;br&gt;Dawno, dawno temu, jako początkujący użytkownik peceta byłem przekonany, że jego głównym elementem, decydującym o ogólnym "ekspiriens" jest procesor i akcelerowana karta graficzna:) "Dziś sam jestem dziadkiem" i pytany przez nietechnicznych znajomych oraz nietechniczną rodzinę doradzam, że najważniejsze elementy zestawu to: krzesło, klawiatura, myszka i matryca (w sensie jej jakości) - reszta zależy już tylko od budżetu:)&lt;br&gt;&lt;br&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/-vMaPTLYFjSs/TuqeGtA7TdI/AAAAAAAAA5Q/VI89yFqakmk/s1600/mysz2.jpg" imageanchor="1" style="margin-left:1em; margin-right:1em"&gt;&lt;img border="0" height="300" width="300" src="http://2.bp.blogspot.com/-vMaPTLYFjSs/TuqeGtA7TdI/AAAAAAAAA5Q/VI89yFqakmk/s320/mysz2.jpg" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br&gt;Warto wiedzieć, że klasyczne "płaskie" myszki wymuszają nienaturalne (skręcone) ułożenie kończyny górnej i prowadzą do:&lt;ul&gt;&lt;li&gt;Skrętu wzajemnego położenia kości promieniowej i łokciowej w naszym &lt;a href="http://pl.wikipedia.org/wiki/Przedramię"&gt;przedramieniu&lt;/a&gt;,&lt;li&gt;Naprężeniu mięśni przedramienia (wynika z powyższego)&lt;li&gt;Ucisku na naczynia krwionośne (wynika z obu powyższych)&lt;/ul&gt;&lt;br&gt;Jeżeli się nad tym chwilę nie zastanowić, to ułożenie dłoni na płaskim blacie tak aby do niego przylegała wydaje się normalne. Ale spróbujcie układać dłoń na zmianę na blacie: w pozycji "do spoliczkowania" i w pozycji "płaskiej", aby powoli zacząć uświadamiać sobie co się dzieje z Waszymi kośćmi i mięśniami.&lt;br&gt;&lt;br&gt;Wielu z nas skarży się na bóle w okolicach nadgarstka. Ja sam w pewnym momencie miałem problem z utrzymaniem kierownicy w prawej ręce podczas powrotu z pracy do domu.&lt;br&gt;Jako rozwiązanie polecam tego typu &lt;a href="http://www.amazon.co.uk/s/ref=nb_sb_ss_i_0_14?url=search-alias%3Daps&amp;field-keywords=vertical+mouse&amp;sprefix=vertical+mouse&amp;x=0&amp;y=0"&gt;konstrukcje&lt;/a&gt;.&lt;br&gt;Osobiście od ok 5 lat używam modelu Vertical Grip i w tym momencie każde zetknięcie mojej odzwyczajonej od tortur ręki z "płaską" myszką skłania do refleksji: ale po co?&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5197374494377847819-3297311326990916488?l=art-of-software.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://art-of-software.blogspot.com/feeds/3297311326990916488/comments/default' title='Komentarze do posta'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5197374494377847819&amp;postID=3297311326990916488' title='Komentarze (6)'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5197374494377847819/posts/default/3297311326990916488'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5197374494377847819/posts/default/3297311326990916488'/><link rel='alternate' type='text/html' href='http://art-of-software.blogspot.com/2011/12/skret-kosci-promieniowej-i-okciowej.html' title='Skręt kości promieniowej i łokciowej, czyli rzecz o myszkach'/><author><name>Sławek Sobótka</name><uri>http://www.blogger.com/profile/15082577671795313109</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='30' height='32' src='http://3.bp.blogspot.com/-tmFOhJC48_E/TkQ0G2DxrqI/AAAAAAAAAz8/WVGBaaS5a_Y/s220/zdjecie2.png'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/-vMaPTLYFjSs/TuqeGtA7TdI/AAAAAAAAA5Q/VI89yFqakmk/s72-c/mysz2.jpg' height='72' width='72'/><thr:total>6</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5197374494377847819.post-2554673006436419131</id><published>2011-12-14T02:35:00.001+01:00</published><updated>2011-12-14T11:57:45.911+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='EJB'/><category scheme='http://www.blogger.com/atom/ns#' term='Domain Driven Design'/><category scheme='http://www.blogger.com/atom/ns#' term='Leaven'/><category scheme='http://www.blogger.com/atom/ns#' term='JPA'/><category scheme='http://www.blogger.com/atom/ns#' term='CqRS'/><title type='text'>DDD na platformie Java EE 6</title><content type='html'>Dzisiaj coś dla miłośników Enterprise Edition.&lt;br&gt;&lt;br&gt;Nieustannie rozwijamy &lt;a href="http://code.google.com/p/ddd-cqrs-sample/"&gt;projekt&lt;/a&gt; ilustrujący implementację zaawansowanych technik Domain Driven Design i architektury Command-query Responsibility Segregation.&lt;br&gt;Dotychczasowa implementacja oparta na Springu doczekała się swego lustrzanego odbicia na platformie Java EE6&lt;br&gt;W projekcie znajdziecie między innymi kilka sztuczek w CDI oraz przykłady wykorzystania silnika zdarzeń w modelowaniu biznesowym (dowiecie się również dlaczego budowany Events&lt;&gt; jest nieco ułomny:).&lt;br&gt;&lt;br&gt;Więcej szczegółów na &lt;a href="http://ddd-cqrs-leaven.blogspot.com/2011/12/alternative-implementation-in-jee.html"&gt;blogu projektu&lt;/a&gt;.&lt;br&gt;&lt;br&gt;//===========================&lt;br&gt;&lt;br&gt;W najbliższych planach aplikacja kliencka na Androidzie w architekturze Eventually Connected Client.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5197374494377847819-2554673006436419131?l=art-of-software.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://art-of-software.blogspot.com/feeds/2554673006436419131/comments/default' title='Komentarze do posta'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5197374494377847819&amp;postID=2554673006436419131' title='Komentarze (0)'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5197374494377847819/posts/default/2554673006436419131'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5197374494377847819/posts/default/2554673006436419131'/><link rel='alternate' type='text/html' href='http://art-of-software.blogspot.com/2011/12/ddd-na-platformie-java-ee-6.html' title='DDD na platformie Java EE 6'/><author><name>Sławek Sobótka</name><uri>http://www.blogger.com/profile/15082577671795313109</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='30' height='32' src='http://3.bp.blogspot.com/-tmFOhJC48_E/TkQ0G2DxrqI/AAAAAAAAAz8/WVGBaaS5a_Y/s220/zdjecie2.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5197374494377847819.post-47860292293860587</id><published>2011-11-30T23:02:00.001+01:00</published><updated>2011-11-30T23:24:36.905+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='śmieszne'/><category scheme='http://www.blogger.com/atom/ns#' term='z dystansu'/><title type='text'>Geneza boskich klas</title><content type='html'>Zarówno po dzisiejszej konferencji &lt;a href="http://softdevcon.pl/"&gt;softdevcon&lt;/a&gt; jak i zeszłotygodniowej &lt;a href="http://www.11.jdd.org.pl/"&gt;JDD&lt;/a&gt; kilka osób prosiło mnie o powtórzenie tekstu o "boskich klasach", którym staram się rozbudzić uczestników prezentacji o DDD. Postanowiłem nieco rozszerzyć opowiastkę...&lt;br&gt;&lt;br&gt;&lt;div class="prezi-player"&gt;&lt;style type="text/css" media="screen"&gt;.prezi-player { width: 450px; } .prezi-player-links { text-align: center; }&lt;/style&gt;&lt;object id="prezi_mwtwdw2i7q4h" name="prezi_mwtwdw2i7q4h" classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" width="450" height="400"&gt;&lt;param name="movie" value="http://prezi.com/bin/preziloader.swf"/&gt;&lt;param name="allowfullscreen" value="true"/&gt;&lt;param name="allowscriptaccess" value="always"/&gt;&lt;param name="bgcolor" value="#ffffff"/&gt;&lt;param name="flashvars" value="prezi_id=mwtwdw2i7q4h&amp;amp;lock_to_path=0&amp;amp;color=ffffff&amp;amp;autoplay=no&amp;amp;autohide_ctrls=0"/&gt;&lt;embed id="preziEmbed_mwtwdw2i7q4h" name="preziEmbed_mwtwdw2i7q4h" src="http://prezi.com/bin/preziloader.swf" type="application/x-shockwave-flash" allowfullscreen="true" allowscriptaccess="always" width="450" height="400" bgcolor="#ffffff" flashvars="prezi_id=mwtwdw2i7q4h&amp;amp;lock_to_path=0&amp;amp;color=ffffff&amp;amp;autoplay=no&amp;amp;autohide_ctrls=0"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;div class="prezi-player-links"&gt;&lt;p&gt;&lt;a title="Domain Driven Design - A place for everything and everything in its place" href="http://prezi.com/mwtwdw2i7q4h/domain-driven-design-a-place-for-everything-and-everything-in-its-place/"&gt;Domain Driven Design - A place for everything and everything in its place&lt;/a&gt; on &lt;a href="http://prezi.com"&gt;Prezi&lt;/a&gt;&lt;/p&gt;&lt;/div&gt;&lt;/div&gt;&lt;br&gt;&lt;br&gt;&lt;h2&gt;Narodziny&lt;/h2&gt;Każda boska klasa ma swój początek jako niewinny ośmiotysięcznik - klasa zawierająca osiem tysięcy linijek kodu.&lt;br&gt;&lt;br&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/-gqmywjekWc0/TtapDglSZJI/AAAAAAAAA4U/hmmPXEsmOjo/s1600/mount-everest.gif" imageanchor="1" style="margin-left:1em; margin-right:1em"&gt;&lt;img border="0" height="240" width="320" src="http://1.bp.blogspot.com/-gqmywjekWc0/TtapDglSZJI/AAAAAAAAA4U/hmmPXEsmOjo/s320/mount-everest.gif" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br&gt;&lt;br&gt;&lt;h2&gt;Eskalacja&lt;/h2&gt;Zmiany w ośmiotysięczniku wymagają specjalnej wyprawy. Śmiałek wspina się przez kilka dni na wysokość ok piątego tysiąca próbując zrozumieć logikę/ironię kodu po czym zakłada tam bazę - rozgrzebuje kod kilkoma enterami aby zrobić sobie nieco miejsca, w którym to następnego dnia (bo aktualnie opada z wycieńczenia i niedoboru podstawowych neuroprzekaźników w mózgu) zacznie drążyć tunelik jako fundament dla nadbudówek.&lt;br&gt;&lt;br&gt;Poczynania śmiałka powodują oczywiście niejednokrotnie lawiny, które rozrywają na dole i tak już nieszczelne siatki bezpieczeństwa testów.&lt;br&gt;&lt;br&gt;&lt;h2&gt;Kolaps&lt;/h2&gt;Z czasem ośmiotysięcznik rozrasta się aby w końcu zapaść się grawitacyjnie pod własnym ciężarem. Powstaje wówczas &lt;a href="http://pl.wikipedia.org/wiki/Osobliwość_(astronomia)"&gt;osobliwość&lt;/a&gt;, z której wyłania się Boska Klasa - klasa, która wszystko wie, wszystko potrafi i jest połączona ze wszystkim w każdym możliwym wymiarze.&lt;br&gt;&lt;br&gt;Boska klasa aby istnieć potrzebuje ofiar. Najlepsze są młode, niewinne praktykantki. W swej naiwności opartej na akademickich wierzeniach we wszechmoc Maszyny Turinga składają się w ofierze na ołtarzu Boskiej Klasy...&lt;br&gt;&lt;br&gt;Z czasem udaje im się wyrwać z grawitacji osobliwości, ale już nigdy nie będą takie jak wcześniej...&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5197374494377847819-47860292293860587?l=art-of-software.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://art-of-software.blogspot.com/feeds/47860292293860587/comments/default' title='Komentarze do posta'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5197374494377847819&amp;postID=47860292293860587' title='Komentarze (8)'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5197374494377847819/posts/default/47860292293860587'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5197374494377847819/posts/default/47860292293860587'/><link rel='alternate' type='text/html' href='http://art-of-software.blogspot.com/2011/11/geneza-boskich-klas.html' title='Geneza boskich klas'/><author><name>Sławek Sobótka</name><uri>http://www.blogger.com/profile/15082577671795313109</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='30' height='32' src='http://3.bp.blogspot.com/-tmFOhJC48_E/TkQ0G2DxrqI/AAAAAAAAAz8/WVGBaaS5a_Y/s220/zdjecie2.png'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/-gqmywjekWc0/TtapDglSZJI/AAAAAAAAA4U/hmmPXEsmOjo/s72-c/mount-everest.gif' height='72' width='72'/><thr:total>8</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5197374494377847819.post-5607283131856839953</id><published>2011-11-01T13:44:00.000+01:00</published><updated>2011-11-01T13:44:46.585+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Domain Driven Design'/><category scheme='http://www.blogger.com/atom/ns#' term='OOD'/><title type='text'>DDD must read</title><content type='html'>Od dłuższego czasu nosiłem się z zamiarem napisania posta poświęconego modelowaniu agregatów - różnym podejściom i wynikającym z nich konsekwencjom.&lt;br&gt;Właściwie temat nie jest związany ze specyfiką DDD, a ogólnie z modelowaniem obiektów biznesowych z zachowaniem ich enkapsulacji, które dzięki niej są bardziej odporne na zmiany.&lt;br&gt;&lt;br&gt;Skoro jednak w sieci istnieją już materiały z dobrą ilustracją graficzną oraz przykładami w kodzie, to oszczędzę sobie pisania i pozwolę polecić ich lekturę każdemu kto zajmuje się modelowanie lub projektowaniem obiektowym (heh kto z czytelników się nie zajmuje "przy okazji" innych spraw?):&lt;br&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://rogeralsing.com/2009/11/08/two-flavors-of-ddd"&gt;Two flavors of DDD&lt;/a&gt;&lt;li&gt;&lt;a href="http://www.udidahan.com/2009/01/24/ddd-many-to-many-object-relational-mapping/"&gt;DDD &amp; Many to Many Object Relational Mapping&lt;/a&gt;&lt;/ul&gt;&lt;br&gt;//============================&lt;br&gt;&lt;br&gt;Tak jak pisałem wcześniej tematyka jest ogólna, nie związana stricte z DDD i lektura powinna być pożyteczna dla każdego.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5197374494377847819-5607283131856839953?l=art-of-software.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://art-of-software.blogspot.com/feeds/5607283131856839953/comments/default' title='Komentarze do posta'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5197374494377847819&amp;postID=5607283131856839953' title='Komentarze (2)'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5197374494377847819/posts/default/5607283131856839953'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5197374494377847819/posts/default/5607283131856839953'/><link rel='alternate' type='text/html' href='http://art-of-software.blogspot.com/2011/11/ddd-must-read.html' title='DDD must read'/><author><name>Sławek Sobótka</name><uri>http://www.blogger.com/profile/15082577671795313109</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='30' height='32' src='http://3.bp.blogspot.com/-tmFOhJC48_E/TkQ0G2DxrqI/AAAAAAAAAz8/WVGBaaS5a_Y/s220/zdjecie2.png'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5197374494377847819.post-2742375495090974538</id><published>2011-10-09T23:38:00.002+02:00</published><updated>2011-10-09T23:38:59.941+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Domain Driven Design'/><category scheme='http://www.blogger.com/atom/ns#' term='prezentacja'/><category scheme='http://www.blogger.com/atom/ns#' term='konferencja'/><category scheme='http://www.blogger.com/atom/ns#' term='CqRS'/><title type='text'>Konferencja Warsjawa - kolejny warsztat DDD&amp;CqRS Leaven</title><content type='html'>Zapraszam na konferencję &lt;a href="https://github.com/warszawajug/warsjawa2011/wiki/Konferencja-warsjawa-2011"&gt;Warsjawa&lt;/a&gt;, która odbędzie się w najbliższą sobotę (15 października) w Warszawie.&lt;br&gt;&lt;br&gt;Warto dodać, że konferencja jest całkowicie darmowa:)&lt;br&gt;&lt;br&gt;Podczas konferencji będziecie mogli uczestniczyć między innymi w naszych warsztatach, poświęconych projektowi &lt;a href="http://bottega.com.pl/ddd-cqrs-sample-project"&gt;DDD&amp;CqRS Leaven&lt;/a&gt;.&lt;br&gt;&lt;br&gt;Szczegółowy program warsztatów: &lt;a href="https://github.com/warszawajug/warsjawa2011/wiki/Warsztaty-DDD-i-CqRS"&gt;https://github.com/warszawajug/warsjawa2011/wiki/Warsztaty-DDD-i-CqRS&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5197374494377847819-2742375495090974538?l=art-of-software.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://art-of-software.blogspot.com/feeds/2742375495090974538/comments/default' title='Komentarze do posta'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5197374494377847819&amp;postID=2742375495090974538' title='Komentarze (2)'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5197374494377847819/posts/default/2742375495090974538'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5197374494377847819/posts/default/2742375495090974538'/><link rel='alternate' type='text/html' href='http://art-of-software.blogspot.com/2011/10/konferencja-warsjawa-kolejny-warsztat.html' title='Konferencja Warsjawa - kolejny warsztat DDD&amp;CqRS Leaven'/><author><name>Sławek Sobótka</name><uri>http://www.blogger.com/profile/15082577671795313109</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='30' height='32' src='http://3.bp.blogspot.com/-tmFOhJC48_E/TkQ0G2DxrqI/AAAAAAAAAz8/WVGBaaS5a_Y/s220/zdjecie2.png'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5197374494377847819.post-1981736728064709568</id><published>2011-10-05T22:53:00.002+02:00</published><updated>2011-12-14T02:37:15.060+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Saga'/><category scheme='http://www.blogger.com/atom/ns#' term='Domain Driven Design'/><category scheme='http://www.blogger.com/atom/ns#' term='Leaven'/><category scheme='http://www.blogger.com/atom/ns#' term='Distributed Domain Driven Design'/><category scheme='http://www.blogger.com/atom/ns#' term='CqRS'/><title type='text'>Persystentny Multi-Listener, czyli... Saga</title><content type='html'>Persystentny multi-listener... jak to pięknie brzmi...:)&lt;br&gt;&lt;br&gt;Cóż to takiego?&lt;br&gt;&lt;br&gt;Listener - czy obiekt słuchający zdarzeń,&lt;br&gt;mulit - czyli chodzi o wiele zdarzeń,&lt;br&gt;persystentny - czyli posiadający trwały stan.&lt;br&gt;&lt;br&gt;&lt;br&gt;Podczas ostatnich warsztatów z zakresu projektu &lt;a href="http://bottega.com.pl/ddd-cqrs-sample-project"&gt;DDD-CqRS Leaven&lt;/a&gt; wspomniana wyżej technika modelowania czasu spotkała się z zainteresowaniem wielu osób. Nic dziwnego, jest to dosyć nowy pattern; również na szkoleniach wzbudza zawsze największe emocje. Głównie dlatego, że ciężko pogodzić się z myślą, że coś tak złożonego można modelować i implementować w tak prosty i przyjemny sposób:P&lt;br&gt;&lt;br&gt;Pattern ma swoją oficjalną nazwę, brzmi ona Saga. Jeżeli saga kojarzy się senior developerom z sagą rodziny Carringtonów, to dobrze się Wam kojarzy. Saga to coś co może rozciągać się w czasie niczym telenowela. Saga jest patternem służącym do orkiestracji wielu zdarzeń, które mogą zajść w rozproszonym systemie w nieokreślonej kolejności. Czas pomiędzy zajściem zdarzeń może być relatywnie długi, dlatego należy persystować jej stan w czasie oczekiwania na kolejne zdarzenie.&lt;br&gt;&lt;br&gt;Przykład:&lt;br&gt;Wyobraźmy sobie system, w którym mamy moduły: sprzedaży, płatności i magazynu.&lt;br&gt;W module sprzedaży możemy zatwierdzić obiekt biznesowy Zamówienie. Zamówienie rzuca wówczas zdarzenie biznesowe ZatwierdzonoMnie zawierające id tegoż zamówienia.&lt;br&gt;W module płatności możemy dokonać wpłaty. Być może jest to przedpłata dokonana wcześniej niż zatwierdzenie zamówienia... Moduł ten rzuca zdarzenie niosące informację o zajściu faktu dokonania wpłaty.&lt;br&gt;Oba zdarzenia są orkiestrowane przez sagę Zakupy. Jeżeli otrzyma ona oba zdarzenia (pasujące po id biznesowym) i stwierdzi, że jesteśmy "kwita" wówczas może wysłać sygnał do modułu magazynowego aby przygotować paczkę do wysyłki.&lt;br&gt;&lt;br&gt;Oczywiście możemy tego typu proces zaimplementować w inny sposób niż zdarzeniowy, ale jeżeli zależy nam na &lt;b&gt;decouplingu modułów systemu&lt;/b&gt; (wraz z wszystkimi konsekwencjami: skalowanie, testowanie, rozszerzalność, otwartość na dodawanie pluginów, redukcja architektury Speaghetti na poziomie modułów) to warto posłużyć się Sagą.&lt;br&gt;&lt;br&gt;&lt;br&gt;Udi Dahan dosyć dobrze wyjaśnia motywację oraz szczegóły koncepcyjne: &lt;a href="http://www.udidahan.com/2009/04/20/saga-persistence-and-event-driven-architectures/"&gt;Saga Persistence and Event-Driven Architectures&lt;/a&gt; dlatego nie chcę powtarzać, tego co zostało napisane ponad 2 lata temu.&lt;br&gt;&lt;br&gt;Jak widać w powyższym linku technicznie Saga to złożenie 2 wzorców: Observer i Memento. O ile observera każdy zna choćby z bibliotek graficznych i wszechobecnych tam onClickListenerów, o tyle Memento jest mniej znanym patternem. Jeżeli ktoś oglądał film pt. Memento o człowieku, który miał problem z transferem danych z pamięci podręcznej (kora przed-czołowa) do pamięci długotrwałej (hipokamp) to skojarzenie jest również poprawne. Memento to pattern służący obiektom na wysyłanie do siebie informacji na przyszłość. Tak jak bohater filmu, który zapisywał i tatuował sobie na rękach informacje o tym co należy zrobić w przyszłości:)&lt;br&gt;&lt;br&gt;Natomiast zainteresowanych szczegółami implementacji Sagi odsyłam do przykładu w projekcie DDD&amp;CqRS Leaven:&lt;br&gt;&lt;ul&gt;&lt;li&gt;opis: &lt;a href="http://code.google.com/p/ddd-cqrs-sample/wiki/DomainDrivenDesignBusinessDeveloperMentalModel#Saga"&gt;http://code.google.com/p/ddd-cqrs-sample/wiki/DomainDrivenDesignBusinessDeveloperMentalModel#Saga&lt;/a&gt;&lt;li&gt;kod os strony programisty biznesowego: &lt;a href="http://code.google.com/p/ddd-cqrs-sample/source/browse/#svn%2Ftrunk%2Fddd_cqrs-sample%2Fsrc%2Fmain%2Fjava%2Fpl%2Fcom%2Fbottega%2Ferp%2Fsales%2Fsaga"&gt;http://code.google.com/p/ddd-cqrs-sample/source/browse/#svn%2Ftrunk%2Fddd_cqrs-sample%2Fsrc%2Fmain%2Fjava%2Fpl%2Fcom%2Fbottega%2Ferp%2Fsales%2Fsaga&lt;/a&gt;&lt;li&gt;idea i implementacja silnika Sagi:&lt;a href="http://code.google.com/p/ddd-cqrs-sample/wiki/CommandQueryResponsibilitySegregationSystemArchitectMentaModel#Saga_Engine"&gt;http://code.google.com/p/ddd-cqrs-sample/wiki/CommandQueryResponsibilitySegregationSystemArchitectMentaModel#Saga_Engine&lt;/a&gt;&lt;/ul&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;//=============================================&lt;br&gt;&lt;br&gt;Jako ciekawostkę dodam, że niektóre szyny komunikatów w .NET wspierają mechanizm Sagi niejako "z pudełka"...&lt;br&gt;Techniczny komunikat (message) jest traktowany na poziomie logicznym jak zdarzenie (event). Ichnie "Message Driven Beany" reagaujące na wiele zdarzeń to po prostu Sagi. Do tego automatyczne ładowanie i zapisywanie Memento, kończenie albo usypianie sagi oraz drobny szczegół: obsługa współbieżności...&lt;br&gt;Natomiast my w swym świecie Javy wciąż szukamy uber-frameworka webowego, który daje złudzenie, że każdy system jest CRUDem...&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5197374494377847819-1981736728064709568?l=art-of-software.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://art-of-software.blogspot.com/feeds/1981736728064709568/comments/default' title='Komentarze do posta'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5197374494377847819&amp;postID=1981736728064709568' title='Komentarze (15)'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5197374494377847819/posts/default/1981736728064709568'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5197374494377847819/posts/default/1981736728064709568'/><link rel='alternate' type='text/html' href='http://art-of-software.blogspot.com/2011/10/persystentny-multi-listener-czyli-saga.html' title='Persystentny Multi-Listener, czyli... Saga'/><author><name>Sławek Sobótka</name><uri>http://www.blogger.com/profile/15082577671795313109</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='30' height='32' src='http://3.bp.blogspot.com/-tmFOhJC48_E/TkQ0G2DxrqI/AAAAAAAAAz8/WVGBaaS5a_Y/s220/zdjecie2.png'/></author><thr:total>15</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5197374494377847819.post-4296772462597730453</id><published>2011-10-03T11:54:00.000+02:00</published><updated>2011-12-14T02:37:02.211+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Leaven'/><title type='text'>Pierwszy warsztat poświęcony "DDD &amp; CqRS Leaven project" za nami.</title><content type='html'>Kilka zdjęć na &lt;a href="http://ddd-cqrs-leaven.blogspot.com/2011/10/first-workshop.html"&gt;blogu projektu&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5197374494377847819-4296772462597730453?l=art-of-software.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://art-of-software.blogspot.com/feeds/4296772462597730453/comments/default' title='Komentarze do posta'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5197374494377847819&amp;postID=4296772462597730453' title='Komentarze (2)'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5197374494377847819/posts/default/4296772462597730453'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5197374494377847819/posts/default/4296772462597730453'/><link rel='alternate' type='text/html' href='http://art-of-software.blogspot.com/2011/10/pierwszy-warsztat-poswiecony-ddd-cqrs.html' title='Pierwszy warsztat poświęcony &quot;DDD &amp; CqRS Leaven project&quot; za nami.'/><author><name>Sławek Sobótka</name><uri>http://www.blogger.com/profile/15082577671795313109</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='30' height='32' src='http://3.bp.blogspot.com/-tmFOhJC48_E/TkQ0G2DxrqI/AAAAAAAAAz8/WVGBaaS5a_Y/s220/zdjecie2.png'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5197374494377847819.post-4710560498153250024</id><published>2011-09-28T13:54:00.001+02:00</published><updated>2011-12-14T02:36:41.318+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Domain Driven Design'/><category scheme='http://www.blogger.com/atom/ns#' term='Behaviour-Driven Development'/><category scheme='http://www.blogger.com/atom/ns#' term='Leaven'/><category scheme='http://www.blogger.com/atom/ns#' term='CqRS'/><title type='text'>Zapraszamy na warsztaty z "wypiekania zaczynu" (DDD, BDD, CqRS)</title><content type='html'>W najbliższą sobotę (1 października) organizujemy w ramach lubelskiego JUGa &lt;b&gt;otwarte&lt;/b&gt; warsztaty z zakresu:&lt;br&gt;- modelowania z wykorzystaniem Domain Driven Design&lt;br&gt;- procesu Behavior Driven Development (w tym wykorzystanie JBehave, Selenium i Agentów)&lt;br&gt;- architektury Command-query Responsibility Segregation&lt;br&gt;&lt;br&gt;Warsztaty będą przeprowadzone na podstawie materiałów z otwartego i darmowego projektu&lt;a href="http://bottega.com.pl/ddd-cqrs-sample-project"&gt; DDD+CqRS Leaven&lt;/a&gt;.&lt;br&gt;&lt;br&gt;Szczegóły wydarzenia na &lt;a href="http://groups.google.com/group/lublin-jug/browse_thread/thread/d01309bc92f3e881"&gt;stronie JUGa&lt;/a&gt;.&lt;br&gt;&lt;br&gt;&lt;br&gt;//============================&lt;br&gt;&lt;br&gt;Dla zainteresowanych z innych zakątków Polski informacja: planujemy tego typu inicjatywy podczas zbliżających się konferencji branżowych - szczegóły wkrótce.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5197374494377847819-4710560498153250024?l=art-of-software.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://art-of-software.blogspot.com/feeds/4710560498153250024/comments/default' title='Komentarze do posta'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5197374494377847819&amp;postID=4710560498153250024' title='Komentarze (0)'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5197374494377847819/posts/default/4710560498153250024'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5197374494377847819/posts/default/4710560498153250024'/><link rel='alternate' type='text/html' href='http://art-of-software.blogspot.com/2011/09/zapraszamy-na-warsztaty-z-wypiekania.html' title='Zapraszamy na warsztaty z &quot;wypiekania zaczynu&quot; (DDD, BDD, CqRS)'/><author><name>Sławek Sobótka</name><uri>http://www.blogger.com/profile/15082577671795313109</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='30' height='32' src='http://3.bp.blogspot.com/-tmFOhJC48_E/TkQ0G2DxrqI/AAAAAAAAAz8/WVGBaaS5a_Y/s220/zdjecie2.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5197374494377847819.post-8741726372445704787</id><published>2011-09-24T15:45:00.003+02:00</published><updated>2011-10-04T22:19:23.058+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Java'/><title type='text'>java.util.Calendar a sprawa Polska, czyli gdzie są moje 24 minuty?</title><content type='html'>Jako członek rady programowej tegorocznej konferencji&lt;a href="http://www.11.jdd.org.pl"&gt; Java Developers' Day&lt;/a&gt; mam zaszczyt zaprosić Was do konkursu na śmieszną (może przez łzy) i ciekawą (może pouczającą) anegdotę z codziennej pracy.&lt;br&gt;&lt;br&gt;Strona konkursu &lt;a href="http://www.11.jdd.org.pl/PL/contests/diary"&gt; Z pamiętnika dewelopera historii kilka…&lt;/a&gt; zawiera szczegółowy regulamin i opis nagród.Planujemy dodatkowo podczas konferencji umożliwić podzielenie się swoimi "przygodami" w formie stand up comedian:) &lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;//====================================&lt;br&gt;&lt;br&gt;Gdyby ktoś z lenistwa nie kliknął linka pod którym znajdują się zgłoszone historyjki, to zamieszczam kopię własnej:&lt;br&gt;&lt;br&gt;&lt;b&gt;Tytuł: java.util.Calendar a sprawa Polska, czyli gdzie są moje 24 minuty?&lt;/b&gt;&lt;br&gt;&lt;br&gt;&lt;b&gt;Problem:&lt;/b&gt;&lt;br&gt;&lt;br&gt;Duży system, w którym klientem do serwera były applety. Na wielu formularzach istnieje możliwość edycji czasu pewnych zdarzeń. Czas edytowany przez zwykłe pole tekstowe w formacie godzina:minuty. Niestety, na niektórych formularzach można zaobserwować następujące schorzenie: wpisujemy pewien czas, zapisujemy, następnie gdy ponownie edytujemy rekord, czas jest zawsze cofnięty o 24 minuty! Liczba 24 kojarzy się każdemu z ilością godzin w dobie tak więc jest to doskonale zwodnicza wartość…&lt;br&gt;&lt;br&gt;&lt;b&gt;Tło techniczne:&lt;/b&gt;&lt;br&gt;&lt;br&gt;Czas – z powodów, które pamiętają już tylko prastarzy Słowianie programujący w technologiach z epoki krzemu łupanego – był zapisywany w bazie danych jako: 01.01.1900 godzina_z_formularza:minuta_z_formularza:00.000&lt;br&gt;&lt;br&gt;Kluczowy jest tutaj pierwszy stycznia roku 1900.&lt;br&gt;&lt;br&gt;Zapis i odczyt działały poprawnie. Komunikacja applet – serwisy serwera poprzez Spring Remoting (zdalne wywołanie metod Beanów Springa, serializacja paramentów i wyników i wyjątków).&lt;br&gt; Czas był przesyłany w DTOsach w postaci obiektów klasy java.util.Calendar (służącej lepiej lub gorzej do manipulacji czasem) zamiast java.util.Date (służącej jako kontener na czas).&lt;br&gt; Calendar jest o tyle sprytną klasą, że jej obiekty badają lokalizację systemu operacyjnego na którym żyją. W przypadku podpisanych appletów robiły to na maszynach klienckich po ich przesłaniu i deserializacji.&lt;br&gt;&lt;br&gt;&lt;b&gt;Warto wiedzieć:&lt;/b&gt;&lt;br&gt;&lt;br&gt;Po tygodniu poszukiwań okazało się, że głęboko w kodzie kalendarza istnieje logika, która uwzględnia następujący fakt: &lt;STRIKE&gt;pewnego dnia w 1904&lt;/STRIKE&gt;  4. sierpnia 1915 roku na terenie Polski dokonano standaryzacji czasu, tak aby dopasować go do globalnych stref czasowych i przesunięto wówczas wskazówki o 24 minuty:)&lt;br&gt;&lt;br&gt;A panowie z Suna (niestety) odrobili lekcje z historii…&lt;br&gt;&lt;br&gt;&lt;iframe width="480" height="360" src="http://www.youtube.com/embed/9-rpPg4L8aU" frameborder="0" allowfullscreen&gt;&lt;/iframe&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5197374494377847819-8741726372445704787?l=art-of-software.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://art-of-software.blogspot.com/feeds/8741726372445704787/comments/default' title='Komentarze do posta'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5197374494377847819&amp;postID=8741726372445704787' title='Komentarze (5)'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5197374494377847819/posts/default/8741726372445704787'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5197374494377847819/posts/default/8741726372445704787'/><link rel='alternate' type='text/html' href='http://art-of-software.blogspot.com/2011/09/javautilcalendar-sprawa-polska-czyli.html' title='java.util.Calendar a sprawa Polska, czyli gdzie są moje 24 minuty?'/><author><name>Sławek Sobótka</name><uri>http://www.blogger.com/profile/15082577671795313109</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='30' height='32' src='http://3.bp.blogspot.com/-tmFOhJC48_E/TkQ0G2DxrqI/AAAAAAAAAz8/WVGBaaS5a_Y/s220/zdjecie2.png'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://img.youtube.com/vi/9-rpPg4L8aU/default.jpg' height='72' width='72'/><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5197374494377847819.post-3446160868553088981</id><published>2011-09-17T13:10:00.003+02:00</published><updated>2011-09-17T18:12:18.027+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Hardware'/><title type='text'>Przyśpiesz swoje środowisko dev - ramdisk</title><content type='html'>Dziś post sprzętowy. Do tej pory nie poruszałem tego typu tematyki na blogu, ale prywatnie hardware interesuje mnie nie mniej niż software:)&lt;br&gt;&lt;br&gt;Jak wiadomo w większości codziennych juzkejsów dysk jest wąskim gardłem naszego narzędzia pracy. Standardowym sposobem na przyśpieszenie maszyny jest wymiana dysku na SSD. Na dzień dzisiejszy aby tak na prawdę przyśpieszyć codzienną ogólną pracę (mieszanka zapisów i odczytów) trzeba wydać relatywnie sporą sumę na na prawdę szybki dysk.&lt;br&gt;&lt;br&gt;Można jednak pójść znacznie dalej z prędkością odczytu/zapisu pokusić się o stworzenie dysku w pamięci RAM.Dysk tego typu jest widziany w systemie tak samo jak zwykłe dyski. Na starcie może on pobrać swój obraz z HDD/SSD do RAM i od tej pory pracujemy na pamięci, która jest bardzo blisko procesora. RamDisk może oczywiście periodycznie utrwalać się na dysku klasycznym (mając więcej niż 1 rdzeń w procesorze nie jest to problem).&lt;br&gt;&lt;br&gt;Tutaj przegląd RamDisków dla Windows:&lt;a href="http://www.raymond.cc/blog/archives/2009/12/08/12-ram-disk-software-benchmarked-for-fastest-read-and-write-speed/"&gt; http://www.raymond.cc/blog/archives/2009/12/08/12-ram-disk-software-benchmarked-for-fastest-read-and-write-speed/&lt;/a&gt;.&lt;br&gt;Od kilku dni testuję na Win7 x64: &lt;a href="http://memory.dataram.com/products-and-services/software/ramdisk"&gt;http://memory.dataram.com/products-and-services/software/ramdisk&lt;/a&gt;który jest darmowy do 4GB.&lt;br&gt;&lt;br&gt;Na taki dysk można skopiować całe środowisko dev:  JDK (wystarczy skopiować), Eclipse, Maven+Repo, Servery...Po prostu śmiga!&lt;br&gt;&lt;br&gt;//========================================&lt;br&gt;&lt;br&gt;Dokupując RAM zwróćcie uwagę oczywiście na taktowanie (tak aby było maksymalne na jakie pozwala szyna) ale również na latencją CAS&lt;a href="http://pl.wikipedia.org/wiki/CAS_latency"&gt; http://pl.wikipedia.org/wiki/CAS_latency&lt;/a&gt;.Przykładowo DDR3 1066MHz w wersji CL7 jest o 10% szybszy niż w wersji CL9. A różnica w cenie kości 4GB to dosłownie kilka zł:)&lt;br&gt;&lt;br&gt;Rozwiązaniem lepszym niż RamDisk (który zapisuje obraz na HDD/SDD) byłby soft, który buforowałby w RAM wskazane katalogi i udostępniał je przez interfejs sterownika dysku. Tak aby po prostu w tle synchronizować się z klasycznym dyskiem wprost do wskazanych katalogów - bez obrazu dysku. Rodzaj stałego obszaru cache dysku. Znacie może tego typu rozwiązania softwareowe (bo istnieją mniej więcej tego typu sprzętowe kontrolery do dysków ssd)?&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5197374494377847819-3446160868553088981?l=art-of-software.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://art-of-software.blogspot.com/feeds/3446160868553088981/comments/default' title='Komentarze do posta'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5197374494377847819&amp;postID=3446160868553088981' title='Komentarze (11)'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5197374494377847819/posts/default/3446160868553088981'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5197374494377847819/posts/default/3446160868553088981'/><link rel='alternate' type='text/html' href='http://art-of-software.blogspot.com/2011/09/przyspiesz-swoje-srodowisko-dev-ramdisk.html' title='Przyśpiesz swoje środowisko dev - ramdisk'/><author><name>Sławek Sobótka</name><uri>http://www.blogger.com/profile/15082577671795313109</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='30' height='32' src='http://3.bp.blogspot.com/-tmFOhJC48_E/TkQ0G2DxrqI/AAAAAAAAAz8/WVGBaaS5a_Y/s220/zdjecie2.png'/></author><thr:total>11</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5197374494377847819.post-1260939002348337924</id><published>2011-08-30T18:20:00.001+02:00</published><updated>2011-12-14T02:36:22.420+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Domain Driven Design'/><category scheme='http://www.blogger.com/atom/ns#' term='Leaven'/><category scheme='http://www.blogger.com/atom/ns#' term='Spring'/><category scheme='http://www.blogger.com/atom/ns#' term='JPA'/><category scheme='http://www.blogger.com/atom/ns#' term='CqRS'/><title type='text'>Zaczyn DDD+CqRS</title><content type='html'>Jak pewnie zauważyliście, częstotliwość publikowania postów spadła ostatnio dosyć znacznie. A to za sprawą mocnego zaangażowania w nowy projekt - projekt ilustrujący techniki modelowania Domain Driven Design oraz wybrane podejścia do implementacji architektury Command-query Responsibility Segreation.&lt;br /&gt;&lt;br /&gt;Projekt osiągnął poziom wersji Beta pierwszego Milestonea, tak więc już oficjalnie możemy go upublicznić: &lt;a href="http://code.google.com/p/ddd-cqrs-sample/"&gt;http://code.google.com/p/ddd-cqrs-sample/&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Zaczyn?&lt;br /&gt;Nazwa ociekająca folklorem jest ilustracją idei: projekt to coś więcej niż Sample ale zdecydowanie nie jest to kolejny Framework - więcej na ten temat na wiki.&lt;br /&gt;Gwoli wyjaśnienia: zaczyn to coś z czego powstaje chleb.&lt;br /&gt;&lt;br /&gt;Odeszliśmy od formy frameworka przekonani przez samego Grega Younga (twórcę CqRS i propagatora DDD). Greg przekonał mnie podczas prywatnych rozmów, że framework dla CqRS delikatnie mówiąc nie ma sensu:)&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Zawartość projektu odpowiada na pytania techniczne, które pojawiają się tak często, że uznaliśmy, że czas stworzyć sampla ilustrującego nasze podejście. Do tej pory istnieją dwa takie Sample napisane w Javie - my jednak chcieliśmy pójść nieco dalej. Tak więc projekt jest sumą doświadczeń jego twórców.&lt;br /&gt;&lt;br /&gt;Co w nim znajdziecie:&lt;br /&gt;- ilustracja wszystkich Builiding Blocków DDD (bez uproszczeń technicznych)&lt;br /&gt;- ilustracja zaawansowany technik DDD (Bounded Context to nie są akademickie rozważania)&lt;br /&gt;- ewolucyjne podejście do architektury warstwowej, różne poziomy separacji CqRS (na tym etapie nie wprowadzamy Event Sourcingu - wyjaśnienie powodów na wiki)&lt;br /&gt;- pragmatyczne podejście do CqRS&lt;br /&gt;- część bardzo specyficznej wiedzy wyniesioną przez nas z wiosennego szkolenia Grega Younga&lt;br /&gt;- modelowanie czasu poprzez zdarzenia i dosyć nową technikę modelowania czasu: Sagi&lt;br /&gt;- kilka eleganckich trików z wykorzystaniem Springa i Hibernate:)&lt;br /&gt;- techniki testowania: jednostkowe, integracyjne i akceptacyjne&lt;br /&gt;- połączenie JBehave (Behavior Driven Development) z Selenium&lt;br /&gt;- już niedługo: nasz własny pomysł na uogólnienie historyjek tak by wspierały zarówno testowanie przez GUI jak i przez API&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Zainteresowanych zapraszamy do:&lt;br /&gt;- &lt;a href="http://code.google.com/p/ddd-cqrs-sample/wiki/TableOfContents"&gt;wiki&lt;/a&gt; - kilkadziesiąt stron A4 plus trzy wizualizacje w Prezi&lt;br /&gt;- &lt;a href="http://code.google.com/p/ddd-cqrs-sample/source/browse/#svn%2Ftrunk"&gt;SVN&lt;/a&gt; - aktualnie ok 150 klas platformy zaczynu oraz przykładów DDD&lt;br /&gt;- &lt;a href="http://groups.google.com/group/ddd-cqrs-sample"&gt;grupy dyskusyjnej&lt;/a&gt;&lt;br /&gt;- &lt;a href="http://ddd-cqrs-leaven.blogspot.com/"&gt;bloga&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;//====================================&lt;br /&gt;&lt;br /&gt;Teksty techniczne z zakresu DDD i CqRS będę publikował na nowym blogu. Natomiast niniejszy będzie wciąż prowadzony jako miejsce na tematy pozostałe.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5197374494377847819-1260939002348337924?l=art-of-software.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://art-of-software.blogspot.com/feeds/1260939002348337924/comments/default' title='Komentarze do posta'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5197374494377847819&amp;postID=1260939002348337924' title='Komentarze (4)'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5197374494377847819/posts/default/1260939002348337924'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5197374494377847819/posts/default/1260939002348337924'/><link rel='alternate' type='text/html' href='http://art-of-software.blogspot.com/2011/08/zaczyn-dddcqrs.html' title='Zaczyn DDD+CqRS'/><author><name>Sławek Sobótka</name><uri>http://www.blogger.com/profile/15082577671795313109</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='30' height='32' src='http://3.bp.blogspot.com/-tmFOhJC48_E/TkQ0G2DxrqI/AAAAAAAAAz8/WVGBaaS5a_Y/s220/zdjecie2.png'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5197374494377847819.post-7294255330607590427</id><published>2011-08-12T09:43:00.014+02:00</published><updated>2011-08-23T21:31:26.105+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='JSF'/><title type='text'>Wygeneruj sobie PDFa - Facelets (JSF) + CSS3 + Flying Saucer</title><content type='html'>Dzisiejszy post będzie nietypowy: dużo kodu i kilka speszyl-haków:)&lt;br /&gt;&lt;br /&gt;Pokażę jak szybko i raczej bezboleśnie generować PDFy na podstawie HTMLa + CSS3 z wykorzystaniem szablonów w wydaniu Facelets.&lt;br /&gt;&lt;br /&gt;&lt;h1&gt;Założenia&lt;/h1&gt;Oczywiście do generowania PDF możemy podejść na wiele sposobów. Możemy np. użyć natywnego api lub nawet zastosować Open Office postawionego w trybie servera (bez GUI) i korzystać ze wszelkich narzędzi do tworzenia dokumentu, aby na końcu "zapisać jako" pdf.&lt;br /&gt;&lt;br /&gt;Natomiast w tym poście zakładam, że chcemy rozwiązać sprawę najprościej jak się da, bez potrzeby studiowania autystycznej dokumentacji.&lt;br /&gt;&lt;br /&gt;&lt;h1&gt;Generujemy PDF&lt;/h1&gt;Na początek potrzebujemy biblioteki: http://code.google.com/p/flying-saucer (w paczce mamy ITexta i xercesa). Flying saucer to wspaniałe narzędzie, które przykrywa iTexta wygodnym api: na wejściu podajemy urla do strony, a na strumieniu wyjściowym dostajemy PDFa. Strona może odwoływać się do CSS3, w którym definiujemy nagłówki, stopki, numerowanie stron, podział stron. Wszystko zostanie kolejno opisane w dalszej części.&lt;br /&gt;&lt;br /&gt;Pdfy będziemy zwracać z następującego servletu:&lt;br /&gt;&lt;div&gt;&lt;pre class="brush: java"&gt;@SuppressWarnings("serial")&lt;br /&gt;@WebServlet("/programy_szkolen_pdf/*")&lt;br /&gt;public class PdfServlet extends HttpServlet {&lt;br /&gt;	&lt;br /&gt;	private static final String FONTS_PACKAGE = "fonts";&lt;br /&gt;	private static final String FONTS_DIR = "/" + FONTS_PACKAGE + "/";&lt;br /&gt;	&lt;br /&gt;	protected void doGet(HttpServletRequest request,&lt;br /&gt;			HttpServletResponse response) throws ServletException, IOException {				&lt;br /&gt;		&lt;br /&gt;		response.setContentType("application/pdf");&lt;br /&gt;		OutputStream os = response.getOutputStream();&lt;br /&gt;		&lt;br /&gt;		String url = getUrl(request);&lt;br /&gt;&lt;br /&gt;		try {&lt;br /&gt;			ITextRenderer renderer = initRenderer();&lt;br /&gt;			&lt;br /&gt;			renderer.setDocument(url);&lt;br /&gt;			renderer.layout();&lt;br /&gt;			&lt;br /&gt;			renderer.createPDF(os);&lt;br /&gt;		} catch (Exception ex){&lt;br /&gt;			throw new ServletException(ex);&lt;br /&gt;		}&lt;br /&gt;		&lt;br /&gt;		response.flushBuffer();&lt;br /&gt;&lt;br /&gt;	}&lt;br /&gt;&lt;br /&gt;	private String getUrl(HttpServletRequest request) {&lt;br /&gt;		String pdfServletPath = request.getServletPath();&lt;br /&gt;		&lt;br /&gt;		String cp = request.getContextPath();&lt;br /&gt;		String program = request.getRequestURI();&lt;br /&gt;		&lt;br /&gt;		program = program.replace(cp + pdfServletPath, "");&lt;br /&gt;		program = program.substring(0, program.length() - 4); // cut .pdf&lt;br /&gt;				&lt;br /&gt;		String url = "http://localhost:8080" + cp + program + ".xhtm?pdf=true";&lt;br /&gt;		&lt;br /&gt;		return url;&lt;br /&gt;	}&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;Jak widać API latającego spodka jest proste:&lt;br /&gt;- posługujemy się obiektem rendererm który posiada stan&lt;br /&gt;- ustawiamy mu URL do strony, którą chcemy skonwertować na PDF&lt;br /&gt;- wołamy metodę układającą pdf&lt;br /&gt;- wynik kierujemy do strumienia odpowiedzi servletu.&lt;br /&gt;&lt;br /&gt;I to generalnie byłoby wszystko:)&lt;br /&gt;&lt;br /&gt;Zostało kilka szczegółów...&lt;br /&gt;Metoda getUrl w moim przypadku robi pewne oszustwo operując na ścieżkach&lt;br /&gt;&lt;br /&gt;Użytkownik woła servlet:&lt;br /&gt;/programy_szkolen_pdf/szkolenie-java-start.pdf&lt;br /&gt;btw: zauważcie jak zamapowany jest servlet: @WebServlet("/programy_szkolen_pdf/*")&lt;br /&gt;&lt;br /&gt;A servlet wskazuje latającemu spodkowi adres:&lt;br /&gt;http://localhost:8080/strona/szkolenie-java-start.xhtm?pdf=true&lt;br /&gt;&lt;br /&gt;Zakładam, że zasoby do renderowania znajdują się na tej samej maszynie, stąd localhost.&lt;br /&gt;Do czego służy parametr pdf dowiemy się za chwilę:)&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Mamy jeszcze nieco smutnych szczegółów technicznych w naszym latającym spodku.&lt;br /&gt;&lt;br /&gt;Renderera trzeba zainicjować - metoda initRenderer.&lt;br /&gt;&lt;br /&gt;Jeżeli w PDF chcemy używać polskich (lub jakichkolwiek innych barbarzyńskich znaków), to musimy zarejestrować w rendereze fonty, których używamy w CSS (Arial, Verdana, cokolwiek). Służy do tego metoda renderer.getFontResolver().addFont&lt;br /&gt;Ja napisałem prosty automat, metodę findFonts(), który automatycznie wyszukuje plików z fontami w *pakiecie* zdefiniowanym w stałej FONTS_PACKAGE. Chodzi o to aby uniknąć konfigurowania ścieżek. Po prostu skanujemy pakiet z class path.&lt;br /&gt;Zatem do odpowiedniego pakietu należy sobie wkopiować (np z systemu) fonty. Oczywiście katalog powinien być niedostępny z sieci aby nie być posądzonym o dystrybucję komercyjnych fontów - jeżeli takowych używacie.&lt;br /&gt;&lt;br /&gt;&lt;div&gt;&lt;pre class="brush: java"&gt;	&lt;br /&gt;	private ITextRenderer initRenderer() throws IOException, DocumentException{&lt;br /&gt;		List&lt;string&gt; fonts = findFonts();&lt;br /&gt;		&lt;br /&gt;		ITextRenderer renderer = new ITextRenderer();&lt;br /&gt;		&lt;br /&gt;		for (String font : fonts) {&lt;br /&gt;			renderer.getFontResolver().addFont(FONTS_DIR + font,&lt;br /&gt;					BaseFont.IDENTITY_H, BaseFont.EMBEDDED);&lt;br /&gt;		}			&lt;br /&gt;		&lt;br /&gt;		return renderer;&lt;br /&gt;	}&lt;br /&gt;&lt;br /&gt;	private List&lt;string&gt; findFonts() throws IOException {&lt;br /&gt;		Enumeration&lt;url&gt; resources = getClass().getClassLoader().getResources(FONTS_PACKAGE);&lt;br /&gt;&lt;br /&gt;		URL resource = resources.nextElement();&lt;br /&gt;		File directory = new File(resource.getFile());&lt;br /&gt;&lt;br /&gt;		List&lt;string&gt; fonts = new ArrayList&lt;string&gt;();&lt;br /&gt;		if (!directory.exists()) {&lt;br /&gt;			return fonts;&lt;br /&gt;		}&lt;br /&gt;		File[] files = directory.listFiles();&lt;br /&gt;		for (File file : files) {			&lt;br /&gt;			fonts.add(file.getName());&lt;br /&gt;		}&lt;br /&gt;		return fonts;&lt;br /&gt;	}&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;h1&gt;Szablony&lt;/h1&gt;Dlaczego Facelets i &lt;a href="http://javaserverfaces.java.net/"&gt;JSF 2&lt;/a&gt;?&lt;br /&gt;&lt;br /&gt;Do tej pory różnego rodzaju strony tworzyłem w PHP z wykorzystaniem &lt;a href="http://www.smarty.net/"&gt;Smarty&lt;/a&gt;. Po kilku doświadczeniach uznałem to za... powiedzmy niewygodne.&lt;br /&gt;&lt;br /&gt;Chcę być dobrze zrozumiany - Smarty są ok dla pewnej klasy problemów: np wówczas gdy mamy kontent w bazie danych (jakiś CMS), pobieramy kontent jako wiersze i rozsmarowujemy po po "dziurkach" w szablonie. Wówczas imperatywne API Smarty (w postaci obiektu, na którym wołamy metody definiujące zmienne szablonu) jest jak najbardziej ok.&lt;br /&gt;&lt;br /&gt;Natomiast ja w klasach problemów typu strona firmowa, preferuję przechowywać kontent (strzępy konwentu) w plikach XHTML. W takim wypadku praca z imperatywnym API to po prostu pomyłka. Jako "weteran" aplikacji webowych czuję się jak ryba w wodzie poruszając się w kodzie. Baza i CMS jedynie mnie ogranicza.&lt;br /&gt;&lt;br /&gt;Dlatego tworząc nową wersję strony formowej zdecydowałem się na coś... delikatnie mówiąc... zastawiającego. Użycie JSF - standardu prezentacji enterprise (która ma swoich fanów jak i anty-fantów) do stworzenia strony www :O&lt;br /&gt;&lt;br /&gt;Okazało się, że jeżeli nie używać formularzy (pomijamy większość faz cyklu obsługi żądania), nie używać ManagedBeanów, a jedynie składania kawałków XHTMla to okazuje się, bo jest to bardzo produktywne narzędzie.&lt;br /&gt;&lt;br /&gt;Przykład:&lt;br /&gt;strona &lt;a href="http://bottega.com.pl/szkolenie-jsf-2"&gt;http://bottega.com.pl/szkolenie-jsf-2&lt;/a&gt;&lt;br /&gt;wygląda jak każdy widzi.&lt;br /&gt;&lt;br /&gt;Jest wyraźnie podzielona na kontent merytoryczny i ozdobniki w postaci nagłówka, stopki i paneli bocznych.&lt;br /&gt;&lt;br /&gt;A tak wygląda jej kod:&lt;br /&gt;&lt;div&gt;&lt;pre class="brush: xhtml"&gt;&lt;ui:composition xmlns="http://www.w3.org/1999/xhtml"&lt;br /&gt;	xmlns:ui="http://java.sun.com/jsf/facelets"&lt;br /&gt;	xmlns:h="http://java.sun.com/jsf/html"&lt;br /&gt;	xmlns:f="http://java.sun.com/jsf/core"&lt;br /&gt;	template="/layout/training_template.xhtml"&gt;&lt;br /&gt;	&lt;br /&gt;	&lt;ui:define name="params"&gt;&lt;br /&gt;		&lt;ui:param name="nameOfTheFile" value="szkolenie-jsf-2" /&gt;&lt;br /&gt;		&lt;ui:param name="description" value="Szkolenie: Java Server Faces 2.0"&gt;&lt;/ui:param&gt;	&lt;br /&gt;	&lt;/ui:define&gt;&lt;br /&gt;&lt;br /&gt;	&lt;ui:define name="category"&gt;Java Enterprise Edition&lt;/ui:define&gt;&lt;br /&gt;&lt;br /&gt;	&lt;ui:define name="code"&gt;JSF 2&lt;/ui:define&gt;&lt;br /&gt;	&lt;br /&gt;	&lt;ui:define name="name"&gt;	Java Server Faces 2&lt;/ui:define&gt;&lt;br /&gt;&lt;br /&gt;	&lt;ui:define name="target"&gt;Projektanci, programiści&lt;/ui:define&gt;&lt;br /&gt;&lt;br /&gt;	&lt;ui:define name="duration"&gt;2 dni&lt;/ui:define&gt;&lt;br /&gt;&lt;br /&gt;	&lt;ui:define name="format"&gt;50% wykłady / 50% warsztaty&lt;/ui:define&gt;&lt;br /&gt;&lt;br /&gt;	&lt;ui:define name="description"&gt;		&lt;br /&gt;	&lt;br /&gt;		&lt;p&gt;		Program został skontrowany tak aby przedstawić zagadnienia w kontekście konkretnych problemów, które ilustrują praktyczne wykorzystanie każdej z funkcjonalności JSF. &lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Program szkolenia zawiera rozszerzenie o najlepsze praktyki projektowe i architektoniczne.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Tematyka szkolenia obejmuje wszystkie cechy frameworka JSF 2.0 istotne z punktu widzenia developera aplikacji.&lt;br /&gt;		&lt;/p&gt;&lt;/ui:define&gt;&lt;br /&gt;&lt;/ui:composition&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;Znaczniki ui:definie definiują wartości zmiennych, które będą używane w szablonie.&lt;br /&gt;Wartości to czysty kod XHTML, który jest na bieżąco validowany przez edytor.&lt;br /&gt;&lt;br /&gt;Stronę możemy zawołać na 3 sposoby:&lt;br /&gt;- podając jej url: &lt;a href="http://bottega.com.pl/szkolenie-jsf-2"&gt;http://bottega.com.pl/szkolenie-jsf-2&lt;/a&gt;&lt;br /&gt;- renderując ją do pdf: &lt;a href="http://bottega.com.pl/programy_szkolen_pdf/szkolenie-jsf-2.pdf"&gt;http://bottega.com.pl/programy_szkolen_pdf/szkolenie-jsf-2.pdf&lt;/a&gt; (wówczas nasz servlet przekaże adres http://bottega.com.pl/szkolenie-jsf-2.xhtm?pdf=true) do Flying Saucera&lt;br /&gt;- zagnieżdżając w pływającej ramce na facebooku podając adres &lt;a href="http://bottega.com.pl/szkolenie-jsf-2.xhtm?fb=true"&gt;http://bottega.com.pl/szkolenie-jsf-2.xhtm?fb=true&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;W każdym z tych przypadków oczekujemy innego wyglądu.&lt;br /&gt;&lt;br /&gt;Zatem znacznik ui:composition wskazuje szablon: template="/layout/training_template.xhtml"&lt;br /&gt;&lt;br /&gt;Plik ten układa w odpowiednich miejscach parametry szkolenia. Szablon ten odpowiada jedynie za fragment strony (układ info o szkoleniu), ale nie zawiera np. nagłówka, stopki, ani bocznych boxów.&lt;br /&gt;&lt;br /&gt;&lt;div&gt;&lt;pre class="brush: xhtml"&gt;&lt;ui:composition xmlns="http://www.w3.org/1999/xhtml"&lt;br /&gt;	xmlns:ui="http://java.sun.com/jsf/facelets"&lt;br /&gt;	xmlns:h="http://java.sun.com/jsf/html"&lt;br /&gt;	xmlns:f="http://java.sun.com/jsf/core"&lt;br /&gt;	template="/layout/dispatching_template.xhtml"&gt;&lt;br /&gt;&lt;ui:define name="title"&gt;&lt;br /&gt;		Szkolenie: &lt;ui:insert name="code" /&gt;&lt;br /&gt;	&lt;/ui:define&gt;	&lt;br /&gt;&lt;br /&gt;	&lt;ui:define name="body"&gt;&lt;br /&gt;		&lt;div class="training"&gt;			&lt;div class="cf"&gt;				&lt;h2 class="position_left"&gt;Informacje ogólne&lt;/h2&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;Jak widać, szablon ten definiuje 2 zmienne: title i body. Wartości tych zmiennych zawierają w sobie XHTMLa oraz wartości zmiennych z dekorowane pliku - znacznik ui:insert.&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Warunkowe renderowanie&lt;/h2&gt;Pomarańczowy przycisk "Zapytaj o szkolenie" jest niepożądany w przypadku wersji PDF i facebook, dlatego został warunkowo renderowany, przy pomocy panelGroup i atrybutu rendered:&lt;br /&gt;&lt;br /&gt;&lt;div&gt;&lt;pre class="brush: xhtml"&gt;&lt;h:panelGroup rendered="#{urlChecker.standard}"&gt;&lt;br /&gt;  &lt;div class="button_orange_small button_right"&gt;&lt;div class="button_left"&gt;&lt;/div&gt;&lt;div class="button_right"&gt;&lt;/div&gt;&lt;a href="kontakt"&gt;zapytaj o szkolenie&lt;/a&gt;&lt;br /&gt;    &lt;/div&gt;&lt;/h:panelGroup&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;Bean UrlChecker będzie opisany już za chwilę.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Wybór szablonu docelowego&lt;/h2&gt;Szablon szkolenia, nie jest szablonem "ostatecznym". Jest on dekorowane znowuż przez szablon wybierający szablon główny: template="/layout/dispatching_template.xhtml"&lt;br /&gt;&lt;br /&gt;Jest to warstwa pośrednia pozwalająca w jednym miejscu przechowywać kod, który potencjalnie ulegnie zmianie. Tak oto wygląda dispatching_template.xhtml:&lt;br /&gt;&lt;br /&gt;&lt;div&gt;&lt;pre class="brush: xhtml"&gt;&lt;ui:composition xmlns="http://www.w3.org/1999/xhtml"&lt;br /&gt;	xmlns:ui="http://java.sun.com/jsf/facelets"&lt;br /&gt;	xmlns:h="http://java.sun.com/jsf/html"&lt;br /&gt;	xmlns:f="http://java.sun.com/jsf/core"&lt;br /&gt;	template="/layout/#{urlChecker.templateName}_pl.xhtml"&gt;&lt;br /&gt;	&lt;br /&gt;&lt;/ui:composition&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;Jak widać nie dodaje żądnej wizualizacji a jedynie deleguje dekorowanie do kolejnego szablonu. Z tym, że nie mamy tutaj konkretnej ścieżki a jedynie wyrażenie wyliczane w Javie (tak w normalnym języku programowania a nie w jakimś pokracznym języku opartym o znaczniki):&lt;br /&gt;&lt;br /&gt;&lt;div&gt;&lt;pre class="brush: java"&gt;@ManagedBean&lt;br /&gt;public class UrlChecker {&lt;br /&gt;&lt;br /&gt;	public String getTemplateName(){&lt;br /&gt;		if (isPdf())&lt;br /&gt;			return "template_pdf";&lt;br /&gt;		&lt;br /&gt;		if (isFacebook())&lt;br /&gt;			return "template_facebook";&lt;br /&gt;		&lt;br /&gt;		return "template";&lt;br /&gt;	}&lt;br /&gt;	&lt;br /&gt;	public boolean isStandard(){&lt;br /&gt;		return ! (isPdf() || isFacebook());&lt;br /&gt;	}&lt;br /&gt;	&lt;br /&gt;	public boolean isPdf(){		&lt;br /&gt;		return "true".equals(getParameter("pdf"));&lt;br /&gt;	}&lt;br /&gt;	&lt;br /&gt;	public boolean isFacebook(){		&lt;br /&gt;		return "true".equals(getParameter("fb"));&lt;br /&gt;	}&lt;br /&gt;	&lt;br /&gt;	private String getParameter(String name){&lt;br /&gt;		ExternalContext externalContext = FacesContext.getCurrentInstance().getExternalContext();				&lt;br /&gt;		return externalContext.getRequestParameterMap().get(name);		&lt;br /&gt;	}&lt;br /&gt;	&lt;br /&gt;	&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;Zatem jeżeli zawołamy naszą stronę w ten sposób:&lt;br /&gt;&lt;a href="http://bottega.com.pl/szkolenie-jsf-2.xhtm"&gt;http://bottega.com.pl/szkolenie-jsf-2.xhtm&lt;/a&gt;&lt;br /&gt;to w wyniku otrzymamy zawartość dekorowaną szablonem template_pl, który zawiera banner, stopę i boczne boxy&lt;br /&gt;&lt;br /&gt;jeżeli natomiast w ten sposób:&lt;br /&gt;&lt;a href="http://bottega.com.pl/szkolenie-jsf-2.xhtm?pdf=true"&gt;http://bottega.com.pl/szkolenie-jsf-2.xhtm?pdf=true&lt;/a&gt;&lt;br /&gt;to szablon dekorujący template_pdf_pl doda nagłówek i stopkę dla dokumnetu&lt;br /&gt;&lt;br /&gt;a takie wywołanie&lt;br /&gt;&lt;a href="http://bottega.com.pl/szkolenie-jsf-2.xhtm?fb=true"&gt;http://bottega.com.pl/szkolenie-jsf-2.xhtm?fb=true&lt;/a&gt; skutkuje zastosowaniem niemal niewidocznego szablonu dla facebooka.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Podsumowanie dekorowania&lt;/h2&gt;&lt;br /&gt;Mamy zatem następującą hierarchię treści:&lt;br /&gt;&lt;br /&gt;szablon: szablon www | szablon pdf | szablon facebook&lt;br /&gt;szablon: dispatcher&lt;br /&gt;szablon: training&lt;br /&gt;strona: konkretne szkolenie&lt;br /&gt;&lt;br /&gt;Czyli na najwyższym poziomie mamy trzy perspektywy (szablony) spojrzenia na dane merytoryczne zawarte w plikach opisujących szkolenie.&lt;br /&gt;&lt;br /&gt;Inne strony nie będące programem szkoleń po prostu pomijają szablon training_template i są dekorowane wprost szablonem dispatcher template&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;h1&gt;Układ dokumentu PDF w HTML i CSS3&lt;/h1&gt;Składanie stron w HTML jest dosyć łatwe. Wręcz banalne w porównaniu z natywnym API lub autyzmem Open Office.&lt;br /&gt;&lt;br /&gt;Szablon pdf to zwykły XHTML:&lt;br /&gt;&lt;div&gt;&lt;pre class="brush: xhtml&gt;&amp;lt;html xmlns="http://www.w3.org/1999/xhtml"&lt;br /&gt;	xmlns:ui="http://java.sun.com/jsf/facelets"&gt;&lt;br /&gt;&amp;lt;head&gt;&lt;br /&gt;&lt;br /&gt;&lt;style type="text/css"&gt;&lt;br /&gt;&lt;br /&gt;body {&lt;br /&gt;	background-image:none;&lt;br /&gt;	font-family: Verdana, sans-serif;&lt;br /&gt;	font-size: 12px;&lt;br /&gt;	line-height: 15px;	&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;.small {font-size: xx-small;}&lt;br /&gt;.line{border-bottom: 1px solid black}&lt;br /&gt;&lt;br /&gt;/**&lt;br /&gt; * Specific Elements&lt;br /&gt; */&lt;br /&gt;&lt;br /&gt;#page-header {&lt;br /&gt;   &lt;br /&gt;}&lt;br /&gt;#page-footer{&lt;br /&gt;   text-align: right;&lt;br /&gt;   margin-bottom: 10mm;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;br /&gt; &lt;br /&gt;@page {&lt;br /&gt;  margin-top: 20mm;&lt;br /&gt;  margin-right: 20mm;&lt;br /&gt;  margin-bottom: 20mm;&lt;br /&gt;  margin-left: 20mm;&lt;br /&gt;&lt;br /&gt;  size: A4; /*letter landscape*/&lt;br /&gt;  background: white;&lt;br /&gt;  &lt;br /&gt;  @top-center {&lt;br /&gt;    content: element(current);&lt;br /&gt;  }&lt;br /&gt;  &lt;br /&gt;  @bottom-right {&lt;br /&gt;    content: element(footer);&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;.page-start { -fs-page-sequence: start; page-break-before: always;}&lt;br /&gt;table {-fs-table-paginate: paginate;page-break-inside: avoid;}&lt;br /&gt;/* forces a page break */&lt;br /&gt;.break {page-break-after:always}&lt;br /&gt;&lt;br /&gt;span.pages:before { content: "Strona: " counter(page) "/" counter(pages);}&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;/style&gt;&lt;br /&gt;&amp;lt;/head&gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;body&gt;&lt;br /&gt;  &lt;div style="-fs-page-sequence: start;"&gt;!!! TUTAJ trzy warstwy opisane poniżej !!!&lt;br /&gt;&lt;/div&gt;&lt;&amp;lt;/body&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;Style po komentarzy "Specific Elements" są *kluczowe*.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Wewnątrz pierwszej warstwy mamy kolejno kolejno:&lt;br /&gt;&lt;br /&gt;nagłówek:&lt;br /&gt;&lt;div&gt;&lt;pre class="brush: xhtml"&gt;&lt;div style="position: running(current);"&gt;		&lt;br /&gt;   &lt;div id="page-header" class="small"&gt;&lt;img src="images/logo.png" height="52px"/&gt;&lt;br /&gt;      			&lt;br /&gt;      &lt;div style="float:right; width: 119mm; text-align: right; border-bottom: 1px solid black; padding-bottom: 3px; padding-left: 20mm; min-height: 12mm"&gt;Program szkolenia: &lt;ui:insert name="name"/&gt;(&lt;ui:insert name="category"/&gt;)				&lt;br /&gt;    &lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;stopkę:&lt;br /&gt;&lt;div&gt;&lt;pre class="brush: xhtml"&gt;&lt;div style="position: running(footer);"&gt;&lt;div id="page-footer" class="small"&gt;&lt;div class="line"&gt;&amp;#160;&lt;/div&gt;&lt;div&gt;&lt;div style="float:left"&gt;	  Bottega IT Solutions&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;http://www.bottega.com.pl&lt;br /&gt;	  &lt;/div&gt;&lt;div style="float:right"&gt;	        			&lt;br /&gt;	  &lt;br /&gt;            &lt;span class="pages"/&gt;&lt;br /&gt;	  &lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;zawartość:&lt;br /&gt;&lt;div&gt;&lt;pre class="brush: xhtml"&gt;&lt;div id="content"&gt;&lt;div style="padding-left:31mm"&gt;&lt;h1&gt;Program szkolenia&lt;/h1&gt;&lt;h1&gt;&lt;b&gt;&lt;ui:insert name="name"/&gt;&lt;/b&gt;&lt;/h1&gt;&lt;/div&gt;&lt;ui:insert name="body" /&gt;&lt;br /&gt;  &lt;/div&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;h1&gt;Na zakończenie bonus dla wytrwałych&lt;/h1&gt;Jak wołać w JSF 2 metody z parametrem? Zapewniam, że może się przydać w bardziej wyrafinowanych szablonach:)&lt;br /&gt;&lt;br /&gt;Tak robimy to w &lt;a href="http://seamframework.org/"&gt;Seam&lt;/a&gt; od 5 lat:&lt;br /&gt;&lt;div&gt;&lt;pre class="brush: xhtml"&gt;&lt;h:commandButton ation="#{bean.metoda(parametr)}" /&gt;&lt;br /&gt;&lt;br /&gt;&lt;h:outputText value="#{bean.metoda(parametr1, parametr2)}" /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;Natomiast w czystym JSF trzeba wykonać kilka prostych kroków aby uzyskać możliwość stosowania powyższej składni:&lt;br /&gt;http://ocpsoft.com/java/jsf2-java/jsf2-how-to-add-the-magic-of-el-el2-to-jsf/&lt;br /&gt;&lt;br /&gt;//====================================&lt;br /&gt;&lt;br /&gt;Mam nadzieję, że udało mi się pokazać, że w Javie można efektywnie a przy tym czysto i elegancko zbudować stronę.&lt;br /&gt;&lt;br /&gt;Przy innej okazji pokażę jak Filtry Servletów w dosłownie kilku linijkach biją na głowę autystyczne htaccess:)&lt;br /&gt;&lt;br /&gt;A Smarki?... Już nigdy więcej:)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5197374494377847819-7294255330607590427?l=art-of-software.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://art-of-software.blogspot.com/feeds/7294255330607590427/comments/default' title='Komentarze do posta'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5197374494377847819&amp;postID=7294255330607590427' title='Komentarze (16)'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5197374494377847819/posts/default/7294255330607590427'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5197374494377847819/posts/default/7294255330607590427'/><link rel='alternate' type='text/html' href='http://art-of-software.blogspot.com/2011/08/wygeruj-sobie-pdfa-facelets-jsf-css3.html' title='Wygeneruj sobie PDFa - Facelets (JSF) + CSS3 + Flying Saucer'/><author><name>Sławek Sobótka</name><uri>http://www.blogger.com/profile/15082577671795313109</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='30' height='32' src='http://3.bp.blogspot.com/-tmFOhJC48_E/TkQ0G2DxrqI/AAAAAAAAAz8/WVGBaaS5a_Y/s220/zdjecie2.png'/></author><thr:total>16</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5197374494377847819.post-2741605632231801858</id><published>2011-07-24T20:59:00.003+02:00</published><updated>2011-07-24T23:06:46.039+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Domain Driven Design'/><title type='text'>Domain Driven Design - prezentacja z konferencji Confitura 2011</title><content type='html'>Prezentacja jest już dostępna na &lt;a href="http://vimeo.com/26797989"&gt;Vimeo&lt;/a&gt;.&lt;br /&gt;Miejscami kod przykładów może być mało czytelny ale przyjrzeć im się można z bliska na &lt;a href="http://prezi.com/mwtwdw2i7q4h/domain-driven-design-a-place-for-everything-and-everything-in-its-place/"&gt;Prezi&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;//=========================================&lt;br /&gt;&lt;br /&gt;Przy okazji chciałbym podziękować wszystkim, którzy wyrazili swe opinie w ankiecie konferencyjnej. Jest to dla mnie najcenniejsze źródło informacji. Z 22 opinii tekstowych, 20 z nich odbieram jako bardzo ciepłe i przyjazne. Wasze słowa są na prawdę motywacją do tego aby następnym razem poświęcić jeszcze więcej czasu (po obejrzeniu video uznałem, że czas należy poświęcić również na kurs emisji głosu i dykcji oraz logopedę:)&lt;br /&gt;&lt;br /&gt;Cieszę się, że niektórym przypadło do gustu poczucie humoru - z uwagi na poprawność nie mogłem powiedzieć wszystkiego co miałem na myśli:)&lt;br /&gt;&lt;br /&gt;Jeszcze bardziej ciesze się z tego, że kilka osób zadeklarowało chęć zgłębiania tematu.&lt;br /&gt;&lt;br /&gt;Co do czasu trwania prezentacji, to temat jest na tyle obszerny, że podczas prezentacji można jedynie zasugerować odbiorcom kierunki do własnych dalszych poszukiwań. Stąd pojawiły się również tematy bardziej zaawansowane (potraktowane zdawkowo jako zajawki) aby skorzystali również uczestnicy znający temat główny.&lt;br /&gt;&lt;br /&gt;Pojawił się jeden zarzut co do użycia prezi. Moim zdaniem jest to narzędzie, które pozwala doskonale pokazywać ogół jak i szczegóły na zasadzie skalowania poziomu abstrakcji. W tym konkretnym przypadku zawiódł projektor, którego ubogi zakres barw nie pozwolił na wyświetlenie schematu warstw, co mogło być mylące.&lt;br /&gt;&lt;br /&gt;Na koniec pozdrowienia dla osoby, która uznała język prezentacji za "bardzo lakoniczny" a efekty za "przytłaczającą ilość wodotrysków" - no cóż... jestem tylko prostym programistą, który próbuje jakoś nieudolnie opowiadać o swoich doświadczeniach i przemyśleniach a braki językowe i retoryczne próbuje nadrabiać/tuszować wodotryskami;P&lt;br /&gt;&lt;br /&gt;Rozkład ocen prezentacji:&lt;br /&gt;5: 62&lt;br /&gt;4: 33&lt;br /&gt;3: 8&lt;br /&gt;2: 1&lt;br /&gt;1: 2&lt;br /&gt;Średnia: 4.43396226415094&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5197374494377847819-2741605632231801858?l=art-of-software.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://art-of-software.blogspot.com/feeds/2741605632231801858/comments/default' title='Komentarze do posta'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5197374494377847819&amp;postID=2741605632231801858' title='Komentarze (4)'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5197374494377847819/posts/default/2741605632231801858'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5197374494377847819/posts/default/2741605632231801858'/><link rel='alternate' type='text/html' href='http://art-of-software.blogspot.com/2011/07/domain-driven-design-prezentacja-z.html' title='Domain Driven Design - prezentacja z konferencji Confitura 2011'/><author><name>Sławek Sobótka</name><uri>http://www.blogger.com/profile/15082577671795313109</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='30' height='32' src='http://3.bp.blogspot.com/-tmFOhJC48_E/TkQ0G2DxrqI/AAAAAAAAAz8/WVGBaaS5a_Y/s220/zdjecie2.png'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5197374494377847819.post-206639543886781902</id><published>2011-07-15T13:47:00.003+02:00</published><updated>2011-07-18T09:48:22.338+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='CqRS'/><title type='text'>Fowler o CqRS</title><content type='html'>Koncepcja architektury CqRS doczekała się oficjalnego błogosławieństwa przez samego guru współczesnej inżynierii oprogramowania - &lt;a href="http://martinfowler.com/bliki/CQRS.html"&gt;Martina Fowlera&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;/*&lt;br /&gt;*Pamiętam jak jeszcze w kwietniu Greg Young opowiadał mi&lt;br /&gt;* o swojej pierwszej prezentacji na temat CqRS,&lt;br /&gt;* gdzie w pierwszych rzędach siedzieli: Uncle Bob, Eric Evans i Martin Fowler.&lt;br /&gt;* Po prezentacji Evans podszedł i powiedział:&lt;br /&gt;*bardzo słaba prezentacja, zrozumiałem tylko 30%:)&lt;br /&gt;*/&lt;br /&gt;&lt;br /&gt;Tak więc możemy uznać, że CqRS wchodzi do kanonu stylów architektonicznych - z zastrzeżeniem jednak co do zakresu stosowalności: okiełznanie chaosu w &lt;b&gt;złożonych częściach&lt;/b&gt; systemu i potrzeba skalowania. Czyli w sumie otrzymujemy pogodzenie dwóch skrajnych interesów: elegancki model (np. DDD) z wysoką wydajnością.&lt;br /&gt;"So while CQRS is a pattern I'd certainly want in my toolbox, I wouldn't keep it at the top."&lt;br /&gt;&lt;br /&gt;Warto zwrócić też uwagę, że Fowler wyraźnie rozróżnia CqRS, który jest stylem architektonicznym od Event Sourcingu, który jest jedną z możliwych technik persystencji. Z obserwacji mogę powiedzieć, że często jest to zbyt silnie utożsamiane, ale należy pamiętać, że zawsze można mieć jedną z tych rzeczy bez drugiej.&lt;br /&gt;&lt;br /&gt;Z ciekawych kontekstów, w których Event Sourcing zaczyna mieć sens oraz mocno się opłaca, jest wykorzystanie porcji zdarzeń jako wektorów uczących dla Sztucznych Sieci Neuronowych. Nie mówi się o tym zbyt wiele w mainstreamie, ale ES jest naturalną i od dawna stosowaną techniką w tych klasach systemów. Próba przeniesienia ES na systemy gdzie nie ma takich zastosowań na pewno się powiedzie, pytanie tylko jakim kosztem w stosunku do jakich zysków...?&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;//==========================================&lt;br /&gt;&lt;br /&gt;Wiele osób pyta o postępy w przygotowywaniu naszego DDD-CqRS Sampla w Javie.&lt;br /&gt;Pierwszy milestone zbliża się dużymi krokami. Mamy trzy małe konteksty domen z przykładami każdego Building Blocku. Stos biznesowy jest ilustrowany zarówno klasycznie serwisami jak i commandami, gdzie mamy kilka ciekawych technik takich jak asynchroniczność i filtrowanie duplikatów. Sagi docelowo będą działać na JMS. Stos prezentacji ilustruje kilka typowych optymalizacji odczytu.&lt;br /&gt;&lt;br /&gt;Chętnych, którzy chcieliby ocenić projekt przez jego upublicznieniem zapraszam do kontaktu.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5197374494377847819-206639543886781902?l=art-of-software.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://art-of-software.blogspot.com/feeds/206639543886781902/comments/default' title='Komentarze do posta'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5197374494377847819&amp;postID=206639543886781902' title='Komentarze (3)'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5197374494377847819/posts/default/206639543886781902'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5197374494377847819/posts/default/206639543886781902'/><link rel='alternate' type='text/html' href='http://art-of-software.blogspot.com/2011/07/fowler-o-cqrs.html' title='Fowler o CqRS'/><author><name>Sławek Sobótka</name><uri>http://www.blogger.com/profile/15082577671795313109</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='30' height='32' src='http://3.bp.blogspot.com/-tmFOhJC48_E/TkQ0G2DxrqI/AAAAAAAAAz8/WVGBaaS5a_Y/s220/zdjecie2.png'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5197374494377847819.post-411887783560241061</id><published>2011-07-04T20:57:00.007+02:00</published><updated>2011-08-17T10:34:04.154+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='artykuł'/><category scheme='http://www.blogger.com/atom/ns#' term='Domain Driven Design'/><title type='text'>Domain Driven Design - Sposób na projektowanie złożonych modeli biznesowych (plus niespodzianka)</title><content type='html'>W &lt;a href="http://sdjournal.pl/magazine/1747-nosql-nierelacyjne-systemy-baz-danych"&gt;ostatnim numerze&lt;/a&gt; Software Developer's Journal ukazał się artykuł mojego autorstwa: "Domain Driven Design - Sposób na projektowanie złożonych modeli biznesowych".&lt;br /&gt;&lt;br /&gt;Tekst przeznaczony jest zarówno dla początkujących jaki i średnio zaawansowanych praktyków DDD.&lt;br /&gt;Początkujący znajdą w nim:&lt;br /&gt;- ogólną ideę oraz zakres stosowalności podejścia&lt;br /&gt;- przykłady kodu&lt;br /&gt;a średnio zaawansowani mogą zapoznać się między innymi z:&lt;br /&gt;- technikami komunikacji zdarzeniowej pomiędzy Bounded Context&lt;br /&gt;- nową koncepcją Sagi biznesowej&lt;br /&gt;&lt;br /&gt;Zachęcam oczywiście do pobrania i przeczytania całego numeru SDJ, ale dla wygodnych link bezpośredni do tekstu: &lt;a href="http://bottega.com.pl/pdf/materialy/sdj-ddd.pdf" target="_blank"&gt;&lt;b&gt;pobierz&lt;/b&gt;&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Dla wzrokowców przydatna może być prezentacja ilustrująca architekturę systemu wykorzystującego DDD: &lt;a href="http://prezi.com/mwtwdw2i7q4h/domain-driven-design-a-place-for-everything-and-everything-in-its-place/"&gt;Domain Driven Design - A place for everything and everything in its place&lt;/a&gt;. tekst artykułu jest niejako narracją do tej prezentacji.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;//====================================&lt;br /&gt;&lt;br /&gt;Przy okazji zdradzę informację związaną z tematem posta. W firmie &lt;a href="http://bottega.com.pl/"&gt;Bottega&lt;/a&gt; pracujemy dla Was nad upublicznieniem projektu-sampla (wraz z dokumentacją) ilustrującego w realny i niestrywializowany sposób &lt;b&gt;wszystkie&lt;/b&gt; techniki DDD oraz kilka możliwych podejść do implementacji CqRS.&lt;br /&gt;&lt;br /&gt;Aktualnie dla środowiska Javy istnieją tylko 2 projekty oscylujące wokół tej tematyki (za: http://cqrsinfo.com/examples) a nasz będzie charakteryzował się:&lt;br /&gt;- prezentacją szerokiego wachlarzu technik DDD w różnych kontekstach&lt;br /&gt;- praktycznym rozwiązaniem typowych wyzwań i problemów projektowych&lt;br /&gt;- gotowym do użycia szkieletem: Spring, Maven, JPA, klienty webowe i zdalne (Android, Ajax)&lt;br /&gt;- kompletna wiki opisująca ideę oraz wyjaśniająca wszystkie szczegóły techniczne, podjęte decyzje projektowe i architektoniczne oraz omawiająca możliwości zmiany podejścia i jego rozbudowy&lt;br /&gt;- wsparciem dla testów integracyjnych oraz metodyki Behavior Driven Developemnt&lt;br /&gt;- wsparciem dla skalowania w środowisku cloud&lt;br /&gt;- racjonalnym podejściem do CqRS bez niepotrzebnego onanizmu technicznego&lt;br /&gt;- i co najważniejsze: &lt;b&gt;nie tworzymy kolejnego frameworka&lt;/b&gt;! Formą dystrybucji będzie "zaczyn" (zaczyn to coś z czego wyrasta chleb - ten prawdziwy:)&lt;br /&gt;To Ty jesteś architektem i decydujesz jak wygląda Twój kod!&lt;br /&gt;- sample będzie oczywiście całkowicie darmowy i otwarty&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5197374494377847819-411887783560241061?l=art-of-software.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://art-of-software.blogspot.com/feeds/411887783560241061/comments/default' title='Komentarze do posta'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5197374494377847819&amp;postID=411887783560241061' title='Komentarze (16)'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5197374494377847819/posts/default/411887783560241061'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5197374494377847819/posts/default/411887783560241061'/><link rel='alternate' type='text/html' href='http://art-of-software.blogspot.com/2011/07/domain-driven-design-wprowadzenie-i.html' title='Domain Driven Design - Sposób na projektowanie złożonych modeli biznesowych (plus niespodzianka)'/><author><name>Sławek Sobótka</name><uri>http://www.blogger.com/profile/15082577671795313109</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='30' height='32' src='http://3.bp.blogspot.com/-tmFOhJC48_E/TkQ0G2DxrqI/AAAAAAAAAz8/WVGBaaS5a_Y/s220/zdjecie2.png'/></author><thr:total>16</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5197374494377847819.post-2076413014817730507</id><published>2011-06-12T12:08:00.009+02:00</published><updated>2011-06-30T20:54:00.730+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='prezentacja'/><category scheme='http://www.blogger.com/atom/ns#' term='konferencja'/><title type='text'>Trawienie Confitury</title><content type='html'>Na parking dotarliśmy o 0850 po 2 godzinach podróżny na dystansie 170km (widocznie gdzieś po drodze nastąpiło lokalne zagięcie czasoprzestrzeni). Następnie udaliśmy się do punktu rejestracji na 3. piętrze...&lt;br /&gt;&lt;br /&gt;STOP!&lt;br /&gt;&lt;br /&gt;Przepraszam, zapomniałem, że blog to nie zeszyt do polskiego, a post to nie sprawozdanie z wycieczki do muzeum w 4. klasie podstawówki;P&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Na wstępie gratulacje i uznanie dla organizatorów za rozmach oraz podziękowania dla wolontariuszy.&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Chciałbym podzielić się przemyśleniami z kilku prezentacji:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://confitura.pl/presentations#36"&gt;&lt;b&gt;Pisz po pijaku, przeglądaj na trzeźwo&lt;/b&gt;&lt;/a&gt;&lt;br /&gt;Bezkompromisowa i nonkonformistyczna forma. Wspaniała interakcja z publicznością, bez puszenia się i pokazywania jaki to ja jestem mądry. Doskonałe zakończenie dnia.&lt;br /&gt;&lt;br /&gt;W momencie kiedy Piotr wniósł sześciopak piwa i żołądkową (bo poprzednicy rozdali wszystkie gadżety przeznaczone na nagrody dla uczestników) pomyślałem tylko: "wiedz, że coś się dzieje":)&lt;br /&gt;&lt;br /&gt;Na prezentacji mieliśmy błyskotliwą syntezę dwóch - popularnych ostatnio w "miękkim" IT - koncepcji:&lt;br /&gt;- Model mózgu składającego się z "procesorów" Rich i Linear&lt;br /&gt;- Model kompetencji Braci Dreyfus&lt;br /&gt;Synteza polegała na postawieniu tezy, że ekspert w danej dziedzinie (piąty poziom Dreyfus) myśli nad problemem głównie "procesorem" Rich.&lt;br /&gt;Nie wiem czy istnieją badania potwierdzające tą hipotezę, ale mnie się podoba, bo wydaje się brzmieć sensownie - póki co "kupuję to".&lt;br /&gt;To do czego dotarłem w literaturze tematu i co wiadomo na pewno, to fakt, że ekspert na pewno czasem (w twórczym uniesieniu) myśli mniej, jest to zjawisko tak zwanego "lśnienia" polegające na tym, że podczas małej aktywności mózgu (zużycie energii) dochodzi do wykonania dużej i przełomowej pracy intelektualnej. Zjawisko to można obserwować na rezonansach.&lt;br /&gt;&lt;br /&gt;Widziałem duże zainteresowanie publiczności, więc polecam materiały:&lt;br /&gt;- &lt;a href="http://www.amazon.com/Pragmatic-Thinking-Learning-Refactor-Programmers/dp/1934356050"&gt;Pragmatic Thinking and Learning: Refactor Your Wetware&lt;/a&gt; - dowiecie się z niej na temat modelu R/L oraz kilkunastu innych arcyciekawych i przydatnych w życiu sprawach. Autor dokonał syntezy wieli zagadnień z psychologii, socjologii, kognitywistyki podając je na tacy tak abyśmy nie musieli już sami szukać. Najlepsza książka jaką czytałem w zeszłym roku. Książki pisane przez programistów zawsze są dobre...&lt;br /&gt;- &lt;a href="http://www.infoq.com/presentations/Developing-Expertise-Dave-Thomas"&gt;Developing Expertise: Herding Racehorses, Racing Sheep&lt;/a&gt; - prezentacja na temat Dreyfus.&lt;br /&gt;Materiał z kategorii "musisz zobaczyć".&lt;br /&gt;- &lt;a href="http://art-of-software.blogspot.com/2010/01/wspinaczka-do-profesjonalizmu.html"&gt;Wspinaczka do profesjonalizmu&lt;/a&gt; - artykuł na temat Dreyfus, który popełniłem w zeszłym roku dla &lt;a href="http://sdjournal.pl"&gt;Software Developer's Journal&lt;/a&gt;.&lt;br /&gt;Miło było usłyszeć na prezentacji kilka odniesień do tekstu:)&lt;br /&gt;&lt;br /&gt;Wracając do prezentacji Piotra, warto zapamiętać dwie rady praktyczne - techniki na uruchamianie Rich "procesora":&lt;br /&gt;- odwracanie problemu: jeżeli nie wiemy jak zoptymalizować kod, to może zastanówmy się jak go spowolnić; jeżeli nie wiemy jak zaprojektować ergonomiczne GUI, to zastanówmy się jak zaprojektować je w sposób ultra-autystyczny.&lt;br /&gt;Dlaczego to działa? Odsyłam do książki "Pragmatic Thinking and Learning" a później dalej...&lt;br /&gt;- pair programming: niewiele osób uświadamia sobie, co się dzieje podczas programowania w parach. Mianowicie driver programując (czyli myśląc symbolicznie) pracuje na swoim "linearnym procesorze" a pilot zwolniony z tych czynności może uruchomić "procesor rich" i dokonywać myślenia syntetycznego na zasadzie nieświadomego pattern matching.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://confitura.pl/presentations#25"&gt;&lt;b&gt;Play!Framework - ewolucja w świecie aplikacji webowych&lt;/b&gt;&lt;/a&gt;&lt;br /&gt;Można opowiedzieć o frameworku webowym w sensowny i poukładany sposób tak aby było od razu wiadomo o co chodzi i kiedy oraz do czego mogę go użyć?&lt;br /&gt;Można!&lt;br /&gt;Brawa dla Wojtka. Konkretnie, na temat, dobrze dobrane przykłady kodu, dobre rysunki, szeroki zakres wiedzy i wszystko w 45 min! Wyszło lepiej niż filmiki na oficjalnej stronie frameworka.&lt;br /&gt;Szczerze mówiąc to zacząłem rozważać Play jako narzędzie do pewnych klas problemów. Dzięki Wojtek. &lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Warto zwrócić uwagę na &lt;a href="http://blog.erbetowski.pl/index.php/2011/06/confitura-presentation/"&gt;prezentację&lt;/a&gt; jako wzór do naśladowania:&lt;br /&gt;- kod na Youtube z komentarzem na żywo prowadzącego (na pewno się nie wywali i nie będziemy tracić czasu na słuchanie nieśmiesznych tłumaczeń, że na prezentacji nigdy nie działa)&lt;br /&gt;- szeroki wachlarz tematów do omówienia do wyboru wg zainteresowania słuchaczy (z uwagi ograniczony czas prezentacji).&lt;br /&gt;&lt;br /&gt;Jeszcze raz brawo.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://confitura.pl/presentations#59"&gt;&lt;b&gt;Quo Vadis IT&lt;/b&gt;&lt;/a&gt;&lt;br /&gt;Pana Tomasza pamiętam jeszcze z zamierzchłych czasów studenckich, gdy przyjeżdżał na nasze rodzime uczelnie i priczował na temat technologii Microsoftu. Dałem się wówczas uwieść - ale tylko na chwilę:)&lt;br /&gt;&lt;br /&gt;Prezentacja bardzo ciekawa, z uwagi na tematykę. Spojrzenie na branżę IT z wysokości 10km, co pozwala zauważyć powtarzające się w czasie patterny.&lt;br /&gt;&lt;br /&gt;Widać było też na jakim poziomie i jak wnikliwie MS analizuje potrzeby oraz nawyki Userów (prywatnie i w pracy) oraz jak dobrze rozumie przemiany społeczne i mentalne zachodzące w czasie.&lt;br /&gt;&lt;br /&gt;Miazga. My robaczki siedzimy sobie i męczymy się z kodzikiem, podczas gdy wysoko ponad naszymi głowami ktoś obserwuje i planuje rzeczywistość na kilkanaście lat do przodu.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://confitura.pl/presentations#39"&gt;&lt;b&gt;Re-fuck-toryzacja czyli sprowadzanie sp****go kodu na właściwe tory&lt;/b&gt;&lt;/a&gt;&lt;br /&gt;Paweł - dzięki za odniesienie do posta na temat &lt;a href="http://art-of-software.blogspot.com/2011/06/sposoby-enkapsulowania-zozonej-logiki.html"&gt;radzenia sobie ze złożonością&lt;/a&gt;.&lt;br /&gt;Muszę jednak zwrócić uwagę, że to co wyszło podczas refaktoryzacji to nie była Strategia a raczej zmodyfikowany Chain of Responsibility. Zmodyfikowany w taki sposób, że każde ogniowo łańcucha odpowiadało na pytanie "czy umiesz zająć się problemem", a jeżeli tak to "zajmij się". Czasem stosuję takie konstrukcję - łańcuch zarządzany przez "managera" - zębatkę.&lt;br /&gt;&lt;br /&gt;Taka "zębatka" może być sama w sobie implementacją interfejsu strategii. Czyli mamy złożenie 2 patternów: strategia na wyższym poziomie (wariacje rozwiązania dużego problemu), a jedną z implementacji strategii może być taka zębatka zarządzająca łańcuchem małych ogniw, które coś tam sobie liczą (mikro problemiki wchodzące w skład jednego z wariantu rozwiązań problemów wyższego rzędu).&lt;br /&gt;&lt;br /&gt;Teledysk na koniec - rotfl. Dobre zdjęcia, ładny dom:)&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Co do mojej prezentacji, to jak zwykle: trema, przez którą wychodzi inaczej niż się planowało. Gadzi mózg podpowiada, że jeżeli stoisz sam bez broni i bez schronienia przed liczną grupą jakiś osobników to najpewniej za chwilę zginiesz. Ehh instynkt.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;//=======================================&lt;br /&gt;&lt;br /&gt;Przy okazji podzielę się jednak ciekawą obserwacją odnośnie psycho-akustyki (którą ostatnimi czasy nieco się interesuję). Z uwagi na wielkość sali, konstrukcję ścian, siłę oraz ustawienia nagłośnienia (i kilkanaście innych niesprzyjających uwarunkowań pomieszczenia) pojawił się efekt echa. Nie &lt;a href="http://pl.wikipedia.org/wiki/Pogłos"&gt;pogłosu&lt;/a&gt;, który jest do zniesienia a &lt;a href="http://pl.wikipedia.org/wiki/Echo"&gt;echa&lt;/a&gt;, które jest dla mówiącej osoby zabójcze.&lt;br /&gt;&lt;br /&gt;Jako, że jestem tak zwanym słuchowcem (nie jest to takie proste, ale przyjmijmy na potrzeby posta, że jest coś takiego jak słuchowcy) to taki efekt nie jest tylko drażniący. U mnie niemal uniemożliwia mówienie. Przez chwilę myślałem, że się rozpłaczę ucieknę ze sceny hehehe.&lt;br /&gt;&lt;br /&gt;Nie wiem czy ktoś włączył tłumienie fal obitych, ale nie widziałem nikogo majstrującego przy wzmacniaczach. Jednak po kilku minutach efekt echa zniknął. Ehh mózg ma niesamowitą zdolność do kompensowanie bodźców. A to co słyszymy jest tylko tym co nam się wydaje:)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5197374494377847819-2076413014817730507?l=art-of-software.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://art-of-software.blogspot.com/feeds/2076413014817730507/comments/default' title='Komentarze do posta'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5197374494377847819&amp;postID=2076413014817730507' title='Komentarze (13)'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5197374494377847819/posts/default/2076413014817730507'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5197374494377847819/posts/default/2076413014817730507'/><link rel='alternate' type='text/html' href='http://art-of-software.blogspot.com/2011/06/trawienie-confitury.html' title='Trawienie Confitury'/><author><name>Sławek Sobótka</name><uri>http://www.blogger.com/profile/15082577671795313109</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='30' height='32' src='http://3.bp.blogspot.com/-tmFOhJC48_E/TkQ0G2DxrqI/AAAAAAAAAz8/WVGBaaS5a_Y/s220/zdjecie2.png'/></author><thr:total>13</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5197374494377847819.post-5818828774747722880</id><published>2011-06-08T21:46:00.002+02:00</published><updated>2011-06-08T22:05:36.194+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Domain Driven Design'/><title type='text'>Degustacja Confitury</title><content type='html'>&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/-V8SvXZMyuWQ/TebHZ0VCiZI/AAAAAAAAAxI/g68KXf7oyBQ/s1600/degustacja3.jpg" imageanchor="1" style="margin-left:1em; margin-right:1em"&gt;&lt;img border="0" height="320" width="240" src="http://2.bp.blogspot.com/-V8SvXZMyuWQ/TebHZ0VCiZI/AAAAAAAAAxI/g68KXf7oyBQ/s320/degustacja3.jpg" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;a href="http://confitura.pl/"&gt;Confitura&lt;/a&gt; odbędzie się 11 czerwca ale już dziś możecie sprawdzić czy warto przyjść na jedną z prezentacji.&lt;br /&gt;&lt;br /&gt;Abstrakt: &lt;a href="http://confitura.pl/presentations#30"&gt;Domain Driven Design - Wszystko ma swoje miejsce i wszystko jest na miejscu&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;div class="prezi-player"&gt;&lt;style type="text/css" media="screen"&gt;.prezi-player { width: 500px; } .prezi-player-links { text-align: center; }&lt;/style&gt;&lt;object id="prezi_mwtwdw2i7q4h" name="prezi_mwtwdw2i7q4h" classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" width="500" height="400"&gt;&lt;param name="movie" value="http://prezi.com/bin/preziloader.swf"/&gt;&lt;param name="allowfullscreen" value="true"/&gt;&lt;param name="allowscriptaccess" value="always"/&gt;&lt;param name="bgcolor" value="#ffffff"/&gt;&lt;param name="flashvars" value="prezi_id=mwtwdw2i7q4h&amp;amp;lock_to_path=0&amp;amp;color=ffffff&amp;amp;autoplay=no&amp;amp;autohide_ctrls=0"/&gt;&lt;embed id="preziEmbed_mwtwdw2i7q4h" name="preziEmbed_mwtwdw2i7q4h" src="http://prezi.com/bin/preziloader.swf" type="application/x-shockwave-flash" allowfullscreen="true" allowscriptaccess="always" width="500" height="400" bgcolor="#ffffff" flashvars="prezi_id=mwtwdw2i7q4h&amp;amp;lock_to_path=0&amp;amp;color=ffffff&amp;amp;autoplay=no&amp;amp;autohide_ctrls=0"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;div class="prezi-player-links"&gt;&lt;p&gt;&lt;a title="CqRS, Domain Driven Design, Event Sourcing, etc" href="http://prezi.com/mwtwdw2i7q4h/domain-driven-design-a-place-for-everything-and-everything-in-its-place/"&gt;Domain Driven Design - A place for everything and everything in its place&lt;/a&gt; on &lt;a href="http://prezi.com"&gt;Prezi&lt;/a&gt;&lt;/p&gt;&lt;/div&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;//==============================&lt;br /&gt;&lt;br /&gt;W branży można spotkać się z dwoma podejściami do prezentacji:&lt;br /&gt;- niespodzianka&lt;br /&gt;- możliwość obejrzenia wcześniej&lt;br /&gt;&lt;br /&gt;Ja preferuję drugie podejście z tego samego względu, dla którego sprawdzam dema gier, czytam wyrywki tekstu z książek w księgarni oraz sprawdzam recenzje filmów - po prostu oszczędność czasu:)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5197374494377847819-5818828774747722880?l=art-of-software.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://art-of-software.blogspot.com/feeds/5818828774747722880/comments/default' title='Komentarze do posta'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5197374494377847819&amp;postID=5818828774747722880' title='Komentarze (2)'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5197374494377847819/posts/default/5818828774747722880'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5197374494377847819/posts/default/5818828774747722880'/><link rel='alternate' type='text/html' href='http://art-of-software.blogspot.com/2011/06/degustacja-confitury.html' title='Degustacja Confitury'/><author><name>Sławek Sobótka</name><uri>http://www.blogger.com/profile/15082577671795313109</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='30' height='32' src='http://3.bp.blogspot.com/-tmFOhJC48_E/TkQ0G2DxrqI/AAAAAAAAAz8/WVGBaaS5a_Y/s220/zdjecie2.png'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/-V8SvXZMyuWQ/TebHZ0VCiZI/AAAAAAAAAxI/g68KXf7oyBQ/s72-c/degustacja3.jpg' height='72' width='72'/><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5197374494377847819.post-1723279634510093556</id><published>2011-06-07T11:26:00.001+02:00</published><updated>2011-06-07T14:00:24.116+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Homo sum...'/><category scheme='http://www.blogger.com/atom/ns#' term='z dystansu'/><title type='text'>Zawiązywanie sznurowadeł - robisz to źle</title><content type='html'>&lt;!--copy and paste--&gt;&lt;object width="334" height="326"&gt;&lt;param name="movie" value="http://video.ted.com/assets/player/swf/EmbedPlayer.swf"&gt;&lt;/param&gt;&lt;param name="allowFullScreen" value="true" /&gt;&lt;param name="allowScriptAccess" value="always"/&gt;&lt;param name="wmode" value="transparent"&gt;&lt;/param&gt;&lt;param name="bgColor" value="#ffffff"&gt;&lt;/param&gt;&lt;param name="flashvars" value="vu=http://video.ted.com/talk/stream/2005/Blank/TerryMoore_2005-320k.mp4&amp;su=http://images.ted.com/images/ted/tedindex/embed-posters/TerryMoore-2005.embed_thumbnail.jpg&amp;vw=320&amp;vh=240&amp;ap=0&amp;ti=1150&amp;lang=eng&amp;introDuration=15330&amp;adDuration=4000&amp;postAdDuration=830&amp;adKeys=talk=terry_moore_how_to_tie_your_shoes;year=2005;theme=ted_in_3_minutes;theme=new_on_ted_com;theme=hidden_gems;event=TED2005;tag=Culture;tag=Entertainment;tag=demo;&amp;preAdTag=tconf.ted/embed;tile=1;sz=512x288;" /&gt;&lt;embed src="http://video.ted.com/assets/player/swf/EmbedPlayer.swf" pluginspace="http://www.macromedia.com/go/getflashplayer" type="application/x-shockwave-flash" wmode="transparent" bgColor="#ffffff" width="334" height="326" allowFullScreen="true" allowScriptAccess="always" flashvars="vu=http://video.ted.com/talk/stream/2005/Blank/TerryMoore_2005-320k.mp4&amp;su=http://images.ted.com/images/ted/tedindex/embed-posters/TerryMoore-2005.embed_thumbnail.jpg&amp;vw=320&amp;vh=240&amp;ap=0&amp;ti=1150&amp;lang=eng&amp;introDuration=15330&amp;adDuration=4000&amp;postAdDuration=830&amp;adKeys=talk=terry_moore_how_to_tie_your_shoes;year=2005;theme=ted_in_3_minutes;theme=new_on_ted_com;theme=hidden_gems;event=TED2005;tag=Culture;tag=Entertainment;tag=demo;"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;br /&gt;&lt;br /&gt;...sprawdź i przekonaj się, video trwa tylko 3 minuty:)&lt;br /&gt;&lt;br /&gt;Zweryfikowałem wczoraj na butach biegowych z wyślizganymi od użytkowania sznurowadłami. Działa!&lt;br /&gt;&lt;br /&gt;TED jak zwykle "uczy i bawi".&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;//==============================&lt;br /&gt;&lt;br /&gt;Swoją drogą ciekawe ile jeszcze takich oczywistych oczywistości robimy nie do końca dobrze...&lt;br /&gt;&lt;br /&gt;"live long and prosper":)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5197374494377847819-1723279634510093556?l=art-of-software.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://art-of-software.blogspot.com/feeds/1723279634510093556/comments/default' title='Komentarze do posta'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5197374494377847819&amp;postID=1723279634510093556' title='Komentarze (5)'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5197374494377847819/posts/default/1723279634510093556'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5197374494377847819/posts/default/1723279634510093556'/><link rel='alternate' type='text/html' href='http://art-of-software.blogspot.com/2011/06/zawiazywanie-sznurowade-robisz-to-zle.html' title='Zawiązywanie sznurowadeł - robisz to źle'/><author><name>Sławek Sobótka</name><uri>http://www.blogger.com/profile/15082577671795313109</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='30' height='32' src='http://3.bp.blogspot.com/-tmFOhJC48_E/TkQ0G2DxrqI/AAAAAAAAAz8/WVGBaaS5a_Y/s220/zdjecie2.png'/></author><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5197374494377847819.post-3664640715766689775</id><published>2011-06-06T19:34:00.019+02:00</published><updated>2011-06-06T23:53:02.904+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Homo sum...'/><title type='text'>Rekrutacja</title><content type='html'>Temat zadań rekrutacyjnych dla developerów przewija się w branży co jakiś czas. Ostatnio znowu odżył ze względu na odbicie do tak zwanego kryzysu.&lt;br /&gt;&lt;br /&gt;Post jest głosem w dyskusji, jaka toczy się na grupie &lt;a href="http://groups.google.com/group/warszawa-jug"&gt;Warszawa JUG&lt;/a&gt;, którą to czytam namiętnie ze względu na spektrum tematów oraz aktywność członków.&lt;br /&gt;&lt;br /&gt;Dyskusja zaczęła od pytania o słuszność lub nie wymagania wiedzy na temat sortowania kolekcji obiektów w Javie. Chodzi o użycie biblioteki standardowej/trzeciej a nie o implementację od zera sortowania bąbelkowego (bo i o takich kuriozach się słyszy).&lt;br /&gt;&lt;br /&gt;Wydaje mi się, że dyskutowanie nad treścią zadań bez określenia kontekstu to podchodzenie do problemu od złej strony.&lt;br /&gt;&lt;br /&gt;Zaczynając rekrutację musisz odpowiedzieć sobie na kilka pytań: &lt;b&gt;kogo poszukuję, do jakich klas problemów, do jakich typów zdań, z kim ma pracować i jakie są plany na przyszłość (co do tej osoby, co do całego teamu)&lt;/b&gt;.&lt;br /&gt;&lt;br /&gt;Pracując w różnych firmach jako lider techniczny zajmowałem się między innymi rekrutowaniem pracowników. Straciłem rachubę, ale w sumie przewinęło się ok 100 osób. Pamiętam jakie błędy robiłem, głównie na poziomie założeń. Teraz pomagam klientom znajdować odpowiednich ludzi na określone stanowiska. &lt;br /&gt;&lt;br /&gt;Inny skillset będzie potrzeby dla kogoś kto dodaje ficzery biznesowe a inny dla kogoś kto rozwiązuje łamigłówki na poziomie optymalizacji lub algorytmicznym. Inny dla kogoś kto projektuje systemy/frameworki a inny dla kogoś kto implementuje aplikacje. Inny dla kogoś kto implementuje sexi gui a inny dla kogoś, kto modeluje złożone domeny biznesowe. Inny dla kogoś kto kreuje kierunek dla nowych projektów a inny dla kogoś, kto utrzymuje legacy.&lt;br /&gt;&lt;br /&gt;Na skillset składa się wiele wymiarów - znajomość języków i technologii to tylko jeden z nich. Czasem wystarczający a czasem nie (czasem pomijalny?). Temat jest generalnie bardzo szeroki i wchodzi głęboko w psychologię - np. typy osobowości, z których wynikają sposoby myślenia, predyspozycje, słabe i mocne strony. Generalnie nie ma ludzi perfekcyjnych, każdy ma słabe strony, chodzi o to aby "w boju nie wystawiać tych miękkich części na ciosy" - po prostu dobierać ludzi do zadań/wyzwań&lt;br /&gt;Ale to wymaga też &lt;b&gt;zrozumienia wyzwań&lt;/b&gt; jakie pojawią się w projekcie oraz zrozumienia cech jakie lepiej lub gorzej predysponują śmiałka do podjęcia wyzwania:)&lt;br /&gt;&lt;br /&gt;Strategia dla teamu jest prosta: wzajemne uzupełnianie się cech - a z tego gratisowo dostajemy efekty synergiczne:)&lt;br /&gt;Podstawowym narzędziem może być model &lt;a href="http://pl.wikipedia.org/wiki/Meredith_Belbin"&gt;Belbina&lt;/a&gt; - ale to dopiero początek układanki.&lt;br /&gt;&lt;br /&gt;Ignorowanie aspektów miękkich i kompletowanie zespołu na zasadzie: "dawać mnie tu sześciopak programistów" sprawdzi się owszem w niektórych przypadkach. W rekrutacji do projektów Komisji Europejskiej w Luksemburgu jednak już nie zadziała...&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/-nKBOKYFxNQA/Te0O7r8ARWI/AAAAAAAAAxU/E2N8MLe6yxE/s1600/szesciopak.jpg" imageanchor="1" style="margin-left:1em; margin-right:1em"&gt;&lt;img border="0" height="320" width="246" src="http://2.bp.blogspot.com/-nKBOKYFxNQA/Te0O7r8ARWI/AAAAAAAAAxU/E2N8MLe6yxE/s320/szesciopak.jpg" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;Wracając do zadania z sortowaniem kolekcji przez bibliotekę standardową... Zastanówmy się co ono sprawdza. Na pewno to czy ktoś już tego używał, czyli czy otarł się o &lt;b&gt;ogólne programowanie&lt;/b&gt; w Javie (i ew. proste wykorzystanie w algorytmach). Oczywiście kandydat mógł nie mieć do tej pory okazji sortowania niczego - zdarza się.&lt;br /&gt;&lt;br /&gt;Skoro tak, to nie miał tez okazji przeczytania &lt;b&gt;żadnej książki&lt;/b&gt; poświęconej programowaniu w Javie. Po prostu nie da się nie trafić na sort. Prawdopodobnie ilość artykułów jakie pochłonął jest niewielka (tak elementarna rzecz jak sortowanie pojawia się z prozaicznej konieczności nawet w zaawansowanych tekstach).&lt;br /&gt;&lt;br /&gt;Jaki wniosek możemy wysnuć na tej podstawie... hmmm... ja się wstrzymam z wnioskowaniem, czekam na propozycje w komentarzach. Nie zakładałbym jednak, że zawsze poszukujemy kogoś, kto "traci czas" na czytanie książek...&lt;br /&gt;&lt;br /&gt;Ale na pewno jeżeli kandydat nie potrafi podać odpowiedzi, warto sprawdzić w jaki sposób ją zdobędzie i na ile ją zrozumie.&lt;br /&gt;&lt;br /&gt;//==============================&lt;br /&gt;&lt;br /&gt;Co do zadań ogólno-programistycznych to wdzięcznym tematem jest napisanie utilsa obliczającego pole prostokąta. Tak utilsa, statyczną metodę, beż żadnych Object Oriented, w przestrzeni Euklidesowej, zwykłe a * b.&lt;br /&gt;&lt;br /&gt;Co sprawdzimy? Coś co można określić stylem.&lt;br /&gt;1. nazwy parametrów - od czego zależy dobór? a,b czy może x,y albo width,height? szczegół? tak, ale jednak...&lt;br /&gt;2. dobór typów. kiedy własne typy? co z jednostkami? wynik jest w kwadracie - jakie operacje są na nim dozwolone później? czy jest to problem naszego utilsa? szeroki temat do dyskusji...&lt;br /&gt;3. sprawdzanie wartości wejściowych - sprawdzać czy nie, od czego to zależy?&lt;br /&gt;4. nazwy, nazwy, nazwy&lt;br /&gt;5. jakie wyjątki? dlaczego?&lt;br /&gt;6. komentarze. a może nie ma takiej potrzeby? dlaczego?&lt;br /&gt;7. testy! a może nie;P dlaczego?&lt;br /&gt;&lt;br /&gt;Nikt nie zarzuci wymogu znajomości bibliotek (ew. junit/testng), egzotycznych algorytmów, wyrafinowanej składni, fizyki kwantowej. Wzoru na pole prostokąta jednak bym nie podawał w treści zadania;)&lt;br /&gt;&lt;br /&gt;Tego typu zadanie oczywiście nie zaważy na przyjęciu/odrzuceniu kandydatury na stanowiska develoepra aplikacji postawionych na stosie 10 frameworków, ale potencjalnie może wskazać wygodne dla kandydata miejsce.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5197374494377847819-3664640715766689775?l=art-of-software.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://art-of-software.blogspot.com/feeds/3664640715766689775/comments/default' title='Komentarze do posta'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5197374494377847819&amp;postID=3664640715766689775' title='Komentarze (8)'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5197374494377847819/posts/default/3664640715766689775'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5197374494377847819/posts/default/3664640715766689775'/><link rel='alternate' type='text/html' href='http://art-of-software.blogspot.com/2011/06/rekrutacja.html' title='Rekrutacja'/><author><name>Sławek Sobótka</name><uri>http://www.blogger.com/profile/15082577671795313109</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='30' height='32' src='http://3.bp.blogspot.com/-tmFOhJC48_E/TkQ0G2DxrqI/AAAAAAAAAz8/WVGBaaS5a_Y/s220/zdjecie2.png'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/-nKBOKYFxNQA/Te0O7r8ARWI/AAAAAAAAAxU/E2N8MLe6yxE/s72-c/szesciopak.jpg' height='72' width='72'/><thr:total>8</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5197374494377847819.post-3608045657360634624</id><published>2011-06-05T15:13:00.000+02:00</published><updated>2011-06-05T15:13:52.917+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='z dystansu'/><title type='text'>Obraz konkurencji</title><content type='html'>Osobiście nie miałem nigdy okazji pracować z developerami z Indii, ale z opowieści wielu znajomych z branży wnioskuję, że jest to ciekawa przygoda...&lt;br /&gt;&lt;br /&gt;Natrafiłem dziś na artykuł, którego autor zdaje się znać sytuację od podszewki: &lt;a href="http://www.racjonalista.pl/kk.php/s,1856"&gt;Guru i trzej idioci&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;//=====================&lt;br /&gt;&lt;br /&gt;Tekst można polecić również tym, którzy narzekają na polski system edukacji:)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5197374494377847819-3608045657360634624?l=art-of-software.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://art-of-software.blogspot.com/feeds/3608045657360634624/comments/default' title='Komentarze do posta'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5197374494377847819&amp;postID=3608045657360634624' title='Komentarze (2)'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5197374494377847819/posts/default/3608045657360634624'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5197374494377847819/posts/default/3608045657360634624'/><link rel='alternate' type='text/html' href='http://art-of-software.blogspot.com/2011/06/obraz-konkurencji.html' title='Obraz konkurencji'/><author><name>Sławek Sobótka</name><uri>http://www.blogger.com/profile/15082577671795313109</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='30' height='32' src='http://3.bp.blogspot.com/-tmFOhJC48_E/TkQ0G2DxrqI/AAAAAAAAAz8/WVGBaaS5a_Y/s220/zdjecie2.png'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5197374494377847819.post-1118256749070274245</id><published>2011-06-01T14:38:00.019+02:00</published><updated>2011-06-02T01:59:29.123+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Domain Driven Design'/><category scheme='http://www.blogger.com/atom/ns#' term='wzorce projektowe'/><category scheme='http://www.blogger.com/atom/ns#' term='OOD'/><title type='text'>Sposoby enkapsulowania złożonej logiki biznesowej</title><content type='html'>W ostatnim &lt;a href="http://art-of-software.blogspot.com/2011/06/koszt-dostawy.html"&gt;poście&lt;/a&gt; poruszyłem pewne podstawowe zagadnienia z zakresu projektowania obiektowego, ale jak słusznie zauważyli komentatorzy przykład jest na tyle trywialny, że narzucające się proste rozwiązania są w zupełności wystarczające.&lt;br /&gt;&lt;br /&gt;Podejdziemy do problemu raz jeszcze, tym razem w bardziej realistycznym kontekście aplikacji biznesowej.&lt;br /&gt;&lt;br /&gt;Mamy zatem ten nieszczęsny OrderItem - nieszczęsny, ponieważ przykład pochodzi z książki, którą ostatnio &lt;a href="http://art-of-software.blogspot.com/2011/05/przemyslane-praktyki-java-ee.html"&gt;recenzowałem&lt;/a&gt;. Klasyczny model zamówienia: Order-OrderItem-Product&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;W książkowym przykładzie OrderItem jest obiektem domenowym (rich model) i posiada oprócz stanu również zachowanie - odpowiedzialności biznesowe. Autor książki nawiązuje do Domain Driven Design, dlatego będę się posługiwał Building Blockami modelowania DDD.&lt;br /&gt;&lt;br /&gt;Nasz OrderItem zawiera metodę getShippingCost(), która nie jest getterem a metodą biznesową - oblicza koszt dostawy danej pozycji na zamówieniu.&lt;br /&gt;&lt;br /&gt;Sugerowana w książce rozbudowa modelu to dodanie nowych klas dziedziczących po OrderItem, które zmieniają sposób liczenia kosztu. Problemy z tym podejściem opisałem w poprzednim poście, w skrócie: w takim obiekcie biznesowym mamy wiele odpowiedzialności, więc prowadzanie dziedziczenia aby zmienić jedną z nich szybko doprowadzi do eksplozji kombinatorycznej bytów.&lt;br /&gt;&lt;br /&gt;&amp;lt;dygresja&gt;&lt;br /&gt;Zacznijmy od tego, czy w ogólne taka metoda powinna należeć do tej klasy? W rzeczywistym systemie obliczenie kosztów dostawy zależy zapewne od wielu czynników - nie tylko od zamawianego produktu, ale również od tego kim jest klient, od miejsca dostawy, od reszty zamówienia itd.&lt;br /&gt;Być może cała wiedza znajduje się w klasie OrderItem... Być może wyżej - w Order... Być może nie... wówczas należy wynieść cały problem do osobnego SerwisuBiznesowego (&lt;a href="http://en.wikipedia.org/wiki/Domain-driven_design#Building_blocks_of_DDD"&gt;BuildingBlock&lt;/a&gt; modelowania DDD).&lt;br /&gt;&lt;br /&gt;Nawet jeżeli dziś cała wiedza znajduje się w OrderItem czy nawet w Order, ale w przyszłości zmienią się wymagania i będziemy musieli implementować dziwne akrobacje aby w OrderItem/Order zdobyć potrzebne do obliczeń obiekty.&lt;br /&gt;&lt;br /&gt;Generalnie serwis rokuje na lepszy design modelu (serwis biznesowy jest częścią modelu w DDD). W DDD nie chodzi o to aby całą logikę rozsmarować po encjach/agregatach/vo. Nic podobnego. Prosta reguła "kciuka" dla początkujących może być taka: encje/agregaty/vo posiadają metody używane wielokrotnie. Specyficzne metody używane jeden raz znajdują się w specyficznych serwisach biznesowych&lt;br /&gt;&lt;br /&gt;Jednak te rozważania nie mają wpływu na dalszą część posta. Abstrahując od tego, którym miejscu umieścimy odpowiedzialność obliczeń wciąż możemy stosować techniki opisane poniżej.&lt;br /&gt;&lt;br /&gt;W dalszej części, dla uproszczenia, zakładamy, że większość potrzebnej wiedzy znajduje się w OrderItem.&lt;br /&gt;&amp;lt;/dygresja&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;W realnej aplikacji obliczenie kosztu dostawy:&lt;br /&gt;- zależy od wielu czynników (rodzaj produktu, klient i jego rabaty, miejsce docelowe, składowe zamówienia, historia zamówień itd)&lt;br /&gt;- jest złożone (załóżmy kilkanaście-kilkaset linijek kodu)&lt;br /&gt;&lt;br /&gt;Ta więc rozważania z poprzedniego posta (i komentarzy) gdzie proponowaliśmy switche albo Mapy strtegii się nie aplikują.&lt;br /&gt;&lt;br /&gt;Przy standardowym podejściu kod będzie wyglądał mniej więcej tak:&lt;br /&gt;&lt;br /&gt;&lt;div&gt;&lt;pre class="brush: java"&gt;class OrderItem{&lt;br /&gt;  Money getShippingCost(){&lt;br /&gt;    if if if if if&lt;br /&gt;      //17 liniek obliczen&lt;br /&gt;    if if if if&lt;br /&gt;      //50 liniek obliczen z ifami&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;... i wcale nie spodziewajmy się "eleganckiego" switcha, który załatwia sprawę. Mamy tutaj do czynienia z potworkiem rzędu setek linijek, brak ustalenia jednego poziomu abstrakcji, nieustanne skoki mentalne po różnych poziomach oraz potencjał na to, że biznes będzie się komplikował i z czasem wyhodujemy ośmiotysięcznika.&lt;br /&gt;&lt;br /&gt;Generalnie przy standardowym podejściu kodzik będzie przeplatał w sobie 3 rodzaje odpowiedzialności:&lt;br /&gt;1. zdecydowanie który scenariusz/algorytm obliczania kosztu zastosować&lt;br /&gt;2. sam algorytm&lt;br /&gt;3. ew. pozyskanie dostępu do danych potrzebnych do obliczeń&lt;br /&gt;&lt;br /&gt;Czyli w jednym miejscu mamy 3 rodzaje zależności, o których pisze &lt;a href="http://misko.hevery.com/2008/08/21/where-have-all-the-singletons-gone/"&gt;Misko Hevery&lt;/a&gt;.&lt;br /&gt;- colaboration&lt;br /&gt;- construction&lt;br /&gt;- call&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Aby uniknąć tego poziomu smutnej złożoności, proponowane w poprzednim poście rozwiązanie (czwarte) sugeruje aby:&lt;br /&gt;1. odseparować samą logikę obliczenia kosztu od reszty kodu.&lt;br /&gt;Wprowadzamy interfejs Strategii, np&lt;br /&gt;&lt;br /&gt;&lt;div&gt;&lt;pre class="brush: java"&gt;interface ShippingCostCalculator{&lt;br /&gt;  Money calculateCost(...);&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;2. kawałki kodu stanowiące każdy z algorytmów pakujemy do osobnej klasy implementującej ten interfejs, np ForeginShippingCostCalculator, LargeItemShippingCostCalculator&lt;br /&gt;&lt;br /&gt;2.a co jeżeli wysyłamy duży przedmiot za granicę? tworzymy trzecią klasę ForeginLargeItemShippingCostCalculator? Nie! Z pomocą przychodzi Decorator Design Pattern.&lt;br /&gt;&lt;br /&gt;&lt;div&gt;&lt;pre class="brush: java"&gt;ShippingCostCalculator calculator = new ForeginShippingCostCalculator(new LargrItemShippingCostCalculator());&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;3. kawałki logiki wybierającej, którą konkretną politykę stworzyć chowamy w Fabryce.&lt;br /&gt;I nie jest jeden switch ale kłębowisko ifów&lt;br /&gt;&lt;br /&gt;Możemy fabrykować cały agregat:&lt;br /&gt;&lt;div&gt;&lt;pre class="brush: java"&gt;//fabrykowanie całego agregatu&lt;br /&gt;&lt;br /&gt;  class OrderItemFactory{&lt;br /&gt;  OrderItem createOrderItem(...){&lt;br /&gt;    ShippingCostCalculator calculator = //100 ifów;&lt;br /&gt;    return new OrderItem(calculator);&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;albo jedynie strategię:&lt;br /&gt;&lt;br /&gt;&lt;div&gt;&lt;pre class="brush: java"&gt;//fabrykowanie jedynie strategii&lt;br /&gt;&lt;br /&gt;  class ShippingCostCalculatorFactory{&lt;br /&gt;  ShippingCostCalculator createShippingCostCalculator(...)&lt;br /&gt;    ShippingCostCalculator calculator = //100 ifów;&lt;br /&gt;    return calculator;&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;Wybór podejścia - co fabrykować: agregat czy strategię zależy do tego w którym momencie mamy wiedzą potrzebną do wyboru kalkulatora. Przed czy dopiero po powołaniu do życia OrderItema.&lt;br /&gt;&lt;br /&gt;Generalnie lepiej jest posługiwać się Agregatem i ukrywać szczegóły typu istnienie strategii, ale nie zawsze jest to możliwe.&lt;br /&gt;&lt;br /&gt;Tutaj jako agregat traktujemy OrderItem a nie Order, bo tak to wygląda w rzeczywistych systemach, np. klasy ERP - widziałem.&lt;br /&gt;&lt;br /&gt;3a. co jeżeli aby wybrać konkretny kalkulator potrzeba znać np aktualnie zalogowanego użytkownika? Lub ogólnie: jakiś kontekst, którego brakuje w OrderItem?&lt;br /&gt;Taka Fabryka może być komponentem zarządzanym (EJB, Speing Bean, itd) i możemy do niej wstrzykiwać potrzebne informacje.&lt;br /&gt;&lt;br /&gt;&lt;div&gt;&lt;pre class="brush: java"&gt;class ShippingCostCalculatorFactory{&lt;br /&gt;  @Inject&lt;br /&gt;  LoggedUser loggedUser;  //logged user to obiekt apliakcyjny (niebiznesowy), trzymany w sesji&lt;br /&gt;&lt;br /&gt;  ShippingCostCalculator createShippingCostCalculator(...)&lt;br /&gt;    //if (loggedUser.role == ADMIN)&lt;br /&gt;    ShippingCostCalculator calculator = //100 ifów ;&lt;br /&gt;    return calculator;&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;3b. co jeżeli któraś konkretna strategia obliczania kosztu potrzebuje informacji o zewnętrznym kontekście (np zalogowanym userze)? Chodzi o przypadek gdy metoda z interfejsu strategii nie ma w parametrze  tego co potrzebuje implementacja. Fabryka może przekazać kontekst do konkretnej strategii przez jej konstruktor.&lt;br /&gt;&lt;br /&gt;&lt;div&gt;&lt;pre class="brush: java"&gt;class ShippingCostCalculatorFactory{&lt;br /&gt;  @Inject&lt;br /&gt;  LoggedUser loggedUser;  //logged user to obiekt apliakcyjny (niebiznesowy), trzymany w sesji&lt;br /&gt;&lt;br /&gt;  ShippingCostCalculator createShippingCostCalculator(...)  &lt;br /&gt;    ShippingCostCalculator calculator = //100 ifów ;&lt;br /&gt;    calculator = new XyzCalculator(loggedUser.getUserId());&lt;br /&gt;  &lt;br /&gt;    return calculator;&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;Podsumowując:&lt;br /&gt;Rozdzielamy silny coupling (współpracy, tworzenia, wywołania) do osobnych "pudełek".&lt;br /&gt;Strategie: tylko obliczenia;&lt;br /&gt;Fabryki: ecydowanie o typie strategii oraz ewentualnie składanie obiektów (przekazywanie szerszego kontekstu do strategii lub dekorowanie strategii)&lt;br /&gt;&lt;br /&gt;Dzięki rozdzieleniu możemy niezależnie testować jednostkowo Agregaty i Strategie (Polityki w nomenklaturze DDD). A to za prawą fabryk, w których mieszkają operatory new. Agregaty są od nich wolne, więc mamy możliwość mockowania/stubowania strategii na czas testów.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;//===============================================&lt;br /&gt;&lt;br /&gt;Tak jak pisałem w poprzednim poście: wprowadzenie Strategii zaczyna się nam opłacać dopiero przy złożonych modelach biznesowych. Pokazałem tutaj dodatkowo złożenie Strategii i Dekoratora wraz z idiomem Fabryki oraz wystrzykiwaniem zależności. Dopiero w synergii technik tkwi prawdziwa siła.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Ważne jest to aby w ogóle modelować złożoność&lt;/b&gt;. Jeżeli nie modelujemy złożonego problemu a jedynie "zamiatamy go pod dywan" w postaci ukrytych gdzieś głęboko ifów to model szybko upada na twarz;)&lt;br /&gt;&lt;br /&gt;Podstawowa zasada Domain Driven Desigm mówi: &lt;b&gt;make explicit what is implict&lt;/b&gt;. Czyli wydobywajmy ważne koncepcje biznesowe na powierzchnię. Nie ukrywajmy ich w ifach w linijkacj od 5000 do 6000.&lt;br /&gt;&lt;br /&gt;A czy jest coś ważniejszego w modelu biznesowym niż różne sposoby liczenia pieniędzy?;)&lt;br /&gt;&lt;br /&gt;Na koniec jedna uwaga: zawsze gdy pokazuję na warsztatach tego typu przykłady część uczestników jest wręcz urzeczona "pudełkowaniem" złożonej logiki w małe, eleganckie pudełeczka. Inni z kolei preferują jedno pudło (np procedurę) ponieważ łatwiej im ogarnąć jedno pudło niż wiele małych, nawet kosztem tego, że w tym jednym pudle jest, powiedzmy delikatnie - bałaganik.&lt;br /&gt;&lt;br /&gt;Wszyscy różnimy się mocno pod względem oceniania tego co jest proste. Więcej na ten temat: &lt;a href="http://jdn.pl/node/1967"&gt;O programiście-pisarzu i programiście-konstruktorze&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5197374494377847819-1118256749070274245?l=art-of-software.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://art-of-software.blogspot.com/feeds/1118256749070274245/comments/default' title='Komentarze do posta'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5197374494377847819&amp;postID=1118256749070274245' title='Komentarze (8)'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5197374494377847819/posts/default/1118256749070274245'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5197374494377847819/posts/default/1118256749070274245'/><link rel='alternate' type='text/html' href='http://art-of-software.blogspot.com/2011/06/sposoby-enkapsulowania-zozonej-logiki.html' title='Sposoby enkapsulowania złożonej logiki biznesowej'/><author><name>Sławek Sobótka</name><uri>http://www.blogger.com/profile/15082577671795313109</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='30' height='32' src='http://3.bp.blogspot.com/-tmFOhJC48_E/TkQ0G2DxrqI/AAAAAAAAAz8/WVGBaaS5a_Y/s220/zdjecie2.png'/></author><thr:total>8</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5197374494377847819.post-1738674524548736062</id><published>2011-06-01T00:27:00.007+02:00</published><updated>2011-06-01T01:04:58.936+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='wzorce projektowe'/><category scheme='http://www.blogger.com/atom/ns#' term='OOD'/><title type='text'>Koszt Dostawy</title><content type='html'>Odnośnie &lt;a href="http://art-of-software.blogspot.com/2011/05/przemyslane-praktyki-java-ee.html"&gt;poprzedniego posta&lt;/a&gt; - Jacek L. zadał pytanie o przykład podejścia do liczenia kosztu dostawy.&lt;br /&gt;&lt;br /&gt;Mamy kilka możliwości...&lt;br /&gt;&lt;br /&gt;Załóżmy, że ma my klasę:&lt;br /&gt;&lt;br /&gt;&lt;div&gt;&lt;pre class="brush: java"&gt;class OrderItem{&lt;br /&gt;  //pola&lt;br /&gt;  metodaBiznesowa1(){..}&lt;br /&gt;  metodaBiznesowa2(){..}&lt;br /&gt;  metodaBiznesowa3(){..}&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;Co jeżeli mamy różne rodzaje/odmiany itemów, gdzie zachowanie tych metod różni się - innymi słowy algorytmy są różne?&lt;br /&gt;&lt;br /&gt;&lt;b&gt;1. Rozwiązanie na switchach:&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;div&gt;&lt;pre class="brush: java"&gt;metodaBiznesowa1(){&lt;br /&gt;  switch(jakisParametr){&lt;br /&gt;    case x: return ...&lt;br /&gt;    case y: return ...&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;Konsekwencje: wszelkie zmiany wymuszają "grzebanie" w corowym kodzie biznesowym, czyli jego "brudzenie" czyli ponowne testowanie (nie jest to problem jeżeli mamy pokrycie testami automatycznymi:)&lt;br /&gt;&lt;br /&gt;&lt;b&gt;2. Rozwiązanie struktura i algorytmy danych&lt;/b&gt;&lt;br /&gt;Generalnie podobne do poprzedniego z tym, że z wyniesieniem kodu biznesowego na zewnątrz - podane dla uzupełnienia wachlarza możliwości:&lt;br /&gt;&lt;br /&gt;&lt;div&gt;&lt;pre class="brush: java"&gt;class OrderItem{&lt;br /&gt;//gettery i settery&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;class BusinessService1{&lt;br /&gt;  doSth(OrderItem oi){&lt;br /&gt;    switch(oi.getSth())&lt;br /&gt;    //...&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;&lt;b&gt;3. SŁABE (ale to zależy od szerszego kontekstu) rozwiązanie z dziedziczeniem:&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;Tworzymy specjalne klaski dziedziczące po OrderItem, w których nadpisujemy odpowiednie metody biznesowe.&lt;br /&gt;&lt;br /&gt;Konsekwencja: mnożenie bytów.&lt;br /&gt;&lt;br /&gt;Co jeżeli:&lt;br /&gt;- OrderItem1 nadpisze metodę metodaBiznesowa1&lt;br /&gt;- OrderItem2 nadpisze metodę metodaBiznesowa2&lt;br /&gt;a OrderItemBum chce mieć obie metody biznesowe 1 i 2 takie jak klasy wymienione poprzednio?&lt;br /&gt;Eksplozja kombinatoryczna!&lt;br /&gt;&lt;br /&gt;Dziedziczenie jest dobre, ale wówczas gdy klasa ma ściśle określoną odpowiedzialność (jeden powód do zmiany). Wówczas nie ma możliwości zajścia eksplozji kombinatorycznej oraz mamy zwykle pewność zachowania &lt;a href="http://en.wikipedia.org/wiki/Liskov_substitution_principle"&gt;Liskov Substitution Principle&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Co jeżeli klasy dziedziczące są wymagane ponieważ dodają nowe atrybuty?&lt;br /&gt;Wówczas rozwiązanie z dziedziczeniem zaczyna się bronić. Jednak wciąż może dojść do eksplozji klas. &lt;br /&gt;Wówczas lepiej łączyć rozwiązanie z dziedziczeniem z rozwiązaniem 4.&lt;br /&gt;&lt;br /&gt;Innym podejściem jest unikanie dziedziczenia i zastosowanie Archetypu Biznesowego Product.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;4. Wprowadzenie wzorca strategii.&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;div&gt;&lt;pre class="brush: java"&gt;class OrderItem{&lt;br /&gt;  metodaBiznesowa1(){&lt;br /&gt;    return strategiaBiznesowa1.go(...);&lt;br /&gt;  }&lt;br /&gt;  metodaBiznesowa2(){&lt;br /&gt;    return strategiaBiznesowa2.run(...);&lt;br /&gt;  }&lt;br /&gt;  metodaBiznesowa3(){..}&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;StrategiaBiznesowa1,2 są interfejsami. Konkretne implementacje zajmują się szczegółami.&lt;br /&gt;Unikamy eksplozji kombinatorycznej z podejścia trzeciego dlatego, że w tym przypadku ilość klas to suma możliwych strategi dla każdej metody biznesowej a nie ich iloczyn.&lt;br /&gt;&lt;br /&gt;Ale zostawmy autystyczne miary ilościowe... Ten design się po prostu "czuje". Tak jak w naiwnym szkolnym przykładzie: samochód zawiera skrzynię biegów - pasującą do interfejsu (śruby, tryby). Samochód w żadnym wypadku nie dziedziczy po skrzyni biegów:)&lt;br /&gt;&lt;i&gt;//Chociaż kiedyś na rekrutacji ktoś na pytanie o nieksiążkowy przykład dziedziczenia odpowiedział mi: "telefonistka dziedziczy po telefonie".&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Skąd OrderItem posiada strategieBiznesowe?&lt;br /&gt;&lt;br /&gt;a) OrderItem pobiera z fabrykStrategii - niedobre ze względu na testability&lt;br /&gt;&lt;br /&gt;b) OrderItem ma je "wstrzyknięte" z zewnątrz przez FabrykiItemów, które go tworzą lub przez RepozytiumItemów, które pobierają go z bazy. &lt;br /&gt;&lt;br /&gt;ew. Fabryki/Repozytoria tworzą nadrzędny agregat (np Order), który zawiera w sobie itemy, ale to zależy od domeny - mechanizm jest ten sam.&lt;br /&gt;&lt;br /&gt;To jaką staregięBiznesową "wstrzyknąć" jest decyzją biznesową, tak więc Fabryki/Repozytoria zawierają taką logikę odciążając coupling tworzenia od coplingu używania. &lt;br /&gt;Więcej o rodzajach couplingu dowiemy się od &lt;a href="http://misko.hevery.com/2008/08/21/where-have-all-the-singletons-gone/"&gt;ekspertów Google&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Warto zauważyć, że sama &lt;a href="http://en.wikipedia.org/wiki/Strategy_pattern"&gt;Strategia&lt;/a&gt; semantycznie jest niczym innym jak Funkcją (w kontekście programowania funkcyjnego) przekazaną na prawach First Class Citizen. Jedynie syntaktycznie mamy niezręczność wynikającą ze składni Javy;)&lt;br /&gt;&lt;br /&gt;Wprowadzenie Wzorca Strategii &lt;b&gt;zaczyna się nam opłacać&lt;/b&gt; pod warunkiem, że:&lt;br /&gt;- spodziewamy się pojawiania się kolejnych strategii w przyszłości&lt;br /&gt;- chcemy testować jednostkowo niezależnie logikę OrderItema od logiki StrategiiBiznesowych&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Pośrednim rozwiązaniem prowadzącym &lt;b&gt;w kierunku&lt;/b&gt; wzorca - dającym potencjał na łatwy refaktoring w przyszłości jest:&lt;br /&gt;1. wyciągnięcie interfejsu&lt;br /&gt;2. dostarczenie jedynej implementacji jako serwisu ze słczami w stylu rozwiązania drugiego.&lt;br /&gt;&lt;br /&gt;//=========================================&lt;br /&gt;&lt;br /&gt;O opłacalności wprowadzenia Strategi możemy mówić również na poziomie modelowania.&lt;br /&gt;&lt;br /&gt;Np w &lt;a href="http://en.wikipedia.org/wiki/Domain-driven_design"&gt;DDD&lt;/a&gt; nie mówi się Strategia lecz Polityka. Polityki są częścią modelu - obok encji i kilku innych "klocków".&lt;br /&gt;Skutkuje to tym, że zaczynamy pokazywać wariacje istotnych zachowań biznesowych w modelu (diagramach, itd) a co za tym idzie zaczynamy o nich mówić (wchodzą do Ubiquotus Language)&lt;br /&gt;Co najważniejsze: zaczynamy zauważać te arcy-ważne z biznesowego punktu widzenia komponenty - już nie siedzą w słiczach w linijce numer 5000 w serwisie-ośmiotysięczniku;P&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/-p8ujj3BWn6s/TeVxNbdxdMI/AAAAAAAAAxA/Sb-YXnfeVjU/s1600/mount-everest.gif" imageanchor="1" style="margin-left:1em; margin-right:1em"&gt;&lt;img border="0" height="240" width="320" src="http://2.bp.blogspot.com/-p8ujj3BWn6s/TeVxNbdxdMI/AAAAAAAAAxA/Sb-YXnfeVjU/s320/mount-everest.gif" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5197374494377847819-1738674524548736062?l=art-of-software.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://art-of-software.blogspot.com/feeds/1738674524548736062/comments/default' title='Komentarze do posta'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5197374494377847819&amp;postID=1738674524548736062' title='Komentarze (7)'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5197374494377847819/posts/default/1738674524548736062'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5197374494377847819/posts/default/1738674524548736062'/><link rel='alternate' type='text/html' href='http://art-of-software.blogspot.com/2011/06/koszt-dostawy.html' title='Koszt Dostawy'/><author><name>Sławek Sobótka</name><uri>http://www.blogger.com/profile/15082577671795313109</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='30' height='32' src='http://3.bp.blogspot.com/-tmFOhJC48_E/TkQ0G2DxrqI/AAAAAAAAAz8/WVGBaaS5a_Y/s220/zdjecie2.png'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/-p8ujj3BWn6s/TeVxNbdxdMI/AAAAAAAAAxA/Sb-YXnfeVjU/s72-c/mount-everest.gif' height='72' width='72'/><thr:total>7</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5197374494377847819.post-8532103126612019269</id><published>2011-05-31T22:27:00.008+02:00</published><updated>2011-05-31T23:18:31.491+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='recenzja'/><title type='text'>Przemyślane praktyki Java EE</title><content type='html'>Dziś krótka recenzja książki &lt;a href="http://blog.adam-bien.com/"&gt;Adama Biena&lt;/a&gt; &lt;a href="http://www.amazon.com/Real-World-Java-Patterns-ebook/dp/B0051OEM5O/ref=sr_1_1?ie=UTF8&amp;m=A2ZHC53Q5OYSS4&amp;s=digital-text&amp;qid=1306850389&amp;sr=1-1"&gt;Real World Java EE Patterns - Rethinking Best Practices&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Zacznę od konkluzji: czy warto? Tak. To jak bardzo warto zależy od Twojego dotychczasowego backroundu, ale gwarantuję, że nawet eksperci Javy EE znajdą dla siebie kilka ciekawych kawałków. Pozycja konkretna, na temat, z przykładami wykorzystującymi ciekawe kruczki z np. EJB 3.1.&lt;br /&gt;&lt;br /&gt;Na początku obawiałem się, że przemyślenia dotyczą trywialnych CRUDów - na crudach opiera się ostatnio cała współczesna literatura programistyczna jak i blogi. Nie dziwota, gdyż jest to bardzo wdzięczna materia - można na nich pokazać jak prosta i łatwa jest technologia X, a później radźcie sobie sami.&lt;br /&gt;&lt;br /&gt;Autor w części rozdziałów wychodzi od crudów jednak za chwilę porusza bardziej zaawansowane tematy, racjonalnie argumentując kiedy opłacalne jest wprowadzenie bardziej złożonych mechanizmów platformy.&lt;br /&gt;&lt;br /&gt;Dla kogo przeznaczona jest książka?&lt;br /&gt;Przede wszystkim dla weteranów J2EE, którzy przesiadając się na Java EE powinni zapomnieć stare nawyki.&lt;br /&gt;Dla osób zaczynających od EE 5 lub przechodzących z innych technologii (Spring) odniesienia do "starych" praktyk będą jedynie ciekawostką archeologiczną.&lt;br /&gt;&lt;br /&gt;Ale tak jak pisałem, znajdziemy w niej kilka ciekawych kruczków, sporo gotowych rozwiązań oraz dużo gotowego kodu. Kruczki i best practices związane z transakcjami, kod użytecznych interceptorów, które łatają braki w specyfikacji;) oraz nieco praktyk odnośnie dobrego designu. Część praktyk odnośnie designu jest dyskusyjna, jednak autor wyjaśnia w dalszej części, że aplikują się w pewnych kontekstach, natomiast gdy wymaga tego problem, wówczas zaczynamy sięgać po inne rozwiązania. Przykładowo obiekty transferowe są dobre tylko wtedy gdy są dobre:) - z czym nie sposób się nie zgodzić. DAO jest usprawiedliwione tylko gdy wnosi wartość - tak ale dyskutować można nad tym co jest wartością.&lt;br /&gt;&lt;br /&gt;Mimo dyskusyjności niektórych pomysłów trzeba docenić inicjatywę, ponieważ generalnie brakuje na rynku pozycji wychodzących poza przysłowiowy Hello World...&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Na uwagę zasługuje fakt, że autor otwarcie mówi o proceduralnym stylu promowanym przez platformę.&lt;br /&gt;Mówi też otwarcie o innych sposobach skalowania - bez rozpraszania obiektów pomiędzy warstwami...&lt;br /&gt;nota bene zgodnie z zasadą Fowlera odnośnie rozpraszania: "Just don't":)&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Nie byłbym sobą gdybym nie znalazł jakiś błędów koncepcyjnych...&lt;br /&gt;Wiem, że w każdej książce technicznej (w sensie opisującej jakąś technologię) projektowanie Object Oriented jest potraktowane po macoszemu ale skoro już polecam książkę to zwrócę uwagę na 2 przykłady:&lt;br /&gt;&lt;br /&gt;Rozdział "Persistent Domain Object (Business Object)"&lt;br /&gt;Po wstępie o tym dlaczego opłaca się stosować model OO (rich model) zamiast proceduralnego (anemic model) mamy taki oto przykład:&lt;br /&gt;&lt;br /&gt;Klasa OrderItem, która między innymi potrafi policzyć swój koszt metodą getShippingCost (jest to metoda biznesowa a nie geter)&lt;br /&gt;&lt;br /&gt;Dalej dziedzicząca po niej klasa BulkyItem, która liczy koszt nieco inaczej - nadpisuje metodę getShippingCost a w niej woła super wersję tej metody!&lt;br /&gt;&lt;br /&gt;@Override&lt;br /&gt;public int getShippingCost() {&lt;br /&gt;return super.getShippingCost() + 5;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Nie róbcie tego w domu ani w pracy!:)&lt;br /&gt;1. OrderItem ma wiele odpowiedzialności, więc wprowadzanie nowej klasy i dziedziczenia tylko dlatego, że zmieniła się jedna z odpowiedzialności jest błędem projektowania obiektowego. Taki sposób rozumowania szybko doprowadzi do ekspolozji kombinatorycznej, gdzie każda zmiana logiki (oraz kombinacje tych zmian) zamieszczana jest w swojej klasie dziedziczącej. &lt;a href="http://en.wikipedia.org/wiki/Strategy_pattern"&gt;Strategia&lt;/a&gt; jest jednym rozwiązań. A jeżeli nie chcemy wprowadzać strategii, to już na prawdę lepszy będzie serwis liczący koszt na podstawie getterów z OrderItem.&lt;b&gt; Dobry kod proceduralny jest zawsze lepszy od słabego kodu obiektowego!&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;2. Wołanie super wersji metody z nadklasy jest tak zwany &lt;a href="http://en.wikipedia.org/wiki/Call_super"&gt;smrodkiem&lt;/a&gt; (code smell). Skoro nadpisuję metodę to jest już nieważna. Generalnie wskazuje to na słaby design.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Kolejna rzecz na jaką należy uważać to rozdział poświęcony "konfliktowi" pomiędzy Domain Driven Design a SOA.&lt;br /&gt;&lt;br /&gt;Niestety muszę powiedzieć, że konflikt ten jest pozorny i wynika z niezrozumienia architektury aplikacji dla systemów, w których stosujemy DDD.&lt;br /&gt;Autor we wcześniejszych rozdziałach promował swój pomysł pod tytułem Gateway i ten styl przeniósł na implementację DDD.&lt;br /&gt;Nigdy nie "publikujemy" Modelu Domeny jako "API". Wiąże się z wieloma przykrymi konsekwencjami, ale tutaj odsyłam do &lt;a href="http://domaindrivendesign.org/books/evans_2003"&gt;Evansa&lt;/a&gt;. Model domenowy przykrywamy właśnie procedurami w stylu SOA - po prostu podstawowy pattern DDD: warstwa Serwisów Aplikacyjnych. I po problemie:)&lt;br /&gt;Było to powiedziane już 5 lat temu: &lt;a href="http://www.udidahan.com/2006/09/04/ddd-the-opposite-of-soa-uh-no/"&gt;DDD the opposite of SOA? Uh, no.&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;//========================================&lt;br /&gt;&lt;br /&gt;Polecam rozdział pod tytułem "Retired Patterns" przypomina nam jak smutne i przykre bywało drzewiej programowanie w EE:)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5197374494377847819-8532103126612019269?l=art-of-software.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://art-of-software.blogspot.com/feeds/8532103126612019269/comments/default' title='Komentarze do posta'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5197374494377847819&amp;postID=8532103126612019269' title='Komentarze (2)'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5197374494377847819/posts/default/8532103126612019269'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5197374494377847819/posts/default/8532103126612019269'/><link rel='alternate' type='text/html' href='http://art-of-software.blogspot.com/2011/05/przemyslane-praktyki-java-ee.html' title='Przemyślane praktyki Java EE'/><author><name>Sławek Sobótka</name><uri>http://www.blogger.com/profile/15082577671795313109</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='30' height='32' src='http://3.bp.blogspot.com/-tmFOhJC48_E/TkQ0G2DxrqI/AAAAAAAAAz8/WVGBaaS5a_Y/s220/zdjecie2.png'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5197374494377847819.post-9104197439169287821</id><published>2011-05-19T22:01:00.006+02:00</published><updated>2011-05-20T14:46:45.384+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Homo sum...'/><category scheme='http://www.blogger.com/atom/ns#' term='wzorce projektowe'/><title type='text'>Stosowalność Wzorców Projektowych</title><content type='html'>Temat Wzorców Projektowych budzi wiele emocji. Niektórzy są ich zagorzałymi fanami, inni podchodzą z pogardą twierdząc, że w rzeczywistym świecie są bezużyteczne.&lt;br /&gt;&lt;br /&gt;Wzorce Projektowe są jedynie narzędziem, a emocjonalne podchodzenie do "młotka" jest po prostu nieracjonalne. Dlatego zaproponuję nieco inne podejście - kontekstowe.&lt;br /&gt;&lt;br /&gt;Swoją drogą ciekawe, że podczas rozmów coraz częściej słyszę z ust wytrawnych programistów wyraz irytacji nad bezkontekstowym podejściem naszej branży do wszelkich technik, praktyk, metodyk, produktów, rozwiązań. Mówi się, że jesteśmy sterowani modą bardziej niż Mediolan lub Paryż;)&lt;br /&gt;Odczuwa się silne zmęczenie marketingiem.&lt;br /&gt;&lt;br /&gt;W swojej karierze programistycznej miałem okazję pracować nad systemami różnej klasy. Przez klasę rozumiem klasę problemów jakie stanowiły główne wyzwania. Ale to praca trenera i konsultanta dała mi dostęp do wglądu w spektrum klas problemów, w ilości jaką standardowo kolekcjonuje się w okolicach emerytury.&lt;br /&gt;&lt;br /&gt;Piszę o tym aby przejść do kontekstu stosowalności Wzorców Projektowych. Z moich obserwacji wynika, że kontekst ten jest rozpięty na 2-wymiarach: wspomnianej już klasie problemu oraz w wymiarze osobowości (otrzemy się o aspekty psychologii programistów).&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;KONTEKST KLASY PROBLEMU&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;Jeżeli jesteśmy w kontekście aplikacji biznesowych, a nasza praca polega na implementowania kolejnych wymagań, to stoją przed nami wyzwania typu:&lt;br /&gt;- okiełzanie nielogicznych wymagań&lt;br /&gt;- modelowanie narzędzia dla biznesu (naszej aplikacji), który działa z natury procesowo&lt;br /&gt;- tworzenie intuicyjnego GUI&lt;br /&gt;- wpasowanie się w istniejącą bazę danych, która była projektowana przed III Wojną Mandżulską, w czasach gdy nikt jeszcze tak na prawdę nie rozumiał domeny.&lt;br /&gt;&lt;br /&gt;W tym kontekście często nie potrzebujemy nawet używania technik OO - aczkolwiek programujemy &lt;b&gt;z użyciem&lt;/b&gt; obiektów (bo niby jak inaczej w mainstreamowych językach?).&lt;br /&gt;&lt;br /&gt;Z szerokiego &lt;a href="http://en.wikipedia.org/wiki/Design_pattern_(computer_science)#Classification_and_list"&gt;wachlarza Wzorców Projektowych&lt;/a&gt; możemy posłużyć się w tym kontekście - w pewnych bardziej złożonych - przypadkach:&lt;br /&gt;- &lt;b&gt;Strategią &lt;/b&gt;- jeżeli mamy odmiany tego samego zachowania/czynności biznesowej. Podejście promowane przez ten wzorzec staje się ostatnio modne za sprawą języków funkcyjnych. By czymże innym na poziomie syntaktycznym jest przekazanie obiektu implementującego interfejs z jedną metodą niż zwykłym przekazaniem funkcji na poziomie semantycznym?&lt;br /&gt;- &lt;b&gt;Łańcuchem Odpowiedzialności&lt;/b&gt; - łańcuch zaczyna się nam opłacać gdy chcemy modelować podejmowanie decyzji o tym, który z wariantów logiki biznesowej chcemy wykonać. Opłaca się gdy spodziewamy się modyfikowania ilości wariantów.&lt;br /&gt;- &lt;b&gt;Specyfikacją &lt;/b&gt;- pozwala na przejrzyste modelowanie złożonych reguł określających czy dany obiekt biznesowy powinien podlegać jakiemuś przetwarzaniu. Opłaca się gdy reguły są zawiłe i istnieją pomiędzy nimi zależności logiczne. Złożony wzorzec, że wystąpić kilka razy w całym kodzie.&lt;br /&gt;- &lt;b&gt;Stanem&lt;/b&gt; - bardzo złożony wzorzec, może wystąpić raz, może dwa w średniej wielkości systemie. Pozwala na przejrzyste modelowanie maszyny stanów, dla obiektów biznesowych, które mają np różne statusy i w zależności od statusu a) mogą lub nie przechodzi w inne oraz b) inaczej się zachowują. Opłaca się gdy mamy wiele statusów i zawiła logikę sterującą zachowaniem zależnym od statusów.&lt;br /&gt;- &lt;b&gt;Metodą Szablonową&lt;/b&gt; - prosty wzorzec, klasyka polimorfizmu, pozwala modelować różne warianty algorytmów biznesowych. Z czasem gdy sytuacja się komplikuje przestaje się opłacać i warto dokonać refaktoringu do Strategii.&lt;br /&gt;- &lt;b&gt;Fasadą &lt;/b&gt;- trywialny wzorzec, który nie zasługuje na miano wzorca, ale wygodnie upraszcza to co najpierw skomplikowaliśmy;)&lt;br /&gt;- &lt;b&gt;Dekoratorem&lt;/b&gt; - wprowadzenie dekoratora zaczyna się nam opłacać gdy chcemy !w runtime! (nie podczas programowania czy kompilacji) decydować o dodawaniu nowych zachowań. Bardzo silny, ale rzadko logika biznesowa daje się tak elegancko zamodelować.&lt;br /&gt;&lt;br /&gt;Pomijam Singletona, który w większości przypadków jest antywzorcem &lt;a href="http://misko.hevery.com/code-reviewers-guide/flaw-brittle-global-state-singletons/"&gt;zabijającym testowalność&lt;/a&gt;. Poza tym jego istnienie w modelu biznesowym rzadko bywa sensowne.&lt;br /&gt;&lt;br /&gt;O ile pojawienie się w aplikacji biznesowej wielu przypadków wykorzystania Strategii, Metody Szablonowej, Fasady jest normalnym zjawiskiem o o tyle duża ilość Łańcuchów, Dekoratorów czy Stanów wskazuje na overengineering i "chorobę wzorcową".&lt;br /&gt;&lt;br /&gt;Pozostałe wzorce z katalogu nie mają zbyt dużej szansy na potencjalne pojawienie się w aplikacji biznesowej - po prostu służą do rozwiązywania problemów innych klas.&lt;br /&gt;&lt;br /&gt;W aplikacjach biznesowych za to więcej pożytku niosą wzorce innego rodzaju:&lt;br /&gt;- sposoby modelowania, oraz strategicznego modelowa z zestawu &lt;a href="http://en.wikipedia.org/wiki/Domain-driven_design"&gt;Domain Driven Design&lt;/a&gt;&lt;br /&gt;- &lt;a href="http://en.wikipedia.org/wiki/Archetype_(information_science)"&gt;archetypy modeli biznesowych&lt;/a&gt;&lt;br /&gt;- najlepsze praktyki odnośnie &lt;a href="http://en.wikipedia.org/wiki/Usability"&gt;Usability&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Jeżeli natomiast jesteśmy w kontekście tworzenia oprogramowania klasy: platforma, framework, server, wysokowydajny dedykowany portal, oprogramowanie specjalistyczne typu: narzędzia do projektowania/komponowania, itp wówczas stajemy przed problemami zupełnie innej klasy:&lt;br /&gt;- otwartość na rozbudowę z jednoczesną ochroną publicznego api przed zmianami core,&lt;br /&gt;- wydajność, oszczędność pamięci,&lt;br /&gt;- bezpieczeństwo, &lt;br /&gt;- giętkość api, &lt;br /&gt;- wyważenie ograniczeń&lt;br /&gt;- itp.&lt;br /&gt;&lt;br /&gt;Przeglądając kody źródłowe tego typu aplikacji możemy dostrzec wiele wystąpień wzorców lub struktur do nich podobny zmodyfikowanych z powodu pewnych intencji. Czasem są po prostu nazwane inaczej z powodu niewiedzy autora - ale ciekawe jest, że wpadł na pewne pomysły niezależnie, nie znając wzorca wcześniej.&lt;br /&gt;&lt;br /&gt;Oprócz wspomnianych wcześniej wzorców opłacalne w tym kontekście &lt;b&gt;dodatkowo &lt;/b&gt;mogą być:&lt;br /&gt;- &lt;b&gt;Builder &lt;/b&gt;- aby odseparować plany budowy obiektów od ostatecznego kształtu konstrukcji. Opłacalny gdy przewidujemy pojawianie się kolejnych "produktów" &lt;br /&gt;- &lt;b&gt;Visitor &lt;/b&gt;- aby umożliwić użytkownikom api wprowadzanie nowych zachowań poprzez dodawanie swojego kodu zamiast modyfikowania biblioteki/frameworka. Double Dispach dla ubogich np. w celu otwarcia core na rozbudowę&lt;br /&gt;- &lt;b&gt;Proxy &lt;/b&gt;- aby umozliwić model programistyczny w stylu Aspect Oriented&lt;br /&gt;- &lt;b&gt;Mediator &lt;/b&gt;- śmietnik na chaos sieci współpracujących obiektów. Jeżeli musisz mieć chaos, to explicite ogranicz jego zakres.&lt;br /&gt;- &lt;b&gt;Most&lt;/b&gt; - jeżeli masz niestabilny core i chcesz zaryzykować publikowanie stabilnego api&lt;br /&gt;- &lt;b&gt;Prototyp &lt;/b&gt;- jeżeli chcesz fabrykować wiele klas i nie chcesz tworzyć analogicznej do nich, lustrzanej hierarchii fabryk.&lt;br /&gt;- &lt;b&gt;Flyweight &lt;/b&gt;- jeżeli musisz mieć ogromną ilość obiektów, ale część ich pół możesz uwspólnić, ponieważ nie jest to ich zmienny stan - oszczędzasz pamięć.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Podając przykłady dla obu klas problemów chciałem pokazać, że po prostu inni programiści/projektanci/architekci mogą żyć w innym świecie. To że coś jest dla nas bezużytecznie, nie oznacza, je jest to bezużyteczne w ogólności.&lt;br /&gt;&lt;br /&gt;Wrzucanie wszystkich programistów do jednego worka (najlepiej wspólnego worka z Informatykami;) powoduje utratę kontekstu a co za tym idzie rozmycie wymaganych do danego zadanie kompetencji. &lt;br /&gt;&lt;br /&gt;Warto też zastanowić się nad klasami problemów jakie nas intrygują i rozwijać odpowiedni skillset - bez odpowiedniego poziomu kompetencji pewne klasy projektów będą dla nas zawsze zamknięte.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;KONTEKST OSOBOWOŚCI&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;Chyba każdy programista przyzna, że zależy mu na zaprojektowaniu najprostszego rozwiązania. Być może to poszukiwanie prostoty jest tym, co przyciąga ludzi do programowania - no może za wyjątkiem robotników umysłowych napędzanych chęcią łatwego (hehe naiwni) zarobku.&lt;br /&gt;&lt;br /&gt;Problem leży w postrzeganiu prostoty.&lt;br /&gt;Niektórzy mówią, że jakieś podejście jest proste jeżeli można szybko zacząć się w tym orientować. I nie ważne, że później okaże się to pogmatwane w szczegółach. Ważne aby szybko zacząć "łapać" o co chodzi, a później - trudno, świat jest pogmatwany.&lt;br /&gt;Inni mówią, że coś jest proste, jeżeli u swoich założeń ma dające się dokładnie zrozumieć fundamenty, które pozwalają wyobrazić sobie całe rozwiązanie mentalnie. Nie ważne, że może na początku trzeba zainwestować czas - dużo czasu - w zrozumienie pryncypiów i nowych rzeczy, które powierzchownie wydają się złożone. Jeżeli później okaże się, że było to proste, to mówią, że jest to proste.&lt;br /&gt;&lt;br /&gt;Które podejście jest lepsze - jak zwykle, zależy to od kontekstu. W kontekście IT np. może zależeć od ograniczeń czasowych, czyli tego ile czasu możemy poświęcić. Innym ograniczeniem może być opłacalność w perspektywie czasu (czasem robimy eksperyment biznesowy i zobaczy jak się to rozwinie:). Dlatego w każdym przykładzie wzorca pisałem o tym kiedy może się nam opłacać wprowadzenie danej konstrukcji.&lt;br /&gt;&lt;br /&gt;Strategia poznawcza, jaką przyjmuje nasz mózg w podejściu do prostoty (musi być proste od razu, musi być proste docelowo) wiąże się mocno z typem naszej osobowości.&lt;br /&gt;- część z nas jest zorientowana na postrzeganie podobieństw, inni na postrzeganie różnic - &lt;a href="http://www.racjonalista.pl/kk.php/s,4588"&gt;model meta-programów &lt;/a&gt;.&lt;br /&gt;- część z nas jest otwarta na nowe doświadczania, inni są bardziej konserwatywni - &lt;a href="http://en.wikipedia.org/wiki/Big_Five_personality_traits#Openness_to_experience"&gt;model Big 5&lt;/a&gt;.&lt;br /&gt;- część z nas ma swój wewnętrzny świat, w którym modeluje postrzeganą rzeczywistość, inni są nastawieni na natychmiastowe działanie i niemal namacalne doświadczanie - &lt;a href="http://en.wikipedia.org/wiki/Myers-Briggs_Type_Indicator"&gt;model MBTI&lt;/a&gt;&lt;br /&gt;- część z nas żyje w przyszłości, w jakimś jej &lt;a href="http://art-of-software.blogspot.com/2009/07/ile-ci-to-zajmie-roznice-w-postrzeganiu.html"&gt;modelu&lt;/a&gt;, inni żyją tu i teraz w &lt;a href="http://ksiegarnia.pwn.pl/produkt/7480/paradoks-czasu-oprawa-miekka.html"&gt;czasie&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;MODEL DREYFUS&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/-eAz1FSyRolk/TdV0Dsd1KFI/AAAAAAAAAwk/A4rLENBoEpg/s1600/dreyfus.jpg" imageanchor="1" style="margin-left:1em; margin-right:1em"&gt;&lt;img border="0" height="181" width="162" src="http://3.bp.blogspot.com/-eAz1FSyRolk/TdV0Dsd1KFI/AAAAAAAAAwk/A4rLENBoEpg/s320/dreyfus.jpg" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;O modelu kompetencji Braci &lt;a href="http://en.wikipedia.org/wiki/Dreyfus_model_of_skill_acquisition"&gt;Dreyfus&lt;/a&gt; pisałem już &lt;a href="http://art-of-software.blogspot.com/search?q=dreyfus"&gt;kilkakrotnie&lt;/a&gt;. Tutaj przytoczę tylko poziom &lt;b&gt;Competent&lt;/b&gt;. Rozwijając jakąś umiejętność, na tym poziomie w naturalny sposób zaczynamy szukać najlepszych praktyk, wzorców (nomen omen). Tak więc naturalne jest, że rozwijając kompetencję pod tytułem "Programowanie/Projektowanie OO" w pewnym momencie zaczniemy szukać wzorców.&lt;br /&gt;Na kolejnych etapach rozwoju tej kompetencji będziemy zadawać pytanie, kwestionować, szukać szerzej. Jednak na trzecim poziomie (Competent) katalog wzorców daje dużego kopa i pozwala po prostu zoptymalizować proces uczenia się. Jak powiedział &lt;a href="http://en.wikipedia.org/wiki/Jim_Coplien"&gt;Jim Copelin&lt;/a&gt;, z czasem odrzucasz "boczne kółka od swego rowerka" i przestajesz mówić o wzorcach, po prostu intuicyjnie robisz to co należy. &lt;br /&gt;&lt;br /&gt;&lt;br /&gt;//==============================================&lt;br /&gt;&lt;br /&gt;Czasem można spotkać głosy, że wzorce projektowe są "zbyt akademickie". Hmm moim zdaniem wręcz odwrotnie. Do katalogu wzorców nie trafiają żądne rozwiązania, które nie są odkryte i przedyskutowane przez community praktyków. Oczywiście, stosując zbyt wyrafinowany wzorzec do zbyt błahego problemu będziemy odczuwać przerost formy nad treścią. Ale wówczas powodem jest nieumiejętne użycie w nieodpowiednim kontekście - czyli jego niezrozumienie.&lt;br /&gt;&lt;br /&gt;Aby nabrać wyobrażenia o tym, co to znaczy "akademickie" podejście do OO należy zapoznać się z &lt;a href="http://art-of-software.blogspot.com/2010/10/przyczyna-caego-za.html"&gt;tym tekstem&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5197374494377847819-9104197439169287821?l=art-of-software.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://art-of-software.blogspot.com/feeds/9104197439169287821/comments/default' title='Komentarze do posta'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5197374494377847819&amp;postID=9104197439169287821' title='Komentarze (6)'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5197374494377847819/posts/default/9104197439169287821'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5197374494377847819/posts/default/9104197439169287821'/><link rel='alternate' type='text/html' href='http://art-of-software.blogspot.com/2011/05/stosowalnosc-wzorcow-projektowych.html' title='Stosowalność Wzorców Projektowych'/><author><name>Sławek Sobótka</name><uri>http://www.blogger.com/profile/15082577671795313109</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='30' height='32' src='http://3.bp.blogspot.com/-tmFOhJC48_E/TkQ0G2DxrqI/AAAAAAAAAz8/WVGBaaS5a_Y/s220/zdjecie2.png'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/-eAz1FSyRolk/TdV0Dsd1KFI/AAAAAAAAAwk/A4rLENBoEpg/s72-c/dreyfus.jpg' height='72' width='72'/><thr:total>6</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5197374494377847819.post-571677725649390376</id><published>2011-05-09T13:33:00.000+02:00</published><updated>2011-05-22T20:53:51.841+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='prezentacja'/><title type='text'>Ułóż swoją Confiturę 2011</title><content type='html'>Już tylko miesiąc pozostał do &lt;a href="http://confitura.pl"&gt;Confitury&lt;/a&gt; - największej i darmowa konferencji poświęconej Javie (konferencji znanej do tej pory pod nazwą Javarsovia).&lt;br /&gt;&lt;br /&gt;Pod &lt;a href="https://spreadsheets.google.com/spreadsheet/viewform?formkey=dDNLWVpxbXAzVkE3OHRObWRndTk1Vmc6MQ"&gt;tym adresem&lt;/a&gt; można głosować na prezentacje, które chcielibyście zobaczyć 11 czerwca.&lt;br /&gt;&lt;br /&gt;Ankieta nie zawiera abstraktów dlatego opiszę pokrótce 3 zgłoszone tematy. Liczę na feedback z Waszej strony (również krytyczny:) odnośnie:&lt;br /&gt;- tematów (czy są interesujące)&lt;br /&gt;- ich zakresu (czy nie jest zbyt pobieżny aby zbyt oczywisty)&lt;br /&gt;- ew. propozycji zmian&lt;br /&gt;&lt;br /&gt;&lt;b&gt;1. Context and Dependency Injection w służbie Domain Driven Design&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;CDI bazuje na zdobyczach nowoczesnej inżynierii oprogramowania dostarczając silnych technik programistycznych. Jednak po przejrzeniu przykładów o złożoności "Hello world" można zadać sobie pytanie - kiedy, jak i do czego powinienem użyć tych technik w praktyce.&lt;br /&gt;&lt;br /&gt;Podczas prezentacji przedstawię w jaki sposób możemy wykorzystać model programistyczny (styl/sposób podejścia do problemu) oferowany przez CDI do implementacji DDD.&lt;br /&gt;&lt;br /&gt;Po krótkim wstępie na temat modelu programistycznego DDD oraz architektury aplikacji wykorzystamy mechanizmy CDI takie jak fabrykowanie w runtime, dekoratory, zdarzenia, interceptory do implementacji wszystkich Building Blocków DDD. W szczególności poświęcę wiele czasu na wykorzystanie zdarzeń do modelowania wydarzeń biznesowych orkiestrowanych w modelu Sagi.&lt;br /&gt;&lt;br /&gt;Prezentacja z założenia przeznaczona jest dla uczestników początkujących w zgadnieniach CDi i DDD. Przedstawione techniki DDD będą na tyle ogólne, że z łatwością można implementować je na innych nić CDI platformach (np. Spring) na zasadzie analogii.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;2. Domain Driven Design - Wszystko ma swoje miejsce i wszytko jest na miejscu&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;//prezentacja wygłoszona w zeszłym roku na &lt;a href="http://www.dworld.pl/static/nyac/v1_Krakow/DDD%20-%20everything%20on%20place%20and%20place%20for%20everything.pdf"&gt;NYAC&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Czy zastanawialiście się co jest przyczyną rozkładu średnich i dużych&lt;br /&gt;systemów? Czy jest on nieunikniony i jest jedynie kwestią czasu? A&lt;br /&gt;może jednak istnieje jakiś sposób na utrzymanie entropii w ryzach?&lt;br /&gt;&lt;br /&gt;Podczas prezentacji zobaczymy w jaki sposób Domain Driven Design&lt;br /&gt;pomaga w okiełznaniu chaosu. W prezentacji znajdą się główne techniki&lt;br /&gt;modelowania takie jak Ubiquitous Language, Bounded Context, Strategic&lt;br /&gt;Design.&lt;br /&gt;&lt;br /&gt;Zostaną przedstawione również podstawowe techniki implementacji DDD:&lt;br /&gt;przykłady Building Blocks, Command-query Responsibility Segregation,&lt;br /&gt;system zdarzeń (w tym Sagi), przypadki racjonalnego wykorzystania zarówno ORM jak i&lt;br /&gt;czystego i SQL.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;3. Command-query Responsibility Segregation - ewolucja architektury warstwowej w stronę modularyzacji i skalowania&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;//prezentacja wygłaszana na &lt;a href="http://art-of-software.blogspot.com/2011/03/tydzien-segregacji.html"&gt;4dev i 33rd degree&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Z biegiem kariery, tworząc kolejny system lub aplikację, stajemy przed problemami innej klasy. Inna klasa problemu to inne wymagania odnośnie technologii, metodyki i architektury.&lt;br /&gt;&lt;br /&gt;Popularne architektury (1/2/3) warstwowe mogą być nieodpowiednie do pewnych klas problemów - mogą np. narzucać nieracjonalne wykorzystanie ORM lub promować naiwne modelowanie domeny biznesowej.&lt;br /&gt;&lt;br /&gt;Podczas prezentacji przedstawię nowe ujęcie warstw - architekturę Command-query Responsibility Segregation, która wspiera aplikacje średniej i dużej skali. Architektura CqRS promuje zdobycze nowoczesnej inżynierii oprogramowania takie jak: Domain Driven Design i noSQL, otwiera system na skalowanie oraz w naturalny sposób rozwiązuje typowe problemy z mapowaniem relacyjno-obiektowym.&lt;br /&gt;&lt;br /&gt;Główne składowe nowej architektury to: dwa stosy warstw, rozwarstwienie logiki,  zdarzeniowa komunikacja pomiędzy modułami oraz opcjonalnie Event Sourcing (składowanie danych w modelu behawioralnym - w przeciwieństwie do klasycznego modelu strukturalnego)&lt;br /&gt;&lt;br /&gt;//=======================&lt;br /&gt;&lt;br /&gt;Pierwsza z prezentacji jest całkowicie nowa - tym razem planuję lekką zmianę formuły i pokazanie dużej ilości kodu.&lt;br /&gt;Drugą z prezentacji być może widzieliście na NYAC lub we Wrocławiu - planowałem pokazać ją również na zeszłorocznej Warsjavie ale niestety mały, głupi i właściwie martwy (bo niemetabolizujący a jedynie replikujący) wirus był ode mnie silniejszy:/&lt;br /&gt;Trzecia z prezentacji zapewne dla większości z Was będzie replayem z kwietnia.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Zapraszam do głosowania, ale przede wszystkim do uczestnictwa w konferencji - na prawdę warto!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5197374494377847819-571677725649390376?l=art-of-software.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://art-of-software.blogspot.com/feeds/571677725649390376/comments/default' title='Komentarze do posta'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5197374494377847819&amp;postID=571677725649390376' title='Komentarze (2)'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5197374494377847819/posts/default/571677725649390376'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5197374494377847819/posts/default/571677725649390376'/><link rel='alternate' type='text/html' href='http://art-of-software.blogspot.com/2011/05/uoz-swoja-confiture-2011.html' title='Ułóż swoją Confiturę 2011'/><author><name>Sławek Sobótka</name><uri>http://www.blogger.com/profile/15082577671795313109</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='30' height='32' src='http://3.bp.blogspot.com/-tmFOhJC48_E/TkQ0G2DxrqI/AAAAAAAAAz8/WVGBaaS5a_Y/s220/zdjecie2.png'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5197374494377847819.post-6510648686132120461</id><published>2011-05-04T15:48:00.004+02:00</published><updated>2011-05-04T18:25:12.351+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Domain Driven Design'/><category scheme='http://www.blogger.com/atom/ns#' term='prezentacja'/><category scheme='http://www.blogger.com/atom/ns#' term='CqRS'/><title type='text'>DDD i CqRS w Toruniu i Lublinie</title><content type='html'>Dziś post czysto ogłoszeniowy.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Lublin: 9. maja&lt;/b&gt;&lt;br /&gt;Zapraszam na prezentację poświęconą CqRS, która przedstawię na lubelskich dniach informatyki (&lt;a href="http://lubelskiedniinformatyki.pl"&gt;szczegóły&lt;/a&gt;).&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Toruń: 13. maja&lt;/b&gt;&lt;br /&gt;Zapraszam czytelników bloga z Torunia i okolic na dwie prezentacje poświęcone DDD i CqRS, które wygłoszę 13 maja w ramach toruńskiej grupy .NET (&lt;a href="http://wss.pl/group-134/CalendareventList/1,20886/asc.aspx"&gt;szczegóły&lt;/a&gt;).&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;//============================&lt;br /&gt;&lt;br /&gt;Jeżeli ktoś widział te prezentacje na konferencjach NYAC, 4Develoeprs lub 33rd Degree to zapewniam, że pojawi się kilka nowych szczegółów:)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5197374494377847819-6510648686132120461?l=art-of-software.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://art-of-software.blogspot.com/feeds/6510648686132120461/comments/default' title='Komentarze do posta'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5197374494377847819&amp;postID=6510648686132120461' title='Komentarze (2)'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5197374494377847819/posts/default/6510648686132120461'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5197374494377847819/posts/default/6510648686132120461'/><link rel='alternate' type='text/html' href='http://art-of-software.blogspot.com/2011/05/ddd-i-cqrs-w-toruniu-i-lublinie.html' title='DDD i CqRS w Toruniu i Lublinie'/><author><name>Sławek Sobótka</name><uri>http://www.blogger.com/profile/15082577671795313109</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='30' height='32' src='http://3.bp.blogspot.com/-tmFOhJC48_E/TkQ0G2DxrqI/AAAAAAAAAz8/WVGBaaS5a_Y/s220/zdjecie2.png'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5197374494377847819.post-2112819187889623410</id><published>2011-04-23T21:32:00.012+02:00</published><updated>2011-04-24T01:03:39.452+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Agile'/><category scheme='http://www.blogger.com/atom/ns#' term='management'/><category scheme='http://www.blogger.com/atom/ns#' term='Craftsmanship'/><category scheme='http://www.blogger.com/atom/ns#' term='metodyki'/><title type='text'>Code Review vs Pair Programming</title><content type='html'>&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/-a5J4cy-yJH8/TbMaqGyB7pI/AAAAAAAAAvU/8lUFgwsPVMM/s1600/rally-team.jpg" imageanchor="1" style="margin-left:1em; margin-right:1em"&gt;&lt;img border="0" height="240" width="320" src="http://3.bp.blogspot.com/-a5J4cy-yJH8/TbMaqGyB7pI/AAAAAAAAAvU/8lUFgwsPVMM/s320/rally-team.jpg" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;Oczywiście w idealnym świecie najlepiej byłoby mieć &lt;b&gt;zarówno&lt;/b&gt; Code Review (CR) jak i Pair Programming (PP).&lt;br /&gt;Jednak w brutalnej rzeczywistości zwykle nie ma to czasu, ponieważ ich wykonywanie wiąże się ze &lt;i&gt;złudzeniem&lt;/i&gt; tracenia czasu.&lt;br /&gt;&lt;br /&gt;Na szczęście w dojrzałych organizacjach znajdujemy czas na tego typu "zbytki" rozumiejąc ich potrzebę - szczególnie w przypadku ekspansji zespołu o "młodych, zdolnych, dobrze zapowiadających się".&lt;br /&gt;Wówczas zwykle defultowo wybór pada na CR.&lt;br /&gt;&lt;br /&gt;Co takiego możemy sprawdzić podczas CR?&lt;br /&gt;Na pewno:&lt;br /&gt;- dużą część zasad &lt;a href="http://helion.pl/ksiazki/czysty-kod-podrecznik-dobrego-programisty-robert-c-martin,czykod.htm"&gt;Clean Code&lt;/a&gt;&lt;br /&gt;- poziom sensowności testów&lt;br /&gt;- bardzo ogólnie zgodność z założonym stylem architektonicznym &lt;br /&gt;- przy &lt;b&gt;większym zaangażowaniu&lt;/b&gt; być może część reguł &lt;a href="http://en.wikipedia.org/wiki/GRASP_(object-oriented_design)"&gt;GRASP&lt;/a&gt; lub &lt;a href="http://en.wikipedia.org/wiki/Solid_(object-oriented_design)"&gt;SOLID&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;&amp;lt;dygresja&gt;&lt;br /&gt;Co do &lt;i&gt;podstawowych&lt;/i&gt; zasad Clean Code to wydawać by się mogło, że są intuicyjne. Że każdy podczas pierwszego roku nauki programowania (czy to w podstawówce czy to na studiach) zrozumiał, że krótkie metody i samoopisujące się identyfikatory - GOOD, odwrotnie - BAD.&lt;br /&gt;&lt;br /&gt;Okazuje się, że jednak niekoniecznie. W wolnej chwili przyjrzycie się sobie i kolegom z teamu pod kątem dominacji jednego z dwóch typów inteligencji: werbalnej i algorytmicznej.&lt;br /&gt;&lt;br /&gt;Polecam Doskonały artykuł Andrzeja Szczodraka: "&lt;a href="http://jdn.pl/node/1967"&gt;O programiście-pisarzu i programiście-konstruktorze...&lt;/a&gt;"&lt;br /&gt;Dobitnie mówi o tym również Greg Young "gdzieś" w swoim 6.5 godzinnym &lt;a href="http://cqrsinfo.com/video/"&gt;video&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Ogólny morał jest taki: ważne aby odpowiednio przypisywać programistów o naturalnych zdolnościach do odpowiednich części systemu.&lt;br /&gt;&lt;br /&gt;Generalnie różnica polega na tym, że programiści o dominującej inteligencji werbalnej dbają o formę wyrazu. Ich nastawienie - a wręcz predyspozycje - determinują elegancki styl, czytelność i &lt;b&gt;prostotę&lt;/b&gt; (prostotę w rozumieniu werbalnym). A Możliwość eleganckiego i prostego wyrażenia intencji jest dla nich narzędziem weryfikacji poprawności pomysłu (weryfikacji nie formalnej ale bardziej intuicyjnej). Algorytmy nie są ich mocną stroną, raczej wzorce, ogólne zasady i formy, architektury, archetypy. Mają niestety chorobliwą tendencję do tworzenia frameworków, aby nadać ramy myślom.&lt;br /&gt;&lt;br /&gt;Z kolei programiści o dominującej inteligencji algorytmicznej doskonale czują się w złożonej gmatwaninie obostrzeń nie dbając o styl i formę - te są dla nich pomijalne. Na poziomie algorytmu liczy się wydajność. Ich mocną stroną są raczej biblioteki niż frameworki.&lt;br /&gt;Dodatkowo kilkanaście lat stukania młotkiem w głowę na lekcjach/zajęciach z matematyki gdzie dobra nazwa funkcji to &lt;i&gt;f&lt;/i&gt; albo &lt;i&gt;g&lt;/i&gt;, dobra nazwa zmiennej to &lt;i&gt;x, y, k, l, m, n&lt;/i&gt; a najlepsze zadania to te bez kontekstu i bez treści - umacniają naturalne nawyki. &lt;br /&gt;&amp;lt;/dygresja&gt;&lt;br /&gt;&lt;br /&gt;Mam nadzieję, że szczypta psychologii rzuci nieco nowego światła na podstawowe zasady Clean Code - z którymi jako entuzjasta dobrych modeli werbalnych osobiście zgadzam się w zupełności. Jednak innych ludzi trzeba również zrozumieć i nie można być zawsze Clean-Nazi.&lt;br /&gt;&lt;br /&gt;Poza tym wiele z podstawowych zasad czystego kodu można sprawdzić automatycznie.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Jak jednak sprawdzić design? Jak sprawdzić sensowność koncepcji rozwiązania? Jak sprawdzić model biznesowy?&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;//Pomijamy tutaj organizacje, gdzie takowe artefakty przychodzą "z góry" do wklepania.&lt;br /&gt;&lt;br /&gt;Zakładam też, że sprawdzanie designu metrykami z automatu to jak ocenianie obrazu poprzez histogram;)&lt;br /&gt;&lt;br /&gt;Zatem aby sprawdzić tej klasy problemy podczas CR, weryfikujący musi niemal powielić całą pracę umysłową osoby, która weryfikowany kod spłodziła. Czyli innymi słowy mamy podwójny wysiłek mentalny!&lt;br /&gt;&lt;br /&gt;Co jeżeli rzeczywiście go poniesiemy (czyli sprawdzimy coś więcej niż nazwy zmiennych i długość metod) i okaże się, że cała koncepcja rozwiązania jest błędna i należało by ją przepisać?&lt;br /&gt;&lt;br /&gt;Czy przepisujemy, czy może kończymy CR stwierdzeniem: "następnym razem postaraj się bardziej"?&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Skoro już &lt;b&gt;inwestujemy&lt;/b&gt; czas drugiej osoby (zwykle tej "mocniejszej") w powstanie kodu, to może warto zrobić to na początku. Tak aby ta osoba brała udział w powstawaniu koncepcji rozwiązania a nie tylko sprawdzała długość metod;)&lt;br /&gt;&lt;br /&gt;Jest wówczas duża szansa na:&lt;br /&gt;- wyklucie się lepszego rozwiązania, modelu, koncepcji&lt;br /&gt;- eliminację potrzeby przepisania&lt;br /&gt;- czysty kod będzie niejako produktem ubocznym - ekspert zwykle nie potrafi pisać inaczej niż czysto - &lt;b&gt;syf po prostu go spowalnia lub wręcz uniemożliwia myślenie&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;Dlatego lepiej &lt;b&gt;zawczasu&lt;/b&gt; uprawiać &lt;a href="http://en.wikipedia.org/wiki/Pair_Programming"&gt;Pair Programming&lt;/a&gt; (model kierowcy i pilota) aniżeli &lt;b&gt;poniewczasie&lt;/b&gt; liczyć linijki w metodach i sprawdzać czy zmienne nazywają się tak podpowiada zdrowy rozsądek;P&lt;br /&gt;Innymi słowy: mając ograniczone man-hoursy do zainwestowania, lepszy zwrot uzyskamy z PP.&lt;br /&gt;&lt;br /&gt;Mam nadzieję, że archaiczne wyrazy użyte w ostatnim akapicie nadały temu postowi poniosły, świąteczny charakter;)&lt;br /&gt;&lt;br /&gt;//=======================================&lt;br /&gt;&lt;br /&gt;W psychologii uczenia się, mentoring uznaje się za najbardziej efektywną technikę uczenia. Po prostu my, ludzie w ogromnej większości uczymy się przez naśladownictwo - przynajmniej na pierwszych poziomach kompetencji (vide &lt;a href="http://art-of-software.blogspot.com/2008/08/unforgiven.html"&gt;model Dreyfus&lt;/a&gt;).&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5197374494377847819-2112819187889623410?l=art-of-software.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://art-of-software.blogspot.com/feeds/2112819187889623410/comments/default' title='Komentarze do posta'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5197374494377847819&amp;postID=2112819187889623410' title='Komentarze (6)'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5197374494377847819/posts/default/2112819187889623410'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5197374494377847819/posts/default/2112819187889623410'/><link rel='alternate' type='text/html' href='http://art-of-software.blogspot.com/2011/04/code-review-vs-pair-programming.html' title='Code Review vs Pair Programming'/><author><name>Sławek Sobótka</name><uri>http://www.blogger.com/profile/15082577671795313109</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='30' height='32' src='http://3.bp.blogspot.com/-tmFOhJC48_E/TkQ0G2DxrqI/AAAAAAAAAz8/WVGBaaS5a_Y/s220/zdjecie2.png'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/-a5J4cy-yJH8/TbMaqGyB7pI/AAAAAAAAAvU/8lUFgwsPVMM/s72-c/rally-team.jpg' height='72' width='72'/><thr:total>6</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5197374494377847819.post-566777057736851920</id><published>2011-04-19T21:15:00.000+02:00</published><updated>2011-04-19T21:15:16.756+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Homo sum...'/><title type='text'>TCP vs UDP</title><content type='html'>Dziś będzie o komunikacji...&lt;br /&gt;&lt;br /&gt;Najpierw nieco teorii:&lt;br /&gt;- protokół &lt;a href="http://pl.wikipedia.org/wiki/TCP_(protokół)"&gt;TCP&lt;/a&gt; - komunikacja klient-serwer, w której klient potwierdza otrzymanie pakietu&lt;br /&gt;- protokół &lt;a href="http://pl.wikipedia.org/wiki/UDP"&gt;UDP&lt;/a&gt; - wysyłanie danych  bez kontroli przepływu i retransmisji; szybszy od TCP z uwagi na pominięcie "ceregieli" związanych z tym czy klient otrzymał i "zrozumiał".&lt;br /&gt;&lt;br /&gt;Nawiązując do poprzedniego, refleksyjnego posta:&lt;br /&gt;podczas jednej z ostatnich konferencji, bardzo dobry znajomy - o pseudonimie artystycznym &lt;i&gt;lburdz&lt;/i&gt; - wyświadczył mi nieocenioną przysługę udzielając następującego fidbeku:&lt;br /&gt;&lt;i&gt;Podczas prezentacji nie chodzi o najszybsze opróżnianie (właściwie to lepszym w tym kontekście słowem będzie wypróżnianie) buforów na strumień UDP. Trzeba traktować ludzi (publiczność) jak drugi koniec strumienia TCP.&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;//==============================&lt;br /&gt;&lt;br /&gt;Niby proste, ale jak dla mnie przełomowe! Może jeszcze komuś się przyda...&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5197374494377847819-566777057736851920?l=art-of-software.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://art-of-software.blogspot.com/feeds/566777057736851920/comments/default' title='Komentarze do posta'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5197374494377847819&amp;postID=566777057736851920' title='Komentarze (1)'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5197374494377847819/posts/default/566777057736851920'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5197374494377847819/posts/default/566777057736851920'/><link rel='alternate' type='text/html' href='http://art-of-software.blogspot.com/2011/04/tcp-vs-udp.html' title='TCP vs UDP'/><author><name>Sławek Sobótka</name><uri>http://www.blogger.com/profile/15082577671795313109</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='30' height='32' src='http://3.bp.blogspot.com/-tmFOhJC48_E/TkQ0G2DxrqI/AAAAAAAAAz8/WVGBaaS5a_Y/s220/zdjecie2.png'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5197374494377847819.post-5037782522401117702</id><published>2011-04-15T17:24:00.001+02:00</published><updated>2011-04-15T17:45:00.580+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Command Query Separation'/><category scheme='http://www.blogger.com/atom/ns#' term='Domain Driven Design'/><title type='text'>Pocztówka z wakacji</title><content type='html'>&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/-ons5Rjb_iT0/TahJazQ0R-I/AAAAAAAAAus/aihBny3ZBzY/s1600/tron.jpg" imageanchor="1" style="margin-left:1em; margin-right:1em"&gt;&lt;img border="0" height="240" width="320" src="http://2.bp.blogspot.com/-ons5Rjb_iT0/TahJazQ0R-I/AAAAAAAAAus/aihBny3ZBzY/s320/tron.jpg" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;Mam za sobą 10-dniowe "wakacje", z których to wrażeniami chciałbym się podzielić.&lt;br /&gt;Ostatnie 10 dni upłynęło mi na:&lt;br /&gt;- konferencji 4 developers&lt;br /&gt;- konferencji 33rd Degree&lt;br /&gt;- szkoleniu na temat Distributed DDD i CqRS prowadzonemu przez Grega Younga&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Podczas obu doskonałych konferencji obserwować można było wyraźnie pewne trendy.&lt;br /&gt;&lt;br /&gt;Mimo, że konferencje mają charakter techniczny, to dużym powodzeniem cieszą się tematy miękkie. Pisał o tym już Martin Fowler w swoim &lt;a href="http://martinfowler.com/bliki/CraftmanshipAndTheCrevasse.html"&gt;artykule&lt;/a&gt; w akapicie na temat &lt;a href="http://www.infoq.com/news/2010/08/agile2010-programmer-sessions"&gt;trendów konferencyjnych&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Generalne głosy ze świata są takie, że szczegóły techniczne można sobie zgłębiać w domu, a podczas konferencji mamy dostęp do wiedzy niedostępnej w literaturze z naszej branży. Cieszy fakt, że nadążamy za najnowszymi trendami - &lt;b&gt;ciekawy jestem Waszych opinii na ten temat&lt;/b&gt;.&lt;br /&gt;&lt;br /&gt;Kolejna obserwacja to wyraźny trend amerykanów - doskonała forma ale treść merytoryczna tak prosta, że miejscami ocierająca się o prostactwo (np. odpustowe sztuczki w aplikacjach klasy hello world;).&lt;br /&gt;&lt;br /&gt;Podczas 33rd degree prowadziliśmy wraz z kolegami z &lt;a href="http://ssepp.pl"&gt;ssepp&lt;/a&gt; panel dyskusyjny na temat profesji w naszej branży. Jako grupa zawodowa wciąż jednak zbytnio skupiamy się na rozgoryczeniu zamiast na działaniu w kierunku krystalizacji profesji.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Jednak trzydniowe szkolenie Grega było jeszcze bardziej intensywne pod względem mentalnym (towarzyskim również - wynajęliśmy na 5 dni wspólnie z Gregiem apartament:)&lt;br /&gt;&lt;br /&gt;Greg przedstawił wiele szczegółów technicznych związanych z jego podejściem do architektury CqRS i modelowania DDD. Poszerzył nam również horyzonty przedstawiając architektury systemów, które obsługują setki tysięcy transakcji na sekundę!&lt;br /&gt;Wniosek jest jeden: świat relacyjnych baz danych, popularnych frameworków i platform oraz standardowych warstw jest mocno ograniczający. Aby podejść do problemu o skali rzędu tysięcy na sekundę trzeba zaprzeczyć wszystko co stanowi naszą bazę wiedzy!&lt;br /&gt;&lt;br /&gt;Klimat panujący na szkoleniu był nie do opisania. Ponad trzydzieści osób z kraju i zagranicy operujących wspólnym poziomie abstrakcji, fechtujących technikami inżynierii oprogramowania z mistrzowską gracją. Bez kompromisów jakościowych - po prostu przy tej klasie problemu nie da się inaczej...&lt;br /&gt;&lt;br /&gt;Do tego doskonały prowadzący z szerokim wachlarzem kompetencji. Począwszy od szczegółów kompilatora poprzez paradygmaty programowania, wzorce projektowe i architektoniczne, znajomość całej klasyki oraz najnowszych zdobyczy inżynierii oprogramowania, metodyk prowadzenia projektów, kreowania wizerunku architektury jako produktu, technik negocjacji po ogólną erudycję sięgającą sieci neuronowych, algorytmów genetycznych, polityki itd itp.&lt;br /&gt;&lt;br /&gt;Kudos Greg.&lt;br /&gt;&lt;br /&gt;//==============================&lt;br /&gt;&lt;br /&gt;Nazywam ten czas wakacjami, ponieważ jestem typem &lt;a href="http://pl.wikipedia.org/wiki/Enneagram#Typ_nr_5_-_Obserwator_.28Prawdziwie_Neutralny.29"&gt;obserwatora&lt;/a&gt; (&lt;a href="http://pl.wikipedia.org/wiki/MBTI"&gt;perceiving&lt;/a&gt;), &lt;a href="http://pl.wikipedia.org/wiki/Meredith_Belbin"&gt;poszukiwacza&lt;/a&gt;. Dlatego cenię sobie stałą stymulację nowymi pomysłami oraz dyskusje z ludźmi wnoszącymi coś do sprawy, ponad leżenie na plaży.&lt;br /&gt;&lt;br /&gt;Patrząc z boku ciężko uwierzyć jak ktoś kto siedzi kilka godzin na konferencji/szkoleniu w bezruchu może przezywać ultra-intensywne doznania poznawcze:)))&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5197374494377847819-5037782522401117702?l=art-of-software.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://art-of-software.blogspot.com/feeds/5037782522401117702/comments/default' title='Komentarze do posta'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5197374494377847819&amp;postID=5037782522401117702' title='Komentarze (4)'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5197374494377847819/posts/default/5037782522401117702'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5197374494377847819/posts/default/5037782522401117702'/><link rel='alternate' type='text/html' href='http://art-of-software.blogspot.com/2011/04/pocztowka-z-wakacji.html' title='Pocztówka z wakacji'/><author><name>Sławek Sobótka</name><uri>http://www.blogger.com/profile/15082577671795313109</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='30' height='32' src='http://3.bp.blogspot.com/-tmFOhJC48_E/TkQ0G2DxrqI/AAAAAAAAAz8/WVGBaaS5a_Y/s220/zdjecie2.png'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/-ons5Rjb_iT0/TahJazQ0R-I/AAAAAAAAAus/aihBny3ZBzY/s72-c/tron.jpg' height='72' width='72'/><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5197374494377847819.post-6426289149223542739</id><published>2011-03-31T01:37:00.003+02:00</published><updated>2011-03-31T13:53:39.114+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Java'/><category scheme='http://www.blogger.com/atom/ns#' term='prezentacja'/><category scheme='http://www.blogger.com/atom/ns#' term='Craftsmanship'/><title type='text'>Dyskusje panelowe</title><content type='html'>Podczas &lt;a href="http://2011.4developers.org.pl/"&gt;4Developers&lt;/a&gt; będę prowadził dyskusję na temat braków w Javie (na różnym poziomie) i sposobach, narzędziach oraz podejściach na ich uzupełnianie.&lt;br /&gt;&lt;br /&gt;Podczas &lt;a href="http://33degree.org/"&gt;33rd Degree&lt;/a&gt; będziemy (wraz z kolegami z &lt;a href="http://ssepp.pl"&gt;SSEPP&lt;/a&gt;) prowadzić dyskusję na temat kompetencji, profesji i profesjonalizmu w naszej branży.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Formuła zakłada, że to Wy wnosicie wiedzę i doświadczenie oraz pytania i wątpliwości. To Wy nadajecie kierunek dyskusji w stronę, która Was interesuje.&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;4Developers&lt;/h3&gt;tytuł: &lt;b&gt;Java - czego nam brakuje, co warto dodać?&lt;/b&gt;&lt;br /&gt;temat przewodni:&lt;br /&gt;Po pewnym czasie pracy z niektórymi narzędziami zaczynamy zauważać ich&lt;br /&gt;braki - szczególnie gdy spróbujemy użyć narzędzi z innego zestawu.&lt;br /&gt;Wszyscy mamy zapewne przemyślenia na temat pewnych braków w&lt;br /&gt;technologii, której używamy.&lt;br /&gt;Część z nas ma inspirujące doświadczenia z innymi technologiami i podejściami.&lt;br /&gt;Podczas dyskusji chcemy zastanowić się nad sposobami uzupełnienia&lt;br /&gt;naszego warsztatu na poziomie: składni, struktury, narzędzi, podejść,&lt;br /&gt;itd.&lt;br /&gt;Uzupełnienia poprzez: biblioteki, frameworki, pluginy, nowe best practices.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;33rd Degree&lt;/h3&gt;tytuł: &lt;b&gt;Dokąd zmierza Software Craftsmanship&lt;/b&gt;&lt;br /&gt;temat przewodni:&lt;br /&gt;Ruch Software Craftsmanship jest odpowiedzią na pojawiające się potrzeby problemy.&lt;br /&gt;&lt;br /&gt;Jest to jednak ogólna idea. Warto jednak zastanowić się nad konkretami:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;jakimi cechami powinien charakteryzować się profesjonalista&lt;br /&gt;&lt;li&gt;jaki zakres bazowych kompetencji powinien posiadać profesjonalista&lt;br /&gt;&lt;li&gt;ew. jakie poziomy kompetencji możemy próbować określać&lt;br /&gt;&lt;li&gt;być może zależy to od klasy problemów&lt;br /&gt;&lt;li&gt;czy nadszedł już czas na krystalizację profesji - czy mamy właściwą ilość doświadczeń&lt;br /&gt;&lt;li&gt;czy i kiedy warto mówić o profesjonalizmie - kiedy jest on potrzeby i kiedy wnosi wartość&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;//=============================&lt;br /&gt;&lt;br /&gt;Jeżeli macie jakieś sugestie odnośnie prezentacji lub dyskusji to zapraszam do pisania komentarzy lub na prv.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5197374494377847819-6426289149223542739?l=art-of-software.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://art-of-software.blogspot.com/feeds/6426289149223542739/comments/default' title='Komentarze do posta'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5197374494377847819&amp;postID=6426289149223542739' title='Komentarze (2)'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5197374494377847819/posts/default/6426289149223542739'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5197374494377847819/posts/default/6426289149223542739'/><link rel='alternate' type='text/html' href='http://art-of-software.blogspot.com/2011/03/dyskusje-panelowe.html' title='Dyskusje panelowe'/><author><name>Sławek Sobótka</name><uri>http://www.blogger.com/profile/15082577671795313109</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='30' height='32' src='http://3.bp.blogspot.com/-tmFOhJC48_E/TkQ0G2DxrqI/AAAAAAAAAz8/WVGBaaS5a_Y/s220/zdjecie2.png'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5197374494377847819.post-3976733207475286013</id><published>2011-03-30T01:25:00.003+02:00</published><updated>2011-03-31T14:01:48.052+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Command Query Separation'/><category scheme='http://www.blogger.com/atom/ns#' term='Domain Driven Design'/><category scheme='http://www.blogger.com/atom/ns#' term='prezentacja'/><category scheme='http://www.blogger.com/atom/ns#' term='Distributed Domain Driven Design'/><title type='text'>Tydzień segregacji</title><content type='html'>Zbliżający się tydzień to dwie konferencje:&lt;br /&gt;- &lt;a href="http://2011.4developers.org.pl"&gt;4 Developers&lt;/a&gt;&lt;br /&gt;- &lt;a href="http://33degree.org/"&gt;33rd Degree&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Przygotowałem dla Was prezentację na temat Command-query Responsibility Segregation, którą przedstawię na obu konferencjach.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Poniżej wersja alfa.&lt;br /&gt;&lt;br /&gt;&lt;div class="prezi-player"&gt;&lt;style type="text/css" media="screen"&gt;.prezi-player { width: 450px; } .prezi-player-links { text-align: center; }&lt;/style&gt;&lt;object id="prezi_nywckem9elvc" name="prezi_nywckem9elvc" classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" width="450" height="400"&gt;&lt;param name="movie" value="http://prezi.com/bin/preziloader.swf"/&gt;&lt;param name="allowfullscreen" value="true"/&gt;&lt;param name="allowscriptaccess" value="always"/&gt;&lt;param name="bgcolor" value="#ffffff"/&gt;&lt;param name="flashvars" value="prezi_id=nywckem9elvc&amp;amp;lock_to_path=0&amp;amp;color=ffffff&amp;amp;autoplay=no&amp;amp;autohide_ctrls=0"/&gt;&lt;embed id="preziEmbed_nywckem9elvc" name="preziEmbed_nywckem9elvc" src="http://prezi.com/bin/preziloader.swf" type="application/x-shockwave-flash" allowfullscreen="true" allowscriptaccess="always" width="450" height="400" bgcolor="#ffffff" flashvars="prezi_id=nywckem9elvc&amp;amp;lock_to_path=0&amp;amp;color=ffffff&amp;amp;autoplay=no&amp;amp;autohide_ctrls=0"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;div class="prezi-player-links"&gt;&lt;p&gt;&lt;a title="CqRS, Domain Driven Design, Event Sourcing, etc" href="http://prezi.com/nywckem9elvc/command-query-responsibility-segregation-nowe-bardziej-racjonalne-podejscie-do-warstw/"&gt;Command-query Responsibility Segregation - nowe, bardziej racjonalne podejście do warstw&lt;/a&gt; on &lt;a href="http://prezi.com"&gt;Prezi&lt;/a&gt;&lt;/p&gt;&lt;/div&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;Prezentacja zgodnie z najnowszymi trendami nie zawiera zbyt wiele tekstu - całość wymaga akompaniamentu paszczowego.&lt;br /&gt;&lt;br /&gt;W świecie Javy mamy ostatnio stagnację (frameworki webowe już nie wychodzą co tydzień, a skoro najnowsze wersja Java EE wyszła rok temu to mamy kilka lat spokoju;). Jest to zatem dobry moment na &lt;a href="http://en.wikipedia.org/wiki/The_Seven_Habits_of_Highly_Effective_People"&gt;ostrzenie piły&lt;/a&gt; - np zastanowienie się nad podstawami. &lt;br /&gt;&lt;br /&gt;Ogólne przesłanie prezentacji: wybór narzędzia i podejścia powinien zależeć od &lt;b&gt;klasy problemu&lt;/b&gt;.&lt;br /&gt;&lt;br /&gt;W świecie Javy mamy z jednej strony platformę korporacyjną, która była pomyślana jako produkt dla klientów (wytwórców oprogramowania) wielkiej skali. Po nasyceniu tego rynku mamy widoczną zmianę strategii marketingowej i atakowanie małych softwarehousów. Z drugiej strony mamy mnogość rozwiązań typu generator jednowarstwowej aplikacji, którymi próbuje się kusić każdego - nawet duże softwarehousy.&lt;br /&gt;&lt;br /&gt;W prezentacji przedstawię rozwiązania architektoniczne podpatrzone w świecie .NET. Nie są one specyficzne dla .NET ale w tej społeczności są mocniej rozwijane i dyskutowane niż w naszej.&lt;br /&gt;&lt;br /&gt;Warto podkreślić, że koncepcja architektoniczna CqRS &lt;b&gt;została wypracowana w ciągu kilku ostatnich lat przez community&lt;/b&gt;. Nie jest to zatem objawienie zesłane przez anonimowych pracowników jakiejś firmy, lecz wynik dyskusji i eksperymentów nad rzeczywistymi problemami. Jest to zatem owoc pracy ludzi żywo zaangażowanych w sprawę - stąd wartość.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Mottem dla mojej prezentacji będzie ewolucja architektury, czyli jej rozbudowa wraz ze wzrostem skali (komplikacji i wielkości) systemu. Wychodzę z założenia, że &lt;b&gt;nie każde podejście może ewoluować&lt;/b&gt;.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Dla zainteresowanych prezentacją mam sugestię: warto wcześniej zapoznać się z moją prezentacją na temat Domain Driven Design. Nie jest to konieczne, ale jeżeli to zrobicie, to całość ułoży się w sumie w spójne rozwiązanie.&lt;br /&gt;Link &lt;a href="http://art-of-software.blogspot.com/2011/02/ddd-we-wrocawiu.html"&gt;tutaj&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Tydzień segregacji właściwie zostanie wydłużony...&lt;br /&gt;&lt;br /&gt;W kolejnym tygodniu Greg Young będzie prowadził otwarty wykład i 3-dniowe szkolenie na temat DDD i CqRS w Krakowie (&lt;a href="http://www.kgdnet.pl/events/16985567/?eventId=16985567&amp;action=detail"&gt;szczegóły&lt;/a&gt;).&lt;br /&gt;&lt;br /&gt;Nieczęsto zdarza się możliwość uczenia od mistrza, tak więc polecam:)&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;//=================================&lt;br /&gt;&lt;br /&gt;Jeżeli ktoś ma uwagi/sugestie odnośnie prezentacji (treść, zakres) to piszcie w komentarzach lub na prv.&lt;br /&gt;Będę bardzo wdzięczny za feedback:)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5197374494377847819-3976733207475286013?l=art-of-software.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://art-of-software.blogspot.com/feeds/3976733207475286013/comments/default' title='Komentarze do posta'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5197374494377847819&amp;postID=3976733207475286013' title='Komentarze (8)'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5197374494377847819/posts/default/3976733207475286013'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5197374494377847819/posts/default/3976733207475286013'/><link rel='alternate' type='text/html' href='http://art-of-software.blogspot.com/2011/03/tydzien-segregacji.html' title='Tydzień segregacji'/><author><name>Sławek Sobótka</name><uri>http://www.blogger.com/profile/15082577671795313109</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='30' height='32' src='http://3.bp.blogspot.com/-tmFOhJC48_E/TkQ0G2DxrqI/AAAAAAAAAz8/WVGBaaS5a_Y/s220/zdjecie2.png'/></author><thr:total>8</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5197374494377847819.post-6913857072683932075</id><published>2011-03-25T12:03:00.007+01:00</published><updated>2011-03-25T14:19:32.260+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Command Query Separation'/><category scheme='http://www.blogger.com/atom/ns#' term='Domain Driven Design'/><category scheme='http://www.blogger.com/atom/ns#' term='Distributed Domain Driven Design'/><title type='text'>Greg Young w Polsce! (UWAGA KONKURS)</title><content type='html'>&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/-In1BO97LohU/TYx2eOChVWI/AAAAAAAAAuE/RTpHcRSGYy4/s1600/young_mini.jpg" imageanchor="1" style="margin-left:1em; margin-right:1em"&gt;&lt;img border="0" height="310" width="229" src="http://4.bp.blogspot.com/-In1BO97LohU/TYx2eOChVWI/AAAAAAAAAuE/RTpHcRSGYy4/s320/young_mini.jpg" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;Mamy już kompletną agendę konferencji &lt;a href="http://2011.4developers.org.pl/"&gt;4Developers&lt;/a&gt;, zatem mogę oficjalnie powiedzieć, że Greg Young, którego udało się nam zaprosić do Polski, przedstawi dwie prezentacje:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;&lt;a href="http://2011.4developers.org.pl/java-agenda"&gt;Zapomnij o szczegółach, liczy się efekt!&lt;/a&gt; - jest to nowa, jeszcze nie publikowana prezentacja, którą Greg przygotował specjalnie dla nas na 4Dev&lt;br /&gt;&lt;li&gt;&lt;a href="http://2011.4developers.org.pl/wydajnosc-skalowalnosc-agenda"&gt;Uwolnij swoją domenę!&lt;/a&gt; - przekrojowa prezentacja, która udowadnia, że możemy skonstruować wysokowydajny, skalowalny system, zachowując nieautystyczny model domeny biznesowej. Czyli jak połączyć Domain Driven Design, Commmand-query Responsibility Segregation, Event Sourcing oraz kilka innych najnowszych zdobyczy inżynierii oprogramowania.&lt;br /&gt;&lt;/ol&gt;Od siebie dodam, że Greg należy do mojej ścisłej czołówki guru współczesnej inżynierii oprogramowania. Posiada tytuł Most Valuable Person Microsoftu, jest głównych twórcą koncpecji architektonicznej &lt;a href="http://cqrsinfo.com/"&gt;CqRS&lt;/a&gt; oraz wniósł duży wkład w rozwój Domain Driven Design.   Dodatkowo potrafi z pasją opowiadać historie o zaawansowanych koncepcyjnie technikach, w taki sposób, że doznajemy efektu "I know Kung Fu".    &lt;br&gt;&lt;br&gt;&lt;iframe title="YouTube video player" width="480" height="390" src="http://www.youtube.com/embed/6vMO3XmNXe4" frameborder="0" allowfullscreen&gt;&lt;/iframe&gt;    &lt;br&gt;&lt;br&gt;btw: czy ktoś z Was odważyłby się wystąpić ze slajdami w TAKIM stylu: &lt;a href="http://domaindrivendesign.org/library/young_2010"&gt;7 Reasons DDD Projects #FAIL&lt;/a&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;        //=========================&lt;br&gt;&lt;br&gt;   &lt;b&gt;KONKURS&lt;/b&gt;&lt;br&gt;&lt;br&gt;    Rejestracja na 4Dev będzie trwać już tylko do końca marca, a dla czytelników bloga mamy niespodziankę w postaci &lt;b&gt;darmowej wejściówki&lt;/b&gt;.  &lt;br&gt;&lt;br&gt;Zasady są proste: wygrywa osoba o największej ilości komentarzy pod postami na moim blogasku. Chodzi oczywiście o posty wystawione przed ogłoszeniem konkursu:0 Zgłoszenia wraz z linkami do komentowanych postów przysyłajcie na maila podanego w sekcji "o mnie". &lt;br&gt;&lt;br&gt;Proszę o udział tylko tych z Was, których potencjalne szanse na przybycie na konferencję wynoszą 99% (obecność sprawdzę osobiście;)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5197374494377847819-6913857072683932075?l=art-of-software.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://art-of-software.blogspot.com/feeds/6913857072683932075/comments/default' title='Komentarze do posta'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5197374494377847819&amp;postID=6913857072683932075' title='Komentarze (4)'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5197374494377847819/posts/default/6913857072683932075'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5197374494377847819/posts/default/6913857072683932075'/><link rel='alternate' type='text/html' href='http://art-of-software.blogspot.com/2011/03/greg-young-w-polsce-uwaga-konkurs.html' title='Greg Young w Polsce! (UWAGA KONKURS)'/><author><name>Sławek Sobótka</name><uri>http://www.blogger.com/profile/15082577671795313109</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='30' height='32' src='http://3.bp.blogspot.com/-tmFOhJC48_E/TkQ0G2DxrqI/AAAAAAAAAz8/WVGBaaS5a_Y/s220/zdjecie2.png'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/-In1BO97LohU/TYx2eOChVWI/AAAAAAAAAuE/RTpHcRSGYy4/s72-c/young_mini.jpg' height='72' width='72'/><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5197374494377847819.post-2114177590570563099</id><published>2011-02-13T21:09:00.001+01:00</published><updated>2011-02-13T21:13:08.825+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Domain Driven Design'/><category scheme='http://www.blogger.com/atom/ns#' term='JUG'/><category scheme='http://www.blogger.com/atom/ns#' term='prezentacja'/><title type='text'>DDD we Wrocławiu</title><content type='html'>&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/-lpY1jNnZCfQ/TVg6emxZsDI/AAAAAAAAAts/Ruyk7k7xKQE/s1600/wroclaw.jpg" imageanchor="1" style="margin-left:1em; margin-right:1em"&gt;&lt;img border="0" height="236" width="320" src="http://2.bp.blogspot.com/-lpY1jNnZCfQ/TVg6emxZsDI/AAAAAAAAAts/Ruyk7k7xKQE/s320/wroclaw.jpg" /&gt;&lt;/a&gt;&lt;/div&gt;Dzięki uprzejmości Pawła Szulca na vimeo pojawiła się moja prezentacja na temat Domain Driven Design (i kilku tematów dodatkowych), którą przedstawiłem podczas spotkania&lt;a href="http://groups.google.com/group/wroclaw-jug"&gt; Wrocławskiego JUG&lt;/a&gt;.&lt;br /&gt;&lt;a href="http://www.vimeo.com/19844548"&gt;część 1&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.vimeo.com/19847508"&gt;część 2&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Dziękuję wszystkim za aktywne uczestnictwo:)&lt;br /&gt;&lt;br /&gt;//================================&lt;br /&gt;&lt;br /&gt;Nawiązanie do community .NET jako przodującego w poszukiwaniu nowych (a może klasycznych?) i lepszych metod modelowania jest zabiegiem celowym, mającym na celu zdopingowanie Was do działania.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5197374494377847819-2114177590570563099?l=art-of-software.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://art-of-software.blogspot.com/feeds/2114177590570563099/comments/default' title='Komentarze do posta'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5197374494377847819&amp;postID=2114177590570563099' title='Komentarze (11)'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5197374494377847819/posts/default/2114177590570563099'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5197374494377847819/posts/default/2114177590570563099'/><link rel='alternate' type='text/html' href='http://art-of-software.blogspot.com/2011/02/ddd-we-wrocawiu.html' title='DDD we Wrocławiu'/><author><name>Sławek Sobótka</name><uri>http://www.blogger.com/profile/15082577671795313109</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='30' height='32' src='http://3.bp.blogspot.com/-tmFOhJC48_E/TkQ0G2DxrqI/AAAAAAAAAz8/WVGBaaS5a_Y/s220/zdjecie2.png'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/-lpY1jNnZCfQ/TVg6emxZsDI/AAAAAAAAAts/Ruyk7k7xKQE/s72-c/wroclaw.jpg' height='72' width='72'/><thr:total>11</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5197374494377847819.post-5263006308868532395</id><published>2011-02-04T20:16:00.005+01:00</published><updated>2011-02-04T21:09:01.613+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='JUG'/><category scheme='http://www.blogger.com/atom/ns#' term='prezentacja'/><category scheme='http://www.blogger.com/atom/ns#' term='wzorce projektowe'/><title type='text'>keepaliver.ping()</title><content type='html'>Sporo czasu minęło od ostatniego posta. Powód jak zwykle ten sam - zgodnie ze starym chińskim przysłowiem: "Jest czas na pracę i jest czas na zbieranie ryżu".&lt;br /&gt;&lt;br /&gt;Ale mimo nawału pracy mam dla Was trochę materiałów:&lt;br /&gt;&lt;br /&gt;1. Prezentacja "Software Craftsmanship - Język wzorców językiem profesjonalistów"&lt;br /&gt;Dzięki uprzejmości &lt;a href="http://dailylog.lenart.org.pl/"&gt;Łukasza Lenarta&lt;/a&gt; na parleys pojawiła się moja &lt;a href="http://beta.parleys.com/#id=2272&amp;sl=3&amp;st=5"&gt;prezentacja&lt;/a&gt; z zeszłorocznej &lt;a href="http://www.javarsovia.pl/"&gt;javarsowi&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;2. Prezentacja "Domain Driven Design. Wszystko jest na miejscu i wszystko ma swoje miejsce".&lt;br /&gt;Najbliższy tydzień spędzam we Wrocławiu. Przy okazji, na zaproszenie Pawła Zubkiewicza - lidera wrocławskiego JUGa - opowiem o DDD; &lt;a href="http://groups.google.com/group/wroclaw-jug/browse_thread/thread/816d5b57e184d667#"&gt;szczegóły&lt;/a&gt;.&lt;br /&gt;Z braku czasu będzie to ta sama prezentacja, którą przedstawiałem na zeszłorocznym &lt;a href="http://www.dworld.pl/static/nyac/"&gt;NYAC&lt;/a&gt;. Slajdy będą te same, ale od czerwca zgromadziłem nowe doświadczenia, o których będę chciał opowiedzieć.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Natomiast w kwietniu szykuję dla Was nowy materiał - prezentację "Command-query Responsibility Segregation - nowe, bardziej racjonalne podejście do warstw". Mam ambitny plan aby forma graficzna tej prezentacji była mocno odmienna od wszystkiego co do tej pory pokazywałem.&lt;br /&gt;&lt;br /&gt;Materiał będzie można zobaczyć na konferencjach:&lt;br /&gt;- &lt;a href="http://33degree.org/talks.html#CqRS"&gt;33rd Degree&lt;/a&gt;&lt;br /&gt;- &lt;a href="http://4developers.org.pl/java-agenda"&gt;4 Developers&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Zapraszam serdecznie na obie konferencje. Myślę, że agenda 33rd Degree już teraz wygląda bardzo zachęcająco.&lt;br /&gt;Natomiast jako członek &lt;a href="http://4developers.org.pl/committee"&gt;komitetu programowego&lt;/a&gt; 4 Developers zdradzę, że również będzie ciekawie:)&lt;br /&gt;&lt;br /&gt;//==========================&lt;br /&gt;&lt;br /&gt;Kolejne posty merytoryczne powinny pojawić się pod koniec miesiąca.&lt;br /&gt;Chociaż przyznam, że Java i inżynieria oprogramowania muszą konkurować o zasoby z moją nową zabawką - audiofilskim zestawem stereo, który trzeba co chwilę testować na nowych kablach, płytach i w nowych rozmieszczeniach (ostrzegam - nie dajcie się w to wciągnąć) ;P&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5197374494377847819-5263006308868532395?l=art-of-software.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://art-of-software.blogspot.com/feeds/5263006308868532395/comments/default' title='Komentarze do posta'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5197374494377847819&amp;postID=5263006308868532395' title='Komentarze (12)'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5197374494377847819/posts/default/5263006308868532395'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5197374494377847819/posts/default/5263006308868532395'/><link rel='alternate' type='text/html' href='http://art-of-software.blogspot.com/2011/02/keepaliverping.html' title='keepaliver.ping()'/><author><name>Sławek Sobótka</name><uri>http://www.blogger.com/profile/15082577671795313109</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='30' height='32' src='http://3.bp.blogspot.com/-tmFOhJC48_E/TkQ0G2DxrqI/AAAAAAAAAz8/WVGBaaS5a_Y/s220/zdjecie2.png'/></author><thr:total>12</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5197374494377847819.post-757119041750988377</id><published>2010-10-22T09:55:00.000+02:00</published><updated>2011-02-13T21:11:18.053+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Command Query Separation'/><category scheme='http://www.blogger.com/atom/ns#' term='Domain Driven Design'/><category scheme='http://www.blogger.com/atom/ns#' term='prezentacja'/><title type='text'>Warsjawa 2010</title><content type='html'>Zapraszam wszystkich czytelników bloga na prezentację &lt;i&gt;Domain Driven Design - Wszystko ma swoje miejsce i wszystko jest na miejscu&lt;/i&gt;, którą przedstawiam w najbliższą sobotę na konferencji &lt;a href="warsjawa.pl"&gt;Warsjawa&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Skrót:&lt;br /&gt;Czy zastanawialiście się co jest przyczyną rozkładu średnich i dużych systemów? Czy jest on nieunikniony i jest jedynie kwestią czasu? A może jednak istnieje jakiś sposób na utrzymanie entropii w ryzach?&lt;br /&gt;&lt;br /&gt;Podczas prezentacji zobaczymy w jaki sposób Domain Driven Design pomaga w okiełznaniu chaosu. W prezentacji znajdą się główne techniki modelowania takie jak Ubiquitous Language, Bounded Context, Strategic Design.&lt;br /&gt;&lt;br /&gt;Zostaną przedstawione również podstawowe techniki implementacji DDD: przykłady Building Blocks, Command-query Responsibility Segregation, system zdarzeń, przypadki wykorzystania ORM i SQL - całość na przykładach w Seam lub Spring.&lt;br /&gt;&lt;br /&gt;//===========================&lt;br /&gt;&lt;br /&gt;Dla tych z Was, którzy byli w Krakowie na NYAC zaznaczam, że core prezentacji będzie taki sam.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5197374494377847819-757119041750988377?l=art-of-software.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://art-of-software.blogspot.com/feeds/757119041750988377/comments/default' title='Komentarze do posta'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5197374494377847819&amp;postID=757119041750988377' title='Komentarze (0)'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5197374494377847819/posts/default/757119041750988377'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5197374494377847819/posts/default/757119041750988377'/><link rel='alternate' type='text/html' href='http://art-of-software.blogspot.com/2010/10/warsjawa-2010.html' title='Warsjawa 2010'/><author><name>Sławek Sobótka</name><uri>http://www.blogger.com/profile/15082577671795313109</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='30' height='32' src='http://3.bp.blogspot.com/-tmFOhJC48_E/TkQ0G2DxrqI/AAAAAAAAAz8/WVGBaaS5a_Y/s220/zdjecie2.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5197374494377847819.post-6089871940043484573</id><published>2010-10-21T01:08:00.008+02:00</published><updated>2010-10-21T01:18:37.588+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Seam'/><title type='text'>Turbo Seam</title><content type='html'>Niniejszy post rozpoczyna mini serię poświęconą &lt;a href="http://seamframework.org"&gt;Seam Framework&lt;/a&gt;. Zawartość to kilka przydatnych technik oraz kilka trików, które udało mi się zebrać podczas paru lat używania tego "ficzer"-worka.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Spis treści&lt;/h3&gt;- &lt;b&gt;Produktywne środowisko developerskie&lt;/b&gt;. Hot deploy wszystkiego. Nawet encji (a podobno się nie da;P) W najgorszym przypadku 3 sek. na przeładowanie.&lt;br /&gt;- &lt;b&gt;Integracja z Maven&lt;/b&gt; - elegancko i bezboleśnie. Panom od JBoss Tools już podziękujemy...&lt;br /&gt;- &lt;b&gt;Integracja z jQuery&lt;/b&gt; - gdy ciężar RichFaces przygniata, narzut na komunikację AJAX osłabia a kontrolki wyglądają jak z poprzedniej epoki&lt;br /&gt;- &lt;b&gt;Asynchroniczny mailing w dobrym stylu&lt;/b&gt; - mikro architektura rozsyłania maili połączona z eleganckim decoupliniem poprzez zdarzenia&lt;br /&gt;- &lt;b&gt;Integracja z BIRT&lt;/b&gt; - speszyl haki&lt;br /&gt;- &lt;b&gt;Seam Gen i Seam App. Framework&lt;/b&gt; - dlaczego nie używać:)&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Powyższa lista będzie sukcesywnie aktualizowana o linki do konkretnych postów oraz ew. nowe pozycje. Docelowo post będzie stanowił swego rodzaju spis treści.&lt;br /&gt;&lt;br /&gt;//==============================&lt;br /&gt;&lt;br /&gt;Generalnie do tej pory nie pisałem zbyt wielu postów technicznych - wychodząc z założenia, że w oceanie treści nie będą wnosić nic nowego.&lt;br /&gt; &lt;br /&gt;Jednak zestawiając dwa aspekty:&lt;br /&gt;- własne przemyślenia&lt;br /&gt;- obserwując jak Seam jest używany&lt;br /&gt;doszedłem do wniosku, że zgromadzona wiedza może się komuś przydać.&lt;br /&gt;&lt;br /&gt;Jeżeli macie jakieś tematy, które chcielibyście poruszyć - piszcie śmiało, być może dodamy je do listy.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5197374494377847819-6089871940043484573?l=art-of-software.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://art-of-software.blogspot.com/feeds/6089871940043484573/comments/default' title='Komentarze do posta'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5197374494377847819&amp;postID=6089871940043484573' title='Komentarze (14)'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5197374494377847819/posts/default/6089871940043484573'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5197374494377847819/posts/default/6089871940043484573'/><link rel='alternate' type='text/html' href='http://art-of-software.blogspot.com/2010/10/turbo-seam.html' title='Turbo Seam'/><author><name>Sławek Sobótka</name><uri>http://www.blogger.com/profile/15082577671795313109</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='30' height='32' src='http://3.bp.blogspot.com/-tmFOhJC48_E/TkQ0G2DxrqI/AAAAAAAAAz8/WVGBaaS5a_Y/s220/zdjecie2.png'/></author><thr:total>14</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5197374494377847819.post-3608195069075168710</id><published>2010-10-13T01:54:00.002+02:00</published><updated>2010-10-18T12:08:22.245+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='śmieszne'/><category scheme='http://www.blogger.com/atom/ns#' term='OOP'/><category scheme='http://www.blogger.com/atom/ns#' term='OOD'/><title type='text'>Przyczyna całego zła</title><content type='html'>Dziś kolejny post z serii &lt;a href="http://art-of-software.blogspot.com/search/label/śmieszne"&gt;geek humor&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Prawdopodobnie odkryłem przyczynę całego zła w projektach, bałaganu, złego designu modelu obiektowego i naszego ulubionego kodu spaghetti.&lt;br /&gt;&lt;br /&gt;Jest nią najprawdopodobniej totalnie niezrozumienie polimorfizmu!&lt;br /&gt;&lt;br /&gt;Tutaj znajdziemy oświecenie: &lt;a href="http://www-users.mat.umk.pl/~grzegorz/polymorphism.pdf"&gt;http://www-users.mat.umk.pl/~grzegorz/polymorphism.pdf&lt;/a&gt;&lt;br /&gt;.. gdyby tak każdy programista się z nim zapoznał, to świat byłby lepszy;)&lt;br /&gt;&lt;br /&gt;//===============================&lt;br /&gt;&lt;br /&gt;Jeżeli macie jakieś ciekawe materiały edukacyjne to wklejajcie w komentarzach.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5197374494377847819-3608195069075168710?l=art-of-software.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://art-of-software.blogspot.com/feeds/3608195069075168710/comments/default' title='Komentarze do posta'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5197374494377847819&amp;postID=3608195069075168710' title='Komentarze (23)'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5197374494377847819/posts/default/3608195069075168710'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5197374494377847819/posts/default/3608195069075168710'/><link rel='alternate' type='text/html' href='http://art-of-software.blogspot.com/2010/10/przyczyna-caego-za.html' title='Przyczyna całego zła'/><author><name>Sławek Sobótka</name><uri>http://www.blogger.com/profile/15082577671795313109</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='30' height='32' src='http://3.bp.blogspot.com/-tmFOhJC48_E/TkQ0G2DxrqI/AAAAAAAAAz8/WVGBaaS5a_Y/s220/zdjecie2.png'/></author><thr:total>23</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5197374494377847819.post-638530214618515565</id><published>2010-09-05T13:09:00.001+02:00</published><updated>2010-09-05T13:38:52.897+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Domain Driven Design'/><category scheme='http://www.blogger.com/atom/ns#' term='Behaviour-Driven Development'/><category scheme='http://www.blogger.com/atom/ns#' term='Agile'/><category scheme='http://www.blogger.com/atom/ns#' term='linki'/><title type='text'>Głuchy telefon</title><content type='html'>&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/_m-NewLwJEb8/TINzIUXqsFI/AAAAAAAAAq8/V2z73pqgQFk/s1600/gluchy_telefon.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://1.bp.blogspot.com/_m-NewLwJEb8/TINzIUXqsFI/AAAAAAAAAq8/V2z73pqgQFk/s320/gluchy_telefon.jpg" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;Głuchy telefon - intrygująca i dająca do myślenia zabawa z dzieciństwa, gdzie nawet bardzo prosta "informacja" może zostać zniekształcona po przejściu przez łańcuch "przekaźników".&lt;br /&gt;&lt;br /&gt;Kultowy obrazek z huśtawką (który wszyscy znamy) obrazuje co dzieje się z informacją nieco bardziej wyrafinowaną (np. na temat wymagań) w procesie produkcji softu.&lt;br /&gt;&lt;br /&gt;Jak temu zapobiec?&lt;br /&gt;Racjonalnym rozwiązaniem jest Ubiquitous Language - kluczowa technika w Domain Driven Design polegająca na operowaniu wspólnym słownictwem domenowym na każdym poziomie abstrakcji: począwszy od eksperta biznesowego po kod źródłowy (sic!) w warstwie logiki aplikacji i logiki domenowej. W logice domenowej oczywiście obowiązuje ścisła "etykieta" - korzystanie z dobrze zdefiniowanych &lt;a href="http://art-of-software.blogspot.com/2009/10/jug-jdd-ddd-cooluary-v3-podsumowanie.html"&gt;Building Blocks&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;W tym miejscu dochodzimy do sedna posta.&lt;br /&gt;Zachęcam do zapoznania się z prezentacją mego guru - Erica Evansa: "&lt;a href="http://www.infoq.com/presentations/Sustainable-Design-for-Agile-Eric-Evans"&gt;Sustainable Design for Agile Teams&lt;/a&gt;" podczas, której mamy próbkę sesji analitycznej pomiędzy programistą a ekspertem domenowym. Zwróćcie uwagę na dobrze zdefiniowany, wspólny język jakim posługują się obie strony oraz w jaki sposób "odkrywają" nowe byty.&lt;br /&gt;&lt;br /&gt;Oczywiście taki proces nie jest tani oraz wymaga cennego zasobu: eksperta domenowego:/&lt;br /&gt;&lt;br /&gt;//===========================================&lt;br /&gt;&lt;br /&gt;Prezentacja porusza również inny, arcyważny aspekt: niezrozumienie projektowania domeny w naiwnym podejściu do Agile. Kiedy skupiamy się na pojedynczym wymaganiu lub na pojedynczej iteracji, wówczas zwykle mamy do czynienia ze &lt;b&gt;specjalnym przypadkiem&lt;/b&gt;  procesu biznesowego w jakiejś domenie. Gubimy "biger pikczer" i z czasem całość sprowadza się do radosnego (później smutnego) "hakowania" kodu opisującego jakieś specjalne przypadki - zaszłości. I nie ma co się oszukiwać - nikt nie jest skory do refaktoringu modelu domenowego, który jest już napełniony danymi w bazie:)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5197374494377847819-638530214618515565?l=art-of-software.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://art-of-software.blogspot.com/feeds/638530214618515565/comments/default' title='Komentarze do posta'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5197374494377847819&amp;postID=638530214618515565' title='Komentarze (2)'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5197374494377847819/posts/default/638530214618515565'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5197374494377847819/posts/default/638530214618515565'/><link rel='alternate' type='text/html' href='http://art-of-software.blogspot.com/2010/09/guchy-telefon.html' title='Głuchy telefon'/><author><name>Sławek Sobótka</name><uri>http://www.blogger.com/profile/15082577671795313109</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='30' height='32' src='http://3.bp.blogspot.com/-tmFOhJC48_E/TkQ0G2DxrqI/AAAAAAAAAz8/WVGBaaS5a_Y/s220/zdjecie2.png'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_m-NewLwJEb8/TINzIUXqsFI/AAAAAAAAAq8/V2z73pqgQFk/s72-c/gluchy_telefon.jpg' height='72' width='72'/><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5197374494377847819.post-4246767392316272943</id><published>2010-08-10T16:02:00.005+02:00</published><updated>2010-08-10T18:32:11.711+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='prezentacja'/><category scheme='http://www.blogger.com/atom/ns#' term='Architektura'/><title type='text'>Pomożecie?</title><content type='html'>&lt;div align="center"&gt;&lt;/div&gt;&lt;div align="center"&gt;&lt;a href="http://3.bp.blogspot.com/_m-NewLwJEb8/TGFV7HvDdyI/AAAAAAAAAqM/jGghBaeptrw/s1600/gierek.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://3.bp.blogspot.com/_m-NewLwJEb8/TGFV7HvDdyI/AAAAAAAAAqM/jGghBaeptrw/s320/gierek.jpg" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;Dzisiejszy post jest nietypowy, ponieważ zwracam się w nim do szanownego grona czytelników z prośbą o pomoc/przysługę. Zostałem zaproszony na tegoroczną konferencję &lt;a href="http://10.jdd.org.pl/"&gt;JDD&lt;/a&gt; w roli prelegenta i zastanawiam się nad tematem, który mógłby Was potencjalnie (nawet jeżeli nie wybieracie się na konferencję, po prostu ogólnie) zainteresować.&lt;br /&gt;&lt;br /&gt;Prezentacja poświęcona &lt;a href="http://art-of-software.blogspot.com/2010/04/majowa-ewangelizacja-software.html"&gt;Software Craftsmanship i Wzorcom&lt;/a&gt; już osiągnęła limit reużywalności, dlatego zastanawiam się nad nowym tematem:) Jeżeli macie jakieś sugestie lub konkretne życzenia odnośnie tego o czym chcielibyście usłyszeć to piszcie śmiało w komentarzu lub na priv (adres w panelu "o mnie" po prawej stronie).&lt;br /&gt;&lt;br /&gt;//===============================&lt;br /&gt;&lt;br /&gt;Patrząc na ogólne trendy, które w tym roku widać również na polskich konferencjach, można zaobserwować, że raczej odchodzi się od zachwalania kolejnych tuzinów frameworków webowych w stronę zagadnień bardziej ogólnych, zwykle syntetyzując przekrój kilku aspektów. Ciekaw jestem co myślicie o tym trendzie.&lt;br /&gt;&lt;br /&gt;Póki co mam pewien pomysł na prezentację poświęconą podejściom do Inversion of Control. Tak, wiem, że temat jest oklepany ale co powiecie na przegląd architektur &lt;b&gt;aplikacji&lt;/b&gt; opartych o IoC. Przegląd będący swego rodzaju wycieczką po rozwiązaniach architektonicznych.&lt;br /&gt;&lt;br /&gt;Najpierw zastanowilibyśmy się czym w ogóle jest architektura, jakie są jej rodzaje i czym arch. różni się od designu. Później wycieczka po kolejnych podejściach do architektur opartych o 3 techniki IoC w kolejności ich "siły".&lt;br /&gt;&lt;br /&gt;Czyli najpierw "najsłabsze" (w sensie siły a nie w sensie, że jest kiepskie) podejście: &lt;i&gt;wstrzykiwanie zależności &lt;/i&gt;- co i kiedy warto wstrzykiwać. Bo wstrzykiwanie DAO/Repo do Servisów jest nudne.&lt;br /&gt;&lt;br /&gt;Dalej technika "mocniejsza" - bo abstrahująca nie tylko od typu współpracownika, ale i ich ilości oraz czasu - &lt;i&gt;arch. zorientowana na zdarzenia&lt;/i&gt;. Przykłady wykorzystania zdarzeń do zwiększania przepustowości oraz do notowania "wydarzeń" biznesowych - wszystko w kontekście event sourcing i Command-query Responsibility Segregation.&lt;br /&gt;&lt;br /&gt;Na zakończenie najsilniejsza technika IoC: &lt;i&gt;Aspect Oriented Programming&lt;/i&gt;.&lt;br /&gt;&lt;br /&gt;Na każdym "przystanku" naszej wycieczki zastanowilibyśmy się co wynika z zastosowania danego podejście i kiedy warto z niego skorzystać - a kiedy jest to tylko moda i owczy pęd.&lt;br /&gt;&lt;br /&gt;Jak widać z opisu prezentacja była by przeznaczona dla początkujących architektów aplikacji - programistów, którzy chcieliby zając się projektowaniem w skali makro.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5197374494377847819-4246767392316272943?l=art-of-software.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://art-of-software.blogspot.com/feeds/4246767392316272943/comments/default' title='Komentarze do posta'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5197374494377847819&amp;postID=4246767392316272943' title='Komentarze (6)'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5197374494377847819/posts/default/4246767392316272943'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5197374494377847819/posts/default/4246767392316272943'/><link rel='alternate' type='text/html' href='http://art-of-software.blogspot.com/2010/08/pomozecie.html' title='Pomożecie?'/><author><name>Sławek Sobótka</name><uri>http://www.blogger.com/profile/15082577671795313109</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='30' height='32' src='http://3.bp.blogspot.com/-tmFOhJC48_E/TkQ0G2DxrqI/AAAAAAAAAz8/WVGBaaS5a_Y/s220/zdjecie2.png'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_m-NewLwJEb8/TGFV7HvDdyI/AAAAAAAAAqM/jGghBaeptrw/s72-c/gierek.jpg' height='72' width='72'/><thr:total>6</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5197374494377847819.post-1931459066350962077</id><published>2010-07-01T22:42:00.020+02:00</published><updated>2010-07-01T23:54:39.407+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Agile'/><category scheme='http://www.blogger.com/atom/ns#' term='Homo sum...'/><category scheme='http://www.blogger.com/atom/ns#' term='z dystansu'/><category scheme='http://www.blogger.com/atom/ns#' term='samodoskonalenie'/><category scheme='http://www.blogger.com/atom/ns#' term='Rozwój'/><title type='text'>Bo w życiu trzeba... być Agile:)</title><content type='html'>&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/_m-NewLwJEb8/TCzxy0xffII/AAAAAAAAApc/63l8s3eJf5k/s1600/czlowiek-guma-839-OBRAZKY.PL.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="400" src="http://1.bp.blogspot.com/_m-NewLwJEb8/TCzxy0xffII/AAAAAAAAApc/63l8s3eJf5k/s400/czlowiek-guma-839-OBRAZKY.PL.jpg" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;Od dzieciństwa słyszmy ze strony różnych "dobrych wujków" co jest "w życiu ważne". Niestety rzadko zdarza się usłyszeć o &lt;b&gt;adaptacyjności &lt;/b&gt;czyli życiowej &lt;b&gt;zwinności &lt;/b&gt;(w sensie agilności).&lt;br /&gt;&lt;br /&gt;Jadnak jakimś cudem w IT wszyscy są Agile - jakiś czas temu robiłem mały research, podczas którego z trudem znalazłem jedną firmę,&amp;nbsp;w Indiach,&amp;nbsp;która otwarcie mówi, że nie jest Agile;)&lt;br /&gt;&lt;br /&gt;Gdy jednak przyjrzeć się bliżej, to z tym Agile jest jak z seksem u nastolatków - każdy o tym mówi ale niewielu tak na prawdę to robi (a przynajmniej tak było kilkanaście lat temu w klasach mat-inf;)&lt;br /&gt;Mówi się, że Agile jest trudny ponieważ z pozoru wydaje się łatwy - tak łatwy, że wszystkim wydaje się, że zrozumieli.&lt;br /&gt;&lt;br /&gt;W niniejszym poście nie będę pisał o problemach z metodykami (przy okazji: metodologia to nauka o metodykach). Skupimy się na materii miękkiej, czyli problemach z ludźmi.&lt;br /&gt;&lt;br /&gt;Jak często napotykacie niemal faszystowskie, &lt;b&gt;anty-adaptacyjne&lt;/b&gt; postawy typu:&lt;br /&gt;&lt;i&gt;&lt;/i&gt;&lt;br /&gt;&lt;i&gt;- nie pisz&amp;nbsp;komentarzy, pisz&amp;nbsp;samo-komentujący&amp;nbsp;się kod&amp;nbsp;(ale samo-komentujący z czyjego punktu widzenia?)&lt;br /&gt;- dobry kod powinien mieć 70% komentarzy tak aby dało się go odtworzyć czytając je (ale po co?)&lt;br /&gt;&lt;/i&gt;&lt;br /&gt;&lt;i&gt;&lt;br /&gt;&lt;/i&gt;&lt;br /&gt;&lt;i&gt;- Stories są lepsze/gorsze niż Use Case (na jakim poziomie?)&lt;/i&gt;&lt;br /&gt;&lt;i&gt;&lt;br /&gt;&lt;/i&gt;&lt;br /&gt;&lt;i&gt;- YAGNI i KISS (nawet jeżeli mam intuicję, że się przyda?)&lt;/i&gt;&lt;br /&gt;&lt;i&gt;&lt;br /&gt;&lt;/i&gt;&lt;br /&gt;&lt;i&gt;- Java rules/.NET rules (ale czym to się różni?)&lt;/i&gt;&lt;br /&gt;&lt;i&gt;&lt;br /&gt;- zawsze używajmy IoC i ORM (ale dlaczego i po co?)&lt;br /&gt;- ORM to badziewie, tylko SQL w procedurach (ale jakim kosztem?)&lt;br /&gt;&lt;br /&gt;- jak baza to tylko Oracle/Postgres/... &amp;nbsp;(ale do każdego projektu?)&lt;br /&gt;- jak baza to tylko noSQL (bo jest sexi?)&lt;br /&gt;&lt;br /&gt;&amp;nbsp;- zawsze pisz testy - "you are not allowed to write a single line of production code without test first" - grzmiał jakiś czas temu Uncle (nomen omen;) Bob&lt;br /&gt;- powinieneś mieć co najmniej 80% pokrycia testami (a dlaczego nie 85%? settery też?)&lt;br /&gt;- nie pisz testów nigdy (nigdy?!?)&lt;br /&gt;&lt;br /&gt;- metody powinny mieć 5 linijek (za 6 pójdę do więzienia?)&lt;br /&gt;- metody powinny być tak długie, że powinno dać się je zrozumieć w 5 minut (ale zrozumieć przez kogo)&lt;br /&gt;&lt;br /&gt;- zawsze używaj Mavena (nawet w jednomodułowym projekcie z 10 libami?)&lt;br /&gt;&lt;br /&gt;- statyczne języki są lepsze (lepsze do czego?)&lt;br /&gt;- dynamiczne języki są lepsze (szczególnie jak do klasy String dokleję sobie 150 metod&lt;/i&gt;&lt;br /&gt;&lt;i&gt;&lt;br /&gt;&lt;/i&gt;&lt;br /&gt;&lt;i&gt;&lt;/i&gt;&lt;i&gt;- przeglądarka/system/IDE X jest lepsze (lepsze do czego? mówisz to aby pomóc czy aby się podroczyć?)&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;Można by tak mnożyć w nieskończoność...&lt;br /&gt;&lt;br /&gt;Nie wiem czy jest to przypadłość jedynie naszej branży, ale &lt;b&gt;tym co hamuje Agile w procesie jest&amp;nbsp;Autorytaryzm&amp;nbsp;w ludziach&lt;/b&gt;. Być może autorytaryzm jest ogólnym&amp;nbsp;&lt;a href="http://pl.wikipedia.org/wiki/Mem"&gt;memem&lt;/a&gt;&amp;nbsp;"odziedziczonym" po wspomnianych w pierwszych zdaniu wujaszkach. Być może jest on wbudowany w nasze ścisłe umysły jako ich integralny ficzer - taki koprocesor poszukiwania jednego, naiwnie prostego równania na wszystko.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;O ile mamy coraz więcej KNOW HOW to często brakuje KNOW WHEN.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Można ująć to inaczej: w równaniu&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: monospace; white-space: pre;"&gt; &lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: monospace; white-space: pre;"&gt;Mądrość = Wiedza + Kontekst&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;najważniejszy jest kontekst.&amp;nbsp;Kontekst jest tym co odróżnia teorię od praktyki. Kontekst pozwalający &lt;b&gt;zaadaptować &lt;/b&gt;wiedzę. Kontekst, który w &lt;a href="http://art-of-software.blogspot.com/2010/01/wspinaczka-do-profesjonalizmu.html"&gt;Modelu Kompetencji Braci Dreyfus&lt;/a&gt; pojawia się z czasem, z doświadczeniem. A doświadczenie to refleksja. Refleksja jest konieczna do &lt;b&gt;adaptacji&lt;/b&gt; podejścia.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;//=================================&lt;br /&gt;&lt;br /&gt;W większości cywilizacji&amp;nbsp;konsekwencja&amp;nbsp;jest cnotą. Zwrot "nie jesteś konsekwentny w swym postępowaniu" ma mocno pejoratywny wydźwięk.&lt;br /&gt;&lt;br /&gt;Ale bardziej Agile jest inne podejście - podejście &lt;b&gt;adaptacyjne&lt;/b&gt;: "Konsekwencja jest fortecą głupców". Konsekwencja zwalnia z obserwowania, myślenia i dostosowania się (nie należy mylić konsekwencji z wytrwałością).&lt;br /&gt;&lt;br /&gt;Nie chodzi o to aby zafiksować się na czymś, spuścić głowę i konsekwentnie ryć niczym świnia za truflami. Co jakiś czas warto ją podnieść sprawdzić czy cel jest jeszcze wciąż na wprost - a może na horyzoncie pojawił się inny, lepszy cel i warto się &lt;b&gt;zaadaptować&lt;/b&gt;?&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5197374494377847819-1931459066350962077?l=art-of-software.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://art-of-software.blogspot.com/feeds/1931459066350962077/comments/default' title='Komentarze do posta'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5197374494377847819&amp;postID=1931459066350962077' title='Komentarze (18)'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5197374494377847819/posts/default/1931459066350962077'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5197374494377847819/posts/default/1931459066350962077'/><link rel='alternate' type='text/html' href='http://art-of-software.blogspot.com/2010/07/bo-w-zyciu-trzeba-byc-agile.html' title='Bo w życiu trzeba... być Agile:)'/><author><name>Sławek Sobótka</name><uri>http://www.blogger.com/profile/15082577671795313109</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='30' height='32' src='http://3.bp.blogspot.com/-tmFOhJC48_E/TkQ0G2DxrqI/AAAAAAAAAz8/WVGBaaS5a_Y/s220/zdjecie2.png'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_m-NewLwJEb8/TCzxy0xffII/AAAAAAAAApc/63l8s3eJf5k/s72-c/czlowiek-guma-839-OBRAZKY.PL.jpg' height='72' width='72'/><thr:total>18</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5197374494377847819.post-3801766995599661525</id><published>2010-05-25T01:40:00.007+02:00</published><updated>2010-05-25T10:25:42.064+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='wzorce architektoniczne'/><category scheme='http://www.blogger.com/atom/ns#' term='Data Context Interaction'/><category scheme='http://www.blogger.com/atom/ns#' term='Research'/><category scheme='http://www.blogger.com/atom/ns#' term='Composite Oriented Programming'/><category scheme='http://www.blogger.com/atom/ns#' term='Architektura'/><title type='text'>Object Oriented czy jedynie Class Oriented?</title><content type='html'>Dziś będzie o "nowym" podejściu do Object Oriented.&lt;br /&gt;Jeżeli komuś wydaje się, że już nic nowego nie można w tym jakże oklepanym temacie dodać, to zachęcam do zapoznania się prezentacjami zawartymi w tekście. Dowiecie się również dlaczego nowym napisałem w cudzysłowie.&lt;br /&gt;&lt;br /&gt;Od jakiegoś czasu z wielu stron pojawiają się zachęty do zainteresowania się nowymi językami, takimi jak Scala, Groovy, Ruby,...&lt;br /&gt;&lt;br /&gt;Do tej pory wszyscy orędownicy pokazują jak to fajnie można sobie operować na kolekcjach (sortować, wyszukiwać) w jednej linijce kodu dzięki możliwości "doklejania" nowych metod do istniejących klas. Z całym szacunkiem, ale jest to nic innego jak objaw &lt;span style="font-weight:bold;"&gt;&lt;a href="http://art-of-software.blogspot.com/2009/03/w-co-sie-bawic.html"&gt;onanizmu technicznego&lt;/a&gt;&lt;/span&gt;. Jeżeli mam zainteresować się nowym językiem tylko po to aby uniknąć klepania pętelek to jednak zastosuję &lt;a href="http://art-of-software.blogspot.com/2010/02/wyginanie-javy.html"&gt;"cwanego" utilsa&lt;/a&gt;. Czy aby na pewno nowe języki powstają tylko po to aby sobie dokleić do klasy String 100 nowych metodek, o których istnieniu wie tylko doklejający?&lt;br /&gt;&lt;br /&gt;Jeszcze inni odkryli ponownie możliwość dynamicznego dodawania "w locie" do encji metod zapisujących i wczytujących je. Myślałem, że niesławny Active Record odszedł już dawno w niepamięć. Ale jednak nie - okazuje się, że jest sexi w niektórych frameworkach.&lt;br /&gt;&lt;br /&gt;Podczas niedawnej sesji researchu trafiłem na ciekawą koncepcję, która nadaje &lt;span style="font-weight:bold;"&gt;prawdziwy i pragmatyczny&lt;/span&gt; sens tym wszystkim konstruktom językowym.Pojawił się oto "nowy" paradygmat programowania: &lt;span style="font-weight:bold;"&gt;Data Context Interaction&lt;/span&gt;, który wskazuje zastosowanie dynamicznych konstruktów do lepszego (a przynajmniej innego) modelowania problemów. Czyli mamy coś więcej niż sortowanie listy, mamy nową jakość myślenia o modelowanej strukturze.&lt;br /&gt;&lt;br /&gt;Twórcy DCI twierdzą, że mainstreamowe podejście do OO to jedynie kilka % prawdziwego OO. Klasyczne podejście skupia się na klasach, czyli na pewnych strukturach. Stawiają oni klasycznemu podejściu zarzuty, że skupia się ono na klasach zamiast na obiektach, co jakoby powoduje "rozsmarowanie" logiki Use Case po wielu klasach, dzięki czemu w nietrywialnych aplikacjach z czasem coraz ciężej przychodzi połapanie się w logice.&lt;br /&gt;&lt;br /&gt;Czy zatem czas na powrót do paradygmatu proceduralnego, gdzie mamy cały "flow" w 1 miejscu?&lt;br /&gt;Niekoniecznie.&lt;br /&gt;Spójrzmy ma poniższy rysunek:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_m-NewLwJEb8/S_sJHBXdT9I/AAAAAAAAAn8/j5-xqB-m0MQ/s1600/dci_concepts-590x507.jpg"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 275px;" src="http://3.bp.blogspot.com/_m-NewLwJEb8/S_sJHBXdT9I/AAAAAAAAAn8/j5-xqB-m0MQ/s320/dci_concepts-590x507.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5474979788229529554" /&gt;&lt;/a&gt;&lt;br /&gt;źródło: http://www.underbjerg.com/2009/11/16/oredev-2009-impressions-and-dci-architecture/&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Dane&lt;/span&gt; opisują przy pomocy &lt;span style="font-style:italic;"&gt;Klas&lt;/span&gt; pewną niezmienną strukturę - można powiedzieć core modelu (może mieć on pewne bazowe, ogólne zachowania).&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Interakcje&lt;/span&gt; są wyniesieniem zachowania do poziomu głównych bytów, dzięki czemu lepiej odpowiadają modelowi mentalnemu usera. Są pewnymi rolami, które mogą być przyjęte przez &lt;span style="font-style:italic;"&gt;obiekty&lt;/span&gt;. Interakcje operują na Danych ponieważ są do nich mixowane w...&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Kontekście&lt;/span&gt; - kontekst odpwiada Use Caseom lub ich krokom. To w pewnym kontekście dane są łączone z rolami (zachowaniem) tworząc dopiero &lt;span style="font-style:italic;"&gt;obiekty&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;Intuicyjny przykład: jestem człowiekiem, opisuje mnie zestaw standardowych parametrów. Ale w zależności od kontekstu przyjmuję niektóre role (a wraz z nimi zachowania): Programista, Manager, Ojciec, Kierowca, Gracz, Klient, ...&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Jeżeli udało mi się chociaż trochę zainteresować Was koncepcją DCI (nie mylić z nieco mniej innowacyjnym &lt;a href="http://jcp.org/en/jsr/detail?id=299"&gt;CDI&lt;/a&gt;;) to polecam następujące materiały:&lt;br /&gt;&lt;br /&gt;- &lt;a href="http://vimeo.com/8235574"&gt;Architektura i ciekawy przykład w Ruby&lt;/a&gt; - aby zaintrygować dodam, że znajdziecie tutaj ostrą krytykę TDD.&lt;br /&gt;- &lt;a href="http://vimeo.com/8235651"&gt;Ciekawe podejście do modelowania&lt;/a&gt; - mamy tutaj przykład niesamowitej jasności myślenia i pokaz tragikomicznego frameworka Qi4j (Java się jednak nie nadaje do DCI)&lt;br /&gt;- &lt;a href="http://vimeo.com/8235394"&gt;Niezbyt porywające wprowadzenie teoretyczne&lt;/a&gt; - z którego dowiemy się, że te koncepcje mają już kilkadziesiąt lat, tylko gdzieś się zapodziały w przemyśle.&lt;br /&gt;- &lt;a href="http://vimeo.com/10895960"&gt;Niekoniecznie świadome DCI w Scali&lt;/a&gt; - plus durne przykłady sortowania kolekcji;)&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Ogólnie polecam materiały z konferencji &lt;a href="http://www.oredev.org"&gt;Øredev&lt;/a&gt; - jak widać tematyka jest jest bardzo ciekawa i mocno wykracza poza mainstream.&lt;br /&gt;&lt;br /&gt;A w inkubatorze (póki co) Eclipse mamy coś bardzo podobnego: &lt;a href="http://www.eclipse.org/objectteams/"&gt;Object Teams&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;//==========================&lt;br /&gt;&lt;br /&gt;Ciekawie DCI podsumował jeden ze znajomych architektów (przy okazji "snajper", który potrafi trafić człowieka z granatnika z odległości całej planszy w Modern Warfare 1): "ale trzeba mieć jaja aby zakwestionować standardy i przedstawić coś tak odmiennego".&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5197374494377847819-3801766995599661525?l=art-of-software.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://art-of-software.blogspot.com/feeds/3801766995599661525/comments/default' title='Komentarze do posta'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5197374494377847819&amp;postID=3801766995599661525' title='Komentarze (23)'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5197374494377847819/posts/default/3801766995599661525'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5197374494377847819/posts/default/3801766995599661525'/><link rel='alternate' type='text/html' href='http://art-of-software.blogspot.com/2010/05/object-oriented-czy-jedynie-class.html' title='Object Oriented czy jedynie Class Oriented?'/><author><name>Sławek Sobótka</name><uri>http://www.blogger.com/profile/15082577671795313109</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='30' height='32' src='http://3.bp.blogspot.com/-tmFOhJC48_E/TkQ0G2DxrqI/AAAAAAAAAz8/WVGBaaS5a_Y/s220/zdjecie2.png'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_m-NewLwJEb8/S_sJHBXdT9I/AAAAAAAAAn8/j5-xqB-m0MQ/s72-c/dci_concepts-590x507.jpg' height='72' width='72'/><thr:total>23</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5197374494377847819.post-969727454918390042</id><published>2010-05-09T16:55:00.012+02:00</published><updated>2010-05-20T00:23:59.234+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Homo sum...'/><category scheme='http://www.blogger.com/atom/ns#' term='Craftsmanship'/><category scheme='http://www.blogger.com/atom/ns#' term='linki'/><title type='text'>Konstruktor-Destruktor</title><content type='html'>Stara indiańska zasada mówi: na blogu zawsze lepiej wkleić linka do czyjegoś mądrego posta niż pisać coś samemu. Dlatego dziś polecam posta Jakuba Nabrdalika: &lt;a href="http://blog.solidcraft.eu/2010/05/writer-versus-constructor.html"&gt;Writer versus Constructor&lt;/a&gt;. Tekst &lt;span style="font-weight:bold;"&gt;trafia w sedno pewnej klasy problemów&lt;/span&gt; z developmentem softu. &lt;br /&gt;&lt;br /&gt;Od siebie dodam, że jak zwykle rzeczywistość nie jest czarno-biała lecz szara. Programista klasy MacGyver (o którym &lt;a href="http://local.joelonsoftware.com/wiki/Programista-MacGyver"&gt;pisał&lt;/a&gt; Joel Spolsky) jest pożytecznym skarbem w zespole, trzeba jedynie objąć go stałą kwarantanną.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;EDIT:&lt;br /&gt;Kontynuacja dyskusji: &lt;a href="http://jdn.pl/node/1967"&gt;O programiście-pisarzu i programiście-konstruktorze, ciąg dalszy czyli: refaktoring po blogersku?&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;//=======================&lt;br /&gt;&lt;br /&gt;Przy okazji warto zwrócić uwagę nad konstrukcję samego posta - wzór do naśladowania dla wszystkich bloggerów technicznych.&lt;br /&gt;&lt;br /&gt;Najpierw mamy krótką historię odwołującą się emocji (w tym wypadku z dzieciństwa), później uogólnienie i postawienie problemu. Dalej w rozwinięciu wypunktowanie konkretów. Wszystko ilustrowane perfekcyjnie dobranymi, klimatycznymi obrazkami Pipboya z Fallouta.&lt;br /&gt;&lt;br /&gt;Brawo, brawo, brawo!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5197374494377847819-969727454918390042?l=art-of-software.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://art-of-software.blogspot.com/feeds/969727454918390042/comments/default' title='Komentarze do posta'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5197374494377847819&amp;postID=969727454918390042' title='Komentarze (0)'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5197374494377847819/posts/default/969727454918390042'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5197374494377847819/posts/default/969727454918390042'/><link rel='alternate' type='text/html' href='http://art-of-software.blogspot.com/2010/05/konstruktor-destruktor.html' title='Konstruktor-Destruktor'/><author><name>Sławek Sobótka</name><uri>http://www.blogger.com/profile/15082577671795313109</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='30' height='32' src='http://3.bp.blogspot.com/-tmFOhJC48_E/TkQ0G2DxrqI/AAAAAAAAAz8/WVGBaaS5a_Y/s220/zdjecie2.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5197374494377847819.post-7030567109264626662</id><published>2010-04-28T16:34:00.009+02:00</published><updated>2010-05-20T00:21:48.616+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='prezentacja'/><category scheme='http://www.blogger.com/atom/ns#' term='Craftsmanship'/><category scheme='http://www.blogger.com/atom/ns#' term='wzorce projektowe'/><title type='text'>Majowa ewangelizacja Software Craftsmanship</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_m-NewLwJEb8/S9hI-5JPbeI/AAAAAAAAAmY/8yIemXT8J2I/s1600/evangelistboy.jpg"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 240px;" src="http://1.bp.blogspot.com/_m-NewLwJEb8/S9hI-5JPbeI/AAAAAAAAAmY/8yIemXT8J2I/s320/evangelistboy.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5465198393142767074" /&gt;&lt;/a&gt;&lt;br /&gt;Prezentacja poświęcona tematyce Software Craftsmanship została dosyć ciepło przyjęta podczas poznańskiego &lt;a href="http://2010.4developers.org.pl/materialy-z-konferencji"&gt;4Developers&lt;/a&gt;, oraz spotkała się z niemałym odzewem w community.&lt;br /&gt;&lt;br /&gt;Dlatego uznałem, że warto kontynuować propagowanie profesji w naszej branży - szczególnie, że nasze community zaczyna coraz wyraźniej sygnalizować pewne problemy.&lt;br /&gt;&lt;br /&gt;Zapraszam zatem wszystkich zainteresowanych tematyką Software Craftsmanship na szereg &lt;span style="font-weight:bold;"&gt;darmowych&lt;/span&gt; konferencji, gdzie planuję wystąpienie:&lt;br /&gt;&lt;br /&gt;- &lt;a href="http://lubelskiedniinformatyki.pl/"&gt;lubelskie dni IT&lt;/a&gt; - 12 maja w Lublinie&lt;br /&gt;- &lt;a href="http://infoshare.pl/"&gt;Infoshare&lt;/a&gt; - 14 maja w Gdańsku&lt;br /&gt;- &lt;a href="http://www.javarsovia.pl/"&gt;Javarsovia&lt;/a&gt; - 26 czerwca w Warszawie&lt;br /&gt;&lt;br /&gt;//==================================&lt;br /&gt;&lt;br /&gt;Cieszy fakt, ze tematyka Craftsmanship pojawia się również na JUGach: warszawskim i wrocławskim&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5197374494377847819-7030567109264626662?l=art-of-software.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://art-of-software.blogspot.com/feeds/7030567109264626662/comments/default' title='Komentarze do posta'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5197374494377847819&amp;postID=7030567109264626662' title='Komentarze (5)'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5197374494377847819/posts/default/7030567109264626662'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5197374494377847819/posts/default/7030567109264626662'/><link rel='alternate' type='text/html' href='http://art-of-software.blogspot.com/2010/04/majowa-ewangelizacja-software.html' title='Majowa ewangelizacja Software Craftsmanship'/><author><name>Sławek Sobótka</name><uri>http://www.blogger.com/profile/15082577671795313109</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='30' height='32' src='http://3.bp.blogspot.com/-tmFOhJC48_E/TkQ0G2DxrqI/AAAAAAAAAz8/WVGBaaS5a_Y/s220/zdjecie2.png'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_m-NewLwJEb8/S9hI-5JPbeI/AAAAAAAAAmY/8yIemXT8J2I/s72-c/evangelistboy.jpg' height='72' width='72'/><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5197374494377847819.post-1895617430764960174</id><published>2010-04-21T18:35:00.031+02:00</published><updated>2010-04-24T14:15:52.596+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='cloud'/><category scheme='http://www.blogger.com/atom/ns#' term='JSF'/><category scheme='http://www.blogger.com/atom/ns#' term='Research'/><category scheme='http://www.blogger.com/atom/ns#' term='z dystansu'/><category scheme='http://www.blogger.com/atom/ns#' term='Spring'/><category scheme='http://www.blogger.com/atom/ns#' term='JPA'/><title type='text'>Google Application Engine</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_m-NewLwJEb8/S88qdKT4paI/AAAAAAAAAl0/Nyesq2mvYPs/s1600/broken+engine.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 242px;" src="http://2.bp.blogspot.com/_m-NewLwJEb8/S88qdKT4paI/AAAAAAAAAl0/Nyesq2mvYPs/s320/broken+engine.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5462631553496032674" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Dziś będzie o rzetelności.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;WYGLĄDA OBIECUJĄCO&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Chmura Google - &lt;a href="http://code.google.com/intl/pl-PL/appengine/"&gt;GAE&lt;/a&gt; ogólnie prezentuje się świetnie. Za darmo (do pewnych limitów) dostajemy platformę, która jest w stanie udźwignąć tysiące transakcji na sekundę oraz przechować dla nas terabajty danych w &lt;span style="font-weight:bold;"&gt;nierelacyjnej&lt;/span&gt; bazie &lt;a href="http://en.wikipedia.org/wiki/BigTable"&gt;BigTable&lt;/a&gt;. Do tego dostęp do wielu usług google takich jak bezpieczeństwo, składowanie obrazków, pobieranie zawartości stron poprzez ichni cache, potężny memcache itp.&lt;br /&gt;&lt;br /&gt;Programować możemy sobie w Pythonie albo w Javie (okrojonej wersji, &lt;a href="http://code.google.com/intl/pl-PL/appengine/docs/java/jrewhitelist.html"&gt;bez części klas standardowych&lt;/a&gt; i z zakazem korzystania z pewnych bibliotek).&lt;br /&gt;&lt;br /&gt;Ogólne założenie jest takie: programiści (i konsultanci;) w większości nie potrafią konfigurować skalowalnych środowisk ani pisać skalowalnych aplikacji, dlatego dostarczmy im platformę, która zajmie się tym problemem w sposób transparentny. Czyli mamy podejście odwrotne do Java EE. Zajmij się problemem biznesowym a chmura zajmie się skalowaniem. Kierunek wydaje się słuszny.&lt;br /&gt;&lt;br /&gt;Zatem zaczynamy zabawę...&lt;br /&gt;Na dzień dobry krótka, oficjalna prezentacja z głównej strony jak to fajnie i szybko klepie się aplikacje i odpala je w kosmos: &lt;a href="http://www.youtube.com/watch?v=P3GT4-m_6RQ"&gt;http://www.youtube.com/watch?v=P3GT4-m_6RQ&lt;/a&gt;&lt;br /&gt;Trzeba przyznać, że plugin do Eclipse jest wzorowy: prosty w obsłudze (3 sugestywne buttony), &lt;span style="font-weight:bold;"&gt;działa&lt;/span&gt; oraz zapewnia wszystko: &lt;br /&gt;- lokalny server emulujący chmurę i jej zasoby (bazę)&lt;br /&gt;- narzędzie automatycznie "wzbogacające" bytecode klas encji na potrzeby ichniej "implementacji" JPA&lt;br /&gt;- narzędzie wystrzeliwujące aplikację w kosmos&lt;br /&gt;- prosty kreator, który generuje cały ten kosmodrom&lt;br /&gt;(nie odważyłem się zmawenizować wygenerowanego projektu, bo to zwykle tydzień w plecy a na koniec może się okazać, że tracimy hotdeploy)&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;WTF?&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Ale, ale... akcja filmu rozkręca się z czasem...&lt;br /&gt;Jedna z największych firm programistycznych na ziemi pokazuje jak tworzyć kod w... Java Server Pages. Patrzcie uważnie i uczcie się: logika i dostęp do danych w... scriptletach (sic!).&lt;br /&gt;&lt;br /&gt;Oczywiście duzi chłopcy wiedzą, ze scriptlety są depricated. A nóż widelec tą scenę zobaczy jakieś małe dziecko i będzie później tak programować jak dorośnie?!? Później znowu przeczytamy w gazecie o tragedii jaka rozegrała się w jakimś spokojnym projekcie. Gdzie byli rodzice?!?&lt;br /&gt;&lt;br /&gt;Hmmm dziwne, dziwne... no ale nie czepiajmy się szczegółów, to przecież tylko taki przykład. Przecież zawsze możemy zaprojektować sobie eleganckie warstwy i całość oprzeć o sprawdzony framework.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;BOLESNE OGRANICZENIA&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Niestety tak jak wspomniałem na początku JVM ma ograniczenia i nie wszystko działa. &lt;a href="http://seamframework.org/"&gt;Seam&lt;/a&gt; co prawda daje się uruchomić po zastosowaniu 15 speszyl haków, ale wszyscy twierdzą, że nie warto ryzykować. Na szczęście stary, dobry &lt;a href="http://www.springsource.org/"&gt;Spring&lt;/a&gt; oficjalnie działa. Wielu dzielnych blogerów publikuje hello worldy i tutoriale jak to poskładać. Wygląda na to, że jedni kopiują od drugich;)&lt;br /&gt;&lt;br /&gt;Ba, nawet 2 książki o GAE preferują Springa i pokazują jak go skonfigurować. Hmmm ciekawe dlaczego omawiają tylko servlecik Spring MVC i dyplomatycznie nie poruszają bardziej zaawansowanych zagdanień...?&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Niestety, jednak nie działa do końca!&lt;/span&gt;&lt;br /&gt;Przykładowo gdy użyjemy technik Aspektowych i przeplatania w czasie uruchomienia to mamy dziwne błędy ClassNotFound. Lokalnie działa, a na chmurze już nie.&lt;br /&gt;Co implikuje, że możemy zapomnieć o aspektowej, eleganckiej obsłudze bezpieczeństwa i transakcji.&lt;br /&gt;Więc po co nam Spring? Tylko do wstrzykiwania? To bez sensu.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;UWAGA NA PERSYSTENCJĘ&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Nieważne, bez Springa można żyć, idźmy dalej... Nierelacyjna baza BigTable została przez Google przykryta interfejsem &lt;a href="http://en.wikipedia.org/wiki/Java_Data_Objects"&gt;JDO&lt;/a&gt; albo &lt;a href="http://en.wikipedia.org/wiki/Java_Persistence_API"&gt;JPA&lt;/a&gt; (do wyboru) więc czujemy się jak w domu.&lt;br /&gt;Nie do końca... specyfikacja ma szereg ograniczeń wynikających z architektury rozwiązania BigTable - chodzi o rozpraszanie struktur danych na różne maszyny po stronie chmury.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Drobny szczególik wspomniany jedynie w dokumentacji jest taki, ze agregaty encji są grupowane w rodziny&lt;/span&gt;. Przykładowo jeżeli mamy encję Zamówienie, która ma w sobie listę ZamówionychProduktów to jest to rodzina. Co z tego wynika?&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Encja może należeć jedynie do jednej rodziny. &lt;/span&gt;&lt;br /&gt;Implikacja: Jeżeli mamy encje Zamówienie i Faktura oraz encję Kleint, który musi być podpięty do Zamówienia jak i Faktury to niestety nie ma takiej możliwości. Dziecko może mieć jednego rodzica. Oczywiście można to obejść i w Zamówieniu jak i Fakturze używać obiektów Kluczy do Klienta. Ale wówczas tracimy łatwość programowania i uzależniamy się od API Chmury. &lt;br /&gt;&lt;br /&gt;Trzeba pamiętać, że podejście do modelowania danych w nierelacyjnej bazie wymaga innego "nastawienia" - taka natura rozwiązania. Jeżeli nierelacyjnie to może obiektowo? Jednak nie do końca - no to jak?&lt;br /&gt;&lt;br /&gt;Osobiście preferuję takie podejście, że Zamówienie czy Faktura ma owszem klucz do Klienta ale ma również niepersystentne pole Klient, które jest ustawiane w niej osobnym zapytaniem (nie jest to duży koszt w bazie BigTable, która jest tak na prawdę wielowymiarową HashMapą). Tego typu szczegóły można hermetyzować z obiektach &lt;a href="http://martinfowler.com/eaaCatalog/repository.html"&gt;Repository&lt;/a&gt;, które zwracają dane "poskładane" tak aby było wygodnie. OK, jeden problem z głowy.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Transakcja może obejmować tylko operacje na jednej rodzinie.&lt;/span&gt;&lt;br /&gt;Czyli jeżeli logika aplikacji chce zapisać zarówno rodzinkę Zamówienie jak i Faktura to będą to 2 osobne transakcje. A co jeżeli w tak zwanym międzyczasie zdarzy się coś przykrego? Ręczna rzeźba i sprzątanie:)&lt;br /&gt;Poza tym, jak wspomniałem, aspektowe transakcje Springa nie działają, więc brudzimy kod biznesowy kodem API transakcji JPA.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Datanucleus - "implementacja" JPA&lt;/span&gt;&lt;br /&gt;Oprócz tego, że jest okrojona to dodatkowo zawiera szereg błędów - nie działają nawet niektóre proste przykłady z tutoriali JPA. Na oficjalnej grupie wisi wiele pytań - bez odpowiedzi.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;GWÓŹDŹ&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Prezentacja&lt;/span&gt;&lt;br /&gt;Z frameworków prezentacji testowałem JSF.&lt;br /&gt;1.2 (z Seam) działa.&lt;br /&gt;2.0 działa po zastosowaniu jednego prostego speszyl haka.&lt;br /&gt;&lt;br /&gt;Działa w sensie, że się uruchamia. W 2.0 występują pewne problemy z wstrzykiwaniem ManagedBeanów. RichFaces ani IceFaces nie mają wersji dla chmury. Oficjalnie Primefaces częściowo działa. Znowu nie jest to rzetelna i informacja - AJAX ogólnie się sypie.&lt;br /&gt;&lt;br /&gt;No i można zapomnieć o uruchamianiu metod z parametrem przy pomocy nowego silnika wyrażeń (el-api w wersji 2.2). Chmura odmawia współpracy z nowymi zdobyczami.&lt;br /&gt;&lt;br /&gt;//==============================&lt;br /&gt;&lt;br /&gt;Biorąc pod uwagę powyższe ograniczenia:&lt;br /&gt;- brak wygodnego frameworka (w tym wsparcia dla AOP)&lt;br /&gt;- uboga funkcjonalność ORM wymagająca wielu ręcznych operacji&lt;br /&gt;- mentalny model programowania sprzed o ok 10 lat&lt;br /&gt;Mamy znaczny spadek produktywności.&lt;br /&gt;&lt;br /&gt;Domyślamy się skąd te JSP, scriptlety i statyczne metody w filmie promocyjnym? Czyżby tylko to działało?&lt;br /&gt;Szkoda tylko, że community i blogosfera zatrzymuje się na poziomie Hello World i nie weryfikuje nieco bardziej dogłębnie i rzetelnie.&lt;br /&gt;&lt;br /&gt;Na zakończenie dodam, że zupełnie inne założenia przy budowie chmury przyjął &lt;a href="http://aws.amazon.com/ec2/"&gt;Amazon&lt;/a&gt;. Dostajemy sprzęt i system operacyjny. Nikt nie narzuca nam dodatkowych bytów zbudowanych nad sprzętem i nie wchodzi nam z butami w nasz wypracowany latami i sprawdzony model programowania. I co najważniejsze - wszystko działa:)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5197374494377847819-1895617430764960174?l=art-of-software.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://art-of-software.blogspot.com/feeds/1895617430764960174/comments/default' title='Komentarze do posta'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5197374494377847819&amp;postID=1895617430764960174' title='Komentarze (14)'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5197374494377847819/posts/default/1895617430764960174'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5197374494377847819/posts/default/1895617430764960174'/><link rel='alternate' type='text/html' href='http://art-of-software.blogspot.com/2010/04/goole-application-engine.html' title='Google Application Engine'/><author><name>Sławek Sobótka</name><uri>http://www.blogger.com/profile/15082577671795313109</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='30' height='32' src='http://3.bp.blogspot.com/-tmFOhJC48_E/TkQ0G2DxrqI/AAAAAAAAAz8/WVGBaaS5a_Y/s220/zdjecie2.png'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_m-NewLwJEb8/S88qdKT4paI/AAAAAAAAAl0/Nyesq2mvYPs/s72-c/broken+engine.png' height='72' width='72'/><thr:total>14</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5197374494377847819.post-5752330161258230708</id><published>2010-03-23T23:59:00.007+01:00</published><updated>2010-03-25T00:55:19.694+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='JUG'/><category scheme='http://www.blogger.com/atom/ns#' term='prezentacja'/><category scheme='http://www.blogger.com/atom/ns#' term='Craftsmanship'/><category scheme='http://www.blogger.com/atom/ns#' term='wzorce projektowe'/><title type='text'>Koszt wykorzystania wzorców projektowych</title><content type='html'>Podczas dzisiejszej prezentacji na temat Software Craftsmanship i Wzorców Projektowych, którą przeprowadziłem w ramach &lt;a href="http://groups.google.com/group/lublin-jug"&gt;lubelskiego JUG&lt;/a&gt; padło szereg pytań odnośnie:&lt;br /&gt;- kosztu posługiwania się w kodzie wzorcami&lt;br /&gt;- presji czasu&lt;br /&gt;- komplikacji&lt;br /&gt;&lt;br /&gt;Jest to pewien ogólny i często powtarzający się zestaw pytań, dlatego sądzę, że warto rozwiać kilka wątpliwości i nieporozumień.&lt;br /&gt;&lt;br /&gt;Część programistów widzi wykorzystanie wzorca jako niepotrzebną komplikację, która wprowadza dodatkowy narzut na wytworzenie kodu. &lt;br /&gt;&lt;br /&gt;Generalnie jeżeli chodzi o poziom komplikacji to wzorce powinny redukować &lt;a href="http://en.wikipedia.org/wiki/Accidental_complexity"&gt;złożoność przypadkową&lt;/a&gt; oraz zwiększać czytelność &lt;a href="http://en.wikipedia.org/wiki/Essential_complexity"&gt;złożoności właściwej&lt;/a&gt;. Jeżeli mamy sytuację odwrotną to wzorzec został wykorzystany niepoprawnie lub niepotrzebnie.&lt;br /&gt;&lt;br /&gt;Odnośnie narzutu czasowego to obserwuję dziwne przeświadczenie jakoby dopisanie interfejsu czy kilku linijek kodu potrzebnych na podzielenie kodu na większą ilość pudełek (klas) było jakoś niezwykle czasochłonne;) Sam proces myślowy również nie powinien się znacząco wydłużyć. Albo wiem jaki wzorzec użyć albo nie wiem. To nie jest tak, że zastanawiam się nad tym godzinami.&lt;br /&gt;&lt;br /&gt;Warto zwrócić uwagę na fakt, że katalog &lt;a href="http://en.wikipedia.org/wiki/Design_pattern_(computer_science)#Classification_and_list"&gt;Wzorców Projektowych Ogólnego Przeznaczenia&lt;/a&gt; jest dosyć bogaty.&lt;br /&gt;&lt;br /&gt;Owszem, część z nich jest dosyć wyrafinowana pod względem koncepcyjnym lub pod względem konstrukcji kodu. Przykładowo taki Visitor, Component Tree, Bridge, Proxy, Builder, Flyweight, Memento prowadzają pewien narzut, ale są to narzędzia, które wybieramy do misji specjalnych. Na pewno nie należą do codziennego wachlarza technik.&lt;br /&gt;&lt;br /&gt;Natomiast Strategia, Stan, Dekorator, Template Method, Command to lekkie "skróty myślowe" &lt;span style="font-weight:bold;"&gt;wynikające wprost w paradygmatu Object Oriented&lt;/span&gt;. Nie ma w nich doprawdy nic nadzwyczajnego. &lt;br /&gt;&lt;br /&gt;Osobiście traktuję część z nich jako "atomowe klocki", z których powinno budować się rozwiązania. Są to byty niemal tej samej klasy ciężaru co IFy, pętele czy metody. Biegłe opanowanie lekkich wzorców sprawia, że poszerzają one nasz zestaw podstawowych "klocków myślowych". Budujemy z nich najpierw mentalne modele, a później naturalnie pojawiają się w kodzie.&lt;br /&gt;&lt;br /&gt;Operując lekkimi wzorcami na poziomie podstawowych klocków nie mamy narzutu czasowego podczas developmentu. Natomiast poziom komplikacji ulega znacznemu obniżeniu, ale tylko dla tych czytelników kodu, który posiadają taki sam zasób skojarzeń jak jego twórca - czyli operują tym samym słownictwem branżowym.&lt;br /&gt;&lt;br /&gt;//=====================================&lt;br /&gt;&lt;br /&gt;Potrzeba posiłkowania się wzorcami "lekkiego" kalibru wynika ze słabej siły wyrazu języków wywodzących się z C++ takich jak np Java. Przykładowo brak domknięć kompensujemy sobie strategiami. Doprawdy nie jest niczym strasznym i pracochłonnym opracowanie interfejsu z jedną metodą oraz kilku jej implementacji. Ilość kodu "biznesowego" nie ulega zwiększeniu (ew redukcji) natomiast pojawiają się jedynie dodatkowe "opakowania" dla niego w postaci zgrabnych i eleganckich klas.&lt;br /&gt;&lt;br /&gt;Jeżeli ktoś aż tak bardzo nie pała chęcią do pisania kodu to może powinien zostać trubadurem;)&lt;br /&gt;&lt;br /&gt;Ciężki kaliber wzorców również może &lt;span style="font-weight:bold;"&gt;czasem&lt;/span&gt; przydać się do emulacji brakujących elementów składni, takich jak:&lt;br /&gt;- &lt;a href="http://en.wikipedia.org/wiki/Double_dispatch"&gt;double dispatch&lt;/a&gt; emulowany przez wzorzec Visitor &lt;br /&gt;- &lt;a href="http://en.wikipedia.org/wiki/Lazy_evaluation"&gt;lazy evaluation&lt;/a&gt; emulowany przez wzorzec Proxy.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5197374494377847819-5752330161258230708?l=art-of-software.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://art-of-software.blogspot.com/feeds/5752330161258230708/comments/default' title='Komentarze do posta'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5197374494377847819&amp;postID=5752330161258230708' title='Komentarze (13)'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5197374494377847819/posts/default/5752330161258230708'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5197374494377847819/posts/default/5752330161258230708'/><link rel='alternate' type='text/html' href='http://art-of-software.blogspot.com/2010/03/koszt-wykorzystania-wzorcow.html' title='Koszt wykorzystania wzorców projektowych'/><author><name>Sławek Sobótka</name><uri>http://www.blogger.com/profile/15082577671795313109</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='30' height='32' src='http://3.bp.blogspot.com/-tmFOhJC48_E/TkQ0G2DxrqI/AAAAAAAAAz8/WVGBaaS5a_Y/s220/zdjecie2.png'/></author><thr:total>13</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5197374494377847819.post-5687719093744614412</id><published>2010-03-09T20:26:00.003+01:00</published><updated>2010-03-10T14:19:19.646+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Java'/><category scheme='http://www.blogger.com/atom/ns#' term='Research'/><title type='text'>Wyginanie Javy</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_m-NewLwJEb8/S5a6pfJy9cI/AAAAAAAAAkM/ynxfv5mNyLI/s1600-h/spoon.JPG"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 239px;" src="http://4.bp.blogspot.com/_m-NewLwJEb8/S5a6pfJy9cI/AAAAAAAAAkM/ynxfv5mNyLI/s320/spoon.JPG" border="0" alt=""id="BLOGGER_PHOTO_ID_5446746021251184066" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Dzisiejsza prezentacja Wojtka Gomoła o wyrażeniach Lambda (C# i "emulacja" w Javie) na &lt;a href="http://groups.google.com/group/lublin-jug"&gt;Lubelskim JUG&lt;/a&gt; przypomniała mi o kilku ciekawych zabawkach, które jakiś czas temu znalazłem i zapomniałem o nich napisać.&lt;br /&gt;&lt;br /&gt;Ciekawą cechą dynamicznych języków funkcyjnych jest:&lt;br /&gt;- możliwość tworzenia konstrukcji zbliżonych do języka naturalnego&lt;br /&gt;- możliwość rozszerzania standardowych, często używanych klas (zwykle kolekcji, kontenerów) o wygodne metody&lt;br /&gt;- nazwijmy to w sumie roboczo "techniczny DSL"&lt;br /&gt;&lt;br /&gt;Przykładowo takie oto sprawiające radość uproszczenia:&lt;br /&gt;&lt;div&gt;&lt;pre class="brush: java"&gt;&lt;br /&gt;kolekcja.wyrzucZNullemWPolu("name").posortuj({e1.age &gt;e2.age}).wytnijPierwszych(10);&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;Jak dla mnie nie ma się czym ekscytować ponieważ jest to jedynie lukier składniowy i w statycznych językach z silną kontrolą typów jest to tylko kwestia stworzenia jakiegoś starego, dobrego, proceduralnego Utilsa z interfejsem strategii komparacji:&lt;br /&gt;&lt;div&gt;&lt;pre class="brush: java"&gt;&lt;br /&gt;MyAlmightyUtils28.wyrzucZNullemWPolu(kolekcja, "name")&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;oraz odpowiednia sekwencja wywołań.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style:italic;"&gt;/*Oczywiście wszyscy wiemy, że Utilsy są złe i brzydkie, ale co zrobić*/&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;No ale już nie będzie tak pięknie jak we wcześniejszym przykładzie z jakiegoś sexi-skryptowego-języka.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Na szczęście istnieje kilka ciekawych zabawek zaimplementowanych w Javie. Dzięki cwanym trikom na generykach i zastosowaniu odpowiedniego nazewnictwa dają nam coś więcej niż namiastkę konstrukcji znanych z dynamicznych, słabo otypowanych języków.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.op4j.org/op4j_bending_the_Java_spoon.pdf"&gt;op4j&lt;/a&gt; - genialna biblioteka, która sprawia, że żmudny kod staje się bardziej czytelny i zwięzły jednocześnie zachowując typowanie.&lt;br /&gt;Bardzo podstawowy przykład:&lt;br /&gt;&lt;div&gt;&lt;pre class="brush: java"&gt;&lt;br /&gt;String[] emailArray = Op.on(userEmails).toArrayOf(Types.STRING).forEach().exec(FnString.toLowerCase()).get();&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://code.google.com/p/lambdaj/"&gt;lambdaj&lt;/a&gt; - podobna zabawka ze stajni google. Można rzucić okiem również na google collections.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://mockito.org/"&gt;Mockito&lt;/a&gt; - nasza rodzima produkcja. Kto jeszcze nie używał, ten powinien spróbować. Warto zajrzeć choćby do kodu ponieważ stanowi on przykład &lt;span style="font-weight:bold;"&gt;wzorcowej dokumentacji&lt;/span&gt;. Cały manual wraz z przykładami znajduje się w JavaDocu głównej "klaski"! Wzór do naśladowania dla innych twórców bibliotek - bo na pewno nie dla developerów komercyjnych produktów;)&lt;br /&gt;&lt;br /&gt;//==================&lt;br /&gt;&lt;br /&gt;Czekamy na Javę &lt;s&gt;1.7&lt;/s&gt; z jej nową konstrukcję closures. Ale forma w jakiej pojawi się ona w nowym wydaniu języka będzie praktycznie niczym innym niż uproszczonym wydaniem anonimowej klasy wewnętrznej. Czyżby ukłon w stronę tych hakerów, którzy nie mogą połapać się w konstrukcji &lt;a href="http://www.javaworld.com/javaworld/javaqa/2000-03/02-qa-innerclass.html"&gt;anonimowych klas&lt;/a&gt; albo &lt;a href="http://en.wikipedia.org/wiki/Strategy_pattern#Java"&gt;Wzorca Strategii&lt;/a&gt;?&lt;br /&gt;&lt;br /&gt;No i na pewno na certyfikatach pojawią się kolejne arcyistotne pytania mające na celu sprawdzenie czy delikwent jest w stanie odróżnić: domknięcie od klasy wewnętrznej i od niekompilującego się kodu;P&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5197374494377847819-5687719093744614412?l=art-of-software.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://art-of-software.blogspot.com/feeds/5687719093744614412/comments/default' title='Komentarze do posta'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5197374494377847819&amp;postID=5687719093744614412' title='Komentarze (5)'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5197374494377847819/posts/default/5687719093744614412'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5197374494377847819/posts/default/5687719093744614412'/><link rel='alternate' type='text/html' href='http://art-of-software.blogspot.com/2010/02/wyginanie-javy.html' title='Wyginanie Javy'/><author><name>Sławek Sobótka</name><uri>http://www.blogger.com/profile/15082577671795313109</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='30' height='32' src='http://3.bp.blogspot.com/-tmFOhJC48_E/TkQ0G2DxrqI/AAAAAAAAAz8/WVGBaaS5a_Y/s220/zdjecie2.png'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_m-NewLwJEb8/S5a6pfJy9cI/AAAAAAAAAkM/ynxfv5mNyLI/s72-c/spoon.JPG' height='72' width='72'/><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5197374494377847819.post-3374836356263812118</id><published>2010-02-07T15:43:00.011+01:00</published><updated>2010-02-09T18:32:30.008+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='usability'/><category scheme='http://www.blogger.com/atom/ns#' term='command design pattern'/><category scheme='http://www.blogger.com/atom/ns#' term='wzorce projektowe'/><title type='text'>Inżynieria w służbie użyteczności</title><content type='html'>/*&lt;br /&gt;&amp;nbsp;*Tytuł niczym wzięty ze sztandaru&lt;br /&gt;&amp;nbsp;*z jakiegoś pochodu&lt;br /&gt;&amp;nbsp;*z uprzedniej smutnej epoki:)&lt;br /&gt;&amp;nbsp;*/&lt;br /&gt;&lt;br /&gt;Witam po długiej przerwie. Zaprezentuję dziś pewne ujęcie &lt;a href="http://en.wikipedia.org/wiki/Usability"&gt;Usability&lt;/a&gt; oraz koncepcję technicznego rozwiązania użytecznej aplikacji - jej architekturę i dwa główne wzorce projektowe.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;NOWICJUSZ vs EKSPERT&lt;/b&gt;&lt;br /&gt;Użyteczność niejedno ma oblicze. Możemy mówić o przejrzystości, intuicyjności, ergonomii itd. Każdy z nas zapewne zdefiniuje dobre GUI jako takie, które oferuje to czego się spodziewamy. Ale co to znaczy? Oczywiście dla każdego coś innego.&lt;br /&gt;&lt;br /&gt;Dziś skupimy się na problemie różnych potrzeb i oczekiwań użytkowników o różnym poziomie zaawansowania.&lt;br /&gt;&lt;br /&gt;Analizując &lt;span style="font-style:italic;"&gt;Model Rozwoju Kompetencji Braci Dreyfus&lt;/span&gt;&lt;br /&gt;&lt;a href="http://art-of-software.blogspot.com/2008/08/unforgiven.html"&gt;krótki opis&lt;/a&gt;&lt;br /&gt;&lt;a href="http://art-of-software.blogspot.com/2010/01/wspinaczka-do-profesjonalizmu.html"&gt;szerszy opis&lt;/a&gt;&lt;br /&gt;możemy wywnioskować, że użytkownicy reprezentujący skrajne poziomy kompetencji potrzebują skrajnie odmiennego GUI.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style:italic;"&gt;Nowicjusz&lt;/span&gt; i &lt;span style="font-style:italic;"&gt;Zaawansowany Początkujący&lt;/span&gt; są nastawieni na zadania ponieważ nie ogarniają jeszcze całości problemu. Potrzebują określonej ścieżki, przez którą będą prowadzeni za rękę a na każdym etapie dostaną jasne wytyczne odnośnie tego CO trzeba zrobić.&lt;br /&gt;&lt;br /&gt;Z drugiej zaś strony &lt;span style="font-style:italic;"&gt;Kompetentny&lt;/span&gt;, &lt;span style="font-style:italic;"&gt;Biegły&lt;/span&gt; i &lt;span style="font-style:italic;"&gt;Ekspert&lt;/span&gt; są nastawieni na osiągnięcie celu i mniej lub bardziej orientują się jak go osiągnąć.&lt;br /&gt;&lt;br /&gt;Jak to w życiu bywa: "różni ludzie, różne potrzeby". &lt;br /&gt;&lt;br /&gt;Mniej zaawansowani użytkownicy potrzebują aplikacji-asystenta &lt;span style="font-weight:bold;"&gt;zorientowanej na zadania&lt;/span&gt;. Aplikacja taka nie powinna atakować mnogością możliwości. Powinna w danym momencie sugerować (lub wręcz zmuszać) do zrobienia właściwej rzeczy. Przykładem mogą być nasze ulubione kretynatory (yyy kreatory).&lt;br /&gt;&lt;br /&gt;Zaawansowany użytkownik potrzebuje &lt;span style="font-weight:bold;"&gt;aplikacji zorientowanej na możliwości&lt;/span&gt;. Dla niego wygodne będzie rozbudowane menu, bez sugerowania co kiedy kliknąć. Zaawansowany użytkownik dobrze wie co chce zrobić i nie potrzebuje aby mu podpowiadać. Mało tego, taki użytkownik ma wyrobiony swój własny styl pracy, zatem aplikacja-asystent jedynie przeszkadza. Najlepszym przykładem może być: IDE (np. Eclipse), zaawansowany edytor tekstu albo narzędzie typu CAD. Tysiące opcji w menu i biała kartka na dzień dobry.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Klasyczny problem występujący w aplikacjach biznesowych to nauka obsługi użytkowników. Stare systemy tej klasy orientowało się na możliwości (teraz powoli sytuacja ulega zmianie). Mamy zatem nieszczęsną użytkowniczkę, która zaczyna naukę obsługi systemu (może również jednocześnie "uczy się komputera"). Przytłoczenie mnogością opcji skutkuje jednym: tresurą. Użytkownik nie ma innego wyjścia jak opanowanie procesu biznesowego na zasadzie szympansa: klikam trzeci z lewej, później ok, później przedostatnia zakładka, później klikam drugi od dołu...&lt;br /&gt;&lt;br /&gt;Wszyscy znamy też nietrafione rozwiązanie, które miało pomagać nowicjuszom w okiełzaniu eksperckiego narzędzia - spinacz w Office;)&lt;br /&gt;&lt;br /&gt;&lt;b&gt;PRZYKŁAD APLIKACJI&lt;/b&gt;&lt;br /&gt;W przypadku aplikacji korporacyjnych jest łatwiej. Użytkownik nie ma innego wyjścia jak zacisnąć zęby i nauczyć się (pardon - wytresować się). Jest to po prostu przykre narzędzie jego pracy.&lt;br /&gt;&lt;br /&gt;Natomiast gdy nasza aplikacja ma konkurować na wolnym rynku wówczas musimy nieco się wysilić. Użytkownik zirytowany &lt;a href="http://www.danah.org/papers/AutisticSocialSoftware.pdf"&gt;autystycznym GUI&lt;/a&gt; aplikacji po prostu porzuci ją, zaklnie i pójdzie sobie do konkurencji:)&lt;br /&gt;&lt;br /&gt;Użytkownicy są teraz niezbyt cierpliwi i mają wysokie wymagania odnośnie przyjemności - pokolenie MTV?&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Aby ustalić kontekst aplikacji walczącej o klienta wysokim poziomem użyteczności wyobraźmy sobie system do projektowania wnętrz, np. wnętrz kuchni.&lt;br /&gt;Niech zaprojektowanie wymaga między innymi: określenia obszaru pomieszczenia, ustalenia otworów i innych przeszkód, rozstawienia mebli i AGD, dopasowania wszystkich wymiarów, wyboru materiałów z których mają być wykonanie poszczególne elementy, itd. Dalej mamy rysunki techniczne, wyliczenia należności, umowy, itp.&lt;br /&gt;&lt;br /&gt;Ustalmy wyzwanie: z aplikacji ma być wykorzystywana przez:&lt;br /&gt;- klientów końcowych, którzy to raz na kilka(naście) lat kupują sobie "kuchnię"&lt;br /&gt;- projektantów kuchni, którzy dziennie wyklikują po kilka takich zestawów.&lt;br /&gt;&lt;br /&gt;Co z kompetencjami naszych użytkowników?&lt;br /&gt;Jasne jest, że klient końcowy jest totalnym &lt;span style="font-style:italic;"&gt;Nowicjuszem&lt;/span&gt; jeżeli chodzi o aplikację. Użyje jej raz (ew jako rodzinny "haker" pomoże szwagrowi wyklikać jego zestaw). Zatem nigdy nie nabędzie wyższych kompetencji. Co gorsza klient może być również niekompetentny w domenie problemu, czyli wszystkich zagadnieniach związanych z kuchniami.&lt;br /&gt;Manual oczywiście odpada, bo zirytowany klient pójdzie sobie do konkurencji.&lt;br /&gt;&lt;br /&gt;Projektant jest zwykle w miarę kompetentny w domenie problemu;) Będzie też &lt;span style="font-style:italic;"&gt;Nowicjuszem&lt;/span&gt; jako użytkownik, ale ponieważ będzie miał motywację i częstą styczność z aplikacją to szybko osiągnie poziom &lt;span style="font-style:italic;"&gt;Kompetentny&lt;/span&gt; a z czasem dojdzie do &lt;span style="font-style:italic;"&gt;Eksperta&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;ARCHITEKTURA ROZWIĄZANIA&lt;/b&gt;&lt;br /&gt;Mamy zatem dwie klasy użytkowników, którzy potrzebują diametralnie różnego interfejsu. Początkujący użytkownik wymaga przeprowadzenia go przez cały proces projektowania krok po kroku, bez zbędnych pytań, defalutowo, szybko, gładko i bez irytacji. Zaawansowany użytkownik potrzebuje natomiast wolności, możliwości i tysięcy szczegółowych opcji.&lt;br /&gt;&lt;br /&gt;Jak to pogodzić? Czy musimy tworzyć niemal 2 osobne aplikacje? &lt;br /&gt;Niekoniecznie, jeżeli podejdziemy do problemu racjonalnie to możemy zredukować narzut związany z przygotowaniem 2 wersji.&lt;br /&gt;&lt;br /&gt;Możemy podejść do problemu następująco:&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_m-NewLwJEb8/S27Muu8xiFI/AAAAAAAAAhc/Qmoc-iZvfwA/s1600-h/architectre.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 297px; height: 320px;" src="http://4.bp.blogspot.com/_m-NewLwJEb8/S27Muu8xiFI/AAAAAAAAAhc/Qmoc-iZvfwA/s320/architectre.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5435506903531751506" /&gt;&lt;/a&gt;&lt;br /&gt;Wydzielamy CORE aplikacji, który zawiera klasy odpowiedzialne za główną funkcjonalność, czyli projektowanie wnętrz (wraz ze wszystkimi regułami z tym związanymi) oraz wizualizację projektu.&lt;br /&gt;Core jest dostępny przez API.&lt;br /&gt;&lt;br /&gt;Mamy 2 zestawy GUI: jeden prosty i intuicyjny oraz zorientowany na zadania przeznaczony dla początkujących. Drugi to klasyczny potwór dla eksperta oferujący niezliczone możliwości w rozbudowanych menu.&lt;br /&gt;&lt;br /&gt;Oba rodzaje GUI komunikują cię z Corem wysyłając polecenia zhermetyzowane przy użyciu wzorca projektowego &lt;a href="http://en.wikipedia.org/wiki/Command_pattern"&gt;Command&lt;/a&gt;. Idea wzorca jest taka, że czynności nie są metodami (jak w klasycznym podejściu proceduralnym). Czynności są obiektami. Dla wszystkich klas poleceń istnieje wspólny interfejs zawierający jedną metodę - jest to sygnał do polecenia aby wykonało ono zawartą w sobie logikę.&lt;br /&gt;&lt;br /&gt;Konkretny command zawiera w sobie zestaw instrukcji operujących na API Cora. Oczywiście commandy wysyłane z GUI &lt;span style="font-style:italic;"&gt;Nowicjusza&lt;/span&gt; będą zawierać więcej kodu operującego na API. Jedna czynność takiego użytkownika wykonuje więcej operacji. Commandy wysyłane z GUI &lt;span style="font-style:italic;"&gt;Eksperta&lt;/span&gt; będą bardziej elementarne. Commandy mogą po sobie dziedziczyć, mogą się na wzajem dekorować z wykorzystaniem wzorca &lt;a href="http://en.wikipedia.org/wiki/Decorator_pattern"&gt;Dekratora&lt;/a&gt; w celu reużycia logiki.&lt;br /&gt;&lt;br /&gt;W przedstawionej architekturze mamy dodatkowo wzorzec &lt;a href="http://en.wikipedia.org/wiki/Mediator_pattern"&gt;Mediatora&lt;/a&gt;. Został on wprowadzony jako "środowisko uruchomieniowe" dla poleceń oraz "hub" spinający wiele komponentów. GUI wysyła commadny do Mediatora, a to mediator wykonuje otrzymane polecenie (uruchamiając wspólną metodę interfejsu) przekazując do nich kontekst uruchomienia, czyli core.&lt;br /&gt;Mediator może również przy okazji manipulować stanem GUI, które nie należy do Core (np nakładać przeźroczystą chmurę na czas długotrwałych operacji bądź włączać dostępność opcji w menu). Mediator może też generować zdarzenia aplikacyjne, które będą obsługiwane przez pewne komponenty graficzne prezentujące zajście danego zdarzenia. Można bawić się do woli z Mediatorem, ale trzeba uważać aby nie stał się boską klasą o zbyt dużej odpowiedzialności.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;ZWIĘKSZAMY USABILITY&lt;/b&gt;&lt;br /&gt;Każdy użyteczny system, którego idea zasadzą się na bogatej interakcji użytkownika powinien oferować funkcjonalność "Cofnij". Wprowadzenie tej funkcjonalności jest generalnie bardzo kłopotliwe. Kto zmagał się z tym problemem ten zapewne próbował niewydajnego rozwiązania polegającego na "zrzucie" aktualnego stanu do pamięci podczas wykonywania każdej operacji modyfikującej stan.&lt;br /&gt;&lt;br /&gt;Ogólnie jest to problematyczna funkcjonalność, chyba że...&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_m-NewLwJEb8/S27M1Qr0zcI/AAAAAAAAAhk/MwQaKrrWNJQ/s1600-h/architectre-anti.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 297px; height: 320px;" src="http://2.bp.blogspot.com/_m-NewLwJEb8/S27M1Qr0zcI/AAAAAAAAAhk/MwQaKrrWNJQ/s320/architectre-anti.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5435507015666683330" /&gt;&lt;/a&gt;&lt;br /&gt;...posiłkujemy się wzorcem Command:)&lt;br /&gt;&lt;br /&gt;Możemy wówczas rozszerzyć go o anti-command.&lt;br /&gt;Każde polecenie zawierające logikę zawiera w sobie anty polecenie (jako obiekt dostępny przez getter - a getter w interfejsie Command). Antypolecenie zawiera logikę odwrotną do polecenie. &lt;br /&gt;&lt;br /&gt;Teraz w naszym przypadku Mediator wykonując polecenie, pobiera z niego anty-polecenie i odkłada je na stosie. W razie potrzeby, czyli gdy użytkownik kliknie cofnij (ctrl+z) wołamy Mediatora, który pobierze polecenie ze stosu anty-poleceń i wykonana go. Proste:)&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;//==============================&lt;br /&gt;&lt;br /&gt;O ile omawiana problematyka usability w kontekście kompetencji użytkownika jest ogólna, to przedstawione rozwiązanie nie aplikuje się do aplikacji webowych z cienkim klientem. Zresztą taki klient ma zastosowanie do innej klasy problemów.&lt;br /&gt;&lt;br /&gt;Natomiast rosnąca popularność grubszych klientów (opartych o: flex, javafx, silverligh, stare-dobre-niedoinwestowane-przez-matołów-suna applety czy nawet GWT) pozwala przewidywać, że coraz częściej będziemy spotykać się problemami tej klasy.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5197374494377847819-3374836356263812118?l=art-of-software.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://art-of-software.blogspot.com/feeds/3374836356263812118/comments/default' title='Komentarze do posta'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5197374494377847819&amp;postID=3374836356263812118' title='Komentarze (3)'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5197374494377847819/posts/default/3374836356263812118'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5197374494377847819/posts/default/3374836356263812118'/><link rel='alternate' type='text/html' href='http://art-of-software.blogspot.com/2010/02/inzynieria-w-suzbie-uzytecznosci.html' title='Inżynieria w służbie użyteczności'/><author><name>Sławek Sobótka</name><uri>http://www.blogger.com/profile/15082577671795313109</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='30' height='32' src='http://3.bp.blogspot.com/-tmFOhJC48_E/TkQ0G2DxrqI/AAAAAAAAAz8/WVGBaaS5a_Y/s220/zdjecie2.png'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_m-NewLwJEb8/S27Muu8xiFI/AAAAAAAAAhc/Qmoc-iZvfwA/s72-c/architectre.png' height='72' width='72'/><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5197374494377847819.post-7101204106284870205</id><published>2010-01-26T18:15:00.009+01:00</published><updated>2011-08-17T10:37:24.917+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='artykuł'/><category scheme='http://www.blogger.com/atom/ns#' term='Homo sum...'/><category scheme='http://www.blogger.com/atom/ns#' term='samodoskonalenie'/><category scheme='http://www.blogger.com/atom/ns#' term='Rozwój'/><title type='text'>Wspinaczka do profesjonalizmu</title><content type='html'>Wreszcie po ponad miesięcznej przerwie znalazłem chwilę czasu na napisanie posta:)&lt;br /&gt;Brak czasu na pisanie wynika głównie z nawału nowych obowiązków związanych z opieką nad 3-tygodniową córką:]&lt;br /&gt;&lt;br /&gt;Dlatego też dziś odsyłam do artykułu mojego autorstwa, który ukazał się w lutowym wydaniu &lt;a href="http://sdjournal.org/magazine/1001-programowanie-gier"&gt;SDJ&lt;/a&gt; pt:&lt;br /&gt;&lt;a href="http://www.bottega.com.pl/pdf/materialy/SDJ-wspinaczka.pdf"&gt;&lt;span style="font-weight:bold;"&gt;"Wspinaczka do profesjonalizmu&lt;br /&gt;Modelowa ścieżka rozwoju kompetencji – podejście pragmatyczne"&lt;/span&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Artykuł traktuje o rozwoju kompetencji developerskich w kontekście &lt;span style="font-weight:bold;"&gt;Modelu Kompetencji Braci Dreyfus&lt;/span&gt;, o którym &lt;a href="http://art-of-software.blogspot.com/2008/08/unforgiven.html"&gt;już pisałem&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;W tekście zachowano znaczniki specyficzne dla wydawnictwa, ponieważ są czytelne dla "ludzi z branży" a jednocześnie nadają mu strukturę. Tekst zawiera kilkanaście stron, ale podobno szybko i lekko się go czyta;)&lt;br /&gt;&lt;br /&gt;Zapraszam do lektury artykułu i być może nawet całego numeru poświęconego programowaniu gier - zawsze to ciekawa odmiana od enterprajz;)&lt;br /&gt;&lt;br /&gt;//========================&lt;br /&gt;&lt;br /&gt;W ciągu najbliższego tygodnia noworodek powinien przepoczwarzyć się w mniej zasobożerne niemowlę a co za tym idzie pojawi się kilka nowych postów. Będą poświęcone zagadnieniom z zakresu &lt;a href="http://manifesto.softwarecraftsmanship.org/"&gt;Craftsmanship&lt;/a&gt;, m. in. projektowaniu systemu pod kątem usability (na podstawie moich ostatnich doświadczeń z paroma autystycznymi koszmarkami) .&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5197374494377847819-7101204106284870205?l=art-of-software.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://art-of-software.blogspot.com/feeds/7101204106284870205/comments/default' title='Komentarze do posta'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5197374494377847819&amp;postID=7101204106284870205' title='Komentarze (11)'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5197374494377847819/posts/default/7101204106284870205'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5197374494377847819/posts/default/7101204106284870205'/><link rel='alternate' type='text/html' href='http://art-of-software.blogspot.com/2010/01/wspinaczka-do-profesjonalizmu.html' title='Wspinaczka do profesjonalizmu'/><author><name>Sławek Sobótka</name><uri>http://www.blogger.com/profile/15082577671795313109</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='30' height='32' src='http://3.bp.blogspot.com/-tmFOhJC48_E/TkQ0G2DxrqI/AAAAAAAAAz8/WVGBaaS5a_Y/s220/zdjecie2.png'/></author><thr:total>11</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5197374494377847819.post-1774638250540384135</id><published>2009-12-20T10:07:00.009+01:00</published><updated>2010-01-26T19:37:41.575+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='z dystansu'/><category scheme='http://www.blogger.com/atom/ns#' term='linki'/><title type='text'>Java EE</title><content type='html'>Kilka dni temu ukazała się finalna wersja specyfikacji Java EE 6.&lt;br /&gt;Jako, że żaden szanujący się blog Javowy nie może nie wspomnieć o tym doniosłym wydarzeniu, zatem niniejszym to czynię:&lt;br /&gt;Proszę Państwa, mamy nową specyfikację &lt;a href="http://jcp.org/en/jsr/detail?id=316"&gt;Java EE&lt;/a&gt;!&lt;br /&gt;&lt;br /&gt;Ok, formalności mamy za sobą. Teraz aby ten post jednak coś wnosił do sprawy i aby zachować niezależny charakter bloga pozwolę sobie polecić 2 linki stanowiące niejako rozliczenie dotychczasowych wersji platformy:&lt;br /&gt;&lt;br /&gt;- Rod Johnson (twórca Spring framework) w prezentacji &lt;a href="http://www.infoq.com/presentations/Lessons-Learned-from-Java-EE"&gt;Lessons Learned From Java EE’s Evolution&lt;/a&gt; opowiada historię platformy, m. in. wpływ niesławnych twórców CORBY na jej kształt:) Człowiek, który zna na wyrywki całą specyfikację Java EE twierdzi, że &lt;span style="font-weight:bold;"&gt;jedyną dobrą rzeczą jest Servlet API&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;- Misko Hevery (Agile Coach w Google odpowiedzialny za automatyzację testów) w swoim poście &lt;a href="http://misko.hevery.com/2009/04/08/how-to-do-everything-wrong-with-servlets/"&gt;How to do Everything Wrong with Servlets&lt;/a&gt; twierdzi natomiast, że &lt;span style="font-weight:bold;"&gt;Servlet API jest przykładem bardzo złego designu&lt;/span&gt;, bardzo złego.&lt;br /&gt;&lt;br /&gt;Aż strach pomyśleć do jakich wniosków doszliby obaj panowie dokonując koniunkcji zbiorów swoich poglądów.&lt;br /&gt;&lt;br /&gt;//============================&lt;br /&gt;&lt;br /&gt;Warto zwrócić uwagę na specyfikację JSF 2.0 (wchodzącą w skład Java EE 6), która wreszcie po latach będzie nieco bardziej pomocna do tworzenia aplikacji webowych. Przykładowo otrzymujemy oficjalne wsparcie dla szablonów (bez Feceletów jak bez ręki) oraz lepszą orientację na URL (taki mały szczegół webowy).&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5197374494377847819-1774638250540384135?l=art-of-software.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://art-of-software.blogspot.com/feeds/1774638250540384135/comments/default' title='Komentarze do posta'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5197374494377847819&amp;postID=1774638250540384135' title='Komentarze (6)'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5197374494377847819/posts/default/1774638250540384135'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5197374494377847819/posts/default/1774638250540384135'/><link rel='alternate' type='text/html' href='http://art-of-software.blogspot.com/2009/12/jee.html' title='Java EE'/><author><name>Sławek Sobótka</name><uri>http://www.blogger.com/profile/15082577671795313109</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='30' height='32' src='http://3.bp.blogspot.com/-tmFOhJC48_E/TkQ0G2DxrqI/AAAAAAAAAz8/WVGBaaS5a_Y/s220/zdjecie2.png'/></author><thr:total>6</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5197374494377847819.post-3399832793508610936</id><published>2009-11-29T23:11:00.019+01:00</published><updated>2009-12-23T22:35:05.295+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='EJB'/><category scheme='http://www.blogger.com/atom/ns#' term='JSF'/><category scheme='http://www.blogger.com/atom/ns#' term='frameworki'/><category scheme='http://www.blogger.com/atom/ns#' term='Seam'/><category scheme='http://www.blogger.com/atom/ns#' term='anty-wzorce'/><category scheme='http://www.blogger.com/atom/ns#' term='Architektura'/><title type='text'>Seam == JSF + EJB ?</title><content type='html'>&lt;span style="font-weight:bold;"&gt;WSTĘP&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Framework &lt;a href="http://seamframework.org/"&gt;Seam&lt;/a&gt; opiera się na bardzo silnym mechanizmie - bijekcji.&lt;br /&gt;&lt;br /&gt;Bijekcja to nowa jakość w technice Dependency Injection, która pozwala na budowanie bardziej naturalnych konstrukcji Inversion on Control.&lt;br /&gt;&lt;br /&gt;/**&lt;br /&gt;&amp;nbsp;* Na marginesie dodam, że DI i IoC to nie jest to samo.&lt;br /&gt;&amp;nbsp;* Wyjaśnienie różnic w tym przydługim poście:&lt;br /&gt;&amp;nbsp;* &lt;a href="http://art-of-software.blogspot.com/2008/11/wprowadzenie-do-wstrzykiwania-zalenoci.html#di-ioc"&gt;Wprowadzenie do wstrzykiwania zależności i Springa zarazem&lt;/a&gt;&lt;br /&gt;&amp;nbsp;*/&lt;br /&gt;&lt;br /&gt;Bijekcja w skrócie przedstawia się następująco:&lt;br /&gt;- podczas wywołania metody&lt;br /&gt;- następuje wstrzyknięcie zależności do obiektu, którego metoda jest wołana (pola adnotowane @In)&lt;br /&gt;- metoda jest wykonana&lt;br /&gt;- następuje wystrzyknięcie obiektów do kontekstu Seam (pola adnotowane @Out)&lt;br /&gt;- następuje czyszczenie (nulllowanie) wstrzykniętych zależności&lt;br /&gt;&lt;br /&gt;Od strony technicznej odbywa się to w Seam dzięki specjalnym interceptorom. Przechwytują one wywołania metod wszystkich komponentów i wokół tych wywołań dodają całą opisaną powyżej magię.&lt;br /&gt;&lt;br /&gt;Koncepcja jest jak już napisałem piękna, ponieważ pozwala na budowanie dużo bardziej naturalnych konstrukcji. Wstrzyknięcia następują per wywołanie metody a nie jedynie raz, po stworzeniu komponentu - zaspawane na wieki wieków (albo przynajmniej do restartu servera z powodu zwisu aplikacji;)&lt;br /&gt;Dodatkowo niemal bez ograniczeń możemy wstrzykiwać w siebie komponenty o różnych zasięgach - nie ma ograniczenia szerszy zasięg w węższy. Dlatego, że wstrzyknięcie następuje jedynie na czas wywołania metody i nie będziemy mieli nigdy problemu z nieświeżą instancją komponentu.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;PROBLEM&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Twórcy frameworka poszli jeszcze dalej...&lt;br /&gt;Umożliwiają używanie Sesyjnych EJB wprost w JSF - bez potrzeby pośredniej warstwy Managed Beanów (lub ich specyficznej odmiany Backing Beanów). Czyli komponenty Seam, które są jednocześnie komponentami EJB będą widoczne w kontekście JSF.&lt;br /&gt;Managed Beany są podobno zbędą warstwą, która tylko przeszkadza. Możliwość wołania EJB z JSF jest rzekomo tryumfem rozumu na platformą korporacyjną. &lt;br /&gt;&lt;br /&gt;Hmmm w bardzo prostych systemach klasy "Przeglądarka Bazy Danych" rzeczywiście można by się obyć bez MB, ale w niniejszym poście przedstawię do jakich &lt;span style="font-weight:bold;"&gt;kuriozalnych&lt;/span&gt; konstruktów dochodzi gdy w nietrywialnych przypadkach wiążemy JSF wprost z EJB.&lt;br /&gt;&lt;br /&gt;Na wstępie zaznaczam, że na potrzeby niniejszych rozważań pomijamy aspekty warstwowej architektury, elementarnych zasad projektowania mówiących o kohezji klasy i temu podobnych staromodnych ograniczeniach. Skupiamy się na "produktywnym" kodowaniu na wyścigi rodem z najlepszych tutoriali i książek.&lt;br /&gt;&lt;br /&gt;Zaczynamy.&lt;br /&gt;Przykład prosty, klasyczny ekran prezentujący listę czegoś. &lt;br /&gt;Wymagania:&lt;br /&gt;Po ordynarnym wejściu na stronę przez GET chcemy aby lista wyświetlała wszystkie dane.&lt;br /&gt;Widok ma pozwalać również na wyszukanie czegoś po jakimś atrybucie - czyli wpisanie szukanego słowa w pole tekstowe i naciśnięcie buttonu z zaokrąglonymi rogami "Szukaj" (POST gwoli ścisłości).&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Na początek implementujemy pierwsze wymaganie: po wejściu na stronę widzimy listę wszystkiego...&lt;br /&gt;&lt;br /&gt;Strzępek kodu widoku:&lt;br /&gt;&lt;pre class="brush: xml"&gt;&lt;br /&gt;  &amp;lt;h:dataTable value="#{listaCzegos}" var="_cos"&gt;&lt;br /&gt;    &amp;lt;h:column&gt;#{_cos.nazwa}&amp;lt;/h:column&gt;&lt;br /&gt;  ...&lt;br /&gt;  &amp;lt;/h:dataTable&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Stateless Session Bean, który dostarcza danych dla widoku:&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush: java"&gt;&lt;br /&gt;@Stateless&lt;br /&gt;@Name("cosProwajder")&lt;br /&gt;public class CosProwajderBean implements CosProwajderLocal{&lt;br /&gt;  @Out&lt;br /&gt;  private List&lt;Cos&gt; listaCzegos;&lt;br /&gt;&lt;br /&gt;  @Factory("listaCzegos")&lt;br /&gt;  public void initListaCzegos(){&lt;br /&gt;    listaCzegos = //pobranie danych&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Co się tutaj dzieje: JSF rząda komponentu listaCzegos. Seam widzi, że nie istnieje on w kontekście, ale na szczęście znalazł ochotnika, który go sfabrykuje - metodę otagowaną adnotacją @Factory("listaCzegos"). Metoda zostaje wywołana, metoda ustawia pole prywatne, a ponieważ pole jest adnotowane @Out to po chwili jest wystrzykiwane do kontekstu. Dzięki temu JSF "widzi" listę i może ją już teraz spokojnie renderować w tabelce.&lt;br /&gt;&lt;br /&gt;Kod Session Beana mógłby równie dobrze wyglądać tak:&lt;br /&gt;&lt;pre class="brush: java"&gt;&lt;br /&gt;@Stateless&lt;br /&gt;@Name("cosProwajder")&lt;br /&gt;public class CosProwajderBean implements CosProwajderLocal{&lt;br /&gt;&lt;br /&gt;  @Factory("listaCzegos")&lt;br /&gt;  public List&lt;Cos&gt; initListaCzegos(){&lt;br /&gt;    listaCzegos = //pobranie danych&lt;br /&gt;    return listaCzegos;&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Ale już śpieszę wyjaśnić skąd poprzednia konstrukcja. Mam już w zamyśle spełnienie drugie wymagania - funkcjonalności wyszukiwania. Zatem na widoku pojawi się pole tekstowe i button:&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush: xml"&gt;&lt;br /&gt;&amp;lt;h:form&gt;&lt;br /&gt;  &amp;lt;h:inputText value="#{searchFilter.name}" /&gt;&lt;br /&gt;  &amp;lt;h:commandButton action="#{cosProwajder.search}" /&gt;&lt;br /&gt;&amp;lt;h:form&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Nasz Session Bean dostanie metodę search, która wyszuka dane na podstawie wstrzykniętych kryteriów, następnie wynik ustawi w prywatnym polu, z którego to po chwili wartość zostanie wystrzyknięta do kontekstu Seam, skąd JSF będzie ją widział.&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush: java"&gt;&lt;br /&gt;@Stateless&lt;br /&gt;@Name("cosProwajder")&lt;br /&gt;public class CosProwajderBean implements CosProwajderLocal{&lt;br /&gt;  @Out&lt;br /&gt;  private List&lt;Cos&gt; listaCzegos;&lt;br /&gt;&lt;br /&gt;  @In&lt;br /&gt;  private SearchCriteria searchCriteria;&lt;br /&gt;&lt;br /&gt;  @Factory("listaCzegos")&lt;br /&gt;  public void initListaCzegos(){&lt;br /&gt;    listaCzegos = //pobranie danych&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  public void search(){&lt;br /&gt;    listaCzegos = //pobranie danych na podstawie searchCriteria&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Jeszcze tylko dla ścisłości komponent przechowujący kryteria wyszukiwania. Zasięg PAGE aby kryteria były widoczne po przeładowaniu strony:&lt;br /&gt;&lt;pre class="brush: java"&gt;&lt;br /&gt;@Name("searchCriteria")&lt;br /&gt;@Scope(PAGE)&lt;br /&gt;public class SearchCriteria implements Serializable{&lt;br /&gt;  private String name;&lt;br /&gt;  //getter i setter&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Pytanie: co jest nie tak z poniższym kodem?&lt;br /&gt;&lt;pre class="brush: java"&gt;&lt;br /&gt;@Stateless&lt;br /&gt;@Name("cosProwajder")&lt;br /&gt;public class CosProwajderBean implements CosProwajderLocal{&lt;br /&gt;  @Out&lt;br /&gt;  private List&lt;Cos&gt; listaCzegos;&lt;br /&gt;&lt;br /&gt;  @In&lt;br /&gt;  private SearchCriteria searchCriteria;&lt;br /&gt;&lt;br /&gt;  @Factory("listaCzegos")&lt;br /&gt;  public void initListaCzegos(){&lt;br /&gt;    listaCzegos = //pobranie danych&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  public void search(){&lt;br /&gt;    listaCzegos = //pobranie danych na podstawie searchCriteria&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Dla ułatwienia wyrzucę linijki odwracające uwagę i zaznaczę kluczowy element:&lt;br /&gt;(To przecież nie jest egzamin na certyfikat - chcemy się tu dowiedzieć czegoś pożytecznego)&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush: java"&gt;&lt;br /&gt;@Stateless  //&lt;&lt;-------------&lt;br /&gt;public class CosProwajderBean implements CosProwajderLocal{&lt;br /&gt;  private List&lt;Cos&gt; listaCzegos;&lt;br /&gt;&lt;br /&gt;  private SearchCriteria searchCriteria;&lt;br /&gt;&lt;br /&gt;  public void search(){&lt;br /&gt;    listaCzegos = //pobranie danych na podstawie searchCriteria&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Właśnie!&lt;br /&gt;Niby mamy &lt;span style="font-weight:bold;"&gt;bezstanowy&lt;/span&gt; komponent, ale korzystamy z niego w &lt;span style="font-weight:bold;"&gt;stanowy&lt;/span&gt; sposób!&lt;br /&gt;&lt;br /&gt;Wyobraźmy sobie, że nasz wspaniały komponent biznesowy jest tak genialny, że chcemy go wykorzystać jeszcze gdzieś poza JSF, np wywołać zdalnie. Musimy wówczas:&lt;br /&gt;1. ustawić kryteria wyszukiwania (zakładając, że mamy setter)&lt;br /&gt;2. odpalić metodę search(), która zmieni stan - tu jest ta nieszczęsna stanowość&lt;br /&gt;3. odebrać wynik przez getter&lt;br /&gt;&lt;br /&gt;Czyli JSF wymusza na nas styl "strzelania z muszkietu": załaduj i wypal.&lt;br /&gt;&lt;br /&gt;Czy dałoby się wykorzystać mimo wszystko ten super-kod poza Seam, np przykrywając go fasadą:&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush: java"&gt;&lt;br /&gt;@Stateless&lt;br /&gt;public class CosProwajderFacadeBean implements CosProwajderFacadeRemote{&lt;br /&gt;  @Ejb&lt;br /&gt;  private CosProwajderLocal cosProwajder;&lt;br /&gt;  public List&lt;Cos&gt; search(SearchCriteria searchCriteria){&lt;br /&gt;    cosProwajder.setSearchCriteria(searchCriteria);&lt;br /&gt;    cosProwajder.search();&lt;br /&gt;    return cosProwajder.getListaCzegos();&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Niestety NIE, ponieważ nie mamy gwarancji, że kontener JEE przy każdym z 3 wywołań bezstanowego komponentu zaserwuje nam tą samą instancję!&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Dlaczego ten bezsensowny kod działa w ogóle w Seam? Tak jak napisałem na wstępie - interceptory Seam. Jeden z nich przechwytuje wołanie metody search na komponencie, wstrzykuje kryteria, wykonuje metodę, wystrzykuje wynik. Ponieważ wstrzykiwanie i wystrzykiwanie nie są wywołaniem metod biznesowych bezstanowego komponentu to interceptor cały czas operuje na tej samej instancji.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;ROZWIĄZANIE&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Łatwo można rozwiązać problem sensowności &lt;span style="font-weight:bold;"&gt;kodu&lt;/span&gt; zmieniając bean bezstanowy na stanowy. Jednak wciąż mamy problem z bezsensownością &lt;span style="font-weight:bold;"&gt;logiczną&lt;/span&gt;. Dlaczego jakiś komponent będący de facto wrapperem dla procedury ma być stanowy?&lt;br /&gt;&lt;br /&gt;Owszem w pewnych sytuacjach stanowość może mieć sens, np: z przyczyn wydajnościowych komponent stanowy trzyma wynik jako jakiś kursor po stronie bazy. Klient Stanowego Komponentu Sesyjnego przegląda listę wynikową po kawałku. Tę argumentację zaliczam.&lt;br /&gt;&lt;br /&gt;Innym usprawiedliwieniem może być chęć wybrania (kliknięcia) wiersza - z technicznych powodów musi wówczas przechować listę. Innym jeszcze usprawiedliwieniem może być naiwna paginacja, która w naiwnych paginatorach działa na danych sesyjnych pobranych w całości z bazy. &lt;br /&gt;Czy jednak sensowne jest dopasowywanie API komponentów biznesowych do takich szczegółów technicznych jakiś frameworków prezentacji? &lt;br /&gt;Poza tym wciąż będziemy mieli kuriozalne korzystanie z niego w fasadzie - w stylu "strzelania z muszkietu": załaduj i wypal.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;PRAWDZIWE ROZWIĄZANIE&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Aby nasze komponenty biznesowe miały sensowny interfejs w nietrywialnych przypadkach musimy ponieść ten niesamowity trud wprowadzenia warstwy jakiś Managed Beanów - w Seam zwanych Akcjami. &lt;br /&gt;&lt;br /&gt;Są to zwykłe POJOs, które mają API w stylu "strzelania z muszkietu" a logikę biznesową delegują do EJB:&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush: java"&gt;&lt;br /&gt;@Name("cosControler")&lt;br /&gt;public class CosControler{&lt;br /&gt;  @In //EJB&lt;br /&gt;  private CosProwajderLocal cosProwajder;&lt;br /&gt;&lt;br /&gt;  @Out&lt;br /&gt;  private List&lt;Cos&gt; listaCzegos;&lt;br /&gt;&lt;br /&gt;  @In&lt;br /&gt;  private SearchCriteria searchCriteria;&lt;br /&gt;&lt;br /&gt;  @Factory("listaCzegos")&lt;br /&gt;  public void initListaCzegos(){&lt;br /&gt;    //używamy pustych kryteriów (w celu optymalizacji można by wynieść je do singeltona)&lt;br /&gt;    listaCzegos = cosProwajder.search(new SearchCriteria());&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  public void search(){&lt;br /&gt;    //Wywolanie EJB&lt;br /&gt;    listaCzegos = cosProwajder.search(searchCriteria);&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Jest to również doskonałe miejsce do wstrzyknięcia np kontekstu FacesMessages, kontekstów Seam, parametrów Request, bindowanie UIComponent i innych zależności typowych dla technikaliów frameworków. W tej warstwie możemy sobie na to śmiało pozwolić i dzięki niej nie musimy brudzić EJB zależnościami od Seam i JSF. &lt;br /&gt;&lt;br /&gt;//==========================&lt;br /&gt;&lt;br /&gt;Sama możliwość wołania Sesyjnych EJB z JSF jest oczywiście bardzo wygodnym ficzerem i warto czasem z niej korzystać. Ale tylko wówczas gdy ma to sens i jest racjonalnie uzasadnione.&lt;br /&gt;&lt;br /&gt;Tworzenie &lt;span style="font-weight:bold;"&gt;komponentu biznesowego&lt;/span&gt;, który jest "zbrukany" stylem i zależnościami pewnych technologii powoduje, że nie jest to już ani komponent ani biznesowy. Komponent - czyli pewna reużywalna część; biznesowy - czyli zajmujący się jedynie logiką biznesową.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5197374494377847819-3399832793508610936?l=art-of-software.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://art-of-software.blogspot.com/feeds/3399832793508610936/comments/default' title='Komentarze do posta'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5197374494377847819&amp;postID=3399832793508610936' title='Komentarze (9)'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5197374494377847819/posts/default/3399832793508610936'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5197374494377847819/posts/default/3399832793508610936'/><link rel='alternate' type='text/html' href='http://art-of-software.blogspot.com/2009/11/seam-jsf-ejb.html' title='Seam == JSF + EJB ?'/><author><name>Sławek Sobótka</name><uri>http://www.blogger.com/profile/15082577671795313109</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='30' height='32' src='http://3.bp.blogspot.com/-tmFOhJC48_E/TkQ0G2DxrqI/AAAAAAAAAz8/WVGBaaS5a_Y/s220/zdjecie2.png'/></author><thr:total>9</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5197374494377847819.post-4203554623882383395</id><published>2009-11-25T21:08:00.011+01:00</published><updated>2009-11-25T22:27:48.456+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='OOP'/><category scheme='http://www.blogger.com/atom/ns#' term='z dystansu'/><category scheme='http://www.blogger.com/atom/ns#' term='linki'/><title type='text'>Geneza i ograniczenia OO</title><content type='html'>Dziś jedynie dwa linki, które uważam za godne polecenia.&lt;br /&gt;&lt;br /&gt;Przeczytałem niedawno tekst, który lekko zachwiał moim światopoglądem: &lt;a href="http://weblogs.java.net/blog/82/2003/09/02/aristotles-error-or-agile-smagile"&gt;Aristotle's Error or Agile Smagile&lt;/a&gt;. Tekst traktuje ogólnie o historii - znajdziecie tam również rzekomą genezę Object Oriented.&lt;br /&gt;&lt;br /&gt;Rzekomo pierwotnie wcale nie chodziło o modelowanie świata, lecz o zabawy ze &lt;a href="http://en.wikipedia.org/wiki/Dynamic_memory_allocation"&gt;stertą&lt;/a&gt; - co będzie gdy zamiast chwilowo przechowywać zmienne na stosie wrzucimy je na dłużej do sterty.&lt;br /&gt;&lt;br /&gt;Teorię OO Analysis i OO Design rzekomo "dorobiono" później. Tak, tak, wiem - sam jestem w szoku podobnym do tego gdy wydedukowałem, że nie ma żadnego św Mikołaja;P&lt;br /&gt;&lt;br /&gt;Nie wiem na ile historia o pierwocinach OO jest prawdziwa, ale tym razem wielki szacunek dla &lt;a href="http://en.wikipedia.org/wiki/Robert_Cecil_Martin"&gt;Uncle Boba&lt;/a&gt; za zdystansowane podejście.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Kolejny link to ciekawa prezentacja człowieka, któremu doświadczenie również pozwala zdystansować się od mainstreamu &lt;a href="http://www.infoq.com/presentations/Are-We-There-Yet-Rich-Hickey"&gt;Are We There Yet?&lt;/a&gt;. Prezentacja pozwala uświadomić sobie ograniczenia OO oraz wyjaśnia (tym, którzy jeszcze tego nie widzą) dlaczego niektóre wydawałoby się proste języki wprowadzają wysoką złożoność (&lt;a href="http://en.wikipedia.org/wiki/Accidental_complexity"&gt;przypadkową&lt;/a&gt;). &lt;br /&gt;&lt;br /&gt;Zobaczycie też jak bardzo podobne są do siebie języki, o które często spieramy się "który lepszy". Nie brakuje też aluzji do takich "przełomowych usprawnień" jak usunięcie średników:) Dowiecie się również z czego wg autora prezentacji wynika potrzeba posiadania testów:)&lt;br /&gt;&lt;br /&gt;//=======================&lt;br /&gt;&lt;br /&gt;Od razu ostrzegam, że treści kryjące się pod linkami są mocno filozoficzne, ale może warto oderwać się na chwilę od kodu aby później móc spojrzeć na niego inaczej...&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5197374494377847819-4203554623882383395?l=art-of-software.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://art-of-software.blogspot.com/feeds/4203554623882383395/comments/default' title='Komentarze do posta'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5197374494377847819&amp;postID=4203554623882383395' title='Komentarze (1)'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5197374494377847819/posts/default/4203554623882383395'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5197374494377847819/posts/default/4203554623882383395'/><link rel='alternate' type='text/html' href='http://art-of-software.blogspot.com/2009/11/geneza-i-ograniczenia-oo.html' title='Geneza i ograniczenia OO'/><author><name>Sławek Sobótka</name><uri>http://www.blogger.com/profile/15082577671795313109</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='30' height='32' src='http://3.bp.blogspot.com/-tmFOhJC48_E/TkQ0G2DxrqI/AAAAAAAAAz8/WVGBaaS5a_Y/s220/zdjecie2.png'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5197374494377847819.post-2077253097753265409</id><published>2009-11-10T01:01:00.003+01:00</published><updated>2009-11-10T01:06:40.049+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='śmieszne'/><title type='text'>SQL Injection</title><content type='html'>Kolejny post z serii &lt;a href="http://art-of-software.blogspot.com/search/label/śmieszne"&gt;geek-humor&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;ZU0 666 - apokalipsa fotoradarów:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_m-NewLwJEb8/SviuJY9Fz9I/AAAAAAAAAdY/0gtqDf6UXeg/s1600-h/sqlinjection.jpeg"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 240px;" src="http://1.bp.blogspot.com/_m-NewLwJEb8/SviuJY9Fz9I/AAAAAAAAAdY/0gtqDf6UXeg/s320/sqlinjection.jpeg" border="0" alt=""id="BLOGGER_PHOTO_ID_5402259229371650002" /&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5197374494377847819-2077253097753265409?l=art-of-software.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://art-of-software.blogspot.com/feeds/2077253097753265409/comments/default' title='Komentarze do posta'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5197374494377847819&amp;postID=2077253097753265409' title='Komentarze (1)'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5197374494377847819/posts/default/2077253097753265409'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5197374494377847819/posts/default/2077253097753265409'/><link rel='alternate' type='text/html' href='http://art-of-software.blogspot.com/2009/11/sql-injection.html' title='SQL Injection'/><author><name>Sławek Sobótka</name><uri>http://www.blogger.com/profile/15082577671795313109</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='30' height='32' src='http://3.bp.blogspot.com/-tmFOhJC48_E/TkQ0G2DxrqI/AAAAAAAAAz8/WVGBaaS5a_Y/s220/zdjecie2.png'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_m-NewLwJEb8/SviuJY9Fz9I/AAAAAAAAAdY/0gtqDf6UXeg/s72-c/sqlinjection.jpeg' height='72' width='72'/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5197374494377847819.post-7710581723947577355</id><published>2009-11-09T21:27:00.021+01:00</published><updated>2009-11-15T14:04:06.744+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Craftsmanship'/><category scheme='http://www.blogger.com/atom/ns#' term='z dystansu'/><category scheme='http://www.blogger.com/atom/ns#' term='metodyki'/><category scheme='http://www.blogger.com/atom/ns#' term='TDD'/><title type='text'>Czysty kod to przetestowany kod?</title><content type='html'>Clean Code to skądinąd szczytna idea, na fali której kilka osób chce się wylansować ostatnimi czasy. Przyjrzymy się jej dzisiaj nieco bliżej aby sprawdzić czy nie kryje się za nią przypadkiem merytoryczna próżnia...&lt;br /&gt;&lt;br /&gt;Ewangelizatorem tej idei jest nasz ulubiony Wujek Dobra Rada - &lt;a href="http://www.objectmentor.com/omTeam/martin_r.html"&gt;Uncle Bob&lt;/a&gt;. Polecam wszystkim jego prezentację pt &lt;a href="http://www.infoq.com/presentations/craftmanship-ethics"&gt;Craftsmanship and Ethics&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Uncle B z pasją opowiada o profesji i etyce w naszej branży. Właściwie to przekonuje, że już najwyższy czas aby wykrystalizowały się one bo póki co jeszcze się ich nie dorobiliśmy. Tutaj zgadzam się z nim bez 2 zdań. Metodyka byle-jak-byle-działało-ale-miało-zaokrąglone-rogi-na-gui to aktualnie standard.&lt;br /&gt;&lt;br /&gt;Jako że są to idee bardzo mi bliskie to pierwsza część prezentacji jest na prawdę budująca. Dalej Uncje B twierdzi, że drogą do profesjonalizacji i nieskazitelnego kodu jest Test Driven Development. "Nie wolno Ci napisać ani linijki produkcyjnego kodu bez napisania uprzednio testu!" grzmi wujaszek! Kropka. &lt;br /&gt;&lt;br /&gt;Postępuj tak a w nagrodzę po śmierci będą czekać na Ciebie w niebie zastępy dziewic - do tego nimfomanek rozumiejących maszynowy kod w reprezentacji binarnej. Marzenia...&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_m-NewLwJEb8/SviLbPcAQNI/AAAAAAAAAdQ/fLkFvCe2UYE/s1600-h/nerd-girl.jpg"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 213px; height: 320px;" src="http://3.bp.blogspot.com/_m-NewLwJEb8/SviLbPcAQNI/AAAAAAAAAdQ/fLkFvCe2UYE/s320/nerd-girl.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5402221053147627730" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;...ale chyba nie będzie tak łatwo.&lt;br /&gt;&lt;br /&gt;TDD owszem jest techniką, która ma swoje przeznaczenie i zastosowania ale nie dajmy się zwieść, że rozwiązuje wszystkie problemy. Co najwyżej &lt;span style="font-weight:bold;"&gt;niektóre&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;Sensowna krytyka tego typu rozumowania znajduje się w typ poście: &lt;a href="http://blogs.msdn.com/cashto/archive/2009/03/31/it-s-ok-not-to-write-unit-tests.aspx"&gt;It's OK Not to Write Unit Tests&lt;/a&gt;. Wujkowi Dobra Rada chyba tylko wydaje się, że rozprawił się z adwersarzem przy pomocy racjonalnych argumentów: &lt;a href="http://blog.objectmentor.com/articles/2009/11/05/its-ok-not-to-write-unit-tests-not"&gt;Excuse me sir, What Planet is this?&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;O ile w pewnych sytuacjach testy mogą "sterować" developmentem to nie zapominajmy o technikach, które &lt;span style="font-weight:bold;"&gt;rzeczywiście prowadzą do clean code&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;Co nam po nawet 100% pokryciu kodu testami jeżeli kod będzie jedną wielką kupą...&lt;br /&gt;Działającą nawet perfekcyjnie, ale wciąż jedną wielką kupą... [wstawić_swoją_ulubioną_metaforę]&lt;br /&gt;&lt;br /&gt;Refaktoryzacja to podstawa? Co nam po wsparciu dla refaktoryzacji dzięki pokryciu kodu testami, które zwalniają nas z napięcia towarzyszącemu zmianom skoro... nie mamy pojęcia jak refaktoryzować ani w ogóle, w którą stronę refaktoryzować?&lt;br /&gt;&lt;br /&gt;Do tego właśnie zmierzam... TDD nie daje żadnych wskazówek jakich technik developerskich użyć aby osiągnąć upragniony Clean Code. To oczywiste, że nie daje wskazówek, bo nie leży to w "domenie" TDD. Ale trzeba to sobie uświadomić i nie dajmy sobie wcisnąć kitu, że testy jednostkowe rozwiązują problem - są po prostu &lt;span style="font-weight:bold;"&gt;niewystarczające&lt;/span&gt;. Pomagają rozwiązać - ale rozwiązanie właściwe leży chyba gdzie indziej.&lt;br /&gt;&lt;br /&gt;Czysty kod, aby powstał musi być wypracowany poprzez pewien wysiłek umysłowy. Nie wystarczy dorwać się do klawiatury i radośnie stukać (o tym na koniec). Na ten proces musi składać się rzetelna analiza problemu, projekt i dopiero implementacja. Nie mam tu oczywiście na myśli metodyki Waterfall, ale po prostu pewnej pracy, którą trzeba wykonać - nawet w umyśle jednej osoby.&lt;br /&gt;&lt;br /&gt;Dla każdego z tych etapów mamy zestaw sprawdzonych technik oraz narzędzi, które oczywiście nie gwarantują sukcesu, ale zwiększają prawdopodobieństwo powstania upragnionego Clean Code.&lt;br /&gt;&lt;br /&gt;Na poziomie analizy możemy posłużyć się Archetypami Modeli Biznesowych. Są to skatalogowane gotowe rozwiązania standardowych problemów biznesowych. Modele te zostały wypracowane przez wytrawnych analityków dzięki czemu można je dostosowywać do swych potrzeb. Są również zaprojektowane z myślą o rozbudowie modelu. Można by dużo o nich pisać, ale nic nie zastąpi przykładu. A przykład w jednym z najbliższych postów. Póki co zastanówmy się co nam po doskonale obłożonym testami modelu, który jest kupą...&lt;br /&gt;&lt;br /&gt;Gdzieś na styku analizy i projektu mamy na przykład &lt;a href="http://art-of-software.blogspot.com/search/label/Domain%20Driven%20Design"&gt;Domain Driven Design&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Zanim przejdziemy do poziomu projektu zatrzymajmy się przez chwilę na architekturze, będącej stylem, na podstawie którego będziemy projektować. Zastanówmy się co nam po doskonale obłożonym testami kod jeżeli architektura jest kupą...&lt;br /&gt;&lt;br /&gt;Na poziomie projektu mamy zestaw technik np Object Oriented. &lt;a href="http://en.wikipedia.org/wiki/GRASP_(Object_Oriented_Design)"&gt;GRASP&lt;/a&gt; i &lt;a href="http://en.wikipedia.org/wiki/Solid_(Object_Oriented_Design)"&gt;SOLID&lt;/a&gt; - pomagające w poprawnym interpretowaniu OO i uniknięciu proceduralnego kodu dziwacznie upchanego w klasy.&lt;br /&gt;Nie zapominajmy o Wzorcach Projektowych. Kiedyś było o nich głośno, ale aktualnie młodzież woli sobie wyklikać/wygenerować trochę kodu. Ci bardziej Agile obłożą go paroma testami i jest git;)&lt;br /&gt;Wzorce mogą pomagać u utrzymaniu czystej struktury kodu, ale przy ich "pomocy" można również bardzo skutecznie niepotrzebnie zagmatwać powinny pozostać prostsze - cała sztuka w wyważeniu. Ale tego oczywiście nie dowiemy się z marketingu TDD;)&lt;br /&gt;&lt;br /&gt;Co do wzorców to planuję kiedyś stworzyć serię postów z realistycznymi (nieksiążkowymi) przykładami - ale jak zwykle czasu brak. Co do GRASP i SOLID to można znaleźć trochę dobrych przykładów - np &lt;a href="http://koziolekweb.pl/2009/02/26/solidne-programowanie-czesc-1-czyli-monogamia/"&gt;ten&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Kiedy już wiemy co i jak to na poziomie implementacji możemy podeprzeć się techniką testów jednostkowych. Ale to czy kod będzie Clean zależy od pracy umysłowej włożonej również (albo przede wszystkim) wcześniej.&lt;br /&gt;&lt;br /&gt;Konkludując: TDD ew. jako dodatek na drodze do Clen Code wujaszku;P&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Aby uzupełnić całość warto wspomnieć o podejściu Specify First - dobry opis w poście &lt;a href="http://blog.orfjackal.net/2009/10/tdd-is-not-test-first-tdd-is-specify.html"&gt;TDD is not test-first. TDD is specify-first and test-last&lt;/a&gt;. Niektórzy twierdzą, że dopiero przy takim podejściu można mówić o prawdziwym TDD. &lt;br /&gt;Chodzi generalnie o to, że pisząc &lt;span style="font-weight:bold;"&gt;najpierw&lt;/span&gt; test - nawet nie interfejs implementacji, a test - stawiamy się w roli kodu "klineta" danej klasy. Na pewno wpływa to pozytywnie na nasz design - bardzo pozytywnie.&lt;br /&gt;&lt;br /&gt;Ale to znowu półśrodek. Technika owszem dobra, ale dla tych z nas, którzy są wciąż jeszcze na poziomie &lt;span style="font-weight:bold;"&gt;myślenia kodem&lt;/span&gt;. &lt;br /&gt;&lt;br /&gt;Myślenie kodem to zupełnie normalna faza w rozwoju programisty i każdy przez nią przechodzi. Jeżeli jesteś początkujący to zapewne zauważyłeś, że gdy mówisz do kogoś ifami i pętlami to on krzywi się i zaczyna rysować jakieś prostokąty połączone strzałkami aby cokolwiek zrozumieć. Jeżeli bawisz się w to już kilka lat to zapewne irytują cię juniorzy, którzy mówią do Ciebie kodem. Normalna sprawa, abstrahowanie przychodzi z czasem ...&lt;br /&gt;&lt;br /&gt;Zatem "Specify first" jest dobre na początek gdy świerzbią nas paluszki i chcemy jak najszybciej dorwać się do klawiatury i nastukać coś co można będzie za chwilę radośnie debugować. Analizowanie, modelowanie, projektowanie... to dobre dla zgredów.&lt;br /&gt;&lt;br /&gt;Przy podejściu Top-Down rzeczywiście klasy "niższe" mogą być pokraczne bez wyobrażenie sobie jak będą używane. Ale top-down powinien być style analizowania problemu, natomiast projektowanie klas można przeprowadzić bottom-up dzięki czemu powstaną "komponenty" - niczym niezależne części "ruchomej machiny". Z czasem przychodzi umiejętność wyobrażania sobie i manipulowania obiektami "w pamięci" (własnej) bez potrzeby pisania czegokolwiek. Pomocy może być ew. ołówek, kartka i UML. Ktoś pamięta w ogóle co to jest UML? Nie to nie jest kolejna biblioteka do mockowania;P&lt;br /&gt;&lt;br /&gt;Taaak.... kiedyś pewnie powstanie &lt;span style="font-weight:bold;"&gt;Unified Mocking Library&lt;/span&gt; - w sumie już nic mnie nie zdziwi w naszej branży...&lt;br /&gt;&lt;br /&gt;//===============&lt;br /&gt;&lt;br /&gt;Od razu uprzedzę ew. komentarze aby uniknąć niepotrzebnego niezrozumienia.&lt;br /&gt;W tekście nie zajmuję stanowiska ZA albo PRZECIW testom jednostkowym. Moim celem było zwrócenie uwagi na fakt, że same testy niewiele wnoszą do koncepcji Clean Code. TDD jest techniką implementacyjną oraz od niedawna jest sprzedawany jako technika specyfikowania dla niecierpliwych/początkujących. &lt;br /&gt;&lt;br /&gt;Moja teza jest następująca: aby osiągnąć Clean Code potrzeba dodatkowo kilku innych technik developerskich. Dopiero synteza całości może dać zadowalający rezultat. &lt;br /&gt;&lt;br /&gt;I niestety trzeba się wysilić znacznie bardziej niż tylko dopisać więcej kodu - testującego. A podstawowe zagadnienia z zakresu inżynierii oprogramowania (Low Coupling, High Cohesion, IoC,...) przydają się również choćby do pisania kodu podatnego na testy - o wysokim poziomie testability.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5197374494377847819-7710581723947577355?l=art-of-software.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://art-of-software.blogspot.com/feeds/7710581723947577355/comments/default' title='Komentarze do posta'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5197374494377847819&amp;postID=7710581723947577355' title='Komentarze (20)'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5197374494377847819/posts/default/7710581723947577355'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5197374494377847819/posts/default/7710581723947577355'/><link rel='alternate' type='text/html' href='http://art-of-software.blogspot.com/2009/11/czysty-kod-to-przetestowany-kod.html' title='Czysty kod to przetestowany kod?'/><author><name>Sławek Sobótka</name><uri>http://www.blogger.com/profile/15082577671795313109</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='30' height='32' src='http://3.bp.blogspot.com/-tmFOhJC48_E/TkQ0G2DxrqI/AAAAAAAAAz8/WVGBaaS5a_Y/s220/zdjecie2.png'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_m-NewLwJEb8/SviLbPcAQNI/AAAAAAAAAdQ/fLkFvCe2UYE/s72-c/nerd-girl.jpg' height='72' width='72'/><thr:total>20</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5197374494377847819.post-314473907601386020</id><published>2009-10-19T14:00:00.005+02:00</published><updated>2009-10-19T14:48:38.966+02:00</updated><title type='text'>Mały refreshing</title><content type='html'>Jako, że na blogspocie pojawiły się nowe szablony (a poprzedni zielony już mi się znudził) uznałem, że czas na zmianę.&lt;br /&gt;&lt;br /&gt;Przy okazji lekkiej zmianie uległa sama nazwa bloga (poprzednia brzmiała chyba zbyt pretensjonalnie), motto i sekcja "o blogu". &lt;br /&gt;&lt;br /&gt;&lt;br /&gt;//================&lt;br /&gt;Zastanawiam się też nad pozbyciem się słowa "holistycznie" z nazwy - ostatnio kojarzy się ono z medycyną alternatywną, homeopatią i innymi tego typu rzeczami;) Ale nie wszystko n a raz.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5197374494377847819-314473907601386020?l=art-of-software.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://art-of-software.blogspot.com/feeds/314473907601386020/comments/default' title='Komentarze do posta'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5197374494377847819&amp;postID=314473907601386020' title='Komentarze (4)'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5197374494377847819/posts/default/314473907601386020'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5197374494377847819/posts/default/314473907601386020'/><link rel='alternate' type='text/html' href='http://art-of-software.blogspot.com/2009/10/may-refreshing.html' title='Mały refreshing'/><author><name>Sławek Sobótka</name><uri>http://www.blogger.com/profile/15082577671795313109</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='30' height='32' src='http://3.bp.blogspot.com/-tmFOhJC48_E/TkQ0G2DxrqI/AAAAAAAAAz8/WVGBaaS5a_Y/s220/zdjecie2.png'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5197374494377847819.post-6685577926699566343</id><published>2009-10-18T16:49:00.012+02:00</published><updated>2009-10-26T17:57:17.889+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Domain Driven Design'/><category scheme='http://www.blogger.com/atom/ns#' term='JUG'/><category scheme='http://www.blogger.com/atom/ns#' term='prezentacja'/><title type='text'>JUG, JDD, DDD, Cooluary v3 - podsumowanie</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_m-NewLwJEb8/StsxtIVNrhI/AAAAAAAAAb4/WJSZoJD8tdw/s1600-h/wawel-royal-castle.jpg"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 204px;" src="http://3.bp.blogspot.com/_m-NewLwJEb8/StsxtIVNrhI/AAAAAAAAAb4/WJSZoJD8tdw/s320/wawel-royal-castle.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5393959630106635794" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Tydzień upłynął pod znakiem Domain Driven Design.&lt;br /&gt;&lt;br /&gt;Wtorek: prezentacja "DDD + impl w Seam" na &lt;a href="http://groups.google.com/group/lublin-jug"&gt;lubelskim JUG&lt;/a&gt;. &lt;br /&gt;&lt;br /&gt;Był to beta test przed piątkową ewangelizacją DDD w Krakowie podczas &lt;a href="http://09.jdd.org.pl/"&gt;Java Developers' Day&lt;/a&gt;. Przy okazji podziękowania za feedback, który otrzymałem od wielu osób po wtorkowym wystąpieniu. Dzięki niemu udało mi się skompresować ponad 2h do 45 min na potrzeby JDD:)&lt;br /&gt;&lt;br /&gt;Sobota: &lt;a href="http://www.dworld.pl/page/show/COOLuary_v3/"&gt;COOluary&lt;/a&gt; i powtórka DDD. Tym razem już 3h, sam DDD bez Seam - panowie słusznie założyli, że technikalia są drugorzędne.&lt;br /&gt;&lt;br /&gt;Zarówno podczas prezentacji na JUG jak i DDD pojawiło się kłopotliwe pytanie odnośnie poniższego slajdu:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_m-NewLwJEb8/St4QWqyomrI/AAAAAAAAAck/90ChzJEiPMQ/s1600-h/bb.jpg"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 229px;" src="http://3.bp.blogspot.com/_m-NewLwJEb8/St4QWqyomrI/AAAAAAAAAck/90ChzJEiPMQ/s320/bb.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5394767385266264754" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Slajd prezentuje Building Block, przy pomocy których to modelujemy domenę biznesową.&lt;br /&gt;Ale zanim przejdziemy do pytania - przyda się wstęp. Jeżeli ktoś był na prezentacji, to może spokojnie przewinąć się &lt;a href="#pytanie"&gt;niżej&lt;/a&gt;...&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;NIEKRÓTKI WSTĘP&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Logikę dzielimy na dwie warstwy:&lt;br /&gt;- Warstwę logiki aplikacji&lt;br /&gt;- warstwę modelu domenowego&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Warstwa logiki aplikacji&lt;/span&gt; jest cienka nie bez kozery. Zawiera ona logikę specyficzną dla danej aplikacji i jednocześnie nie będącą logiką reguł biznesowych - przykładowo: transakcje, bezpieczeństwo, jakiś mailing, ale również koszyk w sklepie internetowym. Model zamówienia i produktów to logika biznesowa, ale sam koszyk jest ficzerem aplikacji.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Warstwa modelu domenowego&lt;/span&gt; jest budowana z klas grających pewne role. Z ról wynika odpowiedzialność tych klas. Czyli opieramy się na paradygmacie &lt;a href="http://c2.com/cgi/wiki?ResponsibilityDrivenDesign"&gt;Responsibility Driven Design&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Te role to:&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Encje&lt;/span&gt; - identyfikowalne (posiadająće ID) byty biznesowe. Nie tylko rzeczowniki, ale również np metafory przejścia/zmiany stanu. Co ważne z rolą encji wiąże się realizacja odpowiedzialności biznesowych. Zatem mówimy stanowcze NIE dla anemicznego modelu;)&lt;br /&gt;Inaczej niż w popularnych ORMach encja jak najbardziej powinna mieć metody biznesowe.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Value Objects&lt;/span&gt; - obiekty nieidentyfikowalne i zwykle niemodyfikowalne. Jeżeli 2 Vo mają takie same atrybuty to są wówczas tożsame. VO również mogą posiadać odpowiedzialność biznesową. W pewnych podejściach są marginalizowane a w innych wręcz wypierają encje - ale to temat na osobne posta, więc zostawmy.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Agregaty&lt;/span&gt; - Encje, które zawierają w sobie grafy encji lub VO. Co ważne agregaty hermetyzują swą implementację więc wszelkie operacje na wnętrznościach wykonujemy przez metody biznesowe encji głównej będącej Aggregate-root.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Repozytoria&lt;/span&gt; - zarządzają persystencją Encji/agregatów. To oczywiście jedynie interfejsy; implementacje są warstwę niżej. Nie ma tu metod wyszukujących po kryteriach pochodzących z GUI znanych z DAO.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Fabryki&lt;/span&gt; - hermetyzują złożoną (zwykle) logikę tworzenia agregatów.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Servisy&lt;/span&gt; - servisy biznesowe (nie mylić z aplikacyjnymi) zawierają logikę, której nie sposób sensownie przypisać do żadnej encji/agregatu/vo.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Polityki&lt;/span&gt; - to nic innego jak &lt;a href="http://en.wikipedia.org/wiki/Strategy_pattern"&gt;Wzorzec Strategii&lt;/a&gt;. Enkapsulują zmienność/wariacje logiki biznesowej. Jest to kluczowa figura podczas modelowania i rozmowy z expertem biznesowym.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Zdarzenia biznesowe&lt;/span&gt; - chodzi po prostu o decoupling artefaktów biznesowych od technicznych obiektów obsługujących. Dodatkowo możemy mieć asynchroniczność.&lt;br /&gt;&lt;br /&gt;Przykład agregatu: Zamówienie zawierające pozycje zamówienia:&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush: java"&gt;&lt;br /&gt;@Entity&lt;br /&gt;public class Order{&lt;br /&gt; @Id private OrderId id;&lt;br /&gt; @OneToMany private List&amp;lt;OrderItem&gt; items = new ArrayList&lt;OrderItem&gt;();&lt;br /&gt; private BigDecimal sum = new BigDecimal(0);&lt;br /&gt; //.... status, createDate, rebatePolicy, productRepository,...&lt;br /&gt;&lt;br /&gt; public void add(Product product, int quantity){&lt;br /&gt;  OrderItem oi = orderItemFactory.build(product, quantity, rebatePolicy);&lt;br /&gt;  //TODO jeżeli produkt jest już na liście to możemy jedynie zmienić ilość w odpowiednim order item&lt;br /&gt;  items.add(oi);&lt;br /&gt;  sum = sum.add(oi.getCost());&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; public void submit(){&lt;br /&gt;  if (status != Status.NEW)&lt;br /&gt;   throw new InvalidStateException();&lt;br /&gt;  status = Status.IN_PROGRESS;&lt;br /&gt;  createDate = new Date();&lt;br /&gt;  eventsManager.handle(orderEventsFactory.orderSubmitted(this));&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; public Iterator&amp;lt;OrderItem&gt; getOrderItems(){&lt;br /&gt;  return items.iterator();&lt;br /&gt; }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Kod zawiera kilka charakterystycznych dla DDD konstrukcji.&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;lista produktów jest prywatna i nie ma do niej gettera a już niedopuszczalny jest setter. Dostęp do listy poprzez iterator, który nie umożliwia zmiany.&lt;br /&gt;Pamiętajmy, że w JPA nie musimy uzywać getterów/setterów - wystarczy adnotacji na polu, wówczas ORM używa refeksji.&lt;br /&gt;&lt;li&gt;operacje biznesowe poprzez odpowiednie metody: add, submit&lt;br /&gt;&lt;li&gt;operacja add przyjmuje produkt - szczegółem impl jest tworzenie wewnątrz zamówienia jakiegoś OrderItem&lt;br /&gt;&lt;li&gt;operacja add zmienia wewnętrzny stan - co by było gdyby można było zmieniać listę udostępnioną getterem? Kto musiałby pamiętać o zmianie sumy?&lt;br /&gt;&lt;li&gt;operacja submit zmienia jakieś pola - jakie? to szczegół. Pojawią się nowe pola w encji Order - wówczas zmieniamy tylko metodę submit. Operacja dodatkowo może sprzeciwić się rzucając wyjątek oraz generuje darzenie.&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;&lt;a name="pytanie"&gt;&lt;/a&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;"KŁOPOTLIWE" PYTANIE&lt;/span&gt; &lt;br /&gt;&lt;span style="font-style:italic;"&gt;Czy agregat/encja może wołać: repozytorium/servis/fabrykę?&lt;br /&gt;Ogólnie: jakie zależności (pomiędzy czym a czym) są dozwolone w DDD?&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Przyznam się, że sam miałem kiedyś tego typu pytania... Nie dawały mi spokoju: jakie są ograniczenia, co z czym można łączyć a co jest zabronione? Co gorsza, członkowie grup dyskusyjnych podawali sprzeczne "złote" zasady.&lt;br /&gt;&lt;br /&gt;Zasada jest prosta: możesz robić wszystko co jest dobre dla modelu.&lt;br /&gt;Wszystkie building blocks DDD są równo traktowane - nie ma ważnych i ważniejszych, mogą korzystać z siebie nawzajem jeżeli wynika to z logiki biznesu.&lt;br /&gt;&lt;br /&gt;Dobre wyjaśnienie tego problemu znajdziecie w prezentacji &lt;a href="http://www.infoq.com/presentations/DDD-Entities-Repositories-Jimmy-Nilsson"&gt;Is Domain-Driven Design More than Entities and Repositories?&lt;/a&gt; Tak, tak - sarkastyczny tytuł oznacza, ze J. Nilsson będzie lekko kpił sobie z prymitywnych interpretacji DDD typu &lt;a href="http://www.javate.amattioli.it/mainsite/description.html"&gt;JavATE&lt;/a&gt;;)&lt;br /&gt;&lt;br /&gt;Ale jak uniknąć kodu spaghetti w warstwie modelu domenowego jeżeli zaczniemy w nim  łączyć wszystko ze wszystkim? Przecież DDD ma chronić nas przed chaosem a nie sprzyjać jego generowaniu.&lt;br /&gt;&lt;br /&gt;Podczas COOLuarów doszliśmy do sformułowania dobrej zasady: Jeżeli z logiki biznesowej wynikają pewne powiązania to nie należy ich unikać. Jeżeli logika biznesowa charakteryzuje się pewnych poziomem złożoności - wynikającej z natury danego procesu, to nie unikniemy powiązań. Ważne aby nie wprowadzać dodatkowej złożoności (&lt;a href="http://en.wikipedia.org/wiki/Accidental_complexity"&gt;przypadkowej&lt;/a&gt;).&lt;br /&gt;&lt;br /&gt;Dobrą metaforą warstwy logiki aplikacji jest scenariusz dla aktorów, którymi są Building blocks. Albo inaczej: kod logiki aplikacji niejako żongluje klockami biznesowymi. Chodzi o to aby czytać taki scenariusz i "widzieć" czystą logikę.&lt;br /&gt;Więcej na ten temat w końcówce posta &lt;a href="http://art-of-software.blogspot.com/2009/05/understandability.html"&gt;Understandability&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Jeżeli teraz jeden z aktorów nie chce pobrudzić się i wywołać np repozytorium to musimy zrobić to wprost w głównym wątku scenariusza (a wynik sztucznie przekazać gdzieś do środka aktora). Powoduje to pojawienie się &lt;span style="font-weight:bold;"&gt;sztucznych&lt;/span&gt; zgrzytów w scenariuszu. I zamiast ułatwiać zrozumienie go - utrudnia.&lt;br /&gt;&lt;br /&gt;//=========================&lt;br /&gt;&lt;br /&gt;J. Nilsson twierdzi, że jest to typowe pytanie zadawane, przez każdego adepta DDD. Wg mnie taka jest kolej rzeczy - w każdej dziedzinie. Wynika to z &lt;a href="http://art-of-software.blogspot.com/2008/08/unforgiven.html"&gt;modelu kompetencji braci Dreyfus&lt;/a&gt; gdzie na początku potrzebujemy dokładnych wytycznych &lt;span style="font-weight:bold;"&gt;jak&lt;/span&gt; zrobić. Później uczymy się, że to zależy od tego &lt;span style="font-weight:bold;"&gt;co&lt;/span&gt; chcemy osiągnąć.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5197374494377847819-6685577926699566343?l=art-of-software.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://art-of-software.blogspot.com/feeds/6685577926699566343/comments/default' title='Komentarze do posta'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5197374494377847819&amp;postID=6685577926699566343' title='Komentarze (5)'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5197374494377847819/posts/default/6685577926699566343'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5197374494377847819/posts/default/6685577926699566343'/><link rel='alternate' type='text/html' href='http://art-of-software.blogspot.com/2009/10/jug-jdd-ddd-cooluary-v3-podsumowanie.html' title='JUG, JDD, DDD, Cooluary v3 - podsumowanie'/><author><name>Sławek Sobótka</name><uri>http://www.blogger.com/profile/15082577671795313109</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='30' height='32' src='http://3.bp.blogspot.com/-tmFOhJC48_E/TkQ0G2DxrqI/AAAAAAAAAz8/WVGBaaS5a_Y/s220/zdjecie2.png'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_m-NewLwJEb8/StsxtIVNrhI/AAAAAAAAAb4/WJSZoJD8tdw/s72-c/wawel-royal-castle.jpg' height='72' width='72'/><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5197374494377847819.post-404267667137663445</id><published>2009-10-16T22:01:00.015+02:00</published><updated>2009-10-18T15:48:09.467+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='wzorce architektoniczne'/><category scheme='http://www.blogger.com/atom/ns#' term='wzorce projektowe'/><category scheme='http://www.blogger.com/atom/ns#' term='Architektura'/><title type='text'>MVC Revisited</title><content type='html'>Kto w 2009r pisze jeszcze o MVC? Czy można jeszcze coś konstruktywnego dodać w tym temacie?&lt;br /&gt;&lt;br /&gt;Spróbuję napisać coś może nie tyle konstruktywnego co porządkującego pojęcia... Doczytajcie do końca a być może dowiedzcie się czegoś co uzupełni wasz zasób ciekawostek służących do robienia wrażenia np na &lt;a href="http://2k.neostrada.pl/wieprzowinki"&gt;niewiastach podczas imprez&lt;/a&gt;;)&lt;br /&gt;&lt;br /&gt;MVC - styl to architektoniczny odkryty bodajże jakieś 30 lat temu. Zatem należy mu się najpierw rys historyczny: jak to drzewiej wyglądało w Smalltalku...&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Widok &lt;/span&gt;- czysty rendering&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Kontroler &lt;/span&gt;- obsługa zdarzeń urządzeń sprzęgu ludzkiego (taki się kiedyś mówiło) typu klik myszką czy naciśnięcie klawisza&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Model &lt;/span&gt;- dane do prezentacji i logika nimi manipulująca.&lt;br /&gt;&lt;br /&gt;Jak to wygląda dziś? Weźmy na ten przykład 2 popularne technologie prezentacji w Javie:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;SWING&lt;/span&gt;&lt;br /&gt;Czym są kontrolki w Swingu... Widokiem? Nie do końca, ponieważ delegują rendering do rendererów. Sam np JButton jest reprezentacją jakiegoś bytu na GUI - posiada atrybuty typu położenie, ale rysowaniem zajmują się renderery wchodzące w skład aktualnego look&amp;feel. Ale może nie wnikajmy w implementację i dla uproszczenie niech będzie to widok.&lt;br /&gt;&lt;br /&gt;Kontrolki mają również swój wewnętrzny model "prezentacyjny". SetText przecież ustawia "coś" we wnętrzu kontrolki. Zwykle kopiujemy to coś z modelu właściwego budując własny framelet (nano framework) wokół Swinga. Ale sam rendering następuje na podstawie wewnętrznego modelu kontrolki.&lt;br /&gt;&lt;br /&gt;Przyjrzyjmy się obsłudze zdarzeń... W Smaltalku zdarzenia techniczne obsługiwał kontroler. W Swingu robi to kontrolka, która deleguje odpowiedzialność do listenerów. Czyli to listenery są kontrolerem? Nie zawsze... w niektórych frameworkach Swingowych implementujemy własne kontrolery wołane przez listenery.   &lt;br /&gt;&lt;br /&gt;Więc co z tym MVC? Wygląda na to, że to kontrolka jako taka implementuje MVC (patrząc z technicznego punktu widzenia) &lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;JSF&lt;/span&gt;&lt;br /&gt;W JSF mamy Managed Beans... Obsługują one zdarzenia oraz decydują o nawigacji - czyli kontroler. Zawierają model do renderingu i zbierania danych z formularzy. &lt;br /&gt;&lt;br /&gt;A co będzie, jeżeli zbindujemy jakieś kontrolki graficzne z ich komponentami UIComponent (będącymi polami Managed Beana)? Wówczas MB może sterować atrybutami kontrolek graficznych, czyli mamy logikę prezentacji, czyli widok. Znowu wszystko w jednym.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;SZERSZY KONTEKST&lt;/span&gt;&lt;br /&gt;Aby tego było mało spójrzmy na listę istniejących reifikacji (koncepcji realizacji) idei MVC zgromadzoną w tym oto poście: &lt;a href="http://www.ctrl-shift-b.com/2007/08/interactive-application-architecture.html"&gt;Interactive Application Architecture Patterns&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Na liście wiele ciekawych pozycji:&lt;br /&gt;- Model-View-Presenter - w podejściu Microsoft (+ Application Controller) oraz Dolphin&lt;br /&gt;- Supervising Controller&lt;br /&gt;- Passive View Pattern&lt;br /&gt;- Presentation-Abstraction-Control&lt;br /&gt;&lt;br /&gt;Sam dodatkowo natknąłem się na:&lt;br /&gt;- Hierarchical MVC (framework &lt;a href="http://scope.sourceforge.net/"&gt;Scope&lt;/a&gt;, który przez parę miesięcy rozwijałem niezależnie od twórców, którzy porzucili coś tak pięknego;)&lt;br /&gt;- MMVC (rozróżnienie na model prezentacyjny + model domenowy)&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Wszystkie wymienione podejścia nazwami nawiązują do MVC, ale nim nie są w formie oryginalnej. Czy to źle? Oczywiście, że nie - MVC w swej oryginalnej formie nie przystaje do konstrukcji współczesnych bibliotek i zakładanego przez nie poziomu abstrakcji. Kto np dziś skupiałby się na szczegółach technicznych obsługi zdarzeń generowanych przez urządzenia.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;WARSTWY&lt;/span&gt;&lt;br /&gt;MVC jest często mylony z architekturą warstwową. Wystarczy zrobić prosty eksperyment myslowy aby uświadomić sobie błąd: zwizualizujmy sobie oba podejścia:&lt;br /&gt;MVC wygląda jak trójkąt.&lt;br /&gt;Natomiast warstwy są jak Ogry;) Albo raczej jak kanapka, tudzież tort.&lt;br /&gt;&lt;br /&gt;MVC &lt;span style="font-weight:bold;"&gt;może &lt;/span&gt; być (i zwykle jest) użyty na szczycie stosu warstw jako wzorzec dla samej warstwy prezentacji. Natomiast pod spodem mamy "zwykłe" warstwy, które nic nie wiedzą o żadnym MVC w prezentacji.&lt;br /&gt;&lt;br /&gt;W literaturze spotyka się jednak uproszczone podejścia, gdzie składniki trójkąta MVC utożsamiane są z warstwową architekturą, odpowiednio:&lt;br /&gt;V - warstwa prezentacji&lt;br /&gt;M - warstwa modelu (anemicznego najlpiej)&lt;br /&gt;C - warstwa logiki aplikacji&lt;br /&gt;Mówi się wówczas, że MVC jest traktowany jako wzorzec architektury aplikacji a nie jako wzorzec projektowy prezentacji.&lt;br /&gt;Niech i tak będzie... ;)&lt;br /&gt;Byle tylko nie twierdzić, że widok to HTML + CSS, kontroler to PHP a model to baza danych;P&lt;br /&gt;&lt;br /&gt;//=================&lt;br /&gt;Post powstał tak a'propos dzisiejszej prezentacji &lt;a href="http://09.jdd.org.pl/prelegenci/mark-richards"&gt;Marka Richardsa&lt;/a&gt; na JDD podczas, której wspomniał on o &lt;span style="font-weight:bold;"&gt;bezmyślnie przyjmowanych dogmatach&lt;/span&gt;:)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5197374494377847819-404267667137663445?l=art-of-software.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://art-of-software.blogspot.com/feeds/404267667137663445/comments/default' title='Komentarze do posta'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5197374494377847819&amp;postID=404267667137663445' title='Komentarze (3)'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5197374494377847819/posts/default/404267667137663445'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5197374494377847819/posts/default/404267667137663445'/><link rel='alternate' type='text/html' href='http://art-of-software.blogspot.com/2009/10/mvc-revisited.html' title='MVC Revisited'/><author><name>Sławek Sobótka</name><uri>http://www.blogger.com/profile/15082577671795313109</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='30' height='32' src='http://3.bp.blogspot.com/-tmFOhJC48_E/TkQ0G2DxrqI/AAAAAAAAAz8/WVGBaaS5a_Y/s220/zdjecie2.png'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5197374494377847819.post-6096930227115595067</id><published>2009-10-06T20:28:00.016+02:00</published><updated>2009-10-22T10:45:26.986+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='wzorce architektoniczne'/><category scheme='http://www.blogger.com/atom/ns#' term='Command Query Separation'/><category scheme='http://www.blogger.com/atom/ns#' term='Domain Specific Language'/><category scheme='http://www.blogger.com/atom/ns#' term='wzorce projektowe'/><title type='text'>Domain Specific Query</title><content type='html'>Zgodnie z obowiązującym trendem polegającym na prześciganiu się w publikowaniu bardziej lub jeszcze_bardziej oczywistych odkryć - dziś kolej na mnie i na coś na co wpadłem już jakiś czas temu.&lt;br /&gt;&lt;br /&gt;Tytułowy wynalazek ma roboczą nazwę DSQ, którą triumfalnie nadałem mu kojarząc dwie modne techniki: Domain Specific Language i Command-query Separation.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;NIEKRÓTKIE WYJAŚNIENIE&lt;/span&gt;&lt;br /&gt;O CQS pisałem 2 miesiące temu w &gt;&lt;a href="http://art-of-software.blogspot.com/2009/09/lazy-loading-w-kontekscie-paradygmatu.html"&gt;tym&lt;/a&gt;&lt; poście. W skrócie jest to styl architektoniczny, który zakłada separację API systemu na dwie wyraźne części. Jedna obsługuje (przyjmuje wysyłane do API) Command - rozkazy wykonania operacji. Druga natomiast obsługuje Query - obiekty specyfikujące kryteria pobierania/wyszukiwania danych.&lt;br /&gt;&lt;br /&gt;W dzisiejszym poście skupimy się właśnie na tej drugiej części, czyli ogólnie mówiąc na wyszukiwarkach danych. Wyszukiwarki są dosyć proste - ot zwykłe servisy, pod którymi nie znajdują się już żadne kolejne warstwy - chyba, że potrzebujemy jeszcze "dodać coś od siebie" do pobranych z pewnego źródła danych.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://en.wikipedia.org/wiki/Domain-specific_language"&gt;DSL&lt;/a&gt; to koncepcja dużo bardziej popularna (w sensie ilości publikacji) niż CQS, więc nie będę się zbytnio rozpisywał na jej temat. Ogólnie rzecz ujmując chodzi o to aby kod logiki biznesowej czytać niemal jak język naturalny. Definiujemy sobie język zorientowany na konkretną domenę biznesową a później to już fraszka - program piszę się niemal sam;)&lt;br /&gt;W statycznych językach typu Java nie mamy zbyt szerokiego pola do popisu jeżeli chodzi o zdefiniowanie własnego języka domenowego.&lt;br /&gt;&lt;br /&gt;Jedyne co możemy zrobić w Javie to zastosować &lt;a href="http://en.wikipedia.org/wiki/Fluent_interface"&gt;Fluent Interface&lt;/a&gt; i opisowe (samoopisujące wręcz) nazwy metod. Czyli jest to jedynie namiastka DSL, ale cieszy:)&lt;br /&gt;&lt;br /&gt;Koncepcja Fluent Interface jest prosta: chodzi o to aby metody danej klasy zwracały instancję obiektu na rzecz którego zostały wykonane. Dzięki temu możemy zamiast pisać tradycyjnie:&lt;br /&gt;&lt;pre class="brush: java"&gt;&lt;br /&gt;Klasa obiekt = new Klasa();&lt;br /&gt;obiekt.metoda1();&lt;br /&gt;obiekt.metoda2();&lt;br /&gt;obiekt.metoda3();&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;możemy zmienić styl na bardziej fluent:&lt;br /&gt;&lt;pre class="brush: java"&gt;&lt;br /&gt;Klasa obiekt = new Klasa();&lt;br /&gt;obiekt.metoda1().metoda2().metoda3();&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Jeżeli teraz zamiast nadawać metodom autystyczne nazwy (w stylu Bruce Eckela), wykażemy się odrobiną inwencji i słowiańskiej fantazji możemy pisać niemalże poetycko:&lt;br /&gt;&lt;pre class="brush: java"&gt;&lt;br /&gt;FabrykaWierszy.stworzUtwor().subtelny().zNutkaDekadencji().rymyNiechBedaCzestochowskie().strof(10);&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Chyba lepiej czyta się kod w takim stylu...&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;DO RZECZY&lt;/span&gt;&lt;br /&gt;Po tym przydługim wstępie powinniśmy już mniej więcej czuć czym jest CQS i DSL...&lt;br /&gt;&lt;br /&gt;Wyobraźmy sobie następujący problem :&lt;br /&gt;&lt;br /&gt;W systemie przechowujemy dokumenty. Dokumenty mają szereg atrybutów: kilka typów statusów (związanych z przepływem dok. jak i technicznych), różnego rodzaju daty, przypisanie do różnych zasobów itp.&lt;br /&gt;&lt;br /&gt;Domena biznesowa standardowa i może niezbyt wyszukana, ale dzięki temu wiadomo o co chodzi i możemy skupić się na samej technice.&lt;br /&gt;&lt;br /&gt;Serwis, który miałby wyszukiwać dokumenty musiałby mieć metodę o kilkunastu parametrach. Pierwszym problem z taką metodą to wysoki ujemny współczynnik czytalności. Drugi problem to ciągłe zmiany sygnatury metody gdy pojawiają się nowe atrybuty dokumentu.&lt;br /&gt;&lt;br /&gt;Zatem dosyć oczywiste jest, że stworzymy sobie klasę przechowującą atrybuty wyszukiwania a nasz serwis będzie miał metodę, do której przekazujemy paczkę kryteriów - po prostu jakiś rodzaj Query z CQS:&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush: java"&gt;&lt;br /&gt;public class SearchDocumentsQuery implements Serializable{&lt;br /&gt;  //atrybuty wyszukiwania + get/set&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush: java"&gt;&lt;br /&gt;public class DocumentsFinder{&lt;br /&gt;public Collection&amp;lt;Document&amp;gt; search(SearchDocumentsQuery criteria){&lt;br /&gt;//..&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Jak do tej pory standard. (Query najpewniej będzie prędzej czy później serializowany.)&lt;br /&gt;&lt;br /&gt;Teraz idąc dalej wg utartych szablonów dodalibyśmy do SearchDocumentsQuery kilkanaście pół prywatnych oraz oczywiście nasze ulubione gettery i settery.&lt;br /&gt;&lt;br /&gt;Kod klasy klienckiej przy pomocy setterów ustawia kryteria wyszukiwania a kod metody DocumentsFinder.search przy pomocy getterów pobiera te parametry i klei sobie zapytanie w SQL, HQL tudzież mój ulubiony Hibernate Criteria API.&lt;br /&gt;&lt;br /&gt;A gdzie miejsce dla DSL? No więc właśnie przy tak ordynarnym podejściu nie uświadczymy.&lt;br /&gt;Załóżmy teraz, że chcemy hermetyzować kod klas klienckich (wywołujących DocumentsFinder)od szczegółów atrybutów Dokumentu.&lt;br /&gt;&lt;br /&gt;Klient zamiast operować szczegółami:&lt;br /&gt;&lt;pre class="brush: java"&gt;&lt;br /&gt;SearchDocumentsQuery criteria = new SearchDocumentsQuery();&lt;br /&gt;criteria.setStatus(Status.ACTIVE);&lt;br /&gt;criteria.setCreateDate(...)&lt;br /&gt;criteria.set...&lt;br /&gt;...&lt;br /&gt;&lt;br /&gt;Collection&amp;lt;Document&amp;gt; result = documentsFinder.search(criteria);&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Wyraża jedynie intencje co do chęci otrzymania dokumentów spełniających zestaw określonych specyfikacji biznesowych:&lt;br /&gt;&lt;pre class="brush: java"&gt;&lt;br /&gt;SearchDocumentsQuery criteria = new SearchDocumentsQuery();&lt;br /&gt;criteria.current().contains("lorem ipsum");&lt;br /&gt;&lt;br /&gt;Collection&amp;lt;Document&amp;gt; result = documentsFinder.search(criteria);&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Gdzie przykładowo metody DSL wyglądają mniej więcej tak:&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush: java"&gt;&lt;br /&gt;public class SearchDocumentsQuery implements Serializable{&lt;br /&gt;  private Status status;&lt;br /&gt;  private Date epiryDate;&lt;br /&gt;  private String[] titleWords;&lt;br /&gt;  private String[] contentWords;&lt;br /&gt;&lt;br /&gt;  public SearchDocumentsQuery current(){&lt;br /&gt;    status = Status.ACTIVE;&lt;br /&gt;    expiryDate = //data jutrzejsza&lt;br /&gt;    return this;&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  public SearchDocumentsQuery contains(String phrase){&lt;br /&gt;    String[] words = phrase.split(" ");//lub bardziej wyrafinowy split&lt;br /&gt;    titleWords = words;&lt;br /&gt;    contentWords = words;&lt;br /&gt;    return this;&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Jak interpretować powyższe metody ustawiające kryteria:&lt;br /&gt;current - oznacza, ze życzymy sobie dokumentów będących aktualnie w obiegu.&lt;br /&gt;Co to znaczy od strony modelu: że maja określony status i że wygasają np najwcześniej jutro.&lt;br /&gt;&lt;br /&gt;contains - oznacza, że dokument ma zawierać określoną frazę. Z punktu widzenia modelu oznacza to, że tytuł lub treść dokumentu zawiera wszystkie słowa frazy.&lt;br /&gt;&lt;br /&gt;Cała idea polega na tym, że klient nie wie nic o polach status, expiryDate, words, ...&lt;br /&gt;Klient wyraża intencję.&lt;br /&gt;&lt;br /&gt;Natomiast pola te są dostępne przez gettery dla DocumentsFinder, który to analizuje je i odpowiedzi składa zapytanie. Aby osiągnąć pożądaną widoczność getterów należałoby zdefiniować SearchDocumentsQuery jako klasę &lt;span style="font-weight:bold;"&gt;statyczną wewnętrzną&lt;/span&gt; w DocumentsFinder. Wówczas DocumentsFinder będzie widział metody prywatne, bo takie powinny być rozważane gettery. Statyczną ponieważ chcemy tworzyć Query bez "wywodzenia" jej z instancji Findera.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush: java"&gt;&lt;br /&gt;public class DocumentsFinder{&lt;br /&gt;&lt;br /&gt;  public static class SearchDocumentsQuery implements Serializable{&lt;br /&gt;    private Status status;&lt;br /&gt;    private Date epiryDate;&lt;br /&gt;    private String[] titleWords;&lt;br /&gt;    private String[] contentWords;&lt;br /&gt;&lt;br /&gt;    //metoda contains i current - pominięto&lt;br /&gt;&lt;br /&gt;    private Status getStatus(){&lt;br /&gt;      return status;&lt;br /&gt;    }&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  public Collection&amp;lt;Document&amp;gt; search(SearchDocumentsQuery criteria){&lt;br /&gt;    if (criteria.getStatus() != null)//wywołanie prywatnej metody&lt;br /&gt;       //dołożenie do zapytania warunku na status&lt;br /&gt;    ...&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Kuszące może wydawać się dodanie do SearchDocumentsQuery metody buildEecutable(), która produkuje na podstawie stanu swoich wewnętrznych pól (statys, words,...) coś co można wykonać. Tym "czymś" może być PreparedStatement z JDBC, Criteria z Criteria API Hibenrate, Query z JPA, czy zwykły String zawierający SQL albo HQL.&lt;br /&gt;&lt;br /&gt;Ale zastanówmy się: czy klasa, która jest widoczna przez klienta (np zdalnego) powinna mieć w sobie kod, który operuje na jakimś API np Hibernate (Criteria API) albo czy powinna wiedzieć coś o jakimś SQL? Przecież Finder może szukać w XMLu lub poprzez web service. Klient nie może tego wiedzieć - ba nie powinien.&lt;br /&gt;&lt;br /&gt;//====================&lt;br /&gt;&lt;br /&gt;Pomysł może mało odkrywczy i zapewne wiele osób wpadło na niego równolegle, ale jeszcze nie spotkałem nigdzie opisu.&lt;br /&gt;&lt;br /&gt;Pomysł oczywiście nie będzie miał zastosowania w aplikacjach z małą abstrakcją pomiędzy bazą danych a GUI - tak zwanych przeglądarkach danych. W tego typu aplikacjach kontrolki na GUI (w tym pola filtrujące) odpowiadają zwykle niemal dosłownie kolumnom w bazie. W tego typu przypadkach próba abstrahowania od parametrów modelu jest niepotrzebnym uprawianiem dyscypliny pod tytułem nakładanie gaci przez głowę;)&lt;br /&gt;&lt;br /&gt;Czekam na opinie, sugestie, krytykę - może być niekonstruktywna:)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5197374494377847819-6096930227115595067?l=art-of-software.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://art-of-software.blogspot.com/feeds/6096930227115595067/comments/default' title='Komentarze do posta'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5197374494377847819&amp;postID=6096930227115595067' title='Komentarze (14)'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5197374494377847819/posts/default/6096930227115595067'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5197374494377847819/posts/default/6096930227115595067'/><link rel='alternate' type='text/html' href='http://art-of-software.blogspot.com/2009/10/domain-specific-query.html' title='Domain Specific Query'/><author><name>Sławek Sobótka</name><uri>http://www.blogger.com/profile/15082577671795313109</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='30' height='32' src='http://3.bp.blogspot.com/-tmFOhJC48_E/TkQ0G2DxrqI/AAAAAAAAAz8/WVGBaaS5a_Y/s220/zdjecie2.png'/></author><thr:total>14</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5197374494377847819.post-8856965863146417395</id><published>2009-09-09T19:27:00.021+02:00</published><updated>2009-10-16T23:02:41.661+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Domain Driven Design'/><category scheme='http://www.blogger.com/atom/ns#' term='management'/><category scheme='http://www.blogger.com/atom/ns#' term='z dystansu'/><category scheme='http://www.blogger.com/atom/ns#' term='Rozwój'/><category scheme='http://www.blogger.com/atom/ns#' term='recenzja'/><title type='text'>Ktoś sprzątać musi aby bałaganić mógł ktoś</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_m-NewLwJEb8/SqfoP9B_XvI/AAAAAAAAAbI/H4urk1Pee9o/s1600-h/mess.jpg"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 266px;" src="http://4.bp.blogspot.com/_m-NewLwJEb8/SqfoP9B_XvI/AAAAAAAAAbI/H4urk1Pee9o/s320/mess.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5379523640695938802" /&gt;&lt;/a&gt;&lt;br /&gt;Wszyscy zapewne pamiętamy burzliwą dyskusją &lt;a href="http://www.joelonsoftware.com"&gt;Joela Spolskyego&lt;/a&gt; z &lt;a href="http://www.java.net/blogs/rmartin/"&gt;Uncle Bobem&lt;/a&gt; (&lt;a href="http://www.infoq.com/news/2009/02/spolsky-vs-uncle-bob"&gt;skrót na infoq&lt;/a&gt;)&lt;br /&gt;&lt;br /&gt;Odbiła się ona szerokim echem dyskusji na ogólny temat: &lt;span style="font-style:italic;"&gt;rzemiosło, profesja, jakość&lt;/span&gt; czy moźe lepiej &lt;span style="font-style:italic;"&gt;byle jak, byle szybko, byle jako tako zadowolić klienta&lt;/span&gt;?&lt;br /&gt;&lt;br /&gt;Kto ma rację?&lt;br /&gt;&lt;br /&gt;Oczywiście ideałem byłoby dobrze i tanio. Ale jak intuicyjnie czujemy - tak to można tylko w mordę dostać;)&lt;br /&gt;&lt;br /&gt;Prawda jak zwykle leży gdzieś po środku.&lt;br /&gt;&lt;br /&gt;/*&lt;br /&gt;&amp;nbsp;* W rozważaniach pomijam specyficzne przypadki typu&lt;br /&gt;&amp;nbsp;* "&lt;a href="http://jdn.pl/node/388"&gt;firma nieustannie na dorobku&lt;/a&gt;" &lt;br /&gt;&amp;nbsp;* albo &lt;a href="http://alexba.eu/2009-04-20/rozwoj-kariera-praca/twoj-dostawca/"&gt;specyficzny rodzaj dostawcy&lt;/a&gt;&lt;br /&gt;&amp;nbsp;*&lt;br /&gt;&amp;nbsp;* Zakładam, że bawimy się w projektach &lt;span style="font-weight:bold;"&gt;perspektywicznych&lt;/span&gt;&lt;br /&gt;&amp;nbsp;* i jesteśmy świadomi zaciąganego kredytu bałaganu&lt;br /&gt;&amp;nbsp;*/&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Ciekawą analizę tego zjawiska oraz &lt;span style="font-weight:bold;"&gt;racjonalne i pragmatyczne&lt;/span&gt; podejście do problemu przedstawił ostatnio w swojej genialnej (i jak zwykle niemiłosiernie ospałej) prezentacji sam guru DDD: Errrrrric Evaaaaans: &lt;a href="http://www.infoq.com/presentations/design-strategic-eric-evans"&gt;Strategic Design - Responsibility Traps&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Poruszana tematyka zaczyna być omawiana od 30. minuty, ale gorąco wszystkich zachęcam do obejrzenia całości. Evans po mistrzowsku (i z typowym dla siebie poczuciem humoru) buduje od początku kontekst aby w 30. minucie wygarnąć nam co o nas myśli.&lt;br /&gt;Wcześniej dowiecie się min. jakich strategicznych błędów nie popełniać podczas modernizacji systemu. Okazuje się, że standardowe 3 podejścia są z góry skazane na porażkę.&lt;br /&gt;&lt;br /&gt;Prezentacja jest wg. mnie tak dobra, że w moim rankingu zajmuje miejsce 2. - zmieniając tym samym &lt;a href="http://art-of-software.blogspot.com/2009/08/jeszcze-prostota-czy-moze-juz.html"&gt;ostatnie notowania&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;ZAŁOŻENIA (SAD BUT TRUE)&lt;/span&gt;&lt;br /&gt;System jako &lt;span style="font-weight:bold;"&gt;całość &lt;/span&gt;nie może być dobrze przemyślany i zaprojektowany. KROPKA.&lt;br /&gt;Nigdy nie będzie dostatecznie dużo: czasu, pieniędzy, wiedzy biznesowej, ludzi z odpowiednimi kwalifikacjami, czasu, pieniędzy, czasu, pieniędzy, czasu, pieniędzy,...&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;CO Z TEGO WYNIKA&lt;/span&gt;&lt;br /&gt;Mamy 2 możliwości:&lt;br /&gt;a) Wszystko zrobić "byle jak"&lt;br /&gt;b) Pewną część zrobić porządnie i zgodnie z zasadami sztuki (oczywiście kosztem tego, że pozostała część będzie jakości mniejszej niż w punkcie a). W którą część i dlaczego warto zainwestować wysiłek - dowiemy się już za chwilę.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;PROBLEM&lt;/span&gt;&lt;br /&gt;Evans wytyka często spotykany problem. Ja nazwałbym go "złym rozłożeniem potencjału".&lt;br /&gt;Evans opisuje taki oto często powtarzający się wzorzec: najlepsi (w sensie doświadczenia, intuicji, smaku a nie np certyfikatów) programiści/projektanci/architekci zajmują się tworzeniem tak zwanej "platformy". W zależności od systemu może to być wewnętrzny framework, główne biblioteki - ogólnie najczęściej są to jakieś zawiłości techniczne.&lt;br /&gt;&lt;br /&gt;Natomiast reszta teamu - radośni hakierzy odpowiadają zwykle za dostarczanie corowych ficzerów biznesowych budowanych na bazie tejże tworzonej przez lokalnych guru platformy. Oczywiście ficzerów okraszonych zaokrąglonymi rogami w GUI - zgodnie z najnowszą modą żadna kanciasta forma nie jest dozwolona;)&lt;br /&gt;&lt;br /&gt;Dostarczają oni funkcjonalności nazwanych przez Evansa &lt;span style="font-weight:bold;"&gt;sexy capabilities&lt;/span&gt;. Robią to tak jak potrafią, czyli byle jak byle szybko:)&lt;br /&gt;&lt;br /&gt;Klient jest oczywiście zachwycony nowymi seksownymi możliwościami i nie zważa na marudzenie "nudziarzy od platformy", którzy narzekają, że znowu muszą sprzątać. Zresztą... po co sprzątać skoro działa?&lt;br /&gt;&lt;a href="http://www.youtube.com/watch?v=rEETC3msD9U"&gt;Hero of the day&lt;/a&gt; to ten, kto zrobił zaokrąglony guzik zwiększający obroty o 1%;)&lt;br /&gt;&lt;br /&gt;Oczywiście przyrost bałaganu jest większy niż możliwości jego sprzątania i mamy problem...&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;ROZWIĄZANIE: DESTYLACJA&lt;/span&gt;&lt;br /&gt;Kto jak kto, ale my Słowianie mamy doświadczenie w destylacji więc mógłbym sobie odpuścić ten rozdział;)&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_m-NewLwJEb8/Sqf1loOcPsI/AAAAAAAAAbQ/Asq6YmVKbfE/s1600-h/destylacja.jpg"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 221px;" src="http://4.bp.blogspot.com/_m-NewLwJEb8/Sqf1loOcPsI/AAAAAAAAAbQ/Asq6YmVKbfE/s320/destylacja.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5379538306719301314" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Pomysł Evansa polega na wydestylowaniu domeny corowej. Zacznijmy od tego, że Evans wyróżnia 3 klasy domen:&lt;br /&gt;&lt;br /&gt;- &lt;span style="font-weight:bold;"&gt;Core Domain&lt;/span&gt; - są to te specyficzne aspekty biznesu, będące powodem dla którego w ogóle warto tworzyć system. Przykładowo to one warunkują przewagę klienta nad konkurencją, lub odróżniają go od innych. To właśnie w tym miejscu mieszkają "sexy capabilities".&lt;br /&gt;&lt;br /&gt;I to właśnie w ten kawałek (a powinien być relatywnie mały) inwestujemy największy wysiłek umysłowy. &lt;br /&gt;&lt;br /&gt;To tutaj jest miejsce dla całej artylerii sprawdzonych technik naszego rzemiosła: szczegółowa analiza, archetypy biznesowe, wzorce projektowe, narzut na hermetyzację domeny, narzut na otwartość na rozbudowę, narzut na testability...&lt;br /&gt;&lt;br /&gt;Core powinien być dobrze uniezależniony od pozostałych domen, które z definicji są w jakimś sensie "mniej godne zaufania" (bo np niestabilne).&lt;br /&gt;&lt;br /&gt;- &lt;span style="font-weight:bold;"&gt;Supporting Domain&lt;/span&gt; - dodatkowe ficzery, bez których jednak można się obyć. Ten kawałek systemu może nawet np outsourceować. Jego jakość z założenia może być niska.&lt;br /&gt;&lt;br /&gt;- &lt;span style="font-weight:bold;"&gt;Generic Domain&lt;/span&gt; - specyficzne domeny typu podsystem fakturowania lub biblioteka do operowania na grafach. Najlepiej kupić/uzyć gotowe rozwiązanie. Pamiętając o unikaniu zależności ze strony Core Domain. &lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Dobrym przykładem ilustrującym relatywizm tego pojęcia w zależności do biznesu jest system komentarzy użytkowników wystawianych kontrahentom.&lt;br /&gt;W ebay jest to corowa funkcja (bez niej nikt nie kupiłby niczego od nieznajomej osoby). Dla amazona to po prostu jakiś poboczny ficzer (supportig domain) - ludzie i tak kupią jeżeli czegoś potrzebują lub po prostu mają ochotę.&lt;br /&gt;&lt;br /&gt;Pamiętajmy, że developerzy nie są w stanie (ba, nie powinni) określić co należy a co nie do Core Domain w konkretnym przypadku danego klienta. Określenie Core Domain to jedna z głównych rzeczy, którą trzeba z niego wydusić;)&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Chyba już domyślacie się jakie rozwiązanie sugeruje Evans...&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Core Team zajmuje się Core Domain.&lt;/span&gt;&lt;br /&gt;Najważniejsza część systemu ma szansę być zrobiona zgodnie ze sztuką a członkowie tego teamu zyskują uznanie jako dostawcy "sexy capabilities":)&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Mam nadzieję, że moja recenzja/streszczenie zachęci Was (a szczególnie managerów) do poświęcenia godziny cennego czasu na prezentację Evansa.&lt;br /&gt;Ciekaw jestem co sądzicie na temat tego podejścia - liczę na dyskusję równie owocną jak ta z przedostatniego posta:)&lt;br /&gt;&lt;br /&gt;//==============================&lt;br /&gt;&lt;br /&gt;Prowokacyjnie dodam, że Joel Spolsky stosuje jednak strategię "klasyczną". Flagowe oprogramowanie w ofercie firmy Joela: Copilot (soft dla helpdesku pozwalający na zdalną pracę na maszynie "petenta") to nic innego jak nakładka na OpenSourceowy projekt na licencji GPL ;PPP&lt;br /&gt;&lt;br /&gt;Czyli ni mniej ni więcej: ktoś zrobił platformę a partacze Joela dodali "sexy capabilities" - a biznes chyba się kręci:)&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;I jeszcze druga myśl, która mi się nasunęła: Nierzadko występują takie przypadki, gdy naprawdę doświadczony developer w ogóle nie interesuje się pewną domeną biznesową. Po prostu uważamy (niebezpodstawnie) za interesują mniej więcej w takim samym stopniu jak zeszłoroczny śnieg. Wolimy zamiast tego skupić się na rozwoju w kierunku technicznym z uwagi na jego ogólność wynikającą z abstrakcyjności. Nic na siłę, każdy powinien znaleźć sobie optymalne zainteresowania...&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5197374494377847819-8856965863146417395?l=art-of-software.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://art-of-software.blogspot.com/feeds/8856965863146417395/comments/default' title='Komentarze do posta'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5197374494377847819&amp;postID=8856965863146417395' title='Komentarze (4)'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5197374494377847819/posts/default/8856965863146417395'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5197374494377847819/posts/default/8856965863146417395'/><link rel='alternate' type='text/html' href='http://art-of-software.blogspot.com/2009/09/ktos-sprzatac-musi-aby-baaganic-mog.html' title='Ktoś sprzątać musi aby bałaganić mógł ktoś'/><author><name>Sławek Sobótka</name><uri>http://www.blogger.com/profile/15082577671795313109</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='30' height='32' src='http://3.bp.blogspot.com/-tmFOhJC48_E/TkQ0G2DxrqI/AAAAAAAAAz8/WVGBaaS5a_Y/s220/zdjecie2.png'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_m-NewLwJEb8/SqfoP9B_XvI/AAAAAAAAAbI/H4urk1Pee9o/s72-c/mess.jpg' height='72' width='72'/><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5197374494377847819.post-5765660968389699422</id><published>2009-09-05T15:43:00.005+02:00</published><updated>2009-09-05T16:57:29.463+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='śmieszne'/><category scheme='http://www.blogger.com/atom/ns#' term='Domain Driven Design'/><title type='text'>Anticorruption layer</title><content type='html'>Dziś łikendowy post z serii &lt;a href="http://art-of-software.blogspot.com/search/label/%C5%9Bmieszne"&gt;geek humor&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;W ostatnim poście wspomniałem o hermetyzacji modelu domenowego poprzez &lt;a href="http://dddstepbystep.com/wikis/ddd/anti-corruption-layer.aspx"&gt;Anticorruption layer&lt;/a&gt;, z którą to komunikujemy się poprzez &lt;a href="http://en.wikipedia.org/wiki/Command-query_separation"&gt;Command i Query&lt;/a&gt; i z której nie wyciekają Encje.&lt;br /&gt;&lt;br /&gt;Zobaczmy jak Eric Evans zobrazował to zagadnienie w 14 rozdziale swej &lt;a href="http://domaindrivendesign.org/books#DDD"&gt;książki&lt;/a&gt; (strona 367):&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_m-NewLwJEb8/SqJtAosjn_I/AAAAAAAAAbA/Tm83oJQFhCg/s1600-h/anticorruption_layer.PNG"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 110px;" src="http://2.bp.blogspot.com/_m-NewLwJEb8/SqJtAosjn_I/AAAAAAAAAbA/Tm83oJQFhCg/s320/anticorruption_layer.PNG" border="0" alt=""id="BLOGGER_PHOTO_ID_5377980762725523442" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;//==================&lt;br /&gt;&lt;br /&gt;Więcej tego typu humoru w ospałych &lt;a href="http://www.infoq.com/author/Eric-Evans"&gt;prezentacjach Evansa&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5197374494377847819-5765660968389699422?l=art-of-software.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://art-of-software.blogspot.com/feeds/5765660968389699422/comments/default' title='Komentarze do posta'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5197374494377847819&amp;postID=5765660968389699422' title='Komentarze (0)'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5197374494377847819/posts/default/5765660968389699422'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5197374494377847819/posts/default/5765660968389699422'/><link rel='alternate' type='text/html' href='http://art-of-software.blogspot.com/2009/09/anticorruption-layer.html' title='Anticorruption layer'/><author><name>Sławek Sobótka</name><uri>http://www.blogger.com/profile/15082577671795313109</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='30' height='32' src='http://3.bp.blogspot.com/-tmFOhJC48_E/TkQ0G2DxrqI/AAAAAAAAAz8/WVGBaaS5a_Y/s220/zdjecie2.png'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_m-NewLwJEb8/SqJtAosjn_I/AAAAAAAAAbA/Tm83oJQFhCg/s72-c/anticorruption_layer.PNG' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5197374494377847819.post-4088147989912674996</id><published>2009-09-03T20:28:00.022+02:00</published><updated>2009-10-19T13:23:13.696+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='wzorce architektoniczne'/><category scheme='http://www.blogger.com/atom/ns#' term='Lazy loading'/><category scheme='http://www.blogger.com/atom/ns#' term='Command Query Separation'/><category scheme='http://www.blogger.com/atom/ns#' term='Hibernate'/><category scheme='http://www.blogger.com/atom/ns#' term='JPA'/><category scheme='http://www.blogger.com/atom/ns#' term='ORM'/><category scheme='http://www.blogger.com/atom/ns#' term='Architektura'/><title type='text'>Lazy loading w kontekście paradygmatu Command-query Separation</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_m-NewLwJEb8/SqAXyfAQrrI/AAAAAAAAAa4/Q0ANNzoDOFA/s1600-h/wielki-mur-chinski-10.jpg"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 240px;" src="http://4.bp.blogspot.com/_m-NewLwJEb8/SqAXyfAQrrI/AAAAAAAAAa4/Q0ANNzoDOFA/s320/wielki-mur-chinski-10.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5377324111163862706" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;ODŚWIEŻENIE KONTEKSTU&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Kilka miesięcy temu popełniłem dwa posty na temat Lazy loadingu (wiem, że nie chce się Wam ich czytać więc streszczam):&lt;br /&gt;&lt;br /&gt;&lt;a href="http://art-of-software.blogspot.com/2009/04/lazy-loading-sprawa-wydajnosci.html"&gt;Lazy Loading a sprawa wydajności&lt;/a&gt; - post traktujący ogólnie o drastycznym spadku wydajności w sytuacjach gdy LL jest stosowany w &lt;span style="font-weight:bold;"&gt;niewłaściwym&lt;/span&gt; momencie. &lt;br /&gt;&lt;br /&gt;Chodzi głównie o klasyczny "n+1 Select problem", który potrafi totalnie zamulić system. W skrócie: problem pojawia się gdy pobieramy z EnityManagera/Sesji hibernate kolekcję a następnie iterujemy po niej i getterami pobieramy zagregowane obiekty. Wówczas do bazy wysyłane jest 1 zapytanie o kolekcję oraz dla każdego z jej n elementów koleje zapytania dociągające potrzebne obiekty.&lt;br /&gt;&lt;br /&gt;Podobne schorzenie występuje gdy naiwnie ustawimy w mapowaniu FetchMode na EAGER.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://art-of-software.blogspot.com/2009/04/dao-sprawa-lazy-loading.html"&gt;DAO a sprawa Lazy Loading&lt;/a&gt; - post poruszający problem tak zwanej cieknącej abstrakcji, czyli "brudzenia" kodu logiki warstw wyższych szczegółami technicznymi typu zamknięta sesji persystencji. &lt;br /&gt;&lt;br /&gt;Oczywiście mamy sprawdzony sposób na cieknącą abstrakcję - podejście Open Session in View (rozwiązanie w Springu np przez &lt;a href="http://blog.miracki.net/2009/08/17/sposob-na-jpa-i-lazyinitializationexception/"&gt;Mateusza Mirackiego&lt;/a&gt;). Niestety w tym przypadku łatwo dopuścić do opisanego powyżej "n+1 Select Problem". Ciekawe rozwiązanie z testowaniem ilości wysyłanych do bazy zapytań przy pomocy &lt;a href="http://art-of-software.blogspot.com/2009/04/lazy-loading-sprawa-wydajnosci.html?showComment=1251823380771#c100018659037091285"&gt;statystyk Hibernate&lt;/a&gt; zaproponował w komentarzu do mojego posta Milus.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;CREDO&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Od razu śpieszę wyjaśnić - żeby nie było, że jestem jakimś fanatycznym wrogiem Lazy loadingu czy ORM w ogólności. Wręcz przeciwnie, namiętnie go stosuję od 5 lat i uważam za bardzo wygodny młotek &lt;span style="font-weight:bold;"&gt;w większości&lt;/span&gt; sytuacji.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;PROBLEM&lt;/span&gt;&lt;br /&gt;Od czasu opublikowania tych postów dostałem kilka maili z zapytaniami o sposoby radzenia sobie z powyższymi problemami.&lt;br /&gt;&lt;br /&gt;Pod postami wywiązały się też krótkie dyskusje prezentujące możliwe podejścia.&lt;br /&gt; &lt;br /&gt;Właściwie to chodzi głównie o problemem z wydajnością, ponieważ filozoficzny problem cieknącej abstrakcji prawie nikogo nie boli. Nauczyliśmy się z nim żyć i raczej się nad nim nie zastanawiamy (na szczęście &lt;a href="http://www.jaceklaskowski.pl/"&gt;Jacek&lt;/a&gt; podziela moje rozterki). &lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;PRAWDZIWY PROBLEM&lt;/span&gt;&lt;br /&gt;Wg mnie prawdziwy problem leży w samym podejściu do dostępu do danych, czyli architekturze aplikacji. Problem polega na zbytnim uogólnieniu. &lt;br /&gt;&lt;br /&gt;Tak samo traktujemy dwa diametralnie różnie rodzaje obiektów: &lt;br /&gt;- obiekty domenowe, które wykonują operacje biznesowe (lub na których to wykonujemy modyfikacje w podejściu proceduralnym) &lt;br /&gt;- dane "przekrojowe" potrzebne jedynie do prezentacji (np wyświetlenia na GUI) wycinka aktualnego stanu systemu&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;CQS&lt;/span&gt;&lt;br /&gt;Teraz nadszedł wreszcie czas na przedstawienie tytułowego bohatera tego posta: zapomniany i zakurzony paradygmat: &lt;a href="http://en.wikipedia.org/wiki/Command-query_separation"&gt;Command-query Separation&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Paradygmat tez zakłada, że system posiada "interfejs", przez który wysyłamy do niego polecenia oraz osobny, przez który odpytujemy o dane. Nigdy nie projektujemy operacji, które zarówno coś modyfikują jak i odczytują dane.&lt;br /&gt;&lt;br /&gt;W jaki sposób możemy wykorzystać to podejście w systemach enterprise?&lt;br /&gt;"Interfejsem" przez który klienty (nie klienci) komunikują się z systemem może być warstwa aplikacji. Cienka warstwa, która zajmuje się wszystkim, oprócz logiki biznesowej i dostępu do danych.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_m-NewLwJEb8/StxL-wjdrKI/AAAAAAAAAcI/l13O2_5H8Ps/s1600-h/cqs.jpg"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 238px;" src="http://3.bp.blogspot.com/_m-NewLwJEb8/StxL-wjdrKI/AAAAAAAAAcI/l13O2_5H8Ps/s320/cqs.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5394269995240631458" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;COMMAND&lt;/span&gt;&lt;br /&gt;Ok, chcemy coś zrobić w systemie, wysyłamy do niego Polecenie. Tak jak wspomniałem "interfejsem" jest warstwa aplikacji "opublikowana" jako jakieś bezstanowe servisy lub obiekty stanowe - zależnie od wymagań.&lt;br /&gt;Jeżeli klient wyśle do tej warstwy Command, wówczas pobiera ona z Repozytorium jakieś encje (lub agregaty w DDD). Dalej na encjach/agregatach uruchamiamy ich metody biznesowe - jeżeli bawimy się obiektowo, lub wywołujemy jakieś biznesowe servisy przekazując im jako parametry pobrane właśnie encje. Nic specjalnego, klasyczna architektura warstwowa. &lt;br /&gt;&lt;br /&gt;Natomiast w tym właśnie przypadku - gdy wysyłamy do systemu Command mający zwykle na celu wykonanie jakiś operacji biznesowych - jak najbardziej możemy (ba powinniśmy) radośnie korzystać z Lazy loadingu. Jest to jak najbardziej właściwy moment ponieważ natura takich operacji jest zwykle taka, że pobieramy kilka obiektów, które wchodzą ze sobą w jakąś interakcję (lub władają nimi servisy). Rzeczone obiekty biznesowe ewentualnie potrzebują do wypełnienia swej biznesowej odpowiedzialności zagregowanych składników. Raczej nic złego się nie stanie, gdy zamiast 3 prostych zapytań do bazy wyślemy ich 5 czy nawet 10.&lt;br /&gt;Czasem nawet będzie to bardziej wskazane niż join - zależy do natury danych.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Cała operacja wykonuje się w obrębie metody z warstwy aplikacji więc jest objęta transakcją i ma cały czas otwartą sesję persystencji więc nie martwimy się o wyjątki Lazy loadingu.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;QUERY&lt;/span&gt;&lt;br /&gt;Natomiast jeżeli do systemu trafia Query, czyli zapytanie o dane, to wówczas sprawa wygląda nieco inaczej...&lt;br /&gt;Przede wszystkim warstwa aplikacji nie ma pod sobą warstwy z logiką (żadnych servisów biznesowych). Czy potrzebujecie abstrakcji dostępu do danych (DAO/Repozytorium)? Raczej nie zmienicie nigdy źródła danych. Nie ma sensu również testowanie jednostkowe "Finderów" aplikacyjnych z podmienionymi na mocki DAO. Czyli czyste pobieranie danych.&lt;br /&gt;&lt;br /&gt;W mniej złożonych systemach możemy sobie pozwolić na zwrócenie encji w odpowiedzi na kwerendę. &lt;br /&gt;W bardziej poważnych raczej nie możemy pozwolić sobie na ujawnianie klientom naszego modelu, więc zwrócimy jakiś Data Transfer Object (DTO). Hermetyzacja modelu to podstawa - dzięki temu może on ewoluować iteracyjnie bez obaw o zniweczenie pracy teamu dospawującego prezentację.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;QUERY ZWRACAJĄCE ENCJE&lt;/span&gt;&lt;br /&gt;Jeżeli zdecydujemy się na zwracanie encji to musimy uporać się z paroma problemami technicznymi:&lt;br /&gt;- wydajność: zwykle scenariusz obsługi kwerendy to pobranie kolekcji danych. Wówczas mamy jak w banku opisany na wstępie "n+1 Select problem". Rozwiązanie jest bardzo proste - wystarczy się pofatygować i napisać zapytanie z klauzulą JOIN FETCH. Przykładowo SELECT p FROM Person p JOIN FETCH p.addresses - dzięki temu chciwie/łapczywie (nie wiem, na które rozkoszne tłumaczenie się zdecydować) pobierzemy osoby wraz z podciągniętymi adresami. Po prostu ORM wygeneruje SQLa z JOINem.&lt;br /&gt;&lt;br /&gt;Niezbyt dobrym pomysłem jest ustawienie w mapowaniu powiązania obiektów z FetchMode.EAGER. Spowoduje ono, że &lt;span style="font-weight:bold;"&gt;zawsze&lt;/span&gt; wyciągając jeden obiekt pobierzemy jego "dziecko". Owszem są sytuacje, gdzie z kontekstu biznesowego takie podejście jest sensowne, ale zwykle stanowią zdecydowaną mniejszość. Zwykle w jednym Use Case zależy nam na pobraniu np osób z adresami a winnym adresy są zbędne.&lt;br /&gt;&lt;br /&gt;Warto pamiętać, że domyślnie strategia EAGER obowiązuje dla powiązań wiele-jeden, jeden-jeden i warto ją wyłączać.&lt;br /&gt;&lt;br /&gt;- Open Session in View - podejście to o ile jest wygodne to niestety pozwala łatwo zapomnieć o tym, że leniwie podciągamy jakieś dane. Po prostu istnieje niemała szansa, że na widoku odwołamy się do adresów osoby a w zapytaniu zapomnimy dopisać JOIN FETCH. Działa? Działa. Muli? W środowisku developerskim z małą ilością danych pewnie nie;P&lt;br /&gt;&lt;br /&gt;- Ilość danych - zwykle Use Case gdzie do systemu trafia Query zakłada, że z bazy trzeba pobrać dane "przekrojowe". Czyli dane z wielu tabel, ale z każdej z nich interesuje nas zaledwie kilka kolumn. W małych systemach, gdzie warstwa GUI i warstwa aplikacji stoją na tej samej JVM będzie to w śmigać. &lt;br /&gt;&lt;br /&gt;Ale nawet w takiej konfiguracji mamy problem z pobieraniem zbędnych danych. Przykładowo: gdy pobieramy z bazy np dokumenty aby jedynie wyświetlić ich listę (data, autor) a każdy z nich ma kolumnę przechowującą dziesiątki stron textu. Rozwiązaniem jest leniwe ładowanie pól - czyli ich nieładowanie:) W hibernate wymaga to poddanie skompilowanego bytecodu &lt;a href="http://na-jawie.blogspot.com/2009/04/leniwe-adowanie-wasciwosci-w-hibernate.html"&gt;instrumentalizacji&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Innym podejściem może być zamapowanie tabeli przez kilka klas. Przykładowo DocumentFull, DocumentLight, itp... Jeżeli czujecie niesmak na myśl o mnożeniu bytów to nie jesteście sami.&lt;br /&gt;&lt;br /&gt;Hibernate pozwala na pobieranie danych wprost do DTO. Tworzymy DTO szyte na miarę danego Use Case, a składnia wygląda tak:&lt;br /&gt;SELECT new pakiet.KlasaDTO(pole1, pole2.podpole) FROM...&lt;br /&gt;Oczywiście przy założeniu, że odpowiedni konstruktor istnieje.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;QUERY ZWRACAJĄCE DTO&lt;/span&gt;&lt;br /&gt;Jeżeli zdecydujemy się na zwracanie DTO to zapewne dlatego, że potrzebne dane są na tyle przekrojowe, że żaden zestaw encji nie modeluje ich sensownie (i optymalnie).&lt;br /&gt;Innym powodem może być chęć hermetyzacji zmiennego modelu poza stabilną &lt;a href="http://dddstepbystep.com/wikis/ddd/anti-corruption-layer.aspx"&gt;anticorruption layer&lt;/a&gt;. Warstwa zapobiegająca gniciu to pojęcie z DDD i ma pragmatyczny sens w nieco bardziej perspektywicznych projektach.&lt;br /&gt;&lt;br /&gt;Poza tym możemy być dumni, że nawet nasza architektura wspiera Agile umożliwiając ewolucję modelu domenowego bez rujnowania wszystkiego dookoła:)&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Częstym błędem w tym przypadku jest pobieranie z ORM encji a następnie przepakowywanie ich w DTO. &lt;br /&gt;Nie tędy droga...&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Pobierzmy tylko to co tak na prawdę jest potrzebne. Najprościej zrealizować to z użyciem  wspomnianej konstrukcji Hibernate SELECT NEW. Jednak w złożonych systemach zwykle nieodzowny będzie co najmniej w paru jakiś szyty na miarę i zoptymalizowany SQL. Jakąś abstrakcją nad SQLem może być wówczas np &lt;a href="http://ibatis.apache.org/"&gt;iBATIS&lt;/a&gt; mapujący result na DTO.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Jak to zwykle bywa najlepsze będzie podejście hybrydowe. Tam gdzie możemy na to sobie pozwolić zwracamy w wyniku obsługi Query encje - zwiększając tym samym swą produktywność. Natomiast tam gdzie krytyczna jest wydajność lub specjalna struktura danych, zwracamy DTO.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;//=======================================&lt;br /&gt;&lt;br /&gt;Opisane powyżej aspekty wydajności związane z Lazy Loadingiem aplikują się do systemów każdej wielkości - szczególnie "n+1 Select problem". Natomiast rozwiązanie z CQS a szczególnie podejście gdzie zwracamy z kwerendy DTO jest bardziej pracochłonne, przez co aplikuje się do projektów bardziej perspektywicznych.&lt;br /&gt;&lt;br /&gt;Ale czy jest sens tworzyć w JEE projekty inne niż perspektywiczne? Do prostych i szybkich zadań typu "przeglądarka do bazy" jest przecież Microsoft Access;P&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5197374494377847819-4088147989912674996?l=art-of-software.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://art-of-software.blogspot.com/feeds/4088147989912674996/comments/default' title='Komentarze do posta'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5197374494377847819&amp;postID=4088147989912674996' title='Komentarze (23)'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5197374494377847819/posts/default/4088147989912674996'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5197374494377847819/posts/default/4088147989912674996'/><link rel='alternate' type='text/html' href='http://art-of-software.blogspot.com/2009/09/lazy-loading-w-kontekscie-paradygmatu.html' title='Lazy loading w kontekście paradygmatu Command-query Separation'/><author><name>Sławek Sobótka</name><uri>http://www.blogger.com/profile/15082577671795313109</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='30' height='32' src='http://3.bp.blogspot.com/-tmFOhJC48_E/TkQ0G2DxrqI/AAAAAAAAAz8/WVGBaaS5a_Y/s220/zdjecie2.png'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_m-NewLwJEb8/SqAXyfAQrrI/AAAAAAAAAa4/Q0ANNzoDOFA/s72-c/wielki-mur-chinski-10.jpg' height='72' width='72'/><thr:total>23</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5197374494377847819.post-6951134357075784237</id><published>2009-08-31T21:01:00.008+02:00</published><updated>2009-08-31T23:31:54.321+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='recenzja'/><title type='text'>Dzień bloggera</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_m-NewLwJEb8/Spwf8bPutWI/AAAAAAAAAao/x240bd9EACU/s1600-h/geek.jpg"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 214px; height: 299px;" src="http://2.bp.blogspot.com/_m-NewLwJEb8/Spwf8bPutWI/AAAAAAAAAao/x240bd9EACU/s320/geek.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5376207178139874658" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Ktoś sobie wymyślił, że dzisiaj będzie &lt;a href="http://www.blogday.org/"&gt;światowy dzień blogerów&lt;/a&gt;. Ok, fajnie.&lt;br /&gt;&lt;br /&gt;Aby jakoś uczcić ten niezwykły, magiczny i jedyny w roku dzień postanowiłem zarekomendować nowego bloga poświęconego Javie i IT ogólnie: &lt;a href="http://technology-for-human.blogspot.com/"&gt;Technology For Human&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Co prawda z założenia blog ma zawierać solidne tutoriale dla początkujących, ale na ile znam autora, to nawet doświadczeni wyjadacze będą mogli dowiedzieć się czegoś nowego z każdego posta.&lt;br /&gt;&lt;br /&gt;Autor postawił sobie za cel przekaz rzetelnej wiedzy popartej &lt;span style="font-weight:bold;"&gt;realistycznymi&lt;/span&gt; przykładami. Bez ściemy znanej z tandetnych tutoriali. Autor zapewnia, że przykłady będą pochodzić z placu boju.&lt;br /&gt;&lt;br /&gt;//==============================&lt;br /&gt;&lt;br /&gt;Przyznam się, że sam miałem kiedyś w planie serię postów na temat własnej "skrzynki z narzędziami" - czyli kilku różnych kompletnych zestawów narzędzi developerskich oraz frameworków, które wykorzystałbym w przypadku problemu danej klasy. Niestety z braku czasu wciąż odkładam to zadanie. Ale na szczęście pojawiła się blog kolegi więc chyba sobie odpuszczę:)&lt;br /&gt;&lt;br /&gt;Hasło na zakończenie tego magicznego i jedynego w roku dnia: Blog to zdrowie (&lt;a href="http://art-of-software.blogspot.com/2008/07/blogasek-javowy-zawsze-smaczny-i-zdrowy.html"&gt;a oto dowody tej tezy&lt;/a&gt;)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5197374494377847819-6951134357075784237?l=art-of-software.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://art-of-software.blogspot.com/feeds/6951134357075784237/comments/default' title='Komentarze do posta'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5197374494377847819&amp;postID=6951134357075784237' title='Komentarze (0)'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5197374494377847819/posts/default/6951134357075784237'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5197374494377847819/posts/default/6951134357075784237'/><link rel='alternate' type='text/html' href='http://art-of-software.blogspot.com/2009/08/dzien-bloggera.html' title='Dzień bloggera'/><author><name>Sławek Sobótka</name><uri>http://www.blogger.com/profile/15082577671795313109</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='30' height='32' src='http://3.bp.blogspot.com/-tmFOhJC48_E/TkQ0G2DxrqI/AAAAAAAAAz8/WVGBaaS5a_Y/s220/zdjecie2.png'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_m-NewLwJEb8/Spwf8bPutWI/AAAAAAAAAao/x240bd9EACU/s72-c/geek.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5197374494377847819.post-6166279807403137998</id><published>2009-08-26T22:55:00.003+02:00</published><updated>2009-09-17T18:30:35.929+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Homo sum...'/><category scheme='http://www.blogger.com/atom/ns#' term='z dystansu'/><title type='text'>Jeszcze prostota czy może już prostactwo?</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_m-NewLwJEb8/SpQjQ2NAjMI/AAAAAAAAAag/dj_GxJUqaPE/s1600-h/ZenStones.jpg"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 214px;" src="http://2.bp.blogspot.com/_m-NewLwJEb8/SpQjQ2NAjMI/AAAAAAAAAag/dj_GxJUqaPE/s320/ZenStones.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5373959027694800066" /&gt;&lt;/a&gt;&lt;br /&gt;Chyba każdy z nas zastanawiał się nad tym co takiego urzekło go w programowaniu, że wybrał właśnie to zajęcie. Co takiego przykuwa nas na długie godziny do komputera i powoduje, że zapominamy o &lt;a href="http://www.przychodnia.pl/reumatyzm/index10.php3?t=10"&gt;zwyrodnieniach kręgów szyjnych&lt;/a&gt; i &lt;a href="http://nasze-choroby.pl/978-c-Cieśń%20nadgarstka.html"&gt;nadgarstków&lt;/a&gt;, o &lt;a href="http://www.emedica.pl/szczeg_choroby.php3?nr=176"&gt;zakrzepach w żyłach głębokich&lt;/a&gt;,...&lt;br /&gt;&lt;br /&gt;Niektórzy odpowiadają, że pociąga ich możliwość tworzenia i kreowania. Inni lubią mieć kontrolę i możliwość decydowania. Są też tacy, którzy pławią się w masochistycznej rozkoszy (choć nigdy się do tego nie przyznają) lawirowania pomiędzy ograniczeniami różnego rodzaju.&lt;br /&gt;&lt;span style="font-style:italic;"&gt;&lt;br /&gt;/*&lt;br /&gt;&amp;nbsp;*Przypadki gdy ktoś po prostu "miał Pascala na studiach"&lt;br /&gt;&amp;nbsp;*i przypadkiem został zatrudniony z jakiejś "łapanki" &lt;br /&gt;&amp;nbsp;*a później "tak już zostało" pominę w tych rozważaniach.&lt;br /&gt;&amp;nbsp;*/&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Jest jednak jeden wzorzec, który powtarza się byt często aby go zignorować. Mianowicie - większość z nas podkreśla, że &lt;span style="font-weight:bold;"&gt;największą przyjemność sprawia poszukiwanie prostoty, elegancji i harmonii&lt;/span&gt;. Nasze umysły nieustannie poszukują zgrabnych modeli pewnych wycinków modelowanego świata. Nic nas tak nie cieszy jak elegancka i prosta forma.&lt;br /&gt;&lt;br /&gt;Po tym przydługim wstępie czas przyznać się co sprowokowało mnie do napisania tego posta: prezentacja Jonathana Dahl &lt;a href="http://www.infoq.com/presentations/dahl-programming-minimalism"&gt;Programming and Minimalism&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Szczerze polecam tą prezentację (to tylko ok pół godziny). Pomimo ogromnego stresu w jakim był prelegent jest to aktualnie prezentacja numer 2 na mojej liście prezentacji dla programistów. Wyprzedza ją tylko znakomita Developing Expertise: Herding Racehorses, Racing Sheep o której pisałem tu: &lt;a href="http://art-of-software.blogspot.com/2008/08/unforgiven.html"&gt;The Unforgiven&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Jonathan Dahl dokonał czegoś niezwykłego i pięknego zarazem. Pokusił się o próbę syntezy zasad minimalistycznej prostoty, występujących w języku naturalnym, muzyce oraz programowaniu oczywiście. Szczególnie ciekawie brzmi część przedstawiająca przekrojowo sinusoidalne zmiany komplikacji w muzyce - począwszy od Mozarta a skończywszy na Punk Rocku:) Być może dowiecie się z niej dlaczego pewne gatunki muzyki Wam odpowiadają a innych kompletnie nie trawicie... wszystko zależy od preferowanego poziomu komplikacji "figur" akustycznych.&lt;br /&gt;&lt;br /&gt;Ale wracając do kontekstu programistycznego... Prezentacja, którą się tak zachwycam traktuje o programowaniu stricte w dosyć zdawkowym wymiarze. Ot mamy jakąś funkcję w Ruby - pogańskim języku, którego nie rozumiem. Jedna jej wersja została upstrzona składnią, którą zna pewnie 5% programistów tegoż języka, natomiast druga (o identycznej funkcjonalności) zawiera prostego ifa. Wniosek: prostota w programowaniu to podstawa. Dziękujemy i do widzenia.&lt;br /&gt;&lt;br /&gt;Chciałbym jednak rozwinąć ten temat, ponieważ z moich obserwacji wynika, że o ile wszyscy powtarzają jakoby prostota była ich świętym Graalem to samo pojęcie prostoty w programowaniu jest mocno rozmyte. Nieraz spotkałem się z sytuacją gdy pewien mniejszy lub większy kawałek kodu był oceniany jak majstersztyk lub kupa guano.&lt;br /&gt;&lt;br /&gt;Od czego to zależy? &lt;br /&gt;Nawet w tak dobrze zdefiniowanej domenie jak muzyka mamy sytuacje, gdy pewien utwór/twórca/gatunek/styl "się podoba" lub "się nie podoba". Klasycznym przykładem jest Chopin, którego się uwielbia albo nienawidzi:)&lt;br /&gt;Odwołując się do wspomnianej wyżej prezentacji: zależy to od stopnia komplikacji i możliwości jej ogarnięcia przez odbiorcę. Pewne formy są zbyt banalne, pewne zbyt skomplikowane (wydają się wręcz chaotyczne) a pewne w sam raz nam odpowiadają. &lt;br /&gt;Większość umysłów ścisłych jest jak inż. Mamoń - podoba im się to co już znają. Mechanizm jest prosty: znając jakiś wzorzec (utwór) wiemy czego się spodziewać w danej chwili i cieszymy się gdy słyszmy właśnie to czego się spodziewamy. Przypomnijcie sobie jak irytująca jest nagła zmiana kawałka albo różnego rodzaju zakłócenia;P&lt;br /&gt;&lt;br /&gt;Wyobraźmy sobie przykładowy problem, którego rozwiązanie można zapisać w jednej klasie z jedną metodą, która ma powiedzmy 10 ekranów a na nich 100 ifów. Ktoś może powiedzieć, że jest to rozwiązanie najprostsze, ponieważ "wszystko po kolei widać", wystarczy się dobrze wczytać;)&lt;br /&gt;Inne podejście może wymagać powiedzmy 5 interfejsów i 10 klas. Każda klasa zawiera parę linijek kodu. Ktoś może stwierdzić, że jest to rozwiązanie zbyt skomplikowane ponieważ aby zorientować się co się dzieje, "trzeba skakać po wielu plikach" i "nie widać całego przebiegu". &lt;br /&gt;&lt;br /&gt;Kto ma rację? To oczywiście zależy od preferencji. Jedni wolą wiele prostych pudełek składających się na bardziej wyrafinowaną strukturę, inni będą preferować jedno pudło, w którym jakoś się połapią.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Aby nie szukać konkretnego przykładu zbyt daleko przyjrzyjmy się &lt;a href="http://java.sun.com/javase/6/docs/api/java/io/package-summary.html"&gt;strumieniom&lt;/a&gt; w standardowej bibliotece Javy. Pamiętacie jeszcze swoje pierwsze z nimi spotkanie?;P Dziesiątki klas, jakieś interfejsy, pokręcone konstruktory. Pierwsza reakcja? Panika i odrzucenie. Ja chcę przecież tylko odczytać głupi tekst z pliku a to panie takie pokomplikowane.&lt;br /&gt;&lt;br /&gt;Natomiast znając pewną ogólną zasadę - &lt;a href="http://pl.wikipedia.org/wiki/Dekorator_(wzorzec_projektowy)"&gt;wzorzec dekoratora&lt;/a&gt; całość nagle okazuje się być piękna w swej prostocie. Trudno stwierdzić co cieszy bardziej: elegancja tego rozwiązania czy prostota używania i niezwykła łatwość składania złożonych strumieni.&lt;br /&gt;&lt;br /&gt;//===========================&lt;br /&gt;Problem prostoty nie jest jednowymiarowy. Nie zawsze problem polega jedynie na tym po prostu działało. Często musi jeszcze dać się zrozumieć, zmienić, rozbudować, skalować, optymalizować, itd. Wówczas kryteria prostoty i elegancji zmieniają wartości. &lt;br /&gt;&lt;br /&gt;Bardzo łatwo wówczas pomylić szlachetną prostotę z pospolitym prostactwem. Linia pomiędzy nimi jest zwykle cienka.&lt;br /&gt;&lt;br /&gt;Słynny cytat Einsteina "rzeczy powinny być tak proste jak to możliwe" niesie ze sobą na prawdę głębokie przesłanie...&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5197374494377847819-6166279807403137998?l=art-of-software.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://art-of-software.blogspot.com/feeds/6166279807403137998/comments/default' title='Komentarze do posta'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5197374494377847819&amp;postID=6166279807403137998' title='Komentarze (7)'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5197374494377847819/posts/default/6166279807403137998'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5197374494377847819/posts/default/6166279807403137998'/><link rel='alternate' type='text/html' href='http://art-of-software.blogspot.com/2009/08/jeszcze-prostota-czy-moze-juz.html' title='Jeszcze prostota czy może już prostactwo?'/><author><name>Sławek Sobótka</name><uri>http://www.blogger.com/profile/15082577671795313109</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='30' height='32' src='http://3.bp.blogspot.com/-tmFOhJC48_E/TkQ0G2DxrqI/AAAAAAAAAz8/WVGBaaS5a_Y/s220/zdjecie2.png'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_m-NewLwJEb8/SpQjQ2NAjMI/AAAAAAAAAag/dj_GxJUqaPE/s72-c/ZenStones.jpg' height='72' width='72'/><thr:total>7</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5197374494377847819.post-1287295897857234027</id><published>2009-07-05T15:33:00.009+02:00</published><updated>2009-07-14T23:33:55.584+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='JUG'/><category scheme='http://www.blogger.com/atom/ns#' term='Homo sum...'/><category scheme='http://www.blogger.com/atom/ns#' term='z dystansu'/><title type='text'>Jakość (życia)</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_m-NewLwJEb8/SlC35Zr9k-I/AAAAAAAAAZg/EafKw3Y9te8/s1600-h/Full_Of_Happyness__by_tostandalone.jpg"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 240px;" src="http://1.bp.blogspot.com/_m-NewLwJEb8/SlC35Zr9k-I/AAAAAAAAAZg/EafKw3Y9te8/s320/Full_Of_Happyness__by_tostandalone.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5354982153719223266" /&gt;&lt;/a&gt;&lt;br /&gt;Kolejna &lt;a href="http://javarsovia.pl/"&gt;Javarsovia&lt;/a&gt; za nami.&lt;br /&gt;Brawa dla organizatorów za profesjonalizm i samą inicjatywę. Podziękowania należą się też (a właściwie to przede wszystkim) prelegentom, którzy altruistycznie dzielili się wiedzą i doświadczeniem.&lt;br /&gt;&lt;br /&gt;W stosunku do poprzedniego roku zauważam pozytywną zmianę patrząc na przekrój tematów. Zdecydowanie mniej &lt;a href="http://art-of-software.blogspot.com/2009/03/w-co-sie-bawic.html"&gt;onanizmu technicznego&lt;/a&gt;. Nowe zabawki nie rozwiązują problemów, oprócz tych, które same stwarzają. Stawiamy bardziej na profesję. To chyba znak, że idą zmiany w mentalności naszego comunity - zgodnie z nowym trendem: &lt;a href="http://www.infoq.com/news/2009/03/software_craftsmanship"&gt;craftsmanship&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;W większości prezentacji, w których uczestniczyłem pojawiała się idea &lt;span style="font-weight:bold;"&gt;jakości&lt;/span&gt;. Jakości rozumianej nie tylko jako atrybut produktu, ale &lt;span style="font-weight:bold;"&gt;przede wszystkim jako jakość naszej codziennej pracy&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;Z jakością produktu bywa różnie - nie zawsze jest istotna. Klient nie jest świadomy - dla niego ma po prostu działać. Szef martwi się o harmonogram i budżet - o inne sprawy będziemy (będziecie;P) martwić się później. Biznes rządzi się swoimi prawami i to jest zrozumiałe.&lt;br /&gt;&lt;br /&gt;Natomiast aspekt jakości rozumianej jako jakość codziennej pracy nad projektem IT to coś z goła innego. Chyba nikt nie lubi tego uczucia, gdy budzisz się rano, otwierasz oczy, patrzysz w sufit a pierwsza myśl jaka przychodzi do głowy na dobry początek nowego dnia to &lt;span style="font-style:italic;"&gt;"k@#$%, nie po to studiowałem x lat żeby teraz wstawać rano, brać widły do ręki i przerzucać ten zgniły kod"&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;W wymiarze osobistym jakość codziennej pracy jest jedną z najważniejszych składowych jakości życia&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;Chyba stąd u prelegentów, którzy swoje w życiu przerzucili, refleksje na tym co robić aby nie szarpać się w codziennej pracy. Krótka relacja z prelekcji, w których uczestniczyłem:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Randori TDD - Krzysztof Jelski&lt;/span&gt; - ciekawe podejście do developemntu. &lt;a href="http://davenicolette.wikispaces.com/Randori"&gt;Randori&lt;/a&gt; w skrócie (i na ile udało mi się zrozumieć) polega na programowani w parach z rolą kierowcy i pilota. Kierowca programuje skupiając się na detalach podczas gdy pilot dba szerszą wizję. &lt;br /&gt;Programowanie odbywa się w cyklach: najpierw test, działająca implementacja, refaktoryzacja do osiągnięcia jakości rozwiązania. Rozpoczęcie programowania od testu powoduje, że zastanawiamy się nad tym JAK nasza klasa będzie używana przez klasę-klienta.&lt;br /&gt;&lt;br /&gt;Co prawda wymaga to zmiany mentalnej, ale spojrzenie z perspektywy klasy-klienta na prawdę się opłaca. Chyba każdy nie raz miał przykre uczucie niesmaku próbując wreszcie użyć swój super zestaw właśnie stworzonych klasek.&lt;br /&gt;Przewiduję również wzrost produktywności - ciężko obijać się gdy siedzi ktoś obok nas;)&lt;br /&gt;&lt;br /&gt;Wg mnie jest również doskonały sposób na efektywne przekazywanie wiedzy.&lt;br /&gt;Najszybciej uczymy się przez naśladownictwo. Zjawisko to może zostać spotęgowane przez obecność eksperta, który na bieżąco wyjaśnia rozwiązania problemów i przesłanki stojące za wyborem danego podejścia. Najbardziej efektywnym i przynoszącym najlepsze rezultaty sposobem na wprowadzenie nowego członka do zespołu jest poświęcenie mu czasu na wspólne programowanie. Niemal naturalnie przejmuje on wówczas nawyki i dobre praktyki, których samodzielne wypracowanie zajmuje niejednokrotnie lata.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Drools Guvnor - Jarosław Kijanowski&lt;/span&gt; - tutaj aspekt jakości pracy nie był zbyt silnie uwypuklony. Może poza aluzjami do poziomu profesjonalizmu analityków;)&lt;br /&gt;Na na podkreślenie zasługuje sama forma prelekcji: z jajem, bez stresu, ogólna idea-zaciekawienie-przykład. O to chodzi!&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Praca z odziedziczonym kodem - Jakub Dziwisz&lt;/span&gt;  przede wszystkim brawa na Jakuba (&lt;a href="http://agiletuning.pl/"&gt;agiletuning&lt;/a&gt;) - profesjonalny prelegent z charyzmą i klasą. Praca z odziedziczonym kodem, hmm temat w sumie bardzo smutny;) Zaprezentowano techniki refaktoryzacji, mające na celu zmniejszenie bólu. Pamiętajmy jednak, że słaby kod to nie tylko problem przeszłości. On powstaje również tu i teraz zatem przedstawione techniki mogą mieć wykorzystanie w codziennej pracy. Podstawa to dobrze zrozumiany OOD, G.R.A.S.P i S.O.L.I.D oraz wzorce projektowe w granicach rozsądku.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Ewolucja Architektury - Paweł Lipiński&lt;/span&gt;. Paweł zaprezentował pragmatyczne podejście do architektury. Architektura - arcy ważny składnik procesu a z dyskusji uczestników widać było, że są różne sposoby rozumienia tego słowa. Przydało by się uporządkowanie pojęć: wskazania domen architektury (aplikacji, systemy, wdrożeniowa) oraz jasnego rozdzielenia architektury od projektowania.&lt;br /&gt;&lt;br /&gt;Najważniejsza wg mnie myśl z prelekcji: architekci muszą programować. Jako architekt potwierdzam i podpisuję się pod zdaniem Pawła. &lt;span style="font-weight:bold;"&gt;Niestety aby móc powiedzieć coś sensownego na temat kształtu systemu trzeba ubabrać sobie rączki&lt;/span&gt;. Nie wystarczy mieć doświadczenia x lat temu, a już kuriozalna jest sytuacja gdy architekt może pochwalić się jedynie programikiem w Pascalu napisanym na studiach.&lt;br /&gt;&lt;br /&gt;//==============================&lt;br /&gt;&lt;br /&gt;Prezentowane zagadnienia poruszyły część aspektów jakości (w sensie bezstresowej pracy) w całym procesie wytwarzania softu.&lt;br /&gt;Do kompletu, jako uzupełnienie, dodałbym:&lt;br /&gt;- Analizę biznesową - zrozumienie problemu klienta, zebranie wymagań&lt;br /&gt;- Rzetelną analizę systemową - analiza to proces myślowy, włożenie wysiłku w uporządkowanie biznesu. Warto wesprzeć się sprawdzonymi rozwiązaniami, takimi jak Archetypy biznesowe. Niestety czasem jest to jedynie spisanie ton dokumentów zawierających nieprzetrawiony bełkot.&lt;br /&gt;- Architektura - podczas prelekcji Pawła padło pytanie o przykłady architektur. Wszystko oczywiście zależy od konkretnego problemu Ja obecnie w nietrywialnych aplikacjach webowych stosuję modyfikowane do problemu architektury &lt;a href="http://www.infoq.com/presentations/greg-young-unshackle-qcon08"&gt;Distributed DDD oparte o Command-Query Separation&lt;/a&gt;.&lt;br /&gt;- Projekt - Architektura narzuca ogólny styl projektowania. Aby uniknąć w niedalekiej przyszłości koszmaru utrzymania własnego kodu warto wspierać się technikami OO takimi jak SOLID czy GRASP.&lt;br /&gt;Ale podstawa to w ogóle projektować zamiast rzucać się jak dzikus na klawiaturę i radośnie napieprzać;)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5197374494377847819-1287295897857234027?l=art-of-software.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://art-of-software.blogspot.com/feeds/1287295897857234027/comments/default' title='Komentarze do posta'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5197374494377847819&amp;postID=1287295897857234027' title='Komentarze (4)'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5197374494377847819/posts/default/1287295897857234027'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5197374494377847819/posts/default/1287295897857234027'/><link rel='alternate' type='text/html' href='http://art-of-software.blogspot.com/2009/07/jakosc-zycia_05.html' title='Jakość (życia)'/><author><name>Sławek Sobótka</name><uri>http://www.blogger.com/profile/15082577671795313109</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='30' height='32' src='http://3.bp.blogspot.com/-tmFOhJC48_E/TkQ0G2DxrqI/AAAAAAAAAz8/WVGBaaS5a_Y/s220/zdjecie2.png'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_m-NewLwJEb8/SlC35Zr9k-I/AAAAAAAAAZg/EafKw3Y9te8/s72-c/Full_Of_Happyness__by_tostandalone.jpg' height='72' width='72'/><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5197374494377847819.post-659401885327714598</id><published>2009-07-01T19:43:00.012+02:00</published><updated>2009-07-03T12:33:58.636+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Homo sum...'/><category scheme='http://www.blogger.com/atom/ns#' term='z dystansu'/><category scheme='http://www.blogger.com/atom/ns#' term='Rozwój'/><category scheme='http://www.blogger.com/atom/ns#' term='kognitywistyka'/><title type='text'>Ile Ci to zajmie? (różnice w postrzeganiu czasu)</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_m-NewLwJEb8/Skupc-xFTEI/AAAAAAAAAZY/5CViB12fBdA/s1600-h/zegar.jpg"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 213px;" src="http://2.bp.blogspot.com/_m-NewLwJEb8/Skupc-xFTEI/AAAAAAAAAZY/5CViB12fBdA/s320/zegar.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5353558897410264130" /&gt;&lt;/a&gt;&lt;br /&gt;Niektóre filozofie zakładają, że czas nie istnieje. Jest tylko tu i teraz, upływ czasu to złudzenie. Inni z kolei chcą go wyginać i zaginać.&lt;br /&gt;&lt;br /&gt;Ale zejdźmy na ziemię. W biznesie czas to tylko pieniądz. Stąd też najczęściej pojawiającym się pytaniem w komercyjnym procesie tworzenia softu jest nasze ulubione:&lt;br /&gt;&lt;br /&gt;ILE CI TO ZAJMIE?&lt;br /&gt;&lt;br /&gt;Managerowie uwielbiają zadręczać tym pytaniem swoich/swoje zasoby. Irytują się, gdy developerzy nie są w stanie odpowiedzieć na tak elementarne pytanie. Przecież jeżeli robi się coś od kilku lat to powinno dać się niemal co do godziny określić ilość potrzebnego czasu. Co za durnie, siedzą w tym po uszy i nie potrafią nawet zarządzać sobą, swoimi zadaniami i swoim czasem. Przecież programowanie jest prawie jak budowanie. Macie nawet te swoje wzorce pokrakowe (czy jakieś tam) oparte na latach doświadczeń budowlańców. Muszę mieć harmonogram i się z niego wywiązać. Budżet Panowie! Budżet!&lt;br /&gt;&lt;br /&gt;Developerom z drugiej strony ciśnie się na usta "Nie wiem! Nigdy wcześniej tego nie robiłem!" - heh ale tylko Ci o mocnej pozycji w plemieniu mogą sobie pozwolić na zwerbalizowanie swoich myśli. Czy on nie rozumie, ze praca badawczo-rozwojowa (a taką właściwie jest każdy nowy projekt z uwagi na nowe narzędzia) nie jest liniowa a eksponencjalna. Stając w kopalni z kilofem w ręku, kilometr pod ziemią i fedrując na przodku nigdy nie wiadomo kiedy trafimy na skałę, ile będzie trwać stagnacja i kiedy pojawi się nagły wybuch ruszający wszystko do przodu. Programowanie to nie murowanie muru z cegieł (1 cegła na minutę = &gt; mur z 1000 cegieł to 16.7 godziny) - to tak nie działa.&lt;br /&gt;&lt;br /&gt;Jedni i drudzy mamroczą pod nosem: co za durnie!&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Zagadnienie szacowania czasu, metodyki szacowania to temat na osobna bajkę, dziś będzie o postrzeganiu czasu.&lt;br /&gt;&lt;br /&gt;Ale zanim przejdziemy do corowej warstwy posta, zatrzymajmy się na chwilę aby pokazać sceptykom, że postrzeganie czasu rzeczywiście jest względne i każdy doświadcza tego niemal codziennie (proszę nie uciekać od ekranów - względne w sensie poznawczym a nie w sensie teorii względności).&lt;br /&gt;&lt;br /&gt;Pomijając filozoficzną i fizyczną naturę czasu, Twój mózg jest po prostu tak skonstruowany, że postrzega upływ czasu. Mamy wbudowane 2 "koprocesory czasu" - zegary dobowy i bieżący. Zegar bieżący opiera się na mechanizmie taktowania (tysiące neuronów) i próbkowania (neurony gwiaździste i piramidalne). Co ciekawe i istotne dla nas, hormony stresu zmieniają stężenie neuroprzekaźników w naszym "koprocesorze" czasu bieżącego co powoduje zmiany w "tykaniu" a co za tym idzie próbkowaniu bodźców ze świata.&lt;br /&gt;&lt;br /&gt;Wszyscy znamy uczucie dłużenia się czasu lub odwrotne do niego - szybki upływ czasu. Jak się okazuje niem tu żadnej magii - wszystko zależy od poziomu hormonów stresu. Dzięki temu np w stresowej sytuacji na drodze mamy "gęste" próbkowanie świata, wchłaniamy więcej danych w jednostce czasu i mamy więcej "cykli" na podejmowanie działań związanym z uniknięciem zderzenia z jakimś durniem.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Przejdźmy do meritum, czyli czasu w kontekście IT.&lt;br /&gt;W tym celu zostawmy poziom "techniczny" czyli neurony i przyjrzyjmy się ogólnym strategiom przeżywania czasu: &lt;a href="http://www.sap.com/poland/company/strategie/21/analizy/plandnia/index.epx"&gt;Spontaniczny plan dnia&lt;/a&gt;.&lt;br /&gt;Wynika z niego, że dysonans w podejściu do czasu i planowania jaki obserwujemy na różnych stanowiskach może wynikać z różnych sposobów myślenia o czasie. Tak, tak, wg tego modelu różnimy się wewnętrznymi reprezentacjami czasu!&lt;br /&gt;&lt;br /&gt;Mamy zatem ludzi żyjących:&lt;br /&gt;- &lt;span style="font-style:italic;"&gt;W czasie&lt;/span&gt; (In time) - żyją chwilą, odczuwają każdy moment, bez planu i kontroli czasu, skupiają się na aktualnym działaniu&lt;br /&gt;- P&lt;span style="font-style:italic;"&gt;omiędzy Czasem&lt;/span&gt; (Between Time) - w pozycji zdystansowanej do czasu, mają na niego ogólny ogląd, widzą możliwości działania, ale nie przypisują im czasu trwania, dowolnie przestawiają zadania&lt;br /&gt;- &lt;span style="font-style:italic;"&gt;Poprzez Czas&lt;/span&gt; (Through Time) - również z dystansem, ale mając ścisły chronologiczny plan, każde zdarzenie ma czas rozpoczęcia i czas trwania, czas jest linią o ograniczonej pojemności (w sumie logiczne;)&lt;br /&gt;&lt;br /&gt;Autorzy artykułu zachęcają nas do trenowania różnych sposobów przeżywania czasu i dobierania najlepszego do danej sytuacji. Powodzenia.&lt;br /&gt;&lt;br /&gt;Zastanawiam się czy można w ogóle być dobrym managerem nie żyjąc &lt;span style="font-style:italic;"&gt;Poprzez Czas&lt;/span&gt; - widząc dokładny plan, zależności czasowe i być przez to cel-oriented?&lt;br /&gt;&lt;br /&gt;Czy można w ogóle prowadzić jakąkolwiek kreatywną działalność (mam na myśli sensowną działalność a nie np malarstwo współczesne) nie żyjąc &lt;span style="font-style:italic;"&gt;Pomiędzy Czasem&lt;/span&gt; - dostrzegając możliwości i potencjał.&lt;br /&gt;&lt;br /&gt;A żyjąc chwilą &lt;span style="font-style:italic;"&gt;W czasie&lt;/span&gt; lepiej chyba nie męczyć się z IT, rzucić to wszystko i rozpocząć karierę w biznesie porno;)&lt;br /&gt;&lt;br /&gt;Każdy powinien zająć się tym w czym jest dobry. A szacunek to podstawa.&lt;br /&gt;&lt;br /&gt;//==============================&lt;br /&gt;&lt;br /&gt;"Ty masz zegarek, ja mam czas"&lt;br /&gt;...Usłyszał w odpowiedzi na nerwowe pokazywanie na cyferblat podróżnik, gdy usiłował ponaglić swego przewodnika na postoju, pod­czas wędrówki gdzieś, na andyjskim bezludziu.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5197374494377847819-659401885327714598?l=art-of-software.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://art-of-software.blogspot.com/feeds/659401885327714598/comments/default' title='Komentarze do posta'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5197374494377847819&amp;postID=659401885327714598' title='Komentarze (6)'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5197374494377847819/posts/default/659401885327714598'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5197374494377847819/posts/default/659401885327714598'/><link rel='alternate' type='text/html' href='http://art-of-software.blogspot.com/2009/07/ile-ci-to-zajmie-roznice-w-postrzeganiu.html' title='Ile Ci to zajmie? (różnice w postrzeganiu czasu)'/><author><name>Sławek Sobótka</name><uri>http://www.blogger.com/profile/15082577671795313109</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='30' height='32' src='http://3.bp.blogspot.com/-tmFOhJC48_E/TkQ0G2DxrqI/AAAAAAAAAz8/WVGBaaS5a_Y/s220/zdjecie2.png'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_m-NewLwJEb8/Skupc-xFTEI/AAAAAAAAAZY/5CViB12fBdA/s72-c/zegar.jpg' height='72' width='72'/><thr:total>6</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5197374494377847819.post-4437632963199510450</id><published>2009-06-05T16:09:00.007+02:00</published><updated>2009-06-05T21:39:13.316+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Domain Driven Design'/><category scheme='http://www.blogger.com/atom/ns#' term='post gościnny'/><title type='text'>Domain Driven Disaster</title><content type='html'>Przygotowania do prezentacji o DDD na &lt;a href="http://groups.google.com/group/lublin-jug/browse_thread/thread/3da3c5e3a70a095b"&gt;LJUG&lt;/a&gt; w toku. Tymczasem mamy niecodzienną okazję aby zobaczyć jak w praktyce możne wyglądać projekt, którego jednym ze szczytnych założeń było podążanie za DDD. &lt;br /&gt;&lt;br /&gt;Dziś pierwszy (i mam nadzieję, że nie ostatni) post z gatunku gościnnych.&lt;br /&gt;&lt;br /&gt;Jako pierwszego mamy zaszczyt gościć tajemniczego Malory z krainy deszczowców, który  podzieli się doświadczeniami z dużego, zagranicznego projektu. Projektu, w którym niestety nieco rozminięto się z filozofią DDD, TDD i Agile:&lt;br /&gt;&lt;br /&gt;&amp;lt;post_goscinny&gt;&lt;br /&gt;Przyjemność bycia częścią projektu napędzanego czystym agilem (iteracje mamy, lecz do &lt;a href="http://agilemanifesto.org/"&gt;Agile&lt;/a&gt; nadal daleka droga), z domieszką domain driven, test driven, i ogólnie driven skłonił do podzielenia się kilkoma refleksjami. Tym gościnnym postem u Sławka podzielę się refleksjami o dysonansie miedzy filozofią którą niosą ze sobą ddd, Agile, TDD a praktyką... czyli Projektem.&lt;br /&gt;&lt;br /&gt;O ddd Sławek pisał tutaj już nie raz i każdy z czytelników mniej lub bardziej "czuje' o co w ddd chodzi. Esencja to słowa z &lt;a href="http://domaindrivendesign.org/resources/what_is_ddd"&gt;ddd.org&lt;/a&gt;: "ddd is a way of thinking and a set of priorities, aimed at accelerating software projects that have to deal with complicated domains". Nic dodać, nic ująć. Koncepcja a raczej filozofia spojrzenia na problem, na domenę. A w praktyce? Bywa różnie. Brak zrozumienia idei którą niesie ze sobą ddd, i twarde (beton) myślenie przez pryzmat aplikacji CRUD driven (formularzyki), gwarantuje Monthego Pythona każdego dnia. Sam wybór ddd nie zawsze jest szczęśliwy bo jak wyraźnie wskazuje cytat: "complicated domain". Więc po co się męczyć, i udawać ddd gdy chcemy zrobić nakładkę na db? Efektem końcowym będzie i tak mieszanka anemicznych encji i a'la serwisów żonglujących encjami w górę i w dół.  W praktyce ddd niebezpiecznie zbliża się do kilku „warstewek” klas delegujących wywołania metod z dao. I nie ma w tym nic złego – to rozwiązanie dobiera się do problemu. Nie odwrotnie. Sama sytuacja w której kończymy z pustymi encjami (@Entity, nie żadne tam encje ddd) i serwisami wskazuje że coś jest nie tak. Fundament OOD jest prosty – odpowiedzialność  a get/set to chyba jednak trochę za mało... &lt;br /&gt;&lt;br /&gt;Siłą napędową ddd to domena, co  w odniesieniu do projektu oznacza eksperta domeny, będącego  światłem w tunelu dla zespolu. Jako ze projekt nie zawsze ma domain eksperta - bywa śmiesznie. Developerzy to cwani ludzie i dadzą radę, ale to raczej Developer Driven Design (co oczywiście nie jest złe.. ale zależy od doświadczenia zespołu...). W przypadku bogatej domeny, bez pomocy eksperta wątpliwe jest stworzenie nawet poprawnych zrębów domeny, nie wspominając nawet o niuansach i bliższym nakreśleniu relacji w domenie. Pora teraz na agile (fonetyka naszego rodzimego języka, nie żaden tam edżajl).&lt;br /&gt;&lt;br /&gt;Skomplikowana domena powoli ewoluuje, nieraz zamiast ewolucji doświadczyć możemy rewolucji, gdy powolny  knowledge crunching zaowocuje przełomem w spojrzeniu na domenę. I czy nie jest to "Responding to change over following a plan" który niesie ze sobą agile manifesto? W tym momencie przypomina mi się pytanie podczas jednego z pierwszych spotkań (spotkanie a raczej meeting jest nieodzownym elementem każdego poważnego agile projektu), a mianowicie "kiedy dostaniemy skończony model domeny?". Hmm - odpowiedź była prosta: nigdy. Po czym zaczęło się wyjaśnianie (okraszone nerwowymi spojrzeniami "góry"), że to nie waterfall. Same iteracje nie sprawią, że będziemy Agile. Do tego potrzeba tzw. bigger picture i zmuszenie całego zespołu (łącznie z managementem) do innego spojrzenia na problem. Iteracje i milestony mogą być jednak wystarczającą dawką agilu. O tym, że to wymagania napędzają development niekoniecznie się pamięta. Zresztą, bywa w niektórych projektach że wymagania odpowiadają poziomem testom (assertTrue(true)); //FIX LATER, its friday, 4 o'clock ). Raz zrobiony task (zrobiony w stylu general concept, bo jak inaczej bez wymagań...) zostaje jako skończony i nie ma nawet mowy o refaktoringu pózniej... To przecież zbędne filozofowanie... W wyniku zostaje brązowa (flagowy kolor branży) papka kodu którą ktoś (nieszczęśnik, albo student, niewolnik IT) będzie miał przyjemność poprawiać. Domena zamiast ewoluować - kostnieje, zamiast odpowiadać na zmiany - &lt;a href="http://www.youtube.com/watch?v=dlOHn6dbSM8&amp;eurl=http%3A%2F%2Fpatogeny.blox.pl%2F2009%2F01%2FJestem-robotem-zapierdalam-w-sobote.html&amp;feature=player_embedded"&gt;napierdalamy&lt;/a&gt; aby zdążyć w terminie.&lt;br /&gt;&lt;br /&gt;Ostatnim kawałkiem układanki jest TDD. Który doskonale wpasowuje się do mieszanki DDD i Agile. Domena powinna ewoluować, dojrzewać, i odpowiadać na zmiany. Tutaj pomocną rączkę wyciąga TDD. Pod warunkiem że napisane testy mają sens. W życiu bywa jednak rożnie, w praktyce testy nie zawsze testują. Mądrze napisane uspokajają sumienie i pozwalają pracować nad aplikacją. Pozwalają na eksperymentowanie i dają ujście wiedzy którą powoli team zdobywa. Testy trzeba jednak umieć pisać.. i mieć na nie czas. Z pierwszym bywa rożnie, na drugie niekoniecznie jest czas w schedule projektu. Efekt - każdy boi się panicznie dotknąć czegoś większego w domenie aby całość się nie rozleciała...&lt;br /&gt;&lt;br /&gt;Na koniec link do doskonałej prezentacji o... &lt;a href="http://www.ted.com/index.php/talks/chris_bangle_says_great_cars_are_art.html"&gt;samochodach&lt;/a&gt;. Obejrzyj i popatrz przez pryzmat naszej branży. Tutaj też są projektanci i inżynierowie. W tej branży jest miejsce na pasję, rzemiosło i jakość. Uwolnijmy się od brązu.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_m-NewLwJEb8/SiksiAknoXI/AAAAAAAAAZQ/M4ipAIrrDBU/s1600-h/achievement.jpg"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 268px;" src="http://3.bp.blogspot.com/_m-NewLwJEb8/SiksiAknoXI/AAAAAAAAAZQ/M4ipAIrrDBU/s320/achievement.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5343851395632570738" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;/post_goscinny&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;//=======================================&lt;br /&gt;&lt;br /&gt;Jak wiadomo najlepiej uczyć się na błędach:) Dobrze, gdy mamy okazję z dystansu przyjrzeć się cudzym:]&lt;br /&gt;Potwierdzają się moje przemyślenia na temat metodyk Agile. Idea piękna, ale pod warunkiem, że mamy dojrzały i świadomy zespól profesjonalistów, którzy wiedzą co robią lub przynajmniej mogą poprowadzić duchowo resztę teamu.&lt;br /&gt;&lt;br /&gt;Sama filozofia DDD o ile nie jest jakoś specjalnie wysublimowana to niestety posiada pewną barierę wejścia: podstawy OO - i nie mam tu na myśli składni dziedziczenia, lecz myślenie obiektami.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5197374494377847819-4437632963199510450?l=art-of-software.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://art-of-software.blogspot.com/feeds/4437632963199510450/comments/default' title='Komentarze do posta'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5197374494377847819&amp;postID=4437632963199510450' title='Komentarze (7)'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5197374494377847819/posts/default/4437632963199510450'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5197374494377847819/posts/default/4437632963199510450'/><link rel='alternate' type='text/html' href='http://art-of-software.blogspot.com/2009/06/domain-driven-disaster.html' title='Domain Driven Disaster'/><author><name>Sławek Sobótka</name><uri>http://www.blogger.com/profile/15082577671795313109</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='30' height='32' src='http://3.bp.blogspot.com/-tmFOhJC48_E/TkQ0G2DxrqI/AAAAAAAAAz8/WVGBaaS5a_Y/s220/zdjecie2.png'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_m-NewLwJEb8/SiksiAknoXI/AAAAAAAAAZQ/M4ipAIrrDBU/s72-c/achievement.jpg' height='72' width='72'/><thr:total>7</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5197374494377847819.post-6663895723226053178</id><published>2009-05-30T17:02:00.007+02:00</published><updated>2009-11-15T13:56:41.391+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='śmieszne'/><category scheme='http://www.blogger.com/atom/ns#' term='linki'/><title type='text'>Nie ma rzeczy niemożliwych</title><content type='html'>/*Post rozpoczynający serię: żarciki branżowe*/&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.getacoder.com/projects/detect_loop_106243.html"&gt;http://www.getacoder.com/projects/detect_loop_106243.html&lt;/a&gt;&lt;br /&gt;...jak widać jest wielu śmiałków gotowych od ręki i za niewielkie pieniądze rozwiązać &lt;a href="http://pl.wikipedia.org/wiki/Problem_stopu"&gt;problem stopu&lt;/a&gt;. &lt;br /&gt;Ba... nawet licytują się, kto zrobi to szybciej i taniej.&lt;br /&gt;&lt;br /&gt;I nie straszny im dowód nierozwiązywalności; teoria jest dla filozofów - &lt;a href="http://art-of-software.blogspot.com/2009/05/stare-chinskie-przysowie-jest-czas-na.html"&gt;"because we can"&lt;/a&gt;!&lt;br /&gt;&lt;br /&gt;//=======================&lt;br /&gt;&lt;br /&gt;Tradycyjnie tu powinien pojawić się mój własny komentarz. Jednak jako, że &lt;span style="font-weight:bold;"&gt;dziś wyjątkowo post z przymrużeniem oka&lt;/span&gt; to tym razem oddam głos temu panu: &lt;br /&gt;&lt;object width="425" height="344"&gt;&lt;param name="movie" value="http://www.youtube.com/v/CfXEF3M4q_A&amp;hl=pl_PL&amp;fs=1&amp;"&gt;&lt;/param&gt;&lt;param name="allowFullScreen" value="true"&gt;&lt;/param&gt;&lt;param name="allowscriptaccess" value="always"&gt;&lt;/param&gt;&lt;embed src="http://www.youtube.com/v/CfXEF3M4q_A&amp;hl=pl_PL&amp;fs=1&amp;" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="425" height="344"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5197374494377847819-6663895723226053178?l=art-of-software.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://art-of-software.blogspot.com/feeds/6663895723226053178/comments/default' title='Komentarze do posta'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5197374494377847819&amp;postID=6663895723226053178' title='Komentarze (3)'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5197374494377847819/posts/default/6663895723226053178'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5197374494377847819/posts/default/6663895723226053178'/><link rel='alternate' type='text/html' href='http://art-of-software.blogspot.com/2009/05/nie-ma-rzeczy-niemozliwych.html' title='Nie ma rzeczy niemożliwych'/><author><name>Sławek Sobótka</name><uri>http://www.blogger.com/profile/15082577671795313109</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='30' height='32' src='http://3.bp.blogspot.com/-tmFOhJC48_E/TkQ0G2DxrqI/AAAAAAAAAz8/WVGBaaS5a_Y/s220/zdjecie2.png'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5197374494377847819.post-891485003479868650</id><published>2009-05-29T20:43:00.010+02:00</published><updated>2009-05-30T16:38:53.512+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Rozwój'/><category scheme='http://www.blogger.com/atom/ns#' term='recenzja'/><title type='text'>Stare Chińskie przysłowie: Jest czas na pracę i jest czas na zbieranie ryżu</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_m-NewLwJEb8/SiAxTcfu-bI/AAAAAAAAAYw/9o0nTQsLqaw/s1600-h/codeforfood.jpg"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 194px; height: 134px;" src="http://2.bp.blogspot.com/_m-NewLwJEb8/SiAxTcfu-bI/AAAAAAAAAYw/9o0nTQsLqaw/s320/codeforfood.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5341323368197978546" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Podobno to Hindusi odkryli system dziesiętny - Arabowie jedynie go rozpowszechnili (mając silne argumenty w dłoniach;).&lt;br /&gt;Nieco mniej chlubnym osiągnięciem indyjskiej myśli jest na przykład biblioteka tagów &lt;a href="http://pl.wikipedia.org/wiki/JavaServer_Pages"&gt;JSP&lt;/a&gt; do integracji z &lt;a href="http://pl.wikipedia.org/wiki/Java_Persistence_API"&gt;JPA&lt;/a&gt;, na którą to niedawno przypadkiem się natknąłem. Zdaje się, że przyświeca jej motto "because we can!"&lt;br /&gt;&lt;br /&gt;Stereotyp programisty Hindusa, który "nakłada gacie przez głowę" jest dosyć mocno rozpowszechniony i zakorzeniony ale wystrzegajmy się pychy.&lt;br /&gt;&lt;br /&gt;Ciekawe studium hinduskiej mentalności znajdziemy w interesującej, lekkiej ale bardzo pouczającej książce &lt;a href="http://www.powernet.pl/ksiazka.php?id=2"&gt;Moja Praca Emigruje do Indii - A wszystko, co dostałem, to ta marna książka&lt;/a&gt;. Ale to tylko jeden z aspektów. Poznamy przede wszystkim globalne mechanizmy korporacyjne mające wpływ na niemal każdego z branży IT.&lt;br /&gt;&lt;br /&gt;Chad Fowler zabiera nas w egotyczną podróż do Bangladuru, gdzie spędził 1.5 roku tworząc Software House dla jednej z amerykańskich korporacji.&lt;br /&gt;&lt;br /&gt;Poznamy szereg kuriozów:&lt;br /&gt;- na ogłoszenie o pracę odpowiada średnio kilkanaście tysięcy chętnych&lt;br /&gt;- a mimo niemałego budżetu nie można sobie pozwolić na tych doświadczonych&lt;br /&gt;- taksówkarz zna 5 języków&lt;br /&gt;- &lt;span style="font-weight:bold;"&gt;a programista nie ma własnego komputera w domu&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Każdy z 52 zgrabnych i wyważonych rozdziałów niesie w sobie pewien morał. Lokalny folklor jest jedynie pretekstem do przekazania metafory lub przesłania. Dostajemy zestaw gotowych strategii, uwag, ostrzeżeń i porad z zakresu szeroko pojętego samorozwoju i autopromocji. Kto się nie rozwija ten się cofa a &lt;a href="http://www.youtube.com/watch?v=ljbI-363A2Q"&gt;zmiany są nieuniknione&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;//=========================&lt;br /&gt;&lt;br /&gt;Wymowa książki w naszym lokalnym kontekście nabiera jednak drugiego dna. Nie musimy obawiać się emigracji naszej pracy do Indii. Być może jesteśmy Indiami Europy:P&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5197374494377847819-891485003479868650?l=art-of-software.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://art-of-software.blogspot.com/feeds/891485003479868650/comments/default' title='Komentarze do posta'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5197374494377847819&amp;postID=891485003479868650' title='Komentarze (0)'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5197374494377847819/posts/default/891485003479868650'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5197374494377847819/posts/default/891485003479868650'/><link rel='alternate' type='text/html' href='http://art-of-software.blogspot.com/2009/05/stare-chinskie-przysowie-jest-czas-na.html' title='Stare Chińskie przysłowie: Jest czas na pracę i jest czas na zbieranie ryżu'/><author><name>Sławek Sobótka</name><uri>http://www.blogger.com/profile/15082577671795313109</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='30' height='32' src='http://3.bp.blogspot.com/-tmFOhJC48_E/TkQ0G2DxrqI/AAAAAAAAAz8/WVGBaaS5a_Y/s220/zdjecie2.png'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_m-NewLwJEb8/SiAxTcfu-bI/AAAAAAAAAYw/9o0nTQsLqaw/s72-c/codeforfood.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5197374494377847819.post-8877037992134385680</id><published>2009-05-23T18:40:00.013+02:00</published><updated>2009-11-14T17:11:39.462+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Homo sum...'/><title type='text'>Understandability</title><content type='html'>Understandability - ostatnio modny termin. Znak, że oto kolejne pokolenie programistów/developerów/inżynierów oprogramowania (byle nie "informatyków"!) dorosło do przepoczwarzenia. Z kał-bojów i szambe-lanów babrzących się w cudzych (tudzież własnych) klasach z archiwum X chcieliby stać się szczęśliwymi profesjonalistami wiodącymi szczęśliwe życie wśród łatwych, prostych i przyjemnych linijek kodu.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Komentarze&lt;/span&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;#define TRUE FALSE&lt;br /&gt;//Happy debugging suckers&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Stara szkoła mówi aby 70% tekstu stanowiły komentarze. Tak aby po hipotetycznym usunięciu kodu można było go łatwo odtworzyć na podstawie ich treści.&lt;br /&gt;W praktyce oczywiście nie ma czasu na twórczość o tej skali - zarówno podczas tworzenia jak i utrzymywania kodu. Poza tym wydaje mi się, że takie podejście zmienia niewiele:&lt;br /&gt;- pisanie dobrych komentarzy jest sztuką jeszcze większą niż pisanie dobrego kodu (o czym dalej) - więc wiadomo czego możemy się spodziewać&lt;br /&gt;- komentarz daje nam jedynie bardzo lokalny obraz sytuacji, aby uchwycić tak zwany biger pikczer potrzeba zdecydowanie czegoś więcej...&lt;br /&gt;&lt;br /&gt;Ileż to razy bierzemy jakąś bibliotekę/framework (załóżmy, że rzetelnie okomentowane) i niestety nie możemy połapać się w gąszczu dziesiątek/setek klas. Przydałby się jakiś wizualny standard prezentowania ogólnej architektury konceptu. Pomocny byłby już choćby jakiś sposób uwypuklenia zastosowanych wzorców projektowych/architektonicznych.&lt;br /&gt;&lt;br /&gt;Owszem jakimś rozwiązaniem jest narzędzie do reverse engineering, przy pomocy którego możemy sobie wygenerować UML. Ale co mi po gąszczu prostokątów jeżeli nie wiem, które są istotne, które stanowią core konceptu, a które jedynie szczegóły impl.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Kod samokomentujący się&lt;/span&gt;&lt;br /&gt;Skoro i tak muszę pracować z kodem to fajnie byłoby gdyby był intuicyjny. Niedoścignionym wzorem na tym polu jest:&lt;br /&gt;Epopeja poświęcona poziomowi inteligencji dzielnego Ryśka - spisana w tej oto abstrakcyjnej klasie &lt;a href="http://stackoverflow.com/questions/184618/what-is-the-best-comment-in-source-code-you-have-ever-encountered/184673#184673"&gt;RichardIsAFuckingIdiotControl&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;To mój styl - nauczyłem się go analizując źródła Springa. Nie boję się opisowych nazewników klas czy metod mających po 30, nawet 50 znaków. To nie czasy dyskietek, gdzie od ilości literek zależało czy musimy żonglować nośnikami aby skompilować projekt.&lt;br /&gt;&lt;br /&gt;Oczywiście gdy z sygnatury metody nie mogę wywnioskować co ona robi to nie powinienem zaglądać do środka - komentarz jest jak najbardziej wymagany.&lt;br /&gt;&lt;br /&gt;W tym przypadku, podobnie jak w poprzednim również mamy problem z ogarnięciem ogólnej idei rozwiązania. Jednak niektórzy porządni rzemieślnicy zostawiają czasem wskazówki w nazwach - przykładowo przyrostki wskazujące na zastosowany wzorzec: &lt;a href="http://en.wikipedia.org/wiki/Command_pattern"&gt;xxxCommand&lt;/a&gt;, &lt;a href="http://en.wikipedia.org/wiki/Strategy_design_pattern"&gt;xxxStrategy&lt;/a&gt;, itp.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Zbiorowa inteligencja&lt;/span&gt;&lt;br /&gt;Niektórzy postulują jakoby dobry kod to taki, gdzie czytamy to czego właśnie w tym miejscu się spodziewamy. W sumie trudno się nie zgodzić - pycha pomysł. Niestety utopijny ponieważ każdy programista jest inny. Każdy ma swój styl (albo i nie - o tym na koniec) i smak. Nie zapominajmy, że zawodnicy w teamie mają różne poziomy skillsów. &lt;br /&gt;&lt;br /&gt;Oczywiście w różnorodności siła, ale świadczy to też o &lt;span style="font-weight:bold;"&gt;braku profesji w naszym fachu, braku elementarnych zasad rzemiosła - jesteśmy bandą indywidualistów&lt;/span&gt; (ale to temat na następnego posta).&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Czas to pieniądz&lt;/span&gt;&lt;br /&gt;Dobra metoda, to taka gdzie zrozumienie co i jak ona robi zajmuje nie więcej niż 5 minut - to jedno z częściej powtarzanych haseł. Miara równie rozmyta jak poprzednia. To co będzie oczywiste dla kodera turbo-ninja z silnym &lt;a href="http://pl.wikipedia.org/wiki/Spektrum_autyzmu"&gt;autyzmem&lt;/a&gt;, który w jednej półkuli kompiluje kod do rozkazów maszynowych nie będzie już takie dla studenta zarabiającego na piwko w PHP.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Z trochę innej strony...&lt;/span&gt;&lt;br /&gt;Nierzadko spotkam się z sytuacją, w której programista nie wie jak nazwać klasę, metodę czy instancję. Albo nazwy pakietów - czy nie powinny wskazywać na "uporządkowanie myśli" i odzwierciedlać architekturę aplikacji? Niby szczegół prawda? Ot po prostu nie mam dziś weny. Zresztą co to za różnica? Kompilatorowi przecież jest wszytko jedno. Nazwę sobie Manager5, doStuff(String param1, String param2) albo x7.&lt;br /&gt;&lt;br /&gt;Jest to jednak niepokojący syndrom - i mam tu na myśli coś gorszego niż rak mózgu;)&lt;br /&gt;&lt;br /&gt;Ale żeby nie było, że sobie coś ubzdurałem, podeprę się najpierw autorytetem paru guru z naszej branży aby nie stać na grząskim gruncie własnych urojeń. &lt;br /&gt;&lt;br /&gt;W 2006 r. niejaki Jarosław Rzeszótko znany również pod zabarwionym perwersją pseudonimem artystycznym "sztywny" wpadł na ciekawy pomysł. Zadał 9 (w większości) znamienitym programistom 10 pytań: &lt;a href="http://www.stifflog.com/2006/10/16/stiff-asks-great-programmers-answer/"&gt;Stiff asks, great programmers answer&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Ciekawych odpowiedzi udzielili panowie na pytanie:&lt;br /&gt;"What do you think is the most important skill every programmer should posses?"&lt;br /&gt;Istotne okazują się zdolności "miękkie", min: komunikacyjne, pisarskie, muzyczne. &lt;br /&gt;Ciekawą - bo niemal ocierającą się o neuropsychologię;) - odpowiedź dał &lt;a href="http://pragdave.pragprog.com/"&gt;Dave Thomas&lt;/a&gt;:&lt;blockquote&gt;I _have_ seen a strong correlation between people who have some music in their background and programming skills. I have no idea why, but I suspect that some of the areas of the brain that make someone musical also make them good at software development.&lt;/blockquote&gt;&lt;br /&gt;Linus Torvalds dla odmiany stawia na poczucie "smaku".&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Do czego porównać kod, który będzie samoopisujący się, którego zrozumienie nie wymaga zbyt wiele czasu - ba, wręczy czytamy to czego się spodziewamy?&lt;br /&gt;Dla mnie taki kod jest jak powieść. Kreujemy aktorów (klasy) o pewnych cechach osobowości (metody). Niektórzy są dwulicowi (interfejsy). Budujemy scenografię (warstwy, moduły) gdzie będzie rozgrywać się akcja. Nie jakieś śmietnisko, ale dobrze zorganizowany kompleks spójnych budowli. Dalej nie pozostaje już nic innego jak opowiedzenie ich historii, począwszy od stworzenia poprzez ew. reinkarnacje;) Bez zbędnych dygresji i wnikania w poboczne wątki - te nich dzieją się we wszechświatach równoległych dostępnych przez portale mangerów zdarzeń.&lt;br /&gt;&lt;br /&gt;Werbalizowanie historii może wydawać się bzdurne, ale zastanówmy się co nam daje. Aby np zbudować metaforę musimy włożyć pewien wysiłek umysłowy. Wypowiedzi w języku naturalnym są obłożone szeregiem ograniczeń - szczególnie ważne są ograniczenia logiczne. Dzięki nim możemy wychwycić luki w naszym rozumowaniu, pokraczne modele, cieknące abstrakcje. Ograniczenia werbalne pomagają w ogarnięciu chaosu. Można je nazwać nieformalnymi regułami walidacji poprawności koncepcji.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;//=======================&lt;br /&gt;&lt;br /&gt;Ktoś kiedyś napisał, że programistów można podzielić na 3 grupy. Tych, który mają dobry styl, tych który mają zły styl i tych, którzy w ogóle stylu nie mają.&lt;br /&gt;Ci drudzy nie są jeszcze straceni. Co prawda ich poczucie stylu jest złe, ale przynajmniej &lt;span style="font-weight:bold;"&gt;jakieś&lt;/span&gt; jest - przy pewnym wysiłku można je zmienić na dobre. Najgorsi są Ci, którzy w ogóle nie rozpatrują czegoś takiego jak styl - jest to poza ich zakresem pojmowania. Ci są straceni.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5197374494377847819-8877037992134385680?l=art-of-software.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://art-of-software.blogspot.com/feeds/8877037992134385680/comments/default' title='Komentarze do posta'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5197374494377847819&amp;postID=8877037992134385680' title='Komentarze (2)'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5197374494377847819/posts/default/8877037992134385680'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5197374494377847819/posts/default/8877037992134385680'/><link rel='alternate' type='text/html' href='http://art-of-software.blogspot.com/2009/05/understandability.html' title='Understandability'/><author><name>Sławek Sobótka</name><uri>http://www.blogger.com/profile/15082577671795313109</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='30' height='32' src='http://3.bp.blogspot.com/-tmFOhJC48_E/TkQ0G2DxrqI/AAAAAAAAAz8/WVGBaaS5a_Y/s220/zdjecie2.png'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5197374494377847819.post-1446516885169428965</id><published>2009-05-14T19:29:00.016+02:00</published><updated>2009-05-15T21:34:54.643+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Qi'/><category scheme='http://www.blogger.com/atom/ns#' term='Domain Driven Design'/><category scheme='http://www.blogger.com/atom/ns#' term='Research'/><category scheme='http://www.blogger.com/atom/ns#' term='linki'/><title type='text'>Risercz: DDD</title><content type='html'>W związku z natłokiem spraw nie mam czasu aby napisać coś bardziej sensownego na blogasku. Właściwie to problem nie tyle z samym czasem co z mózgiem obciążonym zbyt wieloma wątkami, co w rezultacie skutkuje zanikiem weny - czyli impotencją intelektualną (wszyscy pewnie znacie to uczucie nieprzyjemnego napięcia, które odbiera kreatywność).&lt;br /&gt;&lt;br /&gt;Aby jednak podtrzymać aktywność ucieknę się do prastarego triku i wkleję trochę linków, które ostatnio sobie przyswoiłem, i które to uważam za godne zauważenia.&lt;br /&gt;&lt;br /&gt;Będzie to jednocześnie pierwszy z nowej serii postów - raporty/streszczenia z riserczu.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Dziś będzie o (niespodzianka) Domain Driven Design. Dwa artykuły opisujące mniej lub bardziej techniczne aspekty DDD. Tak, wiem, że DDD to filozofia i technikalia nie są ważne, ale ktoś kiedyś jednak będzie musiał wziąć się do roboty i zaimplementować nasze prostokąty i strzałeczki;P &lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Na początek ciekawe kompendium technologiczne na temat domain driven DEVELOPMENT:&lt;br /&gt;&lt;a href="http://www.infoq.com/articles/ddd-in-practice"&gt;Domain Driven Design and Development In Practice&lt;/a&gt;.&lt;br /&gt;wszyscy narzekają, że owszem DDD fajne jest, ale jak tak na prawdę podejść do projektu? W treści znajdziemy wiele ciekawych pomysłów i alternatywnych koncepcji.&lt;br /&gt;Powyższy link jest co prawda Made in India, ale mimo tego jego treść jest rzetelna - poza tym marka infoq do czegoś zobowiązuje.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Dla odmiany teraz coś Made in Germany. Niestety odmiana ma charakter przede wszystkim jakościowy:/&lt;br /&gt;&lt;a href="http://www.javaworld.com/javaworld/jw-05-2009/jw-05-domain-driven-design.html"&gt;Domain-driven design with Java EE 6&lt;/a&gt;&lt;br /&gt;Oto jak kończy się aplikowanie prymitywnej platformy do zaawansowanej koncepcji - naiwna implementacja.&lt;br /&gt;&lt;br /&gt;Pomysł bram (gate) może i ciekawy... Na pewno wygodny z punktu widzenia programisty. Mamy oto coś na kształt stanowego servisu, który ma w sobie entity managera w &lt;a href="http://blogs.sun.com/enterprisetechtips/entry/extended_persistence_context_in_stateful"&gt;trybie rozszerzonym&lt;/a&gt;. Dzięki temu możemy sobie korzystać z lazy lodingu podczas ping-ponga pomiędzy klientem a serverem. Prawie jak konwersacje w seam:)&lt;br /&gt;I czy w ogóle jest o co walczyć? Ile czasu zaoszczędzę posługując się Lazy Loadingiem zamiast napisać sobie Repo, które będzie używane przez agregat w celu pobrania składników tegoż agregatu? A co z &lt;a href="http://art-of-software.blogspot.com/2009/04/lazy-loading-sprawa-wydajnosci.html"&gt;wydajnością Lazy Loadingu&lt;/a&gt;:P&lt;br /&gt;Podsumowując: życzę powodzenia przy nieco większej ilości użytkowników hehe&lt;br /&gt;&lt;br /&gt;Na uwagę zasługuje jednak nowy termin, który próbuje się ukuć "persistent domain object (PDO)" - podoba mnie się to:)&lt;br /&gt;PDO czyli &lt;a href="http://art-of-software.blogspot.com/2008/12/up-ddd-in-action-hermetyczne-agregaty.html"&gt;Agregat&lt;/a&gt; w sensie DDD (posiada stan i odpowiedzialność - metody biznesowe), który dodatkowo ubabrany jest adnotacjami JPA. Czyli wreszcie dojrzewamy aby odejść od proceduralnego rozdziału struktry danych od algorytmów (encje/servisy). &lt;br /&gt;Niestety taki agregat przesłany do warstwy UI ciągnie za sobą metody biznesowe, które nie powinny być dostępne w tej warstwie.&lt;br /&gt;Jednym z rozwiązań jest stworzenie 2 stosów warstw - opisane na końcu &lt;a href="http://art-of-software.blogspot.com/2009/03/undergroundowy-domain-driven-design.html"&gt;tego&lt;/a&gt; nudnego posta, innym są mixiny z frameworki &lt;a href="http://www.qi4j.org/"&gt;qi4j&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;//==========================================&lt;br /&gt;&lt;br /&gt;Na zakończenie ciekawa refleksja: &lt;a href="http://www.infoq.com/interviews/domain-driven-design-eric-evans#view_10448"&gt;http://www.infoq.com/interviews/domain-driven-design-eric-evans#view_10448&lt;/a&gt;. Nasze community nauczyło się wreszcie korzystać z podstawowych technik (które podobno istniały juz w latach 80 w Smalltalk) i wreszcie ukonstytuowały się pewne standardy z zakresu projektowania i architektury.&lt;br /&gt;&lt;br /&gt;W skrócie: community java powoli kończy etap &lt;span style="font-weight:bold;"&gt;&lt;a href="http://art-of-software.blogspot.com/2009/03/w-co-sie-bawic.html"&gt;onanizmu technicznego&lt;/a&gt;&lt;/span&gt; i można zacząć skupiać się na problemach na prawdę istotnych.&lt;br /&gt;&lt;br /&gt;Natomiast z komentarza tego znamienitego dinozaura &lt;a href="http://www.infoq.com/interviews/domain-driven-design-eric-evans#view_10653"&gt;http://www.infoq.com/interviews/domain-driven-design-eric-evans#view_10653&lt;/a&gt; wynika, że już prawie dotarliśmy tam, gdzie community &lt;a href="http://en.wikipedia.org/wiki/Smalltalk"&gt;Smalltalk&lt;/a&gt; było w latach '80...&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5197374494377847819-1446516885169428965?l=art-of-software.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://art-of-software.blogspot.com/feeds/1446516885169428965/comments/default' title='Komentarze do posta'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5197374494377847819&amp;postID=1446516885169428965' title='Komentarze (2)'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5197374494377847819/posts/default/1446516885169428965'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5197374494377847819/posts/default/1446516885169428965'/><link rel='alternate' type='text/html' href='http://art-of-software.blogspot.com/2009/05/risercz-ddd.html' title='Risercz: DDD'/><author><name>Sławek Sobótka</name><uri>http://www.blogger.com/profile/15082577671795313109</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='30' height='32' src='http://3.bp.blogspot.com/-tmFOhJC48_E/TkQ0G2DxrqI/AAAAAAAAAz8/WVGBaaS5a_Y/s220/zdjecie2.png'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5197374494377847819.post-2186869880325652828</id><published>2009-04-20T00:10:00.014+02:00</published><updated>2009-09-03T20:31:34.255+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Lazy loading'/><category scheme='http://www.blogger.com/atom/ns#' term='Hibernate'/><category scheme='http://www.blogger.com/atom/ns#' term='JPA'/><title type='text'>Lazy Loading a sprawa wydajności</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_m-NewLwJEb8/SeuJoKVmfvI/AAAAAAAAAYA/DJqzDmC_jrg/s1600-h/Leniwiec.jpeg"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 240px; height: 320px;" src="http://4.bp.blogspot.com/_m-NewLwJEb8/SeuJoKVmfvI/AAAAAAAAAYA/DJqzDmC_jrg/s320/Leniwiec.jpeg" border="0" alt=""id="BLOGGER_PHOTO_ID_5326502307358473970" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Podążając za ciągiem skojarzeń: od przedwczorajszego DAO przez wczorajsze Lazy Loading dziś czas na aspekt wydajności podczas korzystania z maperów relacyjno-obiektowych. Właściwie to główne niebezpieczeństwo tkwi w tytułowym Lazy Loadingu.&lt;br /&gt;&lt;br /&gt;Sprawa jest w sumie prosta - trzeba uważać co się robi i mniej więcej orientować się jak działa mapper. Nie trzeba wnikać nawet w aspekty implementacyjne Lazy Loadingu: klasy pośredników, które mogą być podstawiane do encji czy to poprzez manipulację byte codem czy w czasie generowania kodu źródłowego (jednak zainteresowanym polecam zgłębienie tematu - warto wiedzieć "jak oni to zrobili").&lt;br /&gt;&lt;br /&gt;Niestety na żadnej ze stron domowych maperów zgodnych z JPA (&lt;a href="http://www.hibernate.org/"&gt;Hibernate&lt;/a&gt;, &lt;a href="http://openjpa.apache.org/"&gt;OpenJPA&lt;/a&gt;, &lt;a href="http://edocs.bea.com/kodo/docs40/full/html/solarmetric_intro.html"&gt;Kodo&lt;/a&gt;, &lt;a href="http://www.oracle.com/technology/products/ias/toplink/index.html"&gt;TopLink&lt;/a&gt;) nie dopatrzymy się ani na głównej stronie, ani na żadnej innej wielkiego czerwonego napisu "UWAGA NA WYDAJNOŚĆ PODCZAS STOSOWANIA LAZY LOADING!". Nie uraczymy również zestawu paru prostych porad, które uchroniły by nas przed &lt;span style="font-weight:bold;"&gt;dramatycznym &lt;/span&gt;spadkiem wydajności. Czyżby nie wyglądało to zbyt marketingowo? Może autorzy sądzą, że ludzie tego nie zauważą i jakoś to będzie - kolejny bubel się przyjmie w społeczności:)&lt;br /&gt;&lt;br /&gt;Problem wydajności jest stary jak Hibernate ale niestety jeszcze nie wszędzie uświadomiony. Jako przykład podam tę oto przypowieść. &lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_m-NewLwJEb8/SeuLznvI1eI/AAAAAAAAAYQ/jSkIqi4o6FU/s1600-h/bushmen_kalahari_safari_botswana_reis1.jpg"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 240px;" src="http://4.bp.blogspot.com/_m-NewLwJEb8/SeuLznvI1eI/AAAAAAAAAYQ/jSkIqi4o6FU/s320/bushmen_kalahari_safari_botswana_reis1.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5326504703252026850" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Niezbyt_dawno, niezbyt_dawno temu w pewnej dużej organizacji strasznie mulił system wykorzystujący Hibernate. Ludzie ze swą wrodzoną skłonnością do tworzenia mitów szybko poradzili sobie z &lt;a href="http://pl.wikipedia.org/wiki/Dysonans_poznawczy"&gt;dysonansem poznawczym&lt;/a&gt; trapiącym ich mózgi: stworzyli sobie prosty system mitologiczny, który nakazywał im wierzyć, że ORMy tak po prostu mają. Po prostu ich magiczne właściwości powodują, że systemy spowalniają a odczyt danych z bazy jest hamowany jakąś niepojętą siłą. Ciemnotę dodatkowo potęgowała Kasta Adminów Baz Danych, mówiąc: "tak oto kończy się sprzeniewierzanie prastarej składni SQL. Nie chciało się wam niewierni pisać procedur i kwerend to teraz sczeźnijcie w piekle!".&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_m-NewLwJEb8/SeuKXWWkuNI/AAAAAAAAAYI/2jjjjLq3Xr4/s1600-h/faryzeusze.jpg"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 240px;" src="http://3.bp.blogspot.com/_m-NewLwJEb8/SeuKXWWkuNI/AAAAAAAAAYI/2jjjjLq3Xr4/s320/faryzeusze.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5326503118037629138" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Po wstępnych oględzinach okazało się, że w większości przypadków obarczonych bardzo niską wydajnością mamy do czynienia z klasycznym problemem występującym w ORMach z Lazy Loadingiem: &lt;span style="font-weight:bold;"&gt;n+1 Select Problem&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;Istotę problemy wyjaśnię na przykładzie: Wyobraźmy sobie, że pobieramy listę obiektów klasy Person. Następnie iterujemy po tej liście i dla każdej osoby wołamy getAddresses() po to aby coś tam z adresami każdej z osób zrobić. Jeżeli zapytanie wygląda mniej więcej tak: SELECT p FROM Person p to mam rzeczony problem. Najpierw silnik persystencji wysyła do bazy jedno zapytanie w celu pobrania listy osób. Następnie dla każdej z n osób wysyła zapytanie o jej adresy. W sumie n+1 zapytań:) Pięknie nieprawdaż? Niestety musimy pofatygować się i napisać &lt;span style="font-weight:bold;"&gt;porządne &lt;/span&gt;zapytanie HQL (lub odpowiednie Criteria w Hibernate), które spowoduje dodżojnowanie adresów do osób tak aby wysłane zostało do bazy jedno zapytanie SQL. Niestety nieodzowne będzie dopisanie w HQL paru JOIN FETCH - a co za tym idzie korzystanie z Entity Managera przestaje być takie trywialne jak w tutorialach, pojawia się złożoność, którą warto hermetyzować w DAO/Repozytorium.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Należy uważać również na "utajony" wariant n+1 select problem&lt;/span&gt;. W powyższym przykładzie mamy sytuację, w której radośnie iterujemy sobie przy pomocy własnego kodu po osobach i grzebiemy w ich adresach. Może być też tak, że nasz własny kod jest OK, ale niefortunnie podepniemy naszą listę osób pod np jakiś komponent GUI (np h:dataTable w JSF), który ma wyświetlić osoby wraz z adresami i nieszczęście gotowe. Logika renderingu tabelki przeiteruje po osobach aby wyrenderować jej adresy. Wówczas mogą zdarzyć się 2 rzeczy:&lt;br /&gt;- aplikacja się wywali z powodu LazyInitializastionException (lub jakiegoś innego wyjątku w zależności od dostawcy JPA - co zresztą uważam za skandaliczne) ponieważ najpewniej w warstwie widoku sesja będzie już dawno zamknięta&lt;br /&gt;- jeżeli jednak stosujemy jakiś trik typu &lt;a href="http://www.hibernate.org/43.html"&gt;Open Session In View&lt;/a&gt; to wówczas ORM radośnie wygeneruje nam n+1 zapytań do bazy:)))&lt;br /&gt;&lt;br /&gt;Pierwszy wariant (wyjątek) jest o tyle dobry, że przynajmniej zwróci czyjąś uwagę podczas devlopmentu i skłoni do napisania porządnego zapytania, które ładuje wszystkie dane w jednym podejściu. Drugi wariant działa więc jest szansa, że nitk nie sprawdzi co się dzieje po stronie bazy:/&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Kolejna przypowieść. W tejże samej organizacji istniał inny system, który również niemiłosiernie mulił. Tym razem był to gruby klient do serwera więc lazy loading nie miał zastosowania. Encje przesłane na klienta nijak nie chcą nawiązać kwantowego kanału z procesorem serwera:/ W tym systemie również panowała mitologia. Kiedyś pewien magik podobno zrobił czary mary i LazyInitalizationException nie pojawiał się gdy na kliencie wołano łańcuszki get get get.&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_m-NewLwJEb8/SeuPu0x7vjI/AAAAAAAAAYY/EZJkXxH99Iw/s1600-h/szaman.jpg"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 243px;" src="http://4.bp.blogspot.com/_m-NewLwJEb8/SeuPu0x7vjI/AAAAAAAAAYY/EZJkXxH99Iw/s320/szaman.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5326509018900577842" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Po krótkiej analizie problemu okazało się, że tym razem przedobrzono w inną stronę. Prawie wszystkie powiązania pomiędzy obiektami były EAGER - czyli chciwe lub jak kto woli łapczywe. Skutkowało wyciąganiem połowy bazy przy każdym zapytaniu. O ile serwer bazodanowy dawał radę to wąskim gardłem okazała się transmisja zserializowanych danych. Wniosek znowu ten sam: niestety na skróty się nie da - trzeba się pofatygować i napisać porządne zapytania specyfikując co w jakim Use Case ma być podciągnięte. Niestety zakorzeniona mitologia i szargana opinia o ORMach pozostanie w organizacji na parę następnych pokoleń.&lt;br /&gt;&lt;br /&gt;Przy okazji warto wspomnieć o kolejnej pułapce jaką szykuje na nas maper. Uwaga na powiązania typu n-1 lub 1-1 - czyli takie gdzie w klasie encji mamy pole klasy innej encji (np Person ma jeden Adres). &lt;span style="font-weight:bold;"&gt;Standard JPA zakłada, że wówczas powiązanie jest typu EAGER.&lt;/span&gt; Czyli pobierając z bazy osobę zawsze od razu wyciągniemy jej adres. Niestety odbywa się to zazwyczaj w osobnym zapytaniu. Czyli w przypadku pobierania listy osób mamy n+1 Select Problem:)&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Żeby nie było, Lazy Loading może również przydać się w celu optymalizacji systemu.&lt;br /&gt;Wyobraźmy sobie taki przypadek: Mamy klasę dokument, która zawiera szereg pół - w tym pole zawierając treść dokumentu: kilkadziesiąt stron A4 (pomińmy kwestię sensowności takiego projektu). Gdy chcemy zaprezentować listę dokumentów na GUI, która zawiera dajmy na to tytuł i datę to oczywiście zupełnie niepotrzebnie będziemy pobierać z bazy i przechowywać w aplikacji (choćby chwilowo) dziesiątki megabajtów tekstu. Jednym z paru rozwiązań ale najprostszym jest ustawienie leniwego ładowania kolumny z treścią. Gdy nie będzie potrzebne wówczas nie będzie ładowane z bazy.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;//============================&lt;br /&gt;&lt;br /&gt;Podstawą pracy z ORM jest &lt;span style="font-weight:bold;"&gt;konsola z logami&lt;/span&gt;. Podczas developmentu należy włączyć wyświetlanie generowanych poleceń SQL i nieustannie obserwować oczami swymi logi silnika ORM czy przypadkiem nie pojawia się na niej w pewnym momencie kilka/-dziesiąt/-set/-tysięcy zapytań. Oczywiście n+1 Select Problem możemy zauważyć na konsoli praktycznie tylko wówczas gdy napełnimy bazę większą ilością danych. Dla n=1 problemu raczej nie uraczymy.&lt;br /&gt;&lt;br /&gt;W dobrym procesie produkcji softu jest czas na takie coś jak &lt;span style="font-weight:bold;"&gt;kontrola kodu&lt;/span&gt; - przeglądanie nowego kodu przez bardziej doświadczonych członków teamu (lub chociaż przez drugą parę oczu). Co powiecie na &lt;span style="font-weight:bold;"&gt;kontrolę konsoli&lt;/span&gt;? Pokaż misiu jakie zapytania do bazy generuje Twój kod.&lt;br /&gt;&lt;br /&gt;Podsumowując dwie przytoczone przypowieści pozwolę sobie zacytować Franka Zappa: "Głupota ma pewien urok, ignorancja nie".&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5197374494377847819-2186869880325652828?l=art-of-software.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://art-of-software.blogspot.com/feeds/2186869880325652828/comments/default' title='Komentarze do posta'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5197374494377847819&amp;postID=2186869880325652828' title='Komentarze (4)'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5197374494377847819/posts/default/2186869880325652828'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5197374494377847819/posts/default/2186869880325652828'/><link rel='alternate' type='text/html' href='http://art-of-software.blogspot.com/2009/04/lazy-loading-sprawa-wydajnosci.html' title='Lazy Loading a sprawa wydajności'/><author><name>Sławek Sobótka</name><uri>http://www.blogger.com/profile/15082577671795313109</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='30' height='32' src='http://3.bp.blogspot.com/-tmFOhJC48_E/TkQ0G2DxrqI/AAAAAAAAAz8/WVGBaaS5a_Y/s220/zdjecie2.png'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_m-NewLwJEb8/SeuJoKVmfvI/AAAAAAAAAYA/DJqzDmC_jrg/s72-c/Leniwiec.jpeg' height='72' width='72'/><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5197374494377847819.post-9204251883698705956</id><published>2009-04-19T16:03:00.011+02:00</published><updated>2009-09-03T20:31:15.550+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Lazy loading'/><category scheme='http://www.blogger.com/atom/ns#' term='Hibernate'/><category scheme='http://www.blogger.com/atom/ns#' term='JPA'/><title type='text'>DAO a sprawa Lazy Loading</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_m-NewLwJEb8/SeszEZW2fjI/AAAAAAAAAX4/qgTABPLQ1oU/s1600-h/3-lazy-polar-bears.jpg"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 240px;" src="http://1.bp.blogspot.com/_m-NewLwJEb8/SeszEZW2fjI/AAAAAAAAAX4/qgTABPLQ1oU/s320/3-lazy-polar-bears.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5326407134914969138" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Wracając do wczorajszego tematu DAO rozwinę nieco kontekst mapowania relacyjno-obiektowego na przykładzie standardu &lt;a href="http://pl.wikipedia.org/wiki/Java_Persistence_API"&gt;JPA&lt;/a&gt;. Dokładnie - skupię się na głównym ficzerze każdego mapera zgodnego z JPA, czyli tytułowym &lt;a href="http://en.wikipedia.org/wiki/Lazy_loading"&gt;leniwym (opóźnionym) ładowaniem&lt;/a&gt; zagregowanych w encji obiektów.&lt;br /&gt;&lt;br /&gt;Niektórzy pewnie zastanawiają się czego znowu ten zgred się czepia. Przecież LL to taki fajny ficzer. Mamy sobie załadowany z bazy obiekt (i jeżeli sesja kontekstu perzystencji nie została zamknięta) to wystarczy zawołać na nim getXXX(), czary mary i pobrany przez getter zagregowany obiekt został podciągnięty z bazy oraz zapakowany do encji.&lt;br /&gt;&lt;br /&gt;Wszystko fajnie, ale jeżeli korzysta się z tego z świadomie i w odpowiednim momencie. W przeciwnym wypadku mamy spore problemy z wydajnością. Ale o tym za w następnym poście. Ja mam z tym jeszcze pewien problem natury filozoficznej, który pojawia się gdy do naszej architektury wprowadzimy warstwę DAO (bez której jak bez ręki - co chciałem wczoraj wykazać)...&lt;br /&gt;&lt;br /&gt;Zatem weźmy przykładowy interfejs DAO:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;public interface PersonDAO{&lt;br /&gt;  Person getPerson(Long id);&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Standard... zwykłe DAO (nie czas teraz na Repozytorium z DDD), zwykły klucz (nie czas teraz na UID czy klasę kluczą w dobrym stylu DDD).&lt;br /&gt;&lt;br /&gt;Dalej będzie oczywiście jedna z możliwych implementacji w JPA:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;public class JpaPersonDAO implements PersonDAO{&lt;br /&gt;  EntityManager em;&lt;br /&gt;  Person getPerson(Long id){&lt;br /&gt;    return (Person)em.find(Person.class, id);&lt;br /&gt;  }&lt;br /&gt;  ...&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Też standard, bez żadnego generic DAO czy innych klas bazowych, bez wnikania w szczegóły wstrzykiwania EM. Nie w tym rzecz, chodzi tak jak wspomniałem o problem natury filozoficznej, mianowicie:&lt;br /&gt;Co ja mam napisać w komentarzu metody getPerson() w interfejsie? (i od razy mówię, że banał typu "return returns person that has ID relevant do given id" mnie nie zadowala)&lt;br /&gt;&lt;br /&gt;Aby w komentarzu napisać prawdę, całą prawdę i tylko prawdę musiałbym popełnić coś takiego (po polsku będę komentarz pisał - wybaczcie):&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style:italic;"&gt;"&lt;br /&gt;Metoda zwraca osobę o zadanym ID. Drogi programisto-użytkowniku klas implmentujących ten interfejs, wiedz ,że niniejszy interfejs zawirea z tobą kontrakt o następujących warunkach:&lt;br /&gt;1. O ile korzystasz z implementacji DAO opartej o JPA to możesz się spodziewać tego, że:&lt;br /&gt;&lt;br /&gt;1.a Niektóre klasy obiektów zagregowanych w zwróconej instancji osoby zostaną zastąpione przez klasy specyficznych pośredników (np &lt;a href="http://www.docjar.net/docs/api/org/hibernate/collection/PersistentBag.html"&gt;PersistentBag&lt;/a&gt; w hibernate) więc niniejszy interfejs nie może zagwarantować Ci poprawnej pracy w środowisku rozproszonym (np aby wynik działa tej metody przesłać na zdalnego klienta musisz mu zapewnić odpowiednie biblioteki w odpowiednich wersjach).&lt;br /&gt;&lt;br /&gt;1.b Być może masz dostęp do obiektów zagregowanych w zwróconej instancji. Na przykład do adresu (przez metodę getAddress). Zależy to od tego czy znajdujesz się w miejscu, w którym jeszcze obowiązuje sesja kontekstu persystencji. Jeżeli sesja będzie zamknięta, a ty będziesz brzydko się bawił z instancją person to dostaniesz np &lt;a href="http://www.jdocs.com/hibernate/3.1.3/org/hibernate/LazyInitializationException.html"&gt;LazyInitializationException&lt;/a&gt; - ale tego w tym momencie nie mogę zagwarantować, gdyż zależy to od dostawcy (specyfiakcja JPA nic nie narzuca w temacie reagowania na zamkniętą sesję). Niestety niniejszy interfejs jest czystą abstrakcją dostępu do danych i nie mogę Ci zdradzić szczegółu na jakim dostawcy JAP będzie oparta implementacja tego interfejsu.&lt;br /&gt;&lt;br /&gt;2. Jeżeli implementacja tego interfejsu nie będzie oparta o JPA (a np o dostęp do web service albo pliku XML) to wiedz, że dostępu do żadnych zagregowanych obiektów nie masz.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;return &lt;/span&gt;osoba o zadanym ID, z którą ni cholery nie wiadomo co można na 100% bezpiecznie zrobić.&lt;br /&gt;"&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Ogólnie chodzi mi o to, że staroświeckie DAO i nowoczesny mechanizm Lazy Loadingu mają się nijak do siebie.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;//==================================&lt;br /&gt;&lt;br /&gt;Mamy tu do czynienia z bardziej ogólnym problemem: &lt;a href="http://en.wikipedia.org/wiki/Leaky_abstraction"&gt;przeciekającą abstrakcją&lt;/a&gt;. Szczegóły techniczne mappera relacyjno-obiektowego (takie jak lazy loading, problem z wygasłą sesją) literalnie wyciekają z interfejsu DAO, który powinien być czystą abstrakcją dostępu do danych niezależną od jakiś maperów. Innymi słowy klient (kod) interfejsu DAO musi być niestety świadomy pewnych "wyciekających" mechanizmów stojących za jedną z jego implementacji. Nie może jej traktować jako czarnej skrzynki, która robi to co ma robić - i robi to dobrze.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5197374494377847819-9204251883698705956?l=art-of-software.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://art-of-software.blogspot.com/feeds/9204251883698705956/comments/default' title='Komentarze do posta'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5197374494377847819&amp;postID=9204251883698705956' title='Komentarze (7)'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5197374494377847819/posts/default/9204251883698705956'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5197374494377847819/posts/default/9204251883698705956'/><link rel='alternate' type='text/html' href='http://art-of-software.blogspot.com/2009/04/dao-sprawa-lazy-loading.html' title='DAO a sprawa Lazy Loading'/><author><name>Sławek Sobótka</name><uri>http://www.blogger.com/profile/15082577671795313109</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='30' height='32' src='http://3.bp.blogspot.com/-tmFOhJC48_E/TkQ0G2DxrqI/AAAAAAAAAz8/WVGBaaS5a_Y/s220/zdjecie2.png'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_m-NewLwJEb8/SeszEZW2fjI/AAAAAAAAAX4/qgTABPLQ1oU/s72-c/3-lazy-polar-bears.jpg' height='72' width='72'/><thr:total>7</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5197374494377847819.post-132865455279907619</id><published>2009-04-18T19:26:00.011+02:00</published><updated>2009-04-19T21:24:50.844+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='wzorce architektoniczne'/><category scheme='http://www.blogger.com/atom/ns#' term='Hibernate'/><category scheme='http://www.blogger.com/atom/ns#' term='JPA'/><category scheme='http://www.blogger.com/atom/ns#' term='Architektura'/><title type='text'>DAO</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_m-NewLwJEb8/SeoSY-UQdaI/AAAAAAAAAXw/o2hEKbpWaAo/s1600-h/fakt-DAO.jpg"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 226px; height: 320px;" src="http://4.bp.blogspot.com/_m-NewLwJEb8/SeoSY-UQdaI/AAAAAAAAAXw/o2hEKbpWaAo/s320/fakt-DAO.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5326089729573156258" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Jak donoszą brukowce &lt;a href="http://pl.wikipedia.org/wiki/Data_Access_Object"&gt;DAO&lt;/a&gt; odeszło i zostało zastąpione przez &lt;a href="http://pl.wikipedia.org/wiki/Java_Persistence_API"&gt;JPA&lt;/a&gt;. Czy aby na pewno?&lt;br /&gt;&lt;br /&gt;Piotrek w &lt;a href="http://it-researches.blogspot.com/2009/04/warstwa-dao-przetrwa-atak-jpa-dzieki.html"&gt;swym poście&lt;/a&gt; (będącym niezłym zbiorem argumentów w dyskusji) wyraził zdziwienie pojawiającymi się od pewnego czasu głosami przeciwko DAO. Natomiast ja chciałbym dodać od siebie dodatkowo nieco typowej dla siebie irytacji spowodowanej wąskim spojrzeniem na problem pojawiającym się w głosach autorytetów z wielkiego świata.&lt;br /&gt;&lt;br /&gt;Problem potrzeby lub nie warstwy DAO nie jest oczywisty i zależy od kontekstu. Czasem DAO jest niezastąpione a czasem może lekko przeszkadzać. Ale na pewno pozbawione kontekstu autorytarne głosy typu "DAO bad" są bez sensu.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;DAO ma na celu separację logiki dostępu do danych od logiki biznesowej/aplikacji.&lt;br /&gt;Co nam to daje?&lt;br /&gt;Szeroką i sensowną listę podał Mario Gleichmann w swoim &lt;a href="http://gleichmann.blog.com/2054653/"&gt;poście&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Ja ograniczę się do paru z nich:&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;wynikającą z separacji możliwość podmiany sposobu dostępu do danych&lt;br /&gt;&lt;li&gt;wynikający z możliwości podmiany zwiększony poziom testability&lt;br /&gt;&lt;li&gt;reużywalność logiki dostępu do danych&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;Przyjrzyjmy się zasadności wylistowanych argumentów:&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Podmiana sposobu dostępu do danych&lt;/span&gt; - teoretycznie silny argument; praktycznie bezużyteczny. Jak często zdarzyła się Wam taka sytuacja? O ile bardzo często zmienią się (no w zależności od klienta) wariacje logiki biznesowej to zmiana źródła danych? O ile zmienną logikę biznesową warto &lt;a href="http://en.wikipedia.org/wiki/GRASP_(Object_Oriented_Design)#Protected_Variations"&gt;hermetyzować pod stabilnym interfejsem&lt;/a&gt; i jej wariacje enkapsulować we &lt;a href="http://en.wikipedia.org/wiki/Strategy_pattern"&gt;wzorcu strategii&lt;/a&gt; to robienie tego z dostępem do danych wydaje się nakładaniem gaci przez głowię. Chyba, że...&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Testowanie&lt;/span&gt; - separacja dostępu do danych od logiki biznesowej zwiększa dramatycznie poziom testability, czyli podatność kodu na testy. Tak podatność na testy - ponieważ &lt;span style="font-weight:bold;"&gt;nie każdy kod można łatwo testować&lt;/span&gt;.&lt;br /&gt;Jeżeli mam osobną klasę realizującą jakąś funkcjonalność biznesową oraz osobną klasę DAO odczytującą/modyfikującą dane to wówczas:&lt;br /&gt;- możemy poddać testom sam "komponent" DAO - co się oczywiście będzie rzadko zdarzać, więc ten argument się nie liczy;P&lt;br /&gt;- możemy testować samą logikę biznesową - na czas testów nasza logika może używać innej implementacji DAO (np takiej, która nie korzysta z bazy danych). Co na to daje?&lt;br /&gt;Testy logiki biznesowej są szybsze ponieważ nie tracimy czasu na operacje zapisu odczytu danych (których poprawność w tym momencie nas nie interesuje). Czas zapisu/odczytu potencjalnie może być stosunkowo długi, wystarczy wyobrazić sobie źródło danych, które jest bazą zawierającą miliony rekordów, gigantycznym plikiem, czujnikiem chemicznym, web servisem wykonującym się średnio 5 min. Zamiast 100000 testów na godzinę, możemy ich wykonać tylko 10 gdy będziemy ciągnąć za sobą bagaż dostępu do danych.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Reużywalność&lt;/span&gt; - posługiwanie się wprost EntityManagerem w kodzie biznesowym do pobierania encji (tak jak chcą tego piewcy śmierci DAO) jest pomysłem arcy-chromym. &lt;br /&gt;Kod w stylu&lt;br /&gt;em.find(Person.class, id)&lt;br /&gt;nie wygląda groźnie - nieprawdaż? &lt;span style="font-weight:bold;"&gt;Niestety jest on jednak typowy dla tandetnych turoriali na poziomie Hello World&lt;/span&gt;. W rzeczywistości jednak piszemy kwerendę ponieważ: &lt;br /&gt;- mamy dynamiczne zapytanie (np doklejamy WHERE person.name = 'xxx' o ile user wpisał imie, itp)&lt;br /&gt;- chcemy dociągnąć chciwie zagregowane obiekty (i nie życzymy sobie lazy loadingu gdyż nierzadko JEST ZŁY - o czym będzie w następnym poście)&lt;br /&gt;&lt;br /&gt;Nawet jeżeli w pierwszej iteracji nasze pobranie danych jest prostym find() to zwykle za miesiąc zmieni się w kwerendę. Nie chcemy zatem programować metodą Kopiego-Pasty. Dzięki istnieniu DAO możemy reużywać złożoną logikę zapytań oraz oczywiście zmieniać je w 1 miejscu.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Separacja&lt;/span&gt; dla mnie osobiście separacja kodu - choćby zapytania były trywialne albo totalnie niereużywalne jest wystarczającą zaletą przemawiającą za DAO.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Potrafię sobie wyobrazić, że żadne z powyższych uwarunkowań nie występują. Tzn:&lt;br /&gt;- nigdy nie zmieniamy źródła danych - co jest naturalne&lt;br /&gt;- nie testujemy kodu - nie oszukujmy się, taka jest rzeczywistość&lt;br /&gt;- nie mamy złożonych zapytań i logiki sklejania HQLa&lt;br /&gt;&lt;br /&gt;Wówczas możemy radośnie używać EntityManagera w kodzie biznesowym. Sugerowałbym jednak &lt;span style="font-weight:bold;"&gt;kompromis&lt;/span&gt;: wystarczą osobne klasy realizujące logikę dostępu do danych - bez abstrakcji: bez interfejsu, bez wstrzykiwania.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Wąski kontekst&lt;/span&gt;&lt;br /&gt;W bardzo prostych aplikacjach trzymanie się ściśle architektury z warstwą DAO niesie ze sobą pewnie narzuty i utratę prostoty. Mam tu na myśli niezbyt ambitne ale bardzo potrzebne na rynku i popularne aplikacje typu &lt;span style="font-weight:bold;"&gt;przeglądarka bazy danych.&lt;/span&gt; Po prostu łatwiej i taniej jest wyprodukować za 1 mln zł system, który w przeglądarce wyświetli tabelkę z listą kalesonów w hurtowni niż postawić samą bazę danych i przyuczyć pracowników z podstaw SQL;)))&lt;br /&gt;&lt;br /&gt;W tego typu systemach zwykle corowa funkcjonalność to ekrany z różnego rodzaju listami + kontrolki do wpisywanie kryteriów + button SZUKAJ. Do tego ekran podglądu i edycji.&lt;br /&gt;&lt;br /&gt;Najbardziej produktywne jest wówczas podejście minimalistyczne. Warstwa prezentacji tworzy obiekt Criteria i przesyła go niżej do wykonania. Przekombinowane podejście polegające na tworzenie warstwy DAO, która abstrahuje źródło danych zmusza nas również do abstrahowania od kryteriów wyszukiwania. GUI musi wysyłać jakieś DTO, które w DAO jest przepakowywane w Criteria. Generalnie: nakładanie gaci przez głowę.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Szerszy kontekst&lt;/span&gt;&lt;br /&gt;Dla kontrastu rozważmy hipotetyczny przykład skomplikowanego dostępu do danych.&lt;br /&gt;Wyobraźmy sobie, że w naszym systemie mamy użytkownika przechowywanego w 1 bazie danych. Z niewiadomych przyczyn jego zamówienia są przechowywane w innej bazie. Adresy tegoż użytkownika są pobierane z zewnętrznego systemu przez jakiś WebService.&lt;br /&gt;Załóżmy też, że w zależności od wdrożenia druga baza danych (ta z zamówieniami) oraz źródło adresów są zmienne.&lt;br /&gt;&lt;br /&gt;Podążając za DDD stworzylibyśmy agregat User oraz repozytorium UserRepository, które jest w stanie go zebrać i poskładać do kupy. Repozytorium mogłoby używać EntityManagera do pobrania encji User oraz dwóch DAO do pobrania zamówień oraz adresów z abstrakcyjnych źródeł. Problem dostępu do danych może zawierać w sobie również aspekt przepakowania obiektów z jednej domeny (np z innego systemu) do domeny innej.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Przykład powyższy może wydawać się nieco wydumany i przesadzony, ale w rzeczywistości tego typu spawy istnieją i nie należy o tym zapominać.  Chciałem tylko pokazać, że architektura dostępu do danych wcale nie jest trywialnym problemem jak przedstawia się to w niektórych materiałach lub (o zgrozo!) przez niektórych członków grup eksperckich JEE. Owszem często taki jest. Ale spektrum problemów jest szerokie i po specyfikacji platformy korporacyjnej spodziewalibyśmy się czegoś więcej.&lt;br /&gt;&lt;br /&gt;//==================================&lt;br /&gt;&lt;br /&gt;Na zakończenie pamiętajmy aby dobierać sobie młotek do problemu, a architekturę dostępu do danych do... też do problemu:)&lt;br /&gt;&lt;br /&gt;Sentencja Alberta Einsteina "Wszystko powinno być tak proste, jak to tylko możliwe, ale nie prostsze" może wydawać się trywialna, ale często o niej zapominamy.&lt;br /&gt;&lt;br /&gt;A do implementacji większości systemów i tak nie potrzeba żadnego JPA - wystarczy Excel + jakieś cwane makro... no może Access ostatecznie;P&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5197374494377847819-132865455279907619?l=art-of-software.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://art-of-software.blogspot.com/feeds/132865455279907619/comments/default' title='Komentarze do posta'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5197374494377847819&amp;postID=132865455279907619' title='Komentarze (3)'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5197374494377847819/posts/default/132865455279907619'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5197374494377847819/posts/default/132865455279907619'/><link rel='alternate' type='text/html' href='http://art-of-software.blogspot.com/2009/04/dao.html' title='DAO'/><author><name>Sławek Sobótka</name><uri>http://www.blogger.com/profile/15082577671795313109</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='30' height='32' src='http://3.bp.blogspot.com/-tmFOhJC48_E/TkQ0G2DxrqI/AAAAAAAAAz8/WVGBaaS5a_Y/s220/zdjecie2.png'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_m-NewLwJEb8/SeoSY-UQdaI/AAAAAAAAAXw/o2hEKbpWaAo/s72-c/fakt-DAO.jpg' height='72' width='72'/><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5197374494377847819.post-9112048662792134822</id><published>2009-03-30T20:49:00.014+02:00</published><updated>2009-03-30T23:35:22.801+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='paranoja'/><title type='text'>Inteligientny projekt</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_m-NewLwJEb8/SdEVT8NpDmI/AAAAAAAAAXo/ejEvKCyxcKQ/s1600-h/Audi_Avant_2015_02.jpg"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 213px;" src="http://4.bp.blogspot.com/_m-NewLwJEb8/SdEVT8NpDmI/AAAAAAAAAXo/ejEvKCyxcKQ/s320/Audi_Avant_2015_02.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5319056067226308194" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Ile kosztuje słaby i nieprzemyślany projekt?&lt;br /&gt;Na początku wydaje się być kusząco tani - kokodżambo i do przodu. &lt;br /&gt;&lt;br /&gt;Mimo iż dużo pisze się o zaciąganiu długu technicznego, o tym, że każda prowizorka i rozwiązania typu "na pałę" lub "byle jak - byle szybko" trzeba spłacić z nawiązką, to jakoś nie zawsze dociera to do świadomości.&lt;br /&gt;&lt;br /&gt;Nudzenie o zgubnych skutkach niestosowania się np do paru prostych zasad &lt;a href="http://en.wikipedia.org/wiki/GRASP_(Object_Oriented_Design)"&gt;GRASP&lt;/a&gt; czy &lt;a href="http://www.derickbailey.com/2009/02/11/SOLIDDevelopmentPrinciplesInMotivationalPictures.aspx"&gt;SOLID&lt;/a&gt; jakoś nie jest zbyt przekonujące - chyba jest zbyt abstrakcyjne. Obiektowe filozofowanie typu &lt;a href="http://en.wikipedia.org/wiki/Domain-driven_design"&gt;DDD&lt;/a&gt; ustępuje miejsca metodykom RÓB i WHISKY (Why the Hell Isn't Somebody Koding Yet).&lt;br /&gt;&lt;br /&gt;Aby zejść z poziomem abstrakcji i unaocznić problem w namacalny sposób zobaczmy na banalnym przykładzie pojazdu ile może kosztować (nie tylko pieniędzy ale i czasu oraz nerwów) słaby projekt.&lt;br /&gt;&lt;br /&gt;Weźmy taki oto trywialny problem jak wymiana żarówki przedniego światła mijania w naszym modelowym systemie, którym niech będzie pojazd osobowy pewnej szwedzkiej marki, produkowany w duńskiej fabryce na amerykański rynek lecz użytkowany w centralnej europie.&lt;br /&gt;&lt;br /&gt;/*&lt;br /&gt; * Śpieszę wyjaśnić nielicznym paniom &lt;br /&gt; * czytającym tego bloga, czym dla samca &lt;br /&gt; * jest wymiana żarówki w jego własnym samochodzie. &lt;br /&gt; * Otóż jest czymś co robimy SAMI - jest to &lt;br /&gt; * punkt honoru. &lt;br /&gt; * Zwracanie się z prośbą o pomoc do innego samca &lt;br /&gt; * w tej jakże błahej sprawie &lt;br /&gt; * jest czymś tak żenującym &lt;br /&gt; * jak prośba o podtarcie tyłka.&lt;br /&gt; * (Metafora może niezbyt elegancka, ale niestety &lt;br /&gt; * nie znajduję w swej prostackiej głowie&lt;br /&gt; * niczego co lepiej oddawało by wagę problemu)&lt;br /&gt; */&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Zaczyna się od tego, że system logów wyświetla na konsoli informację sygnalizującą błąd lewego światła mijania. Hmmm mamy system autodiagnostyczny - pewnie zaszyli testy integracyjne w bootloaderze. Naajz, zapowiada się bułka z masłem.&lt;br /&gt;&lt;br /&gt;Rozpoczynamy podejście do problemu jak rasowy informatyk. Nie informatyk, informatyk to obraźliwe słowo - coś jak konował albo znachor. Jak programista, tudzież developer lub inżynier oprogramowania. No więc zaczynamy od dokumentacji.&lt;br /&gt;&lt;br /&gt;Dokumentacja jest co prawda nieco lakoniczna w temacie interesującej nas wymiany żarówek, ale w sumie to dobrze. Tu nie może być przecież wielkiej filozofii; cieszymy się wręcz, że nie mamy zbyt wiele do czytania - czarno na białym, jeden rysunek, jedno zdanie. Proste. Taką dokumentację to ja lubię... ukazuje sedno problemu, bez zbędnego kontekstu. Heh to musi być proste jak instalacja windowsa.&lt;br /&gt;&lt;br /&gt;Pierwsze podejście do pracy na systemie. Dokonujemy wstępnych oględzin interfejsu użytkownika i już po paru próbach bezbłędnie lokalizujemy reflektory - na których to (jak wynika z dokumentacji) mamy za zadanie wykonać prace związane z maintenance. Właściwie to gwoli ścisłości interfejs użytkownika jest w środku. Na zewnątrz jest... hmmm powłoka (shell) mająca na celu separację użytkownika od podmuchów wiatru tudzież strug wody, która nie może się oprzeć sile grawitacji. Powłoka ma również na celu wywieranie wrażenia na &lt;a href="http://nonsensopedia.wikia.com/wiki/Blachara"&gt;blacharach&lt;/a&gt; - "osobnikach płci żeńskiej, dobierający sobie partnerów do prokreacji przez pryzmat samochodu jakim się poruszają" (że pozwolę sobie zacytować za nonsensopedią).&lt;br /&gt;&lt;br /&gt;Powłoka spełnia zatem zadanie &lt;a href="http://dddstepbystep.com/wikis/ddd/anti-corruption-layer.aspx"&gt;anticorruption layer&lt;/a&gt; (dosłownie chroniąc wnętrze przez rozkładem polegającym np na rdzewieniu) jak i warstwy servisów.&lt;br /&gt;&lt;br /&gt;Zajrzyjmy jednak pod maskę, czyli warstwę niżej. Pięknie...cóż za separacja modułów. Niestety tylko z prawej strony. Coś co na pierwszy rzut oka wydawało się eleganckim warstwowym systemem z separacją modułów, po dokładnych oględzinach okazało się chaotycznym układem. &lt;br /&gt;&lt;br /&gt;O ile instancja modułu oświetlenia zainstalowana prawej strony wydaje się być otwarta na prace utrzymaniowe to z lewej natomiast mamy kłębowisko &lt;a href="http://en.wikipedia.org/wiki/Spagetti_code"&gt;spaghetti&lt;/a&gt; w okolicach modułu wyświetlania fotonów w kierunku jazdy. Do tego stwierdzamy silny &lt;a href="http://en.wikipedia.org/wiki/GRASP_(Object_Oriented_Design)#Low_Coupling"&gt;coupling&lt;/a&gt; interesującego nas modułu z modułem chłodzenia - a dokładnie chyba z filtrem powietrza. &lt;br /&gt;&lt;br /&gt;Co do cholery ma filtr powietrza z reflektorem?!? Kto scalił je tak blisko, że nawet mała rączka junior programera nie wcisnęłaby się aby sięgnąć do interfejsu żarówki - że o jej implementacji nie wspomnę! Spójrzmy jeszcze raz do dokumentacji. O ironio! Radość sprzed paru akapitów wywołana prostotą dokumentacji obraca się w rozpacz. Na tych cholernych rysunkach nie ma pudła z filtrem obok reflektora! Jak się dobrać do żarówki? Teraz przydało by się nieco więcej kontekstu w dokumentacji. Co robić? Aaaaa!&lt;br /&gt;&lt;br /&gt;No ale może da cię coś obejść. Przecież nie pojadę z tym do warsztatu. Wyśmieją mnie. Minęło już 15 minut, czas na wunderwaffe - dekompilator, któremu nic się nie oprze - KOMBINERKI. Wspaniałe niskopoziomowe narzędzie, które obejdzie wszystkie zabezpieczenia. Metoda brute force. Wyciąganie flaków z core silnika aby zrobić nieco miejsca na ręczne prace utrzymaniowe. Hmm na moje oko jednak aby odłączyć moduł filtru powietrza należy iść dalej po zależnościach i wymontować połowę silnika. A przecież obok jest tyle miejsca. Nie możliwe aby zrobili to perfidnie - przecież to taka pożąda firma;)&lt;br /&gt;&lt;br /&gt;Kto to projektował?!? Inżynier praktykant?&lt;br /&gt;&lt;br /&gt;Sam tego nie zrobię, potrzeba guru od modułów oświetlenia z biegłą znajomością architektury (chyba burdelu) silników. Co za wstyd... może by tak wysłać żonę...&lt;br /&gt;&lt;br /&gt;Ale na guru trzeba pewnie czekać w kolejce. I koszt będzie 10 razy większy niż samej żarówki. Ale jak mus to mus - przecież żadna blachara nie zainteresuje się systemem z niesymetrycznym UI.&lt;br /&gt;&lt;br /&gt;Guru w pocie czoła przedarł się przez splątane niby-warstwy i po godzinie wymienił instancję żarówki oraz skompilował wszystko i zrobił deploy. Jeszcze tylko szybki test jednostkowy (szkoda, że po deployu:P) - tak dla formalności i bugfix można uznać triumfalnie za zakończony. Czas na commit faktury... Cholera - czerwony pasek! Yyyy to znaczy szara ściana - tzn żarówka nie świeci. Ponowna dekompilacja. Na szczęście udało się wykryć buga - spalona kostka. Szkoda, że w systemie występuje ona w egzotycznej wersji HB4 - jesteśmy uzależnieni od jednego dostawcy:/&lt;br /&gt;&lt;br /&gt;Podsumowując&lt;br /&gt;problem: wymiana 1 żarówki&lt;br /&gt;czas: 2h&lt;br /&gt;koszt: przemilczę&lt;br /&gt;przewidywane problemy: wymiana 3 innych żarówek w lewym reflektorze w najbliższym czasie oraz związane z tym poczucie beznadziejnej bezradności:)&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;//===========================&lt;br /&gt;Oczywiście nie wymagam absurdu polegającego na tym, że każdy kawałek systemu będzie niezależnym modułem czekającym na łatwą podmianę. Core to core - niektóre kawałki są silnie zespojone bo taka jest natura problemu - jestem w stanie to zrozumieć. Nie potrzebuję przecież zbyt często wyjmować skrzyni biegów, ale żarówka - przecież to podstawa.&lt;br /&gt;&lt;br /&gt;Nie wymagam też niczego szczególnego typu otwartość na rozbudowę (np możliwość wymiany reflektorów na lasery służące do strącania pojazdów poruszających się nieskrajnie prawym pasem;). Chodzi o zwykłe i podstawowe czynności maintenance.&lt;br /&gt;&lt;br /&gt;Chyba, że biznes polega na serwisie:)))&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5197374494377847819-9112048662792134822?l=art-of-software.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://art-of-software.blogspot.com/feeds/9112048662792134822/comments/default' title='Komentarze do posta'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5197374494377847819&amp;postID=9112048662792134822' title='Komentarze (4)'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5197374494377847819/posts/default/9112048662792134822'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5197374494377847819/posts/default/9112048662792134822'/><link rel='alternate' type='text/html' href='http://art-of-software.blogspot.com/2009/03/inteligientny-projekt.html' title='Inteligientny projekt'/><author><name>Sławek Sobótka</name><uri>http://www.blogger.com/profile/15082577671795313109</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='30' height='32' src='http://3.bp.blogspot.com/-tmFOhJC48_E/TkQ0G2DxrqI/AAAAAAAAAz8/WVGBaaS5a_Y/s220/zdjecie2.png'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_m-NewLwJEb8/SdEVT8NpDmI/AAAAAAAAAXo/ejEvKCyxcKQ/s72-c/Audi_Avant_2015_02.jpg' height='72' width='72'/><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5197374494377847819.post-4774062029761476538</id><published>2009-03-18T23:55:00.007+01:00</published><updated>2009-03-19T21:21:23.467+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Homo sum...'/><category scheme='http://www.blogger.com/atom/ns#' term='kognitywistyka'/><title type='text'>Piękny umysł</title><content type='html'>W dzisiejszym poście będę chciał zachęcić grono ponad pół tysiąca czytelników do zainteresowania się czymś z goła innym niż dwurdzeniowa maszyna z zainstalowanym jakimś systemem operacyjnym a na tym JVM i server JEE. Jest coś, co może okazać się jeszcze ciekawsze - Mózg.&lt;br /&gt;&lt;br /&gt;Do napisania posta zainspirowała mnie wizyta na &lt;a href="http://kognitywistyka.net/~dm4/"&gt;Czwartych Dniach Mózgu&lt;/a&gt;. Przy okazji zachęcam wszystkich mieszkańców naszej krainy pszenicy i buraka do skorzystania z okazji i zawitania na konferencji. Mimo backgroundu uczelni organizującej konferencję zapowiada się na prawdę interesująco;)&lt;br /&gt;&lt;br /&gt;Dziś na ten przykład na warsztacie Dr Krzysztofa Stachyra (muzykoterapeuty) dowiedziałem się wielu ciekawostek na temat oddziaływania muzyki na mózg. Pouczające było doświadczenie różnic percepcji muzyki przez indywidualne jednostki jak i różnic zależnych od np pory dnia. Kilkadziesiąt osób na sali, słuchamy fragmentu utworu po czym okazuje się, że dla części uczestników był on relaksujący a dla innych irytujący, dla jeszcze innych pobudzający. Niesamowite... a człowiek dziwi się, dlaczego inni krzywią się gdy puszczam im Boysów;)&lt;br /&gt;&lt;br /&gt;Jaką muzyką uraczyć kogoś kto jest nastawiony agresywnie - lub ogólnie: pod wpływem stresu? Spokojną i relaksacyjna? Okazuje się, że jest to zła odpowiedź:P Wyjaśnienie niesie nam neuropsychologia. Lepiej jest zastosować muzykę, która podniesie poziom stresu - np. wymagającą skupienia uwagi lub stymulującą. Doprowadzi do do szybkiego osiągnięcia maximum napięcia, po którym następuje "przebranie się miarki" i ulga. Przy innym podejściu wysoki (ale nie max) poziom utrzymywałby się stosunkowo długo.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Ciekawe doświadczenie pracy własnego mózgu przeżyła Jill Bolte Taylor (&lt;a href="http://www.ted.com/index.php/talks/jill_bolte_taylor_s_powerful_stroke_of_insight.html"&gt;aktualnie prezentacja #2 na TED&lt;/a&gt;). Sama będąc neuro-naukowcem przeżyła udar mózgu - opowiada o swych doświadczeniach gdy jed
