Nástroje pro vývoj web aplikací ve Forrestu

Pod ladícím nástrojem si většina Java vývojářů představí Java debugger. O něm však v tomto článku řeč nebude. Chtěl bych vám tu představit náš přístup k doprovodným nástrojům pro tvorbu webové vrstvy a podívat se kolem sebe, jestli jsme v tomto ohledu originální či nikoliv.

Nápad vytvořit specifické nástroje se znalostí interních mechanismů použitého frameworku je již poměrně starý. V českém PHP frameworku Nette vznikla tzv. Laděnka někdy na začátku roku 2008 (vycházím ze zmínky na blogu Davida Grudla).

Pro některé Javové frameworky najdeme také podobné nástroje - Wicket má svůj Debug Bar od roku 2009, Tapestry má Inspector snad od roku 2003, Grails mají Debug plugin někdy od roku 2008 a takto bychom mohli pokračovat dál. Se vzrůstající složitostí webových aplikací a frameworků se zdá být užitečné mít po ruce nástroj, který vývojářům dokáže odkrýt vnitřní mechanismy a informace zpracování požadavků browseru. V některých případech se mi zdá, že nástrojem se snaží autoři frameworku pomoci vývojářům lépe kontrolovat jeho slabá místa - v případě Wicketu velikost stavových objektů v session, v případě Nette třeba problematická práce s vyjímkami v PHP. My našeho webového Inspektora a související nástroje vyvíjíme postupně již od začátku roku 2009 a v tomto článku bych vám rád popsal co mají naši vývojáři k dispozici a proč.

Pro vývoj webových aplikací používáme vlastní komponentově orientovaný webový framework integrovaný do Edee CMS. Důvodem proč jsme nešli cestou existujících frameworků jsou naše specifické požadavky na vývoj, kdy aplikaci vyvíjí společně Java vývojáři i tzv. web developeři (což jsou experti na HTML a CSS, ale nejsou to svým zaměřením programátoři) a tato platforma nám umožňuje efektivně dělit i sdílet práci. V zásadě jde o to, že aktuálně jsou naši web developeři vytvořit webovou aplikaci bez účasti Java vývojářů, kteří se primárně zabývají business vrstvou aplikace. V místech, kde je potřeba volat nějaké specifické akce nebo dotahovat data z jádra aplikace se použijí záslepky, které Java vývojáři zamění za reálnou logiku, jakmile je hotova.

Vývoj by se dal přirovnat k tomu, který znáte z Wicket frameworku s tím rozdílem, že u nás práce web developerů nekončí u přípravy statických HTML šablon + CSS, ale sahá dál až k funkčnímu prototypu cílové aplikace - tj. šablony jsou již rozparcelovány do znovupoužitelných komponent, mezi stránkami funguje navigace, texty jsou lokalizované do různých jazyků a formuláře jsou včetně většiny validací funkční. To vše bez jediné čárky Java kódu - pouze s využitím deklarativního DSL v XML formátu, se kterým jsou webdevelopeři sžití.

S rozšířením kompetencí našich web developerů bylo potřeba dát jim k dispozici taky nástroj, pomocí kterého by dokázali nahlédnout pod kapotu toho, co vlastně vytvářejí a používají. Řada věcí se totiž poslepu dělala velmi komplikovaně - kupříkladu určení správného umístění Freemarker šablony, odhadnutí klíče lokalizovaného textu nebo odhalení triviálních chyb v konfiguraci způsobených překlepy. Častokrát nezbylo než požádat o pomoc Java vývojáře s debuggerem, který přes socket pomohl problém odladit. To ale zdržovalo všechny a ne vždy bylo jednoduché se debuggerem na rozjetý projekt napíchnout. Vytvoření pomůcky pro ladění bylo tedy jen logickým krokem k řešení této bolesti.

Jak inspektor vypadá

Inspektor je malá webová aplikace napsaná ve stejné technologii, které umožňuje introspekci a je dostupná pouze ve vývojovém a testovacím prostředí. V těchto režimech jsou ke každé web stránce, která je renderovaná připsány dodatečné cookies, které obsahují URL na jednotlivé části inspektora. Na tyto cookies reaguje náš jednoduchý Firefox plugin, který zobrazuje lištu a kontextové nabídky integrované přímo v prohlížeči. Ten potom při kliknutí na konkrétní tlačítko zobrazí nové popup okno s odpovídající webovou adresou vybraného pohledu inspektora. Představu si můžete udělat z tohoto obrázku:

Výhodou tohoto přístupu je, že webový vývojář má ladící nástroj při práci rychle po ruce. Aktuálně zvažujeme i implementaci pluginu pro Chrome, jelikož ten se i u nás prosazuje čím dál víc. Tím, že je plugin do prohlížeče velmi tenký (v podstatě se jen integruje do nabídek, čte cookies a zobrazuje popup okno) nebude portace do dalších prohlížečů obtížná.

Co inspektor umí?

Základem našeho inspektora, který jsme postupně rozvíjeli, bylo zobrazení stromu komponent aktuálně prohlížené stránky. Jak je vidět z přiloženého obrázku - vlevo je přehledně zobrazená struktura stránky, napravo potom detail konfigurace konkrétní vybrané komponenty. Kromě základních identifikačních informací je zde k dispozici náhled nastavených metadat, konvertorů uživatelských dat na Javovské datové typy a také specifické validace, které se k datům komponenty vztahují. Detail se samozřejmě adaptuje podle typu vybrané komponenty - pokud komponenta neumožňuje vstup uživatele, odpovídající sekce zmizí. Při výběru celé stránky se opět zobrazí jiné relevantní informace:

Záložka Dokumentace zobrazuje aktuální popis vzatý z JavaDoc konkrétní třídy ve verzi, která je na daném projektu nasazená. Dokumentaci vytahujeme automatizovaně pomocí knihovny QDox rovnou z odpovídajících zdrojových souborů, které si podle Maven identifikátorů (groupId, artifactId a version) uložených v bundlovaném JARu stáhneme na pozadí online z naší firemní repository.  Používání aktuální dokumentace z JavaDocu vychází z mé úvahy v článku Zamyšlení nad tvorbou programátorské dokumentace a tam je také myšlenka rozvedena do větších podrobností.

V popisu konkrétního objektu (komponenty, stránky, akce, validace, konverze atp.) je i seznam jejich vlastností a metod, které jsou rozdělené na 2 části - dokumentované -tj. ty, u kterých se počítá s použitím našimi webdevelopery a nedokumentované, které jsou určené spíše pro Java vývojáře a které by výpis znepřehledňovaly a cílovku zbytečně mátly. Ukázka dokumentace validátoru imageFormat vypadá následovně:

V záložce Šablony je vypsán seznam umístění Freemarkerových šablon seřazený prioritně podle toho, jak je webový framework vyhledává. Přetěžování šablon je jednou z unikátních vlastností, které nám umožňují pro konkrétní komponentu definovat univerzální vzhled pro celou aplikaci, ale stále mít možnost ji na konkrétních specifických částech systému přetížit a upravit dle potřeb. Webdeveloperům stačí jen na správném (prioritnějším) místě vytvořit soubor s odpovídajícím názvem a po refreshi stránky se použije nová šablona. Bohužel bez vizualizace nebylo dříve jednoduché odhadout, jak systém vypočetl seznam umístění pro konkrétní šablony.

Vkládání lokalizovaných textů do webových stránek probíhá standardní Javovskou cestou - přes Property bundly. V tomto směru využíváme skvělé podpory Springu ve formě ReloadableResourceBundle, jak jsem jej popsal v tomto článku. Díky pár úpravám jsme schopni monitorovat, jaká oblast stránky používá které lokalizované klíče a zobrazit je v záložce Lokalizace. U dlouhých stránek je možné zúžit výpis výběrem konkrétní komponenty (kontejneru) na stránce.

U jednotlivých klíčů se využívá podobného mechanismu jako ve Spring MVC - tj. každý klíč má vícero variant od té nejvíce specifické až po tu nejobecnější. Je možné tak mít obecné texty pro celý web, které je možné na konkrétních stránkách upravovat dle konkrétních potřeb. Taktéž známe kompletní seznam všech Properties bundlů, které se při vyhledávání lokalizovaných textů berou v úvahu a dokážeme přesně provázat nalezený text se zdrojovým souborem, ve kterém se nachází. Lepší představu si uděláte z následujícího screenshotu:

Slovníky dostupných komponent

Další položkou v naší vývojářské liště jsou Slovníky. Ta zobrazuje seznam dostupných objektů, které mohou webdevelopeři při tvorbě webu použít. Najdou zde kompletní seznam akcí, validátorů, poskytovatelů dat a dalších typů objektů včetně dokumentace, která je přímo vytažená z Javadoců odpovídajících tříd (stejným principem, jaký byl již popsán výše).

Zásadní je ovšem to, že tento dialog čerpá informace přímo z interní struktury webového frameworku, takže poskytuje úplný a přesný obrázek toho, co je skutečně k dispozici. Pokud tedy náš Javista vytvoří novou implementaci poskytovatele dat pro stránkovaný seznam - tj. vytvoří novou třídu, která implementuje konkrétní rozhraní, a uvede ji v konfiguraci slovníku nějakého modulu, objeví se web developerům v tomto seznamu včetně dokumentace, kterou pro ně Javista zanechal v JavaDocu. Tento "publikační" proces nelze obejít - protože jinak by webdeveloper danou implementaci ani nemohl použít - tj. v tomto principu je obsažen jak funkční tak i samodokumentační faktor.

Slovníky je možné definovat na různých místech stromové struktury stránek, vzájemně mezi sebou dědí, je možné je importovat napříč touto strukturou a webdevelopeři je mohou sami doplňovat či upravovat. Ve výchozím stavu je zobrazen slovník, který přináleží aktuálně zobrazované aplikační stránce v prohlížeči. K navigaci mezi slovníky a zúžení výběru zobrazovaných položek slouží ovládací prvky v horní části přiloženého screenshotu (vybrat jiný slovník a zobrazit pouze lokální položky).

Dokumentace

Pod položkou dokumentace se skrývá jednak referenční dokumentace ke všem dostupným klíčovým slovům, tagům, Freemarkeru a dalším základním stavebním kamenům webové části aplikace a také tématická dokumentace k jednotlivým oblastem frameworku, která se dá číst jako knížka a dá programátorům dobrý vhled do různých zákoutí funkcionality. Dokumentace je psána s použitím jednoduchých HTML tagů a je uložena přímo v JARech našich knihoven. Tím pádem se vývojářům zobrazuje dokumentace odpovídající té verzi frameworku, který právě používají k vývoji své aplikace a nemusíme se dlouze zabývat verzováním dostupnosti konkrétních nastavení a funkcí.

Lokalizační nástroj

Pro zjednodušení a urychlení tvorby lokalizovatelných textů je k dizpozici tlačítko lokalizace, které zobrazí seznam všech klíčů na vykreslované stránce, pro které se nepodařilo najít odpovídající lokalizovaný text. Vývojáři stačí většinou jen naskládat komponenty na stránku (popřípadě si vytvořit vlastní specifické šablony a použít v nich tagy pro použití lokalizovaných textů), jednou si nechat stránku vyrenderovat a pak otevřít tento dialog pro usnadnění lokalizace, ve kterém se mu zobrazí všechny klíče, které je třeba zlokalizovat. Klíče zkopíruje do některého z property bundlů a přeloží je. Po refreshi stránky se již zobrazí správně zlokalizované varianty.

Ladička

Ladička je posledním nástrojem na naší paletě a umožňuje se dívat na průběh zpracování jednotlivých HTTP požadavků. Dala by se přirovnat k Firebugu s tím rozdílem, že představuje pohled ze strany serveru. Tj. vidíme, jaké všechny HTTP požadavky dorazily do naší aplikace, jaké měly vstupy, jaký modul je zpracovával, jaké byly hodnoty cookies, hlaviček požadavku atp.

Na druhé záložce je zobrazen průběh zpracování requestu frameworkem. Je vidět jakými fázemi životního cyklu zpracování prochází, jak dlouho jednotlivé části zpracování trvají, jaké akce se volají, jaké hodnoty jsou vráceny poskytovateli dat na dané stránce. Tato stránka je užitečná především ve chvíli, kdy aplikace nedělá, co jako vývojáři očekáváme. Dá se zde odhalit použití prezentační cache (která je neoddělitenou součástí frameworku) místo očekávaného volání aplikační logiky, načítání a zapisování dat do komponent, skrývání / odkrývání podmínečně zobrazovaných částí stránky apod. Často se také hodí introspekce Java objektů (podobná té, kterou znáte ze svého IDE), které se v průběhu zpracování použily (ikona lupy).

Poslední záložka je interaktivní konzole, ve které je možné si nechat vyhodnotit v kontextu vybraného HTTP requestu (i historicky) konkrétní výraz našeho výrazového jazyka - tzv. RJEL. Tento výrazový jazyk je velmi podobný SpEL, který byl, bohužel pro nás, zveřejněn až rok po tom, co jsme my ten náš už produkčně používali. Aktuálně zvažujeme, jestli a jak by bylo možné náš RJEL přetavit ve variantu SpEL, který je z hlediska syntaxe a možností o řád bohatší.

Výsledek ve formě introspektovaných Java objektů zobrazuje ve spodní části obrazovky. Pomocí výrazového jazyka si můžeme nechat zobrazit hodnoty uložené v session, vytáhnout si informace z libovolného ze zaregistrovaných poskytovatelů dat, zobrazovat si hodnoty stavů konkrétních komponent atp.

Pomocí této konzole se můžeme dívat do střev běžící aplikace a dá se tímto způsobem odhalit plno problémů, aniž bychom museli zprovozňovat a používat Java debugger.

A naše zkušenosti po 3 letech používání?

Několik desítek hodin investovaných do Inspektora se nám už několikrát vrátilo ačkoliv přínos je obtížně měřitelný. Některé funkcionality doposud ještě nejsou využívány, tak jak bych si představoval - především část dokumentace, která dlouho pokulhávala (a ještě stále pokulhává) za rozsahem dostupné funkcionality a tak si svoji důvěru teprve získává. Nejvíce využívané funkce jsou ty, které přímo šetří práci - třeba lokalizační dialog nebo záložka inspektora s přístupem k Freemarker šablonám. Interaktivní konzole RJEL, přestože je v sadě nástrojů nejmladší, si svoji oblibu získala taky poměrně rychle.

Celou řadu ostatních funkcí využívám ale pouze já a kolegové Javisti, když na dálku poskytujeme podporu našim webdeveloperům. Při množství projektů, které Forrest realizuje, je úspora času při této činnosti veliká. Dříve jsme si kvůli různorodým verzím použitých knihoven museli stáhnout projekt z VCS, zprovoznit v IDE, pokusit se vzdáleně háknout na JVM, kde projekt běžel, a debuggovat konkrétní třídy. Na řadě míst byl remote debugging nemožný a proto jsme si museli projekt rozjíždět lokálně (např. na testovacích prostředích nám JVM neběží v debug režimu nebo když webdeveloper sedí na jiné pobočce a je potřeba ladit na verzi v jeho lokálním prostředí). Často taková situace představovala třeba 2 hodiny na zprovoznění projektu, kde se během 10 minut oddebugoval a odhalil triviální problém. V současnosti jsme schopni většinu problémů odhalit pomocí inspektora, což kromě času šetří spoustu nervů.

Vím, že naše použití a potřeby jsou poměrně specifické, ale vzhledem k tomu, že podobné nástroje najdete i v jiných frameworcích, možná i vy používáte také nějaký takový nástroj pro podporu vývoje webové vrstvy. Pokud ano, budu rád, když se o své názory a zkušenosti podělíte v komentářích.