manžel a otec, analytik & programátor z říše JVM, petrolhead (aktuálně s příchutí saabistickou), nárazově i fotograf, závislák na hudbě, jablečná ovce, milovník minimalismu (skoro) ve všech jeho podobách
google reader ~ delicious ~ youtube ~ deviantart ~ vimeo ~ mixcloud ~ soundcloud ~ flickr
e-mail: daniel.kvasnicka.jr@gmail.com
I'm a software developer with experience in writing properly architected server-side applications using the JVM platform (Spring and/or Java EE 6).
Clojure / ClojureScript enthusiast hooked on the renaissance of the functional programming paradigm.
Some client-side experience included - JS, jQuery, AngularJS, CoffeeScript.
Experience with native XML db (BaseX - XQuery, XSLT, RESTXQ), graph-oriented databases (Neo4j), MongoDB.
Practical experience with ElasticSearch.
Currently in an engineering team for Vendavo pricing solution.
As a freelancer, I'm looking for interesting software development projects to further advance my experience with the tools I use in my day job (internet / intranet applications)
Designing and implementing the web (and sometimes business) tier for Java EE applications.
CoffeeScript is something that I’ve watched for a very long time and my first attempt at using it in a project was early in its development and while I wanted to commit patches, reading some of the conversation around the purpose and overall goals made me realize that I simply see JavaScript…
Utvítnul jsem si o tom, jak se mi s CoffeeScriptem lépe dýchá, v porovnání s psaním v JavaScriptu, načež se mi v jedné z odpovědí dostal do ruky výše citovaný odkaz.
Jelikož se poslední dobou pohybuju docela dost ve vodách funkcionálního programování (což neznamená, že nemám rád to objektové - tak jak ho Alan Kay kdysi přivedl na svět), zaujal mě kontext oné kritiky. Autor v zásadě argumentuje, že Coffee tahá do funkcionálního JS ošklivé káčátko ve formě klasického objektového programování.
Nechci polemizovat s kritikou deklarace klasických tříd v Coffee - sám tam tento konstrukt zatím nepoužívám a pokud to půjde, ani nebudu. Chápu, že jak to teď je, je to do JavaScriptu tak nějak násilím vlepené. Chtěl bych se spíš zamyslet nad tím, jak podobně “typoidní” přístup k OOP může i v primárně funkcionálních jazycích být k dobru (tedy zda je opravdu prototypová dědičnost jediným funkcionálně-programátorsky akceptovatelným pojetím objektů) a zda je JavaScript skutečně takovým funkcionálním klenotem v porovnání např. s Ruby a Pythonem, které autor ke konci článku tak trochu shazuje (Ano, vím, že Leon je Ruby ninja…).
V první řadě je třeba říci, že souhlasím s tím, že “fat arrow” (=>) v Coffee rozhodně nepřispívá k funkcionálnímu psaní a akorát ulehčuje programátorovi ušpinění čistých funkcí (pure function) plozením levobočků a tím narušení referenční transparentnosti. Nesedí mí ale následující kritické zvolání:
What good does it to force it into an “Animal” type that extends another and another and so on?
Jakou, že to má výhodu? Stačí se podívat na skutečné funkcionální jazyky, tedy např. Common Lisp nebo Clojure. CLisp má CLOS (Common Lisp Object System - možná znáte slavný výrok Alana Kaye o tom, že jediné dva objektové jazyky jsou podle něj Lisp a Smalltalk), Clojure má k dispozici kompletní typový systém JVM plus pár vlastních třešniček. Oba jazyky díky tomu umí funkční polymorfismus, neboli multiple dispatch pomocí takzvaných multimetod.
V Common Lispu:
(defgeneric skin (a))
(defmethod skin ((a Cat)) (skin-a-cat a))
(defmethod skin ((a Dog)) (skin-a-dog a))
Něco jako přetěžování metod v Javě, akorát ve funkcionálním hávu a samozřejmě, na rozdíl od Javy, plně dynamické. V případě Clojure je toto obohaceno ještě o mnoho vychytávek - “alternativy” (funkce) lze za běhu odstraňovat z výběru, lze je manuálně prioritizovat a nakonec nejsou vybírány zdaleka jen na základě typů, ale lze použít tzv. “dispatch functions”. Představte si to jako kdyby alternativu v Javě nevybíral kompilátor, ale byla vybrána za běhu na základě výsledku zcela libovolně definované funkce. Dále pak lze dispatchovat na základě hierarchií - prostě nedefinujete třídy, ale tvoříte primitivní hierarchii klíčových slov. Možnosti jsou nekonečné.
Samozřejmě lze namítnout, že v JavaScriptu by se podobná funkcionalita dala také dodat, nějakou knihovnou např. Ano, dala. Pogooglete a zjistíte, že stačí jen pár desítek řádků strašně ošklivého kódu (subjektivní vsuvka) a je to doma. Ovšem - s největší pravděpodobností pak budete muset ustoupit z puristické prototypové dědičnosti, která říká, že objekt se konstruuje buď poděděním prototypu a nebo “z vody” - { name : Daniel }. Jak v takovém světě dosáhnete rozumného funkčního polymorfismu bez vázání funkcí na konkrétní instance? A nalejme si čistého vína - když se podíváte na dnešní svět JS, prakticky všude uvidíte, že je pojmenovávání “objektů” - tedy jistá typovost - naprosto běžné. Tvrdá obhajoba prototypové dědičnosti tedy v tomto případě neobstojí. (Legrační je, že autor na konci článku nabádá, abyste se šli naučit Clojure, pokud jste funkcionálnem nepolíbeni…)
Ještě pár myšlenek k Pythonu, Ruby a JS. Základní FP výbavu mají všechny. Lambda, funkce vyššího řádu, žádný z nich vás nenutí ke zvěrstvům typu public static void main. Ale jednou ze zásadních věcí, které přispívají k dobrému funkcionálnímu programování a absenci postranních efektů, je neměnnost. Clojure je v tomto velmi tvrdý jazyk (výrazně tvrdší než božský Common Lisp a je to dobře), prakticky vše je persistent a tedy immutable. Python má datový typ tuple, což je neměnná sekvence ne nepodobná takové, jakou najdete v Clojure. Ruby má kouzelné slovíčko freeze, které umí zmrazit prakticky cokoliv, tedy i kolekci (Rubyisti, kdyžtak mě opravte, kdybych tu něco plácnul, co není pravda…). A JavaScript? Tak určitě. Nějaké knihovny na webu najdete… Třeba kásnou mori, která vám umožní používat v JS struktury z ClojureScriptu (od jednoho z überclojurianů, Davida Nolena). Ale ten jazyk s tím nepočítá. FP my ass! Další z věcí, které ve mě podporují představu JavaScriptu jako jednoho velkého bastlu, je implementace slavného funkcionálního tria map, reduce a filter. Je dost solidně zprasená a ukazuje srážku funkcionálního a objektového světa v plné rychlosti. Minimálně v Pythonu jsou tyhle věci regulérní čisté funkce, v Ruby bych tipoval, že taktéž. Takže je JS něco, čím by se funkcionální programátor měl chlubit…?
Nechci popírat genialitu Douglase Crockforda nebo tvrdit, že v JavaScriptu nelze psát slušný funkcionální kód. Jde to, stejně jako v Coffee, Pythonu či Ruby. A stejně tak ve všech těch jazycích napíšete kód, při jehož běhu se bude Alonzo Church točit v hrobě jak na kolotoči a jestli máte dědičnost prototypovou a nebo class-oriented programming, to už na tom mnoho nezmění…
No software abstraction can reduce the inherent complexity of a problem, but it can reduce the complexity overhead, making it possible for engineers to build complex systems faster and with fewer bugs.
…
Unfortunately, OOP doesn’t inherently solve the flaws of procedural programming; it merely sweeps and bounds them under many small rugs. Within the boundaries of an object, OOP code tends to fall back to old procedural habits.
Vždy, když se seběhne nějaká nemilá událost týkající se střelných zbraní, svět hromadně ztratí schopnost racionálně uvažovat a rozhodne se řešit situaci emocionálně. Nejinak tomu bylo i v případě střelby v americkém Newtonu. Tohle médii podporované globální zblbnutí mě vždycky namíchne - snad proto, že v něm nejde jen o zbraně, ale o celkem základní lidské hodnoty a podstatu fungování společnosti vůbec.
K stvoření tohoto malého soupisu mi tedy daly impuls jednak neproduktivní přestřelky na Twitteru a také potřeba si sám pro sebe důležité informace nějak poskládat a zařadit.
Nenechte se zmást - obhájci zákazů často používají data, ale umí je vyzobat tak, aby to na první pohled implikovalo nutnost zakázat i vzduchovky… Jde to až tak daleko, že někteří lidé jsou schopni na jednu osu grafu vynést počet legálně držených střelných zbraní v USA a na druhou počet smrtí způsobených střelbou - z legální zbraně, z nelegální, sebevraždy, sebeobrana(!!!), prostě všecho - a vydávat to zcela vážně za argument.
Snad ještě vyšším levelem nechutnosti je cílená démonizace držitelů legálních střelných zbraní, navzdory všem faktům (viz. níže) - http://zpravy.ihned.cz/svet-usa/c1-59024150-kdo-ve-vasem-okoli-muze-mit-zbran…. Jistě, ta data jsou de fakto veřejná, ale všichni víme, že o to tu nejde… Jde tu o “bububu, soused má asi zbraň - je nebezpečný!”
Racionalito, logiko a fakta - z cesty! V páchání dobra nám bránit nebudete!
Co do palných zbraní — v USA mají civilisté zhruba 250 milionů zbraní. Každý rok se takovou zbraní ubrání 2.500.000 obyčejných lidí jako vy nebo já, kteří tak zastaví zločince. A zneužito k vraždění je ročně 9146 zbraní*. Tedy, ještě jednou: 250 milionů zbraní — 2,5 milionu zachráněných životů — 0,009 milionů zmařených životů.
Mimochodem, až do pondělí patřilo smutné prvenství v počtu obětí (23) šíleného střelce incidentu z roku 1991 v Texaském Killeenu. V místní restauraci tehdy seděla i pozdější texaská zákonodárkyně Suzanna Hupp - a sledovala, jak šílenec popravuje její rodiče. Svoji zbraň nechala v autě, protože jí tak přikazoval nový zákon.
„The most foolish mistake we could possibly make would be to allow the subject races to possess arms. History shows that all conquerors who have allowed their subject races to carry arms have prepared their own downfall by so doing.“ - Adolf Hitler, 1942
Zatčení pana Ratha vyvolalo ve společnosti takové vzedmutí emocí, vtipů a pozitivních očekávání, jako žádná jiná politická hra poslední doby. Chtěl bych se zaměřit hlavně na tu věc poslední - pocit, že jsme ne začátku velkolepého masakru korupčníků, který konečně vyčitstí politiku a udělá z naší země místo k žití. Na můj vkus příliš optimistický je třeba i Tomáš Sedláček. Je mi líto, ale obávám se, že se nic podobného konat nebude.
Proč? Protože systém. Není možné nijak výrazně potlačit korupci v systému, který je postavený na masivním přerozdělování peněz. Jedna věc je takový systém na úrovni státu, druhá na úrovni totálně odosobněného socialistického rádobysuperstátu - EU. Dotace se zneužívaly, zneužívají a zneužívat budou, dokud bude Země kulatá. Žádní kontroloři nepomůžou. Pouze zvýší počet nákladných byrokratických vrstev o 1 a opět přidají jeden díl ze seriálu “Who watches the watchers?”
Proč tedy ten humbuk a proč vůbec Ratha sebrali? Když pomineme (reálnou) možnost, že měl prostě někdo jenom na pana doktora pifku a potřeboval se ho zbavit, zůstane nám jiné vysvětlení, realističtější. Bylo prostě třeba obětního beránka. Jak na to? No prostě někoho, kdo nám není zrovna moc příjemný a případě nám ještě krade to, co jsme si chtěli ukrást my, odděláme. Dav se uslintá blahem a my budeme mít zas na pár let klid, abychom dokončili rozdělanou práci… Ideální řešení. Dva vlci se nažrali, zabily se dvě mouchy, ale koza je pořád celá!
Nenechme ze sebe dělat blbce. Plevel lze odstranit jen jedním způsobem. Drastickým omezením přerozdělování financí.
“A wise and frugal government… shall restrain men from injuring one another, shall leave them otherwise free to regulate their own pursuits of industry and improvement, and shall not take from the mouth of labor the bread it has earned. This is the sum of good government.”
— Thomas Jefferson
Chtěl jsem tuhle informaci jen tweetnout, ale zas tak krátká není :)
Návodů, které popisují to, co je předmětem nadpisu, je kupa, např. tento. Hodně jich ale zmiňuje (už) špatný odkaz na slovníky. Od OpenOffice 3.0 jsou slovníky distribuovány jako extensions a proto je třeba dané rozšíření pro OOo stáhnout (ano, OS X používá stejný formát slovníků).
Nebojte se přípony OXT, je to jen maskovaný ZIP. Stačí přejmenovat, rozbalit a soubory AFF a DIC, které jsou v návodu zmiňovány, tam najdete.
Tak jsem se konečně dokopal zpracovat fotky z červencové služební cesty do USA (Vendavo), tedy spíše z těch jejích částí, které neměly s prací nic společného… Co taky fotit na ajťákově práci, žejo :)
Před pár dny jsme se s kolegy z JetMinds vrátili z příjemného výletu do polského Krakowa, kde se konala javistická konference GeeCON 2011. Z Ostravy jsou to do Krakowa dvě hodinky jízdy autem, takže takovou akci nešlo ignorovat. Vrátili jsme se informačně bohatší a já se pokusím něco málo z toho bohatství převést do psané formy…
Organizačně byla akce více méně povedená. Vytknul bych akorát ne zcela ideální kuchařské výkony (v případě obědů) a také nemožnost si k obědu sednou někde ke stolu, když už to jídlo tedy dávali na normální keramické talíře… posedávání na schodech před kinem nebo jezení ve stoje není ideální. Při příjezdu nám také trochu vadilo, že neexistovala žádná vizuální navigace, která by alespoň lehce řidiče na GeeCON směrovala (TomTom není všemocný). To je ale asi konec výčtu negativ. Pojďme na dojmy z toho, kvůli čemu jsme tam jeli.
University Day
Naše první kroky směřovaly na přednášku Paradoxes of API Design od Jaroslava Tulacha. Věci, nad kterými se zamýšlel, byly zajímavé, ale celkově mi přednáška připadla dost chaotická. Skákání od myšlenky k myšlence, cesta tak trochu odnikud nikam… Zaujalo mě ale dělení uživatelů API do různých skupin, hlavně tedy skupina největší — “clueless”, aneb uživatel API v lazy módu, což ovšem nutně není špatně. Jde o to umět se přepnout do “educated” módu, když je třeba.
Dále jsem se zašel mrknout na tutoriál k Liftu (webový framework pro jazyk Scala). Lift sám o sobě je framework pěkný, hlavně templatovací systém se mi líbil, protože využívá 100% (X)HTML, resp. atribut class a nevymýšlí žádnou šílenou syntaxi. Scala mě ale nijak zvlášť nebere a tak jsem ještě zaskočil na tutoriál k Javě EE 6. EE 6 mě zaujala už před časem. JSF 2(!) mě celkem baví, EJB 3.1 už jsou taky použitelné, stejně jako CDI. Tutoriál neukazoval pro mě nic extra nového, ale minimálně bylo zajímavé poslouchat Antonia Goncalves — energický speaker. Pokud chcete opravdu pěkný popis toho, co je nové např. v JSF 2, doporučuji tento článek. EJB 3.1 dále éjébéčka zjednodušují a zpřístupňují běžným smrtelníkům — méně interfaců, jednodušší konfigurace, singleton beans, možnost deployi v obyčejném WARu, lepší timer service atp. CDI (IoC/DI kontejner) mě zaujalo asi nejvíce, ale zmíním se o něm více později. Důležité je také dělení EE 6 na edice Full a Web. Ovšem výběr co kam bude patřit už tak skvělý není — absence timeru ve Web profilu je bolestná a těžko bude lidi lákat od Springu, kde je periodické souštění jobů samozřejmostí.
Pak jsme zaskočili na přednášku Code Generation on the JVM, kde Hamlet D’Arcy ukazoval různé technologie pro generování kódu v Javě a jazycích postavených na JVM, primárně kvůli zjednodušení kódu. Nejvíce mě zaujal Lombok, který umí např. dogenerovat gettery a settery pro properties dané třídy a další různé praktičnosti. Všechno to ale stojí a padá na tom, že bez podpory v IDE pak ztrácíte doplňování kódu a taky se vám zdrojáky zalijou červenou barvou, protože ty metody tam prostě chybí… Zatím existuje, pokud vím, podpora pro klasický Java kompiler a pro Eclipse. Dokud by něco takového nebylo součástí oficiální Javy, asi bych se do toho moc nehrnul…
No, a to byl konec dne 1. Tedy skoro. Pokračovali jsme večerní procházkou po historickém centru Krakowa, které je opravdu impozantní a večeří+party v jistém klubu na hlavním náměstí. Hned v klubu vedlejším jsme pak mimochodem narazili na moc povedený koncert…
Conference Day 1
Den dva byl de fakto dnem jedna samotné konference. První dvě přednášky byly celoplošné, ve velkém sále. Nejdříve povídání o Javě SE 7 (i 8) a o tom, co (konečně) přinese. Asi nemá smysl, abych to tu vypisoval všechno, když už teď je toho plný internet. Zmíním ale věc, která je podle mě nejdůležitjší — optimalizace střev JVM cílené na běh programů v jazycích nad JVM napsaných (Groovy, Clojure, Scala…). Oracle si evidentně uvědomuje, že s Javou nepřesekne každou větev a že je třeba podporovat i alternativní jazyky, aby JVM zůstala relevantní technologií i ve vzdálenější budoucnosti.
Dále pak nastoupil Juergen Hoeller (jeden z autorů Springu) s obšírně nazvaným povídáním Enterprise Java in 2011 and Beyond: From Java EE 6 to Cloud Computing. Cítil jsem z toho názvu marketingovou nakládačku z dílny VMWare/SpringSourcu a v zásadě jsem se ani moc nemýlil :) Došlo i na rýpavé poznámky na adresu EE 6, což trošku zvířilo vody na Twitter hashtagu #geecon :) Na Javě EE je toho samozřejmě dost, co lze kritizovat a EE 6 v mnoha věcech skutečně pouze dohání rozjetý vlak (a jinak to ani při “design by committee” být nemůže), ale rozhodně je to zajímavý technologický stack (místy i originální) a ignorovat ho nelze. Pocit, že Spring je silver bullet a nic více netřeba, není k ničemu.
Poté jsem se vypravil na povídání dalšího springaře, tentokrát na téma The Social Service Bus. Doufal jsem, že uvidím nějakou pěknou ukázku integrace se sociálními sítěmi za pomoci Springu (který takové věci umí jak přes Spring Social, tak přes Integration), ale dočkal jsem se spíše převyprávění dokumentace a dokonce i slidu na téma “Co to je Twitter” …WTF?
Pak jsme zase mrkli na Juergena a jeho Modern Component Design with Spring 3.1, kde ale z velké části probíral věci dostupné už v 3.0. Každopádně bylo fajn slyšet některé věci (rozdělení sémantiky anotací, jejich funkce) vysvětlené od člověka, který framework prakticky stvořil.
Nikita Ivanov pak mluvil o celkem zajímavé gridové technologii GridGain a hlavně ji prakticky předvedl bez jakéhokoliv předpřipraveného příkladu — což hezky ilustrovalo relativně plochou učící křivku a schopnosti téhle technologie. Jednotlivé nody, které umí běžet všechny v jedé jediné JVM, se spolu velice inteligentně samy baví a hlavně jsou schopné se automaticky ujmout práce, která zůstane po (třeba i násilně) ukončeném nodu.
Jak jsem už zmínil, celkem mě zaujalo CDI (JSR-299, ref. implementace JBoss Weld), o kterém v další přednášce mluvil Antonio Goncalves. Zajímavá věc je to především proto, že je to součást EE 6, která je ale použitelná v jakémkoliv servlet kontejneru (i na Google App Engine), bez nutnosti plnohodnotného aplikačního serveru. Princip je stejný jako u Springu — ServletContextListener. CDI je v podstatě Inversion of Control (Dependency Injection) kontejner podobný Spring IoC, Guice a podobným. Zajímavá na něm je 100% typesafe injekce — ani kvalifikátory na beanách nelze mít textové jako ve Springu a tím pádem je vše velmi jednoduše refaktorovatelné. Na druhou stranu je třeba vše při změnách kompilovat a je to také neatraktivní pro milovníky XML, jelikož v něm beany wirovat nelze. Je určeno pouze pro základní konfiguraci alternativ bean stejného typu, nastavení exclude/include patternů atp. To druhé zmiňované je důležité, jelikož Weld je dosti agresivní a jakmile najde POJO, které má někde v sobě @Inject, automaticky ho samotné bere jako beanu a už ho tvoří… pokud tedy chcete mít např. kontrolery vašeho oblíbeného MVC frameworku, jejichž životní cyklus spravuje framework sám, je třeba Weld plácnout přes prsty, ať ty třídy nechá napokoji a pak si je owirovat ručně v rámci životního cyklu v tom webovém frameworku (v podstatě jako s jakýmkoliv jiným IoC udělátkem). Pro uživatele JSF je to jednodušší, jelikož Faces s CDI automaticky počítají a pokud běží oba v jedné aplikaci, není třeba Faces nijak instruovat, aby beany našly (na rozdíl od ELResolveru v případě Springu) — ověřeno na Google App Enginu s JSF 2. Další velmi lákavou vlastností CDI je vestavěný Event/Observer framework, který umožňuje za použití pár anotací odpalovat události a předávat je observerům — vše v režii CDI. Už párkrát jsem něco takového hledal pro Spring a nikdy jsem nebyl s výsledky hledání moc spokojen…
Další hodinku jsme strávili poslechem plánů na Javu EE 7, jimž vévodil termín cloud. Není divu… App Engine, Amazon, CloudForge. Silná konkurence. Mluvilo se také o podpoře NoSQL databází, což je ale opět pole, na kterém má už teď Spring obrovskou převahu. Když chcete použít full-stack EE pro vývoj s NoSQL, nic moc růžového vás nečeká.
Conference Day 2
Druhý konferenční den začal celoplošnou přednáškou Jima Webbera na téma SOA v 21. století. Z Jima se velmi rychle vyklubal suverénně nejlepší speaker celé konference. Brit s krásnou angličtinou, ostrým humorem (pokud byli v sále nějací francouzi, asi jim bylo dost horko) a zcela evidentním zápalem a zájmem o věc. Kritizoval mamutí SOA řešení, převážně ztělesněná ESB a nabízel klasický web (HTTP & REST) jako alternativu.
Dál jsme si zašli poslechnout pár pokročilých tipů ze světa Bean Validation, anotacemi se to tam jen hemžilo. Následoval blok přednášek, ze kterých jsem měl dost problém si vybrat, tak jsem seděl na přednášce o Hadoop a HBase a hrál si s Javou EE 6…
Fin Joonas Lehtinen, autor Vaadinu, pak vyprávěl o různých typech útoků na RIA aplikace a ukazoval je na příkladu bankovní aplikace napsané ve Vaadinu. Mezi radami, jak se takovým věcem vyhnout, byla samozejmě v první řadě rada: neobcházejte serverovou validaci.
Autor přednášky o Bean Validation pak představoval projekt Hibernatu na podporu NoSQL databází přes JPA. Osobně jsem z toho nadšen nebyl — JPA bylo vždy cíleno na databáze relační a tak to taky zůstane. Pro obecnou persistenci je tady JDO (i když má své mouchy) a já nevidím důvod, proč to ohýbat. Vytvářet další JSR standard čistě pro NoSQL databáze by bylo taky dosti těžké, protože typů je mnoho.
Moc jsem se těšil na lákavě nazvanou přednášku 3 Case Studies in NoSQL and Java in the Real World, ale byl jsem zklamán. Šlo napůl o maketing a napůl o změť slidů s obřími “enterprise” diagramy. Nejzábavnější na téhle přednášce bylo sedět v řadě za Jimem Webberem a sledovat, co mu na tváři jednotlivé slidy kouzlí za úsměvy…
Druhý den už pak nešlo zakončit lépe, než přednáškou Jima Webbera o grafové NoSQL databázi Neo4j. Nejen, že Jim opět předvedl svůj přednášecí um, ale grafově orientovaná databáze je nesmírně zajímavá věc. V první řadě proto, že je podle mého nejblíže tomu, jak je skutečný svět kolem nás poskládán a “zadrátován”. Určitě to není věc vhodná pro každou aplikaci (např. čistě dokumentově orientované záležitosti), ale mnoha týmům by vytrhla trn z paty. Rychlost je také vysoká, ovšem škálovatelnost ještě ideální není (myšleno škálovatelnost do opravdu mamutích rozměrů typu Facebook). Každopádně jde o open source záležitost a lze ji použít jak v módu serverovém, tak jako embedded záležitost. Pro vývoj webových aplikací je škoda, že interface Node není kamarád s EL (JSP, JSF…), resp. že traverzování po propertách a vztazích s ostatními nody je v EL nemožné. Napsat si na to vlastní wrapper ale nebylo těžké.
Tím konference oficiálně skončila. V sobotu jsme se už museli během dopoledne odebrat zpět domů, takže Community Day jsme se neúčastnili. Každopádně ale stála celá akce za to a pevně věřím, že příští rok bude zas o něco lepší.
Když jsem v diplomce rozebíral MVC a zmiňoval se o neřestech, kterým se vývojáři oddávají při tvorbě Modelu, došlo i na anemický doménový model, neřest to ohavnou a bohužel dnes velmi běžnou. No jen se přiznejte, kdo z vás nemá aplikaci, ve které je doménový model jen sadou anorektických DTOček doprovázených obézními servisami, manažery a DAOčky…? Jednou z odpovědí na tenhle problém je právě doménově orientovaný návrh aplikací. Ten má samozřejmě několik odstínů, přičemž tím nejsytějším jsou asi nahaté objekty (přiznejte se, co jste za tím odkazem čekali? :)). Možností, jak DDD nějakým způsobem zapojit, je ale více a v souvislosti s tím mě celkem zaujal - a k DDD zase přivedl - článek nedávno publikovaný na Java Code Geeks: Domain Driven Design with Spring and AspectJ.
Článek celkem dobře vystihuje dnešní problém, tedy to, že mnoho aplikací - ač psaných s použitím objektů a v objektových prostředích - jsou ve své podstatě aplikace procedurální:
On the other hand, look at all those great stateless services. They do not have any state. Although they operate on domain objects, they are not part of them or not even aggregate them (low cohesion). All the data is passed explicitly through the method parameters. They aren’t objects as well – they are simply collection of procedures arbitrary gathered together on a common namespace, corresponding to class name.
…
Let’s face it, we are not OOP programmers, as everything we need are structures and procedures, invented fifty years ago.
Autor v článku dále představuje svou variantu řešení problému, ve které ovšem podle mého v jednom místě překročil mantinely. Problém vidím v odkazu na EntityManagera přímo v doménovém objektu. Jednak to zatahuje do DO odkaz na konkrétní persistentní mechanismus a pak to také není košer z hlediska modelování problémové domény. Funkcionalita persistence přece není věcí objektu modelujícího nějakou část problému, který řešíme. Jak tedy na věc?
Univerzální řešení nemám, protože neexistuje. Vím ale, jak si pomoci použitím JDO. Nejjednodušeji si to ověříte asi na Google App Engine, který je aktuálně asi nejznámější široce používanou aplikací tohoto standardu. JDO má totiž tu vlastnost, že zatímco při persistování nového objektu se volání PersistenceManageru nevyhnete (ovšem na rozdíl od autora článku bych ho určitě nedělal v DO), update je zajímavější. Pokud totiž změníte již persistovaný objekt mezi jeho vyzvednutím z manageru a zavřením daného manageru, GAE při zavření změny automaticky persistuje. Přihodíme trochu Springu, zamícháme a máme polívčičku.
Vytvořme si tedy jakousi skořápku pro PersistenceManagerFactory:
public final class PMF {
private static final PersistenceManagerFactory PMF_INSTANCE = JDOHelper
.getPersistenceManagerFactory("transactions-optional");
private PMF() {
}
public static PersistenceManager getPersistenceManager() {
return PMF.PMF_INSTANCE.getPersistenceManager();
}
}
…a Spring beanu:
<bean id="persistenceManager" class="net.danielkvasnicka.common.gae.PMF"
factory-method="getPersistenceManager" scope="request" destroy-method="close">
<aop:scoped-proxy />
</bean>
Pokud máte dojem, že skořápka je zbytečná a že všechno zvládne Spring, máte pravdu - pokud nepoužíváte GAE, díky jehož class blacklistům následující Spring konfigurace nefunguje. Pokud ale používáte JDO na vlastní pěst, neměl by být problém to vykutit takto:
<bean id="persistenceManagerFactory" class="javax.jdo.JDOHelper"
factory-method="getPersistenceManagerFactory" lazy-init="true">
<constructor-arg value="transactions-optional" />
</bean>
<bean id="persistenceManager" factory-bean="persistenceManagerFactory"
factory-method="getPersistenceManager" scope="request" destroy-method="close">
<aop:scoped-proxy />
</bean>
Tento persistenceManager pak injektujeme do našich DAO tříd. Důležité jsou hlavně dvě věci. Request scope persistence manageru a jeho destroy metoda. Tato konfigurace říká, že persistence manager, který bude v průběhu HTTP requestu vytvořen a použit, má být také na jeho konci popraven, přičemž jeho posledním přáním je zavolat na sobě metodu close(). V praxi to znamená, že vaše DAO třídy se obejdou pouze s metodani pro vyzvedávání dat z datastoru a s metodou, která bude na persistent managerovi volat makePersistent(object) pro objekty, které ještě nebyly persistovány a zároveň na ně neodkazuje žádný již persistovaný objekt (taková metoda bude samozřejmě existovat jen jedna, na nějakém generic DAO).
To je věc, která radikálním způsobem zjednodušuje datovou vrstvu aplikace. Představte si, že vaše aplikace potřebuje v nějaký moment přidat např. objekt Auto do kolekce v objektu Garáž. Podle jednoznačného identifikátoru si z datastore vezmete Garáž, přidáte do něj nově instancovaný objekt Auto a… a to je všechno. Žádná metoda updateGarage na servisní třídě, jejíž jediným řádkem je volání updateGarage na DAO… S koncem requestu, ve kterém byl odeslán formulář na přidání Auta, se změny zapíšou. Samozřejmě se může stát, že potřebujete větší granularitu a pak jsou tu transakce, kterými si můžete práci s daty rozsekat jak chcete. Výše popsané však funguje i bez explicitní transakce, což je, pokud vím, rozdíl oproti JPA.
Výše popsané samozřejmě neřeší problém s anemií doménového modelu a ve své podstatě to ani nevede přímo k DDD. Je to ale takové malé pošťouchnutí loďky správným směrem. Umožňuje to soustředit se více na to, proč vlastně aplikaci píšete, ne na nudnou rutinu. Také to je takové malé “neuveď nás v pokušení” - když nepotřebujete update řešit explicitně, je menší pravděpodobnost, že sklouznete ke zvěrstvům typu GarageService.addCarToGarage(Garage, Auto) a větší pravděpodobnost, že vám doménové objekty nevytratí logiku, která v nich má zůstat. Na anorexii i anemii se totiž umírá.
Google App Engine se stal poslem dobrých zpráv pro všechny javisty, kteří už přestali doufat v rozumný Java hosting za rozumnou cenu. Má sice své “ale”, ale suma sumárum je to hodně schopná platforma, která leckterý projekt solidně uhostuje. No a vzhledem k tomu, že jakožto dlouholetý eclipsář jsem nedávno začal Eclipse celkem nemít rád, hledal jsem způsob, jak pro GAE vyvíjet v IDE, které se u mě stalo eclipsím nástupcem: NetBeans.
A našel jsem. Projekt sice zrovna nesrší aktivitou, ale funguje a účel v podstatě plní — až na jednu maličkost. Dev server GAE standardně skladuje svou databázi ve WEB-INFu dané aplikace a NetBeans spouští server nad standardním web build adresářem (${projekt}/build/web). A to znamená, že kdykoliv provedete nad projektem Clean, o data přijdete. A to není moc ideální…
Nahlásil jsem chlapcům bug, ale čekat na jeho spravení se mi nechce a tak jsem si z Kenai naklonoval zdrojáky a jal se v nich hrabat. Fix je v podstatě jednoduchý, jelikož dev server se spouští Ant skriptem, kterému je akorát třeba dodat ty správné properties, abychom data měli v nějakém adresáři zcela mimo dosah buildu. Možnosti jsou 2 (3, pokud berete v úvahu čekání na opravu bugu).
runserver, runserver-debug a runserver-profile přidat pod tag dev_appserver toto (pokud už tam optionsjsou, dodat k nim):<options> <arg value="--jvm_flag=-Ddatastore.backing_store=/cesta/k/datastore.bin" /> <arg value="--jvm_flag=-Dblobstore.backing_store=/cesta/k/blobstore.bin" /> </options>
${user.home}/nbappengine-data/${project.dir}, kde project.dir je název adresáře vašeho NB projektu. V nastavení konkrétního projektu (viz. bod 1) si pak můžete změnit tu složku ${user.home}/nbappengine-data, pokud chcete mít data jinde. Patchnutý modul za vás navíc cílový adresář vytvoří.Doufejme, že tvůrci pluginu časem dovolí nějakou globální i lokální konfiguraci přímo v NetBeans. Zatím snad tenhle tip někomu poslouží ;)
Jednou z předností Mac OS X jsou kvalitní nástroje pro práci s PDF vestavěné přímo do systému. Není to jen tak — obrazový model grafické vrstvy Quartz, která je nedílnou součástí OS X, je totiž svou strukturou modelu PDF dost podobný.
Jedním z takových nástrojů jsou Quartz filtry, které při přeukládání PDF v Preview umožňují daný soubor všelijak “vylepšit” (a nebo zprasit). Mezi nejpraktičtější filtry určitě patří Reduce File Size, který umožňuje celkem výrazně snížit velikost PDFka, používaje při tom primárně JPEG kompresi na vloženou grafiku.
Problém ovšem nastává v případě, kdy jsou určité části PDF ve CMYKu. Quartz s takovou grafikou při kompresi vyvede tohle:
Řešení je jednoduché a spočívá v editaci daného filtru, resp. v jeho duplikaci a změně nastavení duplikátu. Otevřete ColorSync Utility, vlezte do sekce Filters, klikněte na šipečku vpravo od filtru Reduce File Size a filtr duplikujte. Do duplikátu pak přidejte kliknutím na stejnou šipečku Color Management Componentu s názvem Convert To Profile a nastavte ji následovně:
Pak prostě a jednoduše při kompresi CMYK PDF použijte tento filtr místo toho původního a výsledkem bude velmi pěkná komprese se zachováním původního vzhledu. Samozřejmě tím přijdete o CMYK data, ale vzhledem k tomu, že komprese se většinou dělá u PDF, která je třeba dát na web pro online prohlížení a nebo je poslat mailem, tak to nevadí. Soubor, který půjde do tiskárny a bude třeba u něj data zachovat, asi nebudete potřebovat komprimovat (i kvůli kvalitě grafiky).
Ověřeno v 10.5 i 10.6.
Už nějakou dobu sleduju dní kolem Solarisu, resp. OpenSolarisu. Přecejen když už jsem ten javista, stojí za to omrknout operační systém, který by měl mít k Javě teoreticky nejblíže. Ne, že bych chtěl v dohledné době mít na desktopu něco jiného než Mac OS X, ale už kvůli hostování aplikací běžících nad JVM stojí za to vědět, jak se věci mají.
Původně jsem chtěl využít nabídky vpsfree.cz a stát se pokusným králíkem pro KVM, ale pánové z qemu-kvm mají na triku ošklivý bug, který prakticky znemožňuje provoz novějších systémů postavených nad SunOS. No a protože můj pracovní notebook se s OpenIndianou (nástupcem OpenSolarisu) moc nekamarádí (pořád ale lépe, než s aktuálním Ubuntu), skončil jsem ve VirtualBoxu.
Do jedné virtuální mašiny jsem nainstaloval serverovou verzi aktuální OpenIndiany (b148), do druhé aktuální Ubuntu Server Edition (10.10). Šlo mi v zásadě o to porovnat oba systémy z pohledu člověka, který si řekne: “OK, mám Java EE aplikaci ve WARu, teď potřebuju na tohle železo nahodit nějaký serverový OS, na něj GlassFish 3 a do něj deploynout aplikaci.”
Pokud vám nesedí termíny Java EE, WAR a GlassFish v jedné větě, vězte, že jsem se rozhodl pro otestování použít primitivní Java EE 6 Web Profile aplikaci (EJB 3.1 Lite & JSF 2). Pro jistotu, aby se neflejmovalo: nezanevřel jsem na Spring a nezamiloval jsem se do EJB. Nepopírám ale, že EE 6 je věc, kterou stojí za to omrknout a rozhodně je hezké, jak rychle a s naprostým minimem konfigurace se dá nahodit primitivní EJB Lite aplikace s konektivitou do databáze přes JPA a nějakým tím ksichtem ve Faces…
Ale k věci. Instalace OI je vskutku primitivní. Instalátor se vás zeptá jen na ty opravdu nejnutnější věci a instalace běží. Popravdě to hoši s tím minimalismem trošku přehnali — nastavit síť totiž lze pouze přes DHCP a nebo vůbec. Staticky až po instalaci (třeba přes docela schopný NWAM). Instalace Ubuntu je oproti tomu o dost zdlouhavější. Instalátor se z vás v jednu chvíli snaží dostat informace o tom, jak budete server používat a to tak, že vám nabídne několik předkonfigurovaných softwarových balíků — pro mailserver, LAMP atp. Jediný z nich, který má něco společného s Javou, je Tomcat. Ten my ale nechceme, i když pravděpodobně bychom s ním tu Javu dostali. Takže zaškrtneme jen OpenSSH server a instalujeme. Proč se SSH neinstaluje naprosto automaticky, to nevím. Kolik server adminů ho nepotřebuje?
Žasnutí nad chybějícím SW nekončí ani po instalaci Ubuntu. V první řadě samozřejmě nemáte Javu (tomu se popravdě moc divit nelze). V repozitářích je OpenJDK 1.6u20, což je málo. Aby bylo možno porovnávat, chce to Javu přímo od Oraclu a to 1.6u21 — ta je totiž standardně v OpenIndianě b148 hned po instalaci. Dále nemáte např. Vim a unzip. U unzipu by se dalo polemizovat, ovšem nemít Vim v základní instalaci serverového OS…? A to má ISO serverového Ubuntu o 200 MB více než OI.
Suma sumárum, do OpenIndiany jsem kromě GlassFishe nemusel instalovat nic. Do Ubuntu i docela zásadní věci. Ubuntu má plus za bleskový start (OI startuje strašně pomalu), ovšem je to plus malé a bezvýznamné — bavíme se o serveru.
Co se týká rozdílu ve výkonu, tak pár jednoduchých testů s JMeterem ukazuje, že rozdíly ve výkonu jsou prakticky nulové. Zdůrazňuju, že šlo o jednoduché testy, jednoduchou aplikaci a oba OS běžely virtualizovaně. Testy mají tedy daleko k dokonalosti, ale když by měl jeden z OS výrazný výkonový deficit, dalo by se to podle mého poznat.
Co dodat? Asi jen to, že OpenIndianu stojí za to zvažovat jako serverový OS a nebo alespoň po očku sledovat její vývoj. Snad se udrží a bude zdatně konkurovat oraclímu Solarisu.
Jelikož mám rád Top Gear (ovšemže britský, i když i tomu americkému dávám v poslední době šanci), čas od času se snažím sledovat sólové počiny protagonistů téhle show. Tak se také stalo, že jsem zakopl o seriál, který pro BBC natočil James May: James May’s Toy Stories. Uh… seriál o hračkách? Jsem snad cvok, nebo co? To sice jo, ale spíš jsem se nemohl zbavit dojmu, že když to točil James, tak to prostě nějakým způsobem zajímavé bude, i když to téma tak na první pohled nevypadá. Bylo.
Podstatou seriálu je v zásadě snaha dovést lidi k přemýšlení o tom, zda nám v dnešním digitálním světě nechybí trocha té fascinace skutečnými hmatatelnými koníčky a hračkami. V prvním dílu si James bere na pomoc plastikové modely, konkrétně jejich velkého propagátora v Anglii — firmu Airfix. A tady se do příběhu začínám zapojovat já.
Plastikové modely letadel, stejně jako letadla samotná, patřily v mém dorostovém věku mezi mé největší koníčky. Mě moje výstavka vyšperkovaných stíhaček a bombardérů fascinovala, mamku přiváděla k šílenství - o moc lepší místa, kam chytat prach, už totiž nejsou. Do modelářského kroužku jsem se těšil jak malý kluk. Sbíral jsem i fotky letadel a do různých sešitů si (z dnešního internetového pohledu zcela zbytečně) vypisoval všemožné údaje. Jak už to ale bývá, s přibývajícími léty se priority i zájmy měnily a prach se chytal čím dál víc. Rozumíte, ty internety, ženské… a tak.
Když jsem ale viděl Jamese, jak se (zprvu jakoby zoufale) snaží přesvědčit děcka, že stavět tank je stejně cool, jako jít na koncert Beyoncé, bylo mi ho líto. A netrvalo dlouho a začalo mi být líto i toho, že jsem na tom v podstatě tak trochu stejně jako ty děcka.
Pak nastala fáze odmítání. Pche, sentimentálníma náladama se nenechám rozhodit. Lepit letadýlka? Kdo ví, kde je moje sbírka barev, štětce, lepidla… a kdy to jako budu lepit? Musím zkontrolovat RSS čtečku, Facebook, Twitter, pokecat na Jabberu, zamajlovat si, programovat, sekat dříví, chodit do práce, spát (to poslední se tam nějak připletlo). Dlouho to ale netrvalo a posunul jsem se k fázi zatím poslední: hecnutí se, aneb nadšení a odhodlání. Ano, rozumíte správně, opravdu se chystám postavit si model. A ne jen tak ledajaký.
V první řadě to samozřejmě musí být od Airfixu, aby měl James radost. V řadě druhé to musí být stroj, který je ne uplně nový, spíše tak trochu klasický, taky tak jako lehce ujetý, ale vlastně krásný… No ano, musí to být samozřejmě SAAB a to rovnou J 35 Draken.
Aktuálně jsem tedy ve stavu, že je model objednaný. Zbývá sehnat vercajk a může se jít na věc. Tím samozřejmě myslím se podívat, zda z mého modelářského materiálu něco zbylo a když ne, připomenout si další z mých modelářských vzpomínek — nakupování barev a lepidel, kteréžto ve skutečnosti bylo hlavně omluvou pro bloumání po modelářském obchodě a snění o těch krásných velkých letadlech tam v horních policích… s horními cenami.
Pro dnešek ale končíme. Jak to bude pokračovat, o tom si sem možná zase ublognu.