Vysoká škola ekonomická v Praze Fakulta informatiky a statistiky Katedra informačních technologií Studijní program: Aplikovaná informatika Obor: Informační systémy a technologie
Diplomant: Vedoucí diplomové práce: Oponent diplomové práce:
Bc. Jan Kapčiar Ing. Luboš Pavlíček Ing. Libor Gála
Podpora prezentační vrstvy v aplikačních frameworcích
školní rok 2009/2010
Prohlášení
Prohlašuji, že jsem diplomovou práci zpracoval samostatně, a že jsem uvedl všechny použité prameny a literaturu, ze kterých jsem čerpal.
V Praze dne 30.6.2010
………………………………. podpis
Poděkování
Rád bych zde poděkoval Ing. Luboši Pavlíčkovi za vedení mé diplomové práce a za cenné rady, podněty a připomínky.
Abstrakt Tato diplomová práce se zabývá prezentační vrstvou a její podporou ve frameworcích pro webové aplikace. Je rozdělena na teoretickou a praktickou část. Prezentační vrstva je nejprve obecně popsána. Poté jsou vypsány jednotlivé základní technologie běžící ve webovém prohlížeči a komunikace se serverem. Práce rozebírá ajaxové techniky a z teoretického hlediska nahlíží na serverovou část prezentační vrstvy pomocí návrhových vzorů. Všechny teoretické poznatky jsou dále zkoumány na třech frameworcích (Zend, PRADO, Nette), na praktickém příkladu jsou sledovány možnosti, které každý aplikační rámec nabízí. Závěrečné zhodnocení sumarizuje konkrétní nabyté poznatky. Čtenáři je tak popsána prezentační vrstva ze všech úhlů pohledu. Navíc má k dispozici praktické srovnání, které mu může pomoci s výběrem vhodného frameworku pro vývoj.
Abstract This master thesis deals with the presentation layer and its framework support for the web applications. The thesis is divided into theoretical and practical part. First of all, the presentation layer is described; followed by the depiction of the particular basic technologies running within the web browsers. Communication with the server is one of the topics mentioned as well. The thesis analyzes the AJAX techniques and from a theoretical perspective focuses on the server part of the presentation layer by means of the design patterns. Afterwards, theoretical findings are analyzed with three different frameworks (Zend, PRADO, Nette) while the practical example shows all the options offered by each framework. The final conclusion summarizes the particular experiences observed. Therefore, the reader is expected to obtain information regarding the presentation layer from all the points of view. Moreover, the practical comparisons are provided in order to help the reader to choose an efficient framework for development.
Seznam přiložených příkladů ............................................................................................ - 74 -
1. Úvod Každá profesionální firma, každý zkušený vývojář, každý, kdo se dnes snaží vyvíjet kvalitní software či webové aplikace, ví, že jedinou možnou cestou, jak úspěšně vytvářet vetší a rozsáhlejší projekty, je na dané oblasti problematiky aplikovat výhody dostupných frameworků. Může se přitom klidně jednat i o frameworky, které autor (autoři) vyvinuli jen za účelem vývoje jedné konkrétní aplikace. Podmínkou je však perfektní funkcionalita v dané oblasti a podpora vývoje dalších navazujících úseků. Důsledkem toho, že vývojáři nejsou zcela zaslepeni problematikou elementárních funkcionalit systému, by mělo dojít zejména ke zkvalitnění funkcionality, která řeší business logiku. Samozřejmě je zde řada dalších nesporných výhod, o kterých bude dále řeč. V téměř každé problematice vývoje často existuje hned několik hotových řešení, které můžeme využít. Záleží na našich požadavcích, kterou variantu zvolíme. Kritéria výběru mohou být různá, výkonnostní, licenční nebo také možnosti integrace s jiným již využitým řešením v systému. Tato práce se však zaměřuje na ještě jeden jiný aspekt, a to na způsob, jakým tyto frameworky řeší problematiku prezentační vrstvy, neboli laicky, jak je vyřešeno zobrazování informací. Zdaleka se dnes nejedná o okrajové kritérium. Naopak trend poslední doby, tj. přechod na webové aplikace, pouze podtrhnul důležitost této vlastnosti a v důsledku nastartoval masivní rozvoj technik prezentování informací ve všech směrech. V této diplomové práce se proto konkrétně zaměřím na prezentační vrstvu. Budu sledovat její architektonická řešení, jaké technologie jsou v daných úsecích použity, jaké techniky frameworky implementují a jaké jsou nedostatky daného přístupu. Je také důležité zmínit, že tato oblast je nesmírně dynamická, každým rokem přibývá nespočet nových technologií a každých několik let se objeví několik zásadních technologií a přístupů, které zcela nahradí ty předchozí. Tato práce (s výjimkou snad jen kapitoly o návrhových vzorech) není imunní vůči plynoucímu času.
1.1.
Cíle
Nejprve bych rád vytvořil popis celé prezentační vrstvy, aby bylo každému zcela jasné, o čem práce pojednává. Tento popis musí zahrnovat výčet technologií vyšší i nižší úrovně a technik, které vznikly nad danými technologiemi. K problematice přistoupím i z druhé strany, tj. popíšu teoreticky architekturu prostřednictvím návrhových vzorů, které mají vliv na fungování a uspořádání prezentační vrstvy. V poslední části detailně představím několik konkrétních frameworků v jazyce PHP a popíšu, jakým způsobem přistupují k prezentační vrstvě, jaké technologie a techniky využívají, jaké návrhové vzory aplikují a kde jsou jejich nedostatky.
1.2.
Přínos
Díky teoretickému, a poté i praktickému rozboru, by práce měla poskytnout odpovědi na následující otázky: V jaké technologické fázi jsou dnešní verze frameworků ve vztahu k problematice prezentační vrstvy Jaké problémy v prezentační vrstvě čekají na vývojáře, který se rozhodne pro určitý způsob řešení
[- 1 -]
Další přínos bude zřejmě můj osobní, neboť vzhledem k množství informací, které je potřeba shromáždit (teoretické informace a kompletní informace o každém z popisovaných frameworků), bych očekával, že budu schopen mnohem snáze a rychleji pochopit fungování dalších frameworků v libovolném jazyce.
1.3.
Předpoklady
Vzhledem k tomu, že práce popisuje problematiku, která se prolíná do mnoha oblastí webové aplikace zároveň, jsou vyžadovány minimálně základní znalosti problematiky fungování internetu, webových aplikací a objektového programování. V práci se snažím vše demonstrovat na konkrétních příkladech, nicméně třeba již nepopisuji, jak nastavit aplikační server, kam kopírovat soubory, nepopisuju syntaxi jazyků, ale pouze vysvětluji chování programů.
2. Architektura webových aplikací Do 90. let minulého století byl koncept dvouvrstvé architektury (tzv. „Two-tier architecture“) běžně používaným návrhem ve všech tehdy moderních aplikacích. K centrálnímu úložišti se připojovalo prostřednictvím tlustého klienta, tj. nainstalovaného klientského softwaru na pracovní stanici. Zde také probíhala veškerá aplikační logika. Výhodou byla rychlost či uživatelský komfort, nevýhodou například údržba, neboť s každou aktualizací bylo potřeba aktualizovat i všechny klienty. Rozvoj internetu a nástup webových aplikací podnítily technologický posun a k dvěma stávajícím vrstvám se přidala vrstva třetí1 – aplikační a napasovala se přesně mezi ně. Tato architektura se nazývá třívrstvá, v angličtině se označuje jako „Three-tier architecture“. Místo o tlustých klientech rázem mluvíme o tenkých klientech, často označované jako „front-end“. Máme tím na mysli internetový prohlížeč. Jeho jedinou úlohou bylo pouze zobrazit informace, veškerá logika spojená s přípravou dat k zobrazení a business logika se přesunula do nově vzniklé aplikační vrstvy, na server neboli „middle-ware”. Třetí vrstvou zůstává datové úložiště alias „back-end“. Klientská vrstva je tak zcela odstíněna od datového úložiště. Takto popsané rozdělení popisuje fyzické rozložení aplikace. Pokud budeme mluvit o třívrstvé architektuře (tzv. „Three-layer architecture“) z hlediska logického rozdělení, narazíme na pojmy prezentační vrstva („Presentation layer“), business vrstva („Business logic layer“) a datová vrstva („Data access layer“). V tomto pojetí prezentační vrstva zahrnuje aktivitu webového prohlížeče a tu část aplikačního serveru, který má na starost přípravu a generování zobrazovaného kódu. Business vrstvu tvoří hlavní logika aplikace (výpočty, validace dat, transformace dat atd.). Datovou vrstvu tvoří ta část aplikace, která má na starost přístup a práci s datovým úložištěm a ono úložiště samotné. Obě uspořádání lze zjednodušeně graficky znázornit (viz Obrázek 1).
1
Architekturu aplikace lze dále vrstvit na menší celky, popřípadě lze jako další vrstvu považovat třeba operační systém, záleží na míře abstrakce, viz např. zdroj: CleverSmart (http://www.cleverandsmart.cz/vicevrstvaarchitektura-popis-vrstev/)
[- 2 -]
Obrázek 1: Třívrstvá architektura webové aplikace
Vzhledem k tomu, že výpočetní výkon se neustále zvyšoval a zvyšuje, začali tencí klienti stále více a více zahálet, neboť pouhé zobrazení výstupu přestalo být výkonnostně náročnou úlohou. Proto se začaly objevovat skriptovací jazyky, které měly prohlížečům poskytnout větší technické možnosti při zobrazování informací. Bez skriptování totiž nebylo možné realizovat funkce jako „drag and drop“, kontextové nápovědy, vizuální efekty a jiné. Přitom toto bylo u desktopových aplikací zcela běžná rutina. Nakonec ani samotný koncept „požadavek/odpověď“, typický pro třívrstvou architekturu, také mnoho uživatelského pohodlí webovým aplikacím nepřidal. Díky tomuto vzniká specifická skupina webových aplikací označovaná jako “Rich internet application” či zkráceně RIA. Tenký klient v RIA aplikaci je doplněn softwarem minimálního objemu (např. pluginem, tj. doplňkem v internetovém prohlížeči). Tento program obsahuje nutné komponenty pro zprovoznění dané technologie. Proto také se celá prezentační vrstva přesouvá mimo aplikační server2 (viz Obrázek 2).
Obrázek 2: Třívrstvá architektura RIA aplikace
Prezentační vrstvu webových aplikací rozeberu v dalších kapitolách detailněji. I přes jmenovaná technická úskalí mnoho dnešních webů dokáže konkurovat do určité míry RIA aplikacím. Musejí ale využít naplno dostupné technické prostředky a nejnovější techniky. Navíc musí být architektura serverové prezentační vrstvy velmi dobře navržena, ideálně podle prověřených postupů. O tom všem budou pojednávat následující kapitoly. Business vrstva a datová vrstvu bude vynechána.
2
Také vzniká opět problém s aktualizací doplňku. Nicméně v době psaní této práce se začal realizovat nápad spolupráce vývojářů internetových prohlížečů a vývojářů pluginů s cílem vydávat nové verze doplňků v rámci nových verzí internetových prohlížečů.
[- 3 -]
3. Klientské technologie Nejrozšířenějším klientem pro webové aplikace je internetový prohlížeč stolních počítačů3. Ve své základní verzi by si měl hravě poradit s dnes již běžnými technologiemi souhrnně označovanými jako DHTML. Do této skupiny řadíme značkovací jazyky (HTML či XHTML), skriptovací jazyky vycházející z ECMAScriptu (Javascript, JScript v Internet Exploreru), kaskádové styly (CSS) a rozhraní DOM. Existuje řada dalších doplňujících technologií, avšak ty jsou využitelné vždy jen v konkrétním prohlížeči (např. VBScript pro Internet Explorer). K DHTML dále řadíme doplňky (tzv. pluginy) a v případě Internet Exploreru také tzv. “Ovládací prvky ActiveX”. Prostřednictvím doplňků se prohlížeče stávají mnohem mocnější, zejména v oblasti kvality grafického zobrazení dynamických objektů. Nejrozšířenější je určitě Adobe Flash Player, který přehrává Adobe Flash aplikace. Asi nejznámější jsou bannerové reklamy, hry a animace. Druhý a mladší je Microsoft Silverlight, který zatím není tak rozšířený, ale díky svému zázemí v podobě Microsoftu představuje hlavního konkurenta Adobe Flash Playeru. Nelze opomenout JRE (Java Runtime Environment), což je sada základních tříd jazyka JAVA a JVM (Java Virtual Machine) 4. Toto prostředí umožňují spouštět java applety a aplikace JavaFX. Java applety jsou starší, JavaFX je technologická odpověď na aplikace Adobe Flash. V JRE běží i další typ aplikací, jako například Java Web Start, což jsou desktopové aplikace doplněné o sadu tříd, které umožňují distribuci přes webový prohlížeč. Mezi další doplňky patří méně známý Curl RTE (Curl Runtime Environment) přehrávající aplikace psané v jazyce Curl. Zcela mimo webový prohlížeč stojí technologie HTA (HTML Application) kompatibilní pouze s operačními systémy Windows s Internet Explorerem verze 5 a vyšším. Jedná se o DHTML aplikaci běžící mimo bezpečnostní model prohlížeče (např. může přistupovat k souborovému systému počítače). Následující přehled5 (viz Obrázek 3) zachycuje rozložení technologií v prezentační vrstvě. Jak je vidět, aplikace používající technologie Silverlight, JavaFX a Curl mohou být nasazené vedle klasické verze pro prohlížeč také jako desktopové aplikace.
3
Pomalu se také přidávají webové prohlížeče mobilních zařízení, ostatní zařízení (např. herní konzole) mají zatím minimální podíl. 4 V případě mobilních zařízení se jedná o Java ME (Java Micro Edition), kde místo JVM je KVM, což je speciálně upravená verze mající minimální paměťové nároky. 5
V přehledu uvádím i AIR aplikace (Adobe Internet Runtime application) běžící v prostředí AIR. Jedná se čistě o desktopové aplikace, ale vytvořené prostřednictvím HTML, Ajaxu, Adobe Flash a Adobe Flex technologií.
[- 4 -]
Obrázek 3: Technologie klienta
Základní technologie popíšu detailněji, ostatní, jako například doplňky či technologie běžící zcela mimo prohlížeč, budou vynechány.
3.1.
Značkovací jazyky, kaskádové styly a DOM
3.1.1. HTML HTML neboli HyperText Markup Language, je značkovací jazyk používaný pro prezentaci hypertextu, neboli informací, které jsou navíc vzájemně propojeny odkazy. Jeho aplikací tak vzniká propojená dokumentová pavučina, neboli World Wide Web. Jazyk vychází z podstatně složitějšího jazyka – metajazyka - SGML (Standard Generalized Marup Language), dá se říci, že HTML je vlastně podmnožinou SGML. HTML je sada tagů, které člení text do odstavců a jiných logických celků, formátují text a poskytují možnost přidávat do stránky další objekty (například obrázky). HTML prošlo poměrně dlouhým vývojem, je zajímavé, že jazyk podstatně ovlivnily prohlížeče, které rozšiřovaly jeho definici, autoři pak některá z těchto rozšíření zpětně přidávali do dalších verzí. Vše začalo v březnu roku 1989, když počítačový vědec Tim Berners-Lee ze švýcarského CERNu v Ženevě přišel s myšlenkou vytvoření distribuovaného hypertextového systému, což de facto znamenalo zahájení projektu WWW (World Wide Web). S přispěním Roberta Cailliauho byl v říjnu 1990 projekt hotov. Tehdejší název byl “WorldWideWeb”, tedy bez mezer. Pro prohlížení a editaci jednotlivých stránek byl vyvinut první prohlížeč (tzv. “The WorldWideWeb browser”) 6. V tomto stádiu se jednalo o HTML 0.9, pouze prostý text, žádné obrázky. V únoru 1993 přišlo NCSA (“National Center for Supercomputing Applications”) neboli “Národní centrum pro aplikace superpočítačů” s prohlížečem Mosaic, který již dokázal zobrazit obrázky. Hlavními autory byli Marc Andreesen a Eric Bina. Možná, aniž by to autoři tušili, učinili další krůček ve vývoji. Marc Adreesen NCSA opustil a založil “Mosaic Communications Corporation”, později přejmenovanou na “Netscape Communications”. V červenci následujícího roku bylo ohlášeno 6
později přejmenovaný na “Nexus”
[- 5 -]
založení konsorcia W3 zřízené CERNem a MIT (“Massachusetts Institute of Technology”). Organizace byla oficiálně založena 1. října 1994. Postupem času producenti prohlížečů obohacovali HTML o další nové prvky. Byla nutnost zavést opatření, které zachová kompatibilitu mezi jednotlivými modifikacemi HTML. Proto v listopadu 1995 vzniká pod hlavičkou IETF (“Internet Engineering Task Force”) návrh standardu HTML 2.0, který zahrnoval všechny běžně užívané prvky a přidal podporu formulářů či později i tabulek. Leden 1997 se nesl ve znamení HTML 3.2, což byl další standardizovaný milník ve vývoji. Oficiálně tak přibyla podpora tabulek, appletů, obtékání textu kolem obrázků či superscript a subscript. Netrvalo dlouho a v prosinci téhož roku bylo vypuštěno HTML 4.0, oficiálně standardizováno bylo v dubnu 1998. Tato verze přinesla některé funkčnosti z neúspěšné verze HTML 3.0, dále pak podporu kaskádových stylů (atributy id, class a style) či internacionalizace. V prosinci 1999 následovala poslední verze HTML 4.01, která přinesla několik oprav a vylepšení. V současné době se pracuje na verzi HTML 5 (již od roku 2004). Na vývoji se podílí W3C HTML WG (W3C HTML Working Group), WHATWG (Web Hypertext Application Technology Working Group), ale také i klíčoví hráči na trhu jako Microsoft, Apple, Mozilla nebo Opera a další organizace. HTML 5 uvádí celou sadu nových elementů. Například element canvas, který umožňuje kreslení grafiky pomocí JavaScriptu. Elementy video a audio, jak už název napovídá, přinesou zase podporu pro přehrávání videa a hudby. Doposud se musely využívat doplňky třetích stran, jako je například Adobe Flash Player. Některé nové elementy obsahují sémantické prvky (viz Obrázek 4). Jedná se o implementaci jednoduchého rozvržení webové stránky.
Obrázek 4: Srovnání zápisu rozvržení v HTML 4 a HTML 5 [zdroj: Hunt]
Finální podoba specifikace je ale stále zatím v nedohlednu (a ještě pár let bude), proto se masivní rozšíření v nejbližší době nedá očekávat. Nicméně již nyní prohlížeče podporují některé dílčí funkcionality (např. canvas). Až bude HTML 5 specifikace hotova, mohla by představovat konkurenta pro Adobe Flash v základních funkcionalitách (dynamická menu, grafy, animace). 3.1.2. XHTML Jak se HTML neustále doplňovalo o nové značky sloužící k prezentaci informací, pravá podstata HTML – struktura dat - neustále ustupovala do pozadí. Navíc, prohlížeče se snažily zobrazovat i chybně napsané HTML stránky, aby práci autorům zjednodušily. Důsledek byl ale ten, že dokumenty se stávaly po stránce sémantiky strojově nečitelné. Odpověď na sebe dlouho nenechala čekat a konsorcium W3 přišlo se standardem XHTML 1.0 (Extensible HyperText Markup Language). Stalo se tak v lednu 2000. V dnešní době lze XHTML zatím chápat jako nástupce HTML (což v budoucnu kvůli verzi HTML 5 zřejmě nebude pravda).
[- 6 -]
XHTML je HTML stránka splňující požadavky XML dokumentu. Vzhledem k tomu, že tyto požadavky jsou velmi přísné, je pak pro prohlížeče mnohem snazší celému dokumentu správně porozumět. Důraz je kladen hlavně na sémantiku informací. Jazyk se vůbec nestará o prezenční vlastnosti informace, ale dává značkám význam. Ty pak interpretují povahu informace, která je právě na stránce zobrazována. Důsledkem toho je třeba fakt, že informace jsou platformně nezávislé a jejich informační povahu pochopí nejen klasické prohlížeče ve stolních počítačích, ale třeba i hlasové čtečky pro hendikepované osoby. Jednoduchým příkladem budiž párová značka . V HTML ji používáme pro tučný text. V dobře napsané stránce pomocí XHTML by měla být použita pouze tam, kde se vyžaduje zdůraznění. Jak bude toto zdůraznění graficky interpretováno, o to se XHTML už nestará. XHTML bylo k dispozici ve 3 verzích, Strict, Transitional a Frameset, lišily se od sebe množstvím prvků a atributů, které podporovaly. V současnosti se upravují některé detaily okolo verze XHTML 1.1 a paralelně je také vyvíjena verze XHTML 2.0 a XHTML 5. 3.1.3. CSS CSS je zkratkou pro “Cascading Style Sheets” a jedná se o jazyk, který popisuje způsob zobrazení informací kódovaných pomocí značkovacího jazyka (nejčastěji HTML, XHTML, ale může se jednat o jakýkoliv druh XML jazyka, např. SVG). CSS je určeno k oddělení informace od její grafické interpretace. Definují se zde barvy, fonty, podklady či rozvržení dokumentu. Díky tomu dochází k lepší přístupnosti obsahu. Grafická podoba je flexibilnější, lze také celé schéma měnit podle potřeb (například různé grafické varianty jednoho webu). CSS pravidla lze jednoduše napsat tak, aby byla znovupoužitelná pro celou skupinu podobných dokumentů, což snižuje nároky na údržbu a zvyšuje přehlednost. Kaskádové styly mají další výhodu, lze je využít i pro definici ostatních „zobrazovacích“ metod, jako například pro tisk, hlasové čtečky či hmatové čtečky Braillova písma. Princip CSS je postaven na prioritách. Každá definice skupiny vlastností na stránce má svou prioritu. Výsledná podoba se sestaví podle těchto priorit. Můžeme tedy říci, že výsledek je snadno předvídatelný, a proto práce s kaskádovými styly není nikterak náročná. Nevýhodou je fakt, že implementace pravidel se v každém prohlížeči mírně liší. Někdy se jedná o chybu, někdy má odlišnost historické důvody. To vede k dvěma jevům. První je ten, že autoři stránek svá díla vybavují alternativními CSS kódy, které suplují odlišnosti a nutí dokument vypadat konzistentně i v jiných prohlížečích. Bohužel znamená to režii navíc, ať už ve vývoji, tak také i v údržbě. Druhý důsledek je zajímavější. Spolu s odlišnou interpretací javascriptu v prohlížečích zde vzniká ideální prostor pro vývoj javascriptových a CSS frameworků, které mají za cíl převzít tyto odlišnosti na svá bedra. O potřebě speciálního jazyka pro styly se hovořilo od počátku vzniku HTML, neboť jak značkovací jazyk rostl, vzrůstaly i nekompatibility ve stylu prezentace jednotlivých prohlížečů. CSS vzniklo z dvou jazyků, konkrétně z CHSS (Cascasind HTML Style Sheets) a SSP (Stream-based Style Sheet Proposal)7. Samotné CSS bylo oficiálně publikováno v prosinci 1996, samozřejmě již pod křídly tehdy fungujícího konsorcia W3C. V listopadu následujícího roku byla představena CSS verze 2 a na třetí verzi se stále zatím pracuje, finální podoba by měla být hotova někdy v tomto roce.
7
Autorem CHSS je Hakon Wium Lie, své dílo zveřejnil v prosinci 1994. SSP má naopak na svědomí Bert Bos, je také autorem prohlížeče Argo, které tento stylovací jazyk využívalo.
[- 7 -]
3.1.4. DOM DOM (Document Object Model) je objektově orientovaná reprezentace XML, HTML a XHTML dokumentu. DOM je rozhraní umožňující přístup či modifikaci obsahu, struktury, nebo stylu dokumentu, či jeho částí. Původně měl každý webový prohlížeč své vlastní specifické rozhraní k manipulaci s HTML elementy pomocí Javascriptu. Vzájemná nekompatibilita těchto rozhraní však přivedla konsorcium W3C k myšlence standardizace, a tak vznikl tzv. “W3C Document Object Model” (zkráceně W3C DOM). Tato specifikace je platformě a jazykově nezávislá. Předchozí specifická rozhraní byla nazvána “Intermediate DOM” (přechodný DOM). DOM umožňuje přístup k dokumentu jako ke stromové struktuře (tzv. strom), což je zároveň i datová struktura používaná ve většině XML parserů a XSL procesorů. Každému elementu odpovídá jeden uzel stromu. Odpovídající uzly mají samozřejmě i komentáře, instrukce pro zpracování atd. Tomuto způsobu reprezentace se říká „grove“8. Rozhraní DOM obsahuje funkce, které nám umožňují celý strom procházet, modifikovat jeho jednotlivé uzly, mazat je či přidávat. Ve stromu se můžeme pohybovat libovolně (na rozdíl od druhé technologie, tzv. sekvenčního modelu, kde strom procházíme od začátku do jeho konce). Nevýhodou je větší paměťová náročnost, neboť celý načtený dokument držíme v paměti. Specifikace W3C DOM jsou rozděleny do několika úrovní (tzv. DOM level), z nichž každá obsahuje povinné a volitelné moduly. K tomu, aby nějaká aplikace mohla prohlásit, že podporuje určitou DOM úroveň, musí tato implementovat všechny požadavky dané úrovně a všech nižších. V současné době vykreslovací jádra prohlížečů (Gecko, Trident, WebKit, KHTML, Presto) implementují DOM na úrovni 1 (jedná se o navigaci v dokumentu a manipulaci s obsahem). Úroveň 2 (jmenné prostory, události a filtrované pohledy) nejlépe zvládá Gecko, WebKit, KHTML a Presto. Implementace jader úrovně 3 jsou teprve v raném stádiu, nejdále je zatím Gecko.
3.2.
Skriptovací jazyky
3.2.1. Javascript Javascript je představitel skriptovacího jazyka na straně klienta. Jde o multiplatformní, dynamický, objektově orientovaný programovací jazyk podporující prototypování. Syntaxí je jazyk velmi podobný Javě či C++. S programovacím jazykem Java ale nemá nic společného. Programy napsané v Javascriptu se tedy spouští na straně klienta, tj. až po stažení stránky do prohlížeče. Nicméně existuje i využití na straně serveru9. Javascriptový kód lze vkládat přímo do HTML kódu, nebo odkazovat na něj z HTML podobně jako na kaskádové styly do samostatného souboru. Specifické pro Javascript jsou asociativní pole. Objekty jsou také asociativní pole. Názvy atributů jsou klíče a zápis o.klic = 1 je ekvivalentní k zápisu o[‘klic’] = 1. Atributy a jejich hodnoty mohou být měněny za běhu. Javascript podporuje dynamické přiřazení typů, tj. proměnné mohou být deklarovány těsně před tím, než se s nimi bude pracovat. Navíc typy nejsou asociovány s proměnnou ale s hodnotou proměnné. Funkce v Javascriptu jsou také samy o sobě objekty. Mohou mít své atributy, mohou být předány dále nebo s nimi lze manipulovat jako s kterýmkoli jiným objektem. Javascript podporuje také vnitřní funkce, uzávěry (tzv. closures), výjimky a místo klasické dědičnosti prototypování. 8 9
zkratka z Graph Representation of Property Values Tímto použitím se tato práce nezabývá.
[- 8 -]
Autorem javascriptu je Brendan Eich, někdejší zaměstnanec společnosti Netscape Communications Corporation. Eich jazyk vyvíjel pro prohlížeč Netscape Navigator. V prosinci roku 1995 byl prohlížeč poprvé vybaven jeho implementací. Na vývoji také participovala společnost Sun Microsystems. Javascript10 zažíval strmý růst v oblibě. Mezitím v srpnu roku 1996 společnost Microsoft vytvořila skriptovací jazyk Jscript, který byl velmi Javascriptu podobný. Jeho pozitiva měla být vyřešení problematiky přechodu času do nového tisíciletí neboli problém Y2K. Rivalita těchto dvou táborů vedla k velkému chaosu na poli klientského vývoje. V červenci 1997 společnost ECMA11 (European Computer Manufacturers Association) oficiálně vydala normu ECMA-262, kterou bylo standardizováno společné “jádro” jazyků a vznikl tzv. ECMAScript. Javascript nebo Jscript představují de facto ECMAScript plus nějakou tu funkcionalitu navíc. Poslední oficiální ECMA normou je ECMA262 verze 312 a vyhovuje jí Javascript 1.5. Vývoj Javascriptu nadále podporuje nezisková společnost Mozilla Foundation13. Aktivně zde působí také samotný autor, Brendan Eich. Poslední verzí Javascriptu je verze 1.9, kterou podporuje prohlížeč Firefox vyvíjený také pod Mozilla Foundation. Odlišnosti mezi Javascriptem a JScriptem řeší tzv. „javascriptové frameworky“. Nabízí navíc hotová řešení typických problémů (speciální formulářové prvky, obsluha událostí, pokročilé stylování, ajaxová komunikace, drag and drop, kontextová nápověda) a často přidávají i řadu vizuálních efektů (stíny, průhlednost, pohybové efekty). Mezi nejznámější představitele patří následující frameworky: Prototype Dojo YUI JQuery Google Web Toolkit (GWT) nebo další, méně známe: Ext JS, Mochikit, MooTools, qooxdoo, Rico atd. Vzhledem k rozsáhlosti nebudou dále tyto frameworky rozebírány, i když představují velmi důležitý prvek ve skladbě prezentační vrstvy. 3.2.2. JScript JScript, soupeř Javascriptu z dílny společnosti Microsoft, implementace ECMAScriptu podle normy ECMA-262 verze 3. Stejně jako u Javascriptu, je základní charakteristika tohoto jazyku identická, tj. skriptovací, interpretovaný, objektově orientovaný jazyk používaný zejména na klientské straně. Velkým omezením je však fakt, že JScript lze používat pouze v kombinaci s ASP (Active Server Pages) v prohlížeči Internet Explorer14. JScript byl poprvé představen v prohlížeči Internet Explorer 3.0 v roce 1996. Aktuální verze jazyka nese označení 5.8. Je podporovaná v Internet Exploreru 8.0, Internet Exploreru 6.0 v mobilní verzi. Tato verze je podobná Javascriptu 1.5 a vychází z norem ECMA-262 (3. vydání) a ECMA-327 a doporučení RFC-462715 (JSON).
10
Nejprve se jazyk jmenoval “Mocha”, později byl přejmenován na “LiveScript” a až teprve poté na Javascript. http://www.ecma-international.org/ 12 http://www.ecma-international.org/publications/standards/ecma-262.htm 13 http://www.mozilla.org/ 14 A také v prostředí Windows Script Host nebo v HTML aplikacích. 15 http://www.ietf.org/rfc/rfc4627.txt 11
[- 9 -]
3.2.3. VBScript Dalším scriptovacím jazykem z Microsoft dílny je VBScript. Jako předchozí zástupci, vkládá se přímo do webových stránek a lze díky němu rozšířit spektrum funkcí v prohlížeči, než jaké nabízí prostý značkovací jazyk. Spolu s JScriptem s ním lze pracovat ve Windows Script Host prostředí či na straně serveru v ASP nebo také v kombinaci s HTA (HTML Application). Syntaxe vychází z programovacího jazyka Visual Basic. Tento jazyk má v operačním systému poměrně velké pravomoci, lze skrze něj přistupovat k velkému množství programů, představuje tak jisté bezpečnostní riziko. Například velmi známý vir “I love you” je toho důkazem. Prohlížeče Firefox či Opera tento jazyk nepodporují.
4.
Komunikace klienta se serverem
4.1. HTTP 4.1.1. Obecná charakteristika Hypertext Transfer Protocol je protokol aplikační vrstvy patřící do rodiny protokolů TCP/IP. HTTP je určený k výměně hypertextových dokumentů a je nejvíce využívaným protokolem v celém internetu. Protokol vychází z architektury klient – server a jeho aktuální verze nese označení 1.1. Původní verze 1.0. byla pomalejší, pro každý dokument na serveru se vytvářela nová spojení, naproti tomu verze 1.1 spojení znovuvyužívá (např. při stahování obrázků). Protokol obvykle běží na portu 80. Využívá se také pro přenos souborů či ve webových službách. HTTP přistupuje ke zdrojům prostřednictvím URL. Vedle HTTP protokolu existuje také protokol HTTPS, který poskytuje oproti HTTP ochranu přenášených dat v podobě šifrování. Protokol je postaven na konceptu „požadavek/odpověď“. Klient (internetový prohlížeč) pošle dotaz jako prostý text ve formě: typ HTTP metody, adresa zdroje na serveru a verze HTTP protokolu. K dotazu jsou přiloženy další informace, tzv. hlavičky (request headers), prázdný řádek a případně tělo požadavku. HTTP-metoda URL-dokumentu HTTP-verze HTTP hlavičky (každá na nový řádek) prázdný řádek data (u HTTP metody POST)
Server klientovi vrátí odpověď. Ta se skládá z HTTP metody, HTTP stavového kódu, stavového hlášení. Dále z hlaviček (response headers), prázdného řádku a samotných dat. HTTP-verze HTTP-stavový-kód stavové-hlášení HTTP hlavičky (každá na nový řádek) prázdný řádek obsah odpovědi
Když bude klient požadovat další informace od stejného serveru, server nemá možnost z dotazu určit, jestli tento dotaz nějak souvisí s dotazem původním. Proto HTTP protokol nazýváme bezestavový. Tuto vlastnost lze překonat pomocí HTTP cookies, které byly k tomuto účelu navrženy.
[- 10 -]
Obrázek 5: HTTP požadavek, část HTTP odpovědi
4.1.2. HTTP stavové kódy HTTP stavový kód je číslo, kterému je také přiřazeno jeho stavové hlášení. Jedná se o kvalifikaci operace, kterou server na základě požadavku klienta vykonal, nebo se vykonat pokusil. Kódy jsou podle čísel sdruženy do skupin. Tabulka 4.1. Skupiny HTTP stavových kódů Skupina Informační Úspěšné provedení
Rozpětí kódů 100 - 199 200 – 299
Popis Provizorní odpověď. Požadavek klienta byl úspěšně zpracován. Přesměrování 300 – 399 Splnění tohoto požadavku je podmíněno provedením další akce (přesměrováním). Chyba požadavku 400 – 499 V požadavku klienta je pravděpodobně chyba a server ho nemohl zpracovat. Chyba serveru 500 – 599 Při zpracování požadavku došlo k interní chybě na serveru. Při využití techniky AJAX se pravděpodobně setkáme s následujícími konkrétními kódy: Tabulka 4.2. HTTP stavové kódy využívané v ajaxové komunikaci Stavový kód 200
Stavové hlášení OK
304
NOT MODIFIED
401
UNAUTHORIZED
403 404
FORBIDDEN NOT FOUND
Popis hlášení Server požadavek úspěšně zpracoval. Obecně to znamená, že server poskytl požadovanou stránku. Požadovaná stránka nebyla od posledního požadavku změněna. Když server vrátí tuto odpověď, nevrátí obsah příslušné stránky. Požadavek vyžaduje ověření. Tuto odpověď může server vrátit u stránky, která je přístupná až po přihlášení. Server nemá povoleno daný požadavek vykonat. Server nemůže požadovanou stránku nalézt. Server často zobrazuje tento kód například tehdy, když reaguje na požadavek na stránku, která na serveru neexistuje.
[- 11 -]
4.1.3. HTTP Metody Doporučení RFC 261616 definuje mimo jiné následující HTTP metody: GET POST PUT DELETE HEAD Metody GET, PUT, DELETE a HEAD je vhodné využít v případě, že je požadavek idempotentní, neboli pokud více požadavků vrací stále totožný výsledek. Metody GET a HEAD se označují jako bezpečné, tj. že při jejich volání dochází pouze ke čtení informací ze serveru a k žádným jiným operacím. Metody GET a POST jsou často jediné, používané. Metoda GET se hodí na read-only operace, neboli operace, které data ze serveru pouze čtou. Například vždy, když zadám do prohlížeče adresu určitého produktu, vždy také očekávám, že se mi stránka s kompletními informacemi zobrazí. Výsledky, které volání této metody vrací, mohou být cachovány. Při použití této metody se všechna předávaná data připojují k volanému URL jako parametry. Seznam parametrů je oddělen od URL vlastního požadavku symbolem otazníku, hodnota parametru od názvu parametru ampersandem &, takže výsledný tvar může vypadat následovně: http://www.server.cz/index.php?názevParametru=hodnotaParametru
URL má však omezení na svojí délce. Limity jsou jak v prohlížečích, tak na straně webových serverů a jsou různé. Proto lze tímto způsobem předat pouze omezené množství dat a tedy například přenos binárních dat je tímto způsobem nemyslitelný. V případě, že se jedná o operaci, kdy na serveru dochází k vytvoření, změně nebo vymazání informací, je vhodné využít HTTP metodu POST. Ta není idempotentní, proto také se musí počítat s tím, že každé její vyvolání může mít různé vedlejší efekty na straně serveru. Například přidávám-li do košíku zboží vždy po jednom kusu, celkový počet položek bude vždy o jeden kus vyšší, navíc některé zboží nemusí být již v takovém množství k dispozici. Další typické použití je odesílání formulářů nebo binárních dat. Data jsou tentokrát předávány v těle HTTP požadavku, jsou ale stejně formátovány, tj. jednotlivé dvojice parametr/hodnota jsou odděleny ampersandem &, dvojice jsou pak opět ve tvaru názevParametru=hodnotaParametru. Výsledky POST metody nejsou cachovány, není-li hlavičkami určeno jinak. Metoda HEAD je identická metodě GET s tím rozdílem, že odpověď nesmí obsahovat tělo, ve které se přenáší zpráva (textový výstup) ze serveru. Pomocí této metody server odpoví pouze hlavičkami. HTTP metoda PUT se používá pro vytvoření zdroje na volané adrese, popřípadě pro jeho aktualizaci, pokud již zdroj na dané adrese existuje. Metoda DELETE se používá k vymazání zdroje. Tyto metody jsou ovšem nahrazovány metodou POST a původní účel metod se ztrácí 17. 16
http://www.w3.org/Protocols/rfc2616/rfc2616.html
17
Naopak k původnímu významu se vrací architektura REST, která bere metody GET, POST, PUT a DELETE jako základní architektonický prvky a ve stejném duchu jde i struktura tzv. „REST“ aplikace.
[- 12 -]
4.2.
Formát dat odpovědi
4.2.1. Prostý text Klasická a nejběžnější situace už jen proto, že takto se data předávají při běžném načítání celých HTML nebo XHTML stránek (viz Obrázek 6). Prostý text lze ale využít i v případě přenášení fragmentů.
Obrázek 6: Kompletní HTTP odpověď na požadavek zobrazení kompletní HTML stránky
Získání odpovědi ve formě prostého textu je dostačující v těch nejjednodušších případech, tj. třeba pokud je odpověď zobrazena v dialogovém okně nebo pokud je odpovědí jednoslovný výraz indikující úspěch či neúspěch volané serverové logiky. Prostý text nemá žádnou strukturu a je obtížné provést jeho zpracování pomocí Javascriptu. Také se tím stává složitější dynamicky generovat obsah stránek. Můžeme však využít atributu innerHTML u elementů HTML. Atribut innerHTML je nestandardním atributem nejdříve implementovaným v Internet Exploreru, později i v dalších prohlížečích. Jedná se o řetězec reprezentující obsah daného elementu včetně dalších HTML značek. Pokud tedy server vygeneruje jako odpověď text nebo HTML kód, můžeme tento řetězec navěsit do elementu s id „cilovyElement“ pomocí následující konstrukce document.getElementById("cilovyElement").innerHTML = odpovedZeServeru;
Tento přístup má dvě velké nevýhody. První vychází z toho, že atribut innerHTML není standardním atributem HTML, což činí jeho implementaci v prohlížečích volitelnou. Většina tento atribut podporuje, ovšem liší se způsoby implementace. Například některé prohlížeče mají pro určité elementy HTML tento atribut nastavený pouze pro čtení. Není pak možné tento atribut modifikovat. Druhá nevýhoda je již také zmíněná nestrukturovanost, z které vyplývá nulová flexibilita obdrženého kódu, obtížná manipulace a udržovatelnost. Pokud server odpovídá prostým textem, je HTTP hlavička Content-Type nastavena na hodnotu text/plain nebo text/html. 4.2.1. XML Složité datové struktury jsou dobrými kandidáty na odeslání ve formátu XML. Moderní prohlížeče mají poměrně dobrou podporu pro procházení dokumentu XML a také pro modifikaci struktury a obsahu dokumentu XML. Jak přesně prohlížeč zpracuje dokument XML, který vrátí server jako svojí odpověď? Prohlížeče zachází s XML dokumentem v souladu se specifikací W3C DOM. W3C DOM [- 13 -]
specifikuje pestrou sadu funkcí aplikačního rozhraní pro manipulaci a vyhledávání v dokumentech XML. Prohlížeče odpovídající standardu DOM musí implementovat tyto funkce a dodržet předepsané chování a tak maximalizovat přenositelnost skriptů mezi prohlížeči. DOM je nezávislý na jakémkoliv programovacím jazyku. Typicky je k němu přistupováno pomocí Javascriptu, ale není to podmínka. Díky jeho jednotnému a konzistentnímu rozhraní lze pro přístup k němu použít jakýkoliv skriptovací jazyk. Tabulka 4.1 shrnuje užitečné atributy DOM elementů, tabulka 4.2 pak užitečné metody. Tabulka 4.3. Atributy DOM elementů užitelné pro zpracování XML dokumentů Název atributu childNodes firstChild lastChild nextSibling nodeValue parentNode previousSibling
Popis Vrací pole potomků daného elementu Vrací prvního přímého potomka daného elementu Vrací posledního potomka daného elementu Vrací element následující ihned za daným elementem Specifikuje atribut pro čtení/zápis reprezentující hodnotu elementu Vrací rodičovský uzel elementu Vrací element předcházející daný element
Tabulka 4.4. Metody DOM elementů užitečné pro zpracování XML dokumentů Název metody getElementById(id) getElementsByTagName(nazev) hasChildNodes() getAttribute(nazev)
Popis Vrací element podle hodnoty atributu id Vrací pole potomků daného elementu se specifikovaným názvem značky Vrací true nebo false podle toho, zda element má potomky Vrací hodnotu atributu nazev daného elementu
Výpis 4.1. Tělo odpovědi ze serveru, data ve formátu XML ŠályRukaviceČepiceTrikaKraťasy
Je asi na první pohled jasné, jaké výhody v tomto případě využití XML formátu přináší. Na druhou stranu je použití XML dokumentu složitější a práce s ním zdlouhavá. Pro doplnění, pokud server odpovídá XML dokumentem, je HTTP hlavička Content-Type nastavena na hodnotu text/xml.
[- 14 -]
4.2.2. JSON JSON (Javascript Object Notation) je formát pro výměnu dat a je to současně hlavní konkurent formátu XML. Navrhl jej Douglas Crockford18 a jeho specifikaci lze najít v RFC 462719. JSON se objevil ve chvíli, kdy se na webu pro výměnu dat používal převážně formát XML. Ten v očích javascriptových vývojářů trpěl některými nedostatky, např. práce s ním byla složitá (bylo nutné používat DOM, řešit přítomnost uzlů obsahujících pouze bílé znaky apod.). Ačkoliv při zápisu celých dokumentů JSON nemůže (a ani nemá) formátu XML konkurovat, v zápisu krátkých strukturovaných dat vyměňovaných webovými aplikacemi konkurenční boj vyhrál JSON. Zápis JSON je platným zápisem jazyka JavaScript (nicméně je jazykově nezávislý a jeho implementace najdeme i v jiných jazycích). To je jedna z jeho výhod. Ze samotného pohledu na zápis v JSON rovnou vidíme, jak s ním budeme v programu pracovat. Následující ukázka je odpověď serveru zapsaná formátem JSON. Odpověď je shodná, jako v předchozí kapitole, kde byla zapsaná ve formátu XML. Výpis 4.2. Tělo odpovědi ze serveru, data ve formátu JSON { druhy:{ zimni:{ kategorie:['Šály','Rukavice','Čepice'] }, letni:{ kategorie:['Trika','Kraťasy'] } } }
Na první pohled je zřejmé, že tento formát je o něco úspornější, než formát XML. Hlavní výhodou je ale to, že s daty můžeme ihned v Javascriptu pracovat. Nemusíme využívat DOM k tomu, abychom část dat načetli do nějakého pole. Pomocí JSON formátu tak vynecháváme jeden krok při zpracování.
4.3.
Speciální techniky komunikace
S rostoucí oblibou webových aplikací rostly také nároky uživatelů. Zásadní problém představovala nutnost obnovovat stránku s každým požadavkem. Proto vznikly techniky, které se snažily tento problém vyřešit. Jednalo se nejprve o využití elementu IFRAME, nebo méně známé techniky využívající cookies. S rozšířením techniky AJAX obě předchozí zanikly a již se nepoužívají. 4.3.1. IFRAME Tento odstavec popisuje komunikaci se serverem pomocí HTML elementu IFRAME. Pro představu celého principu bude nejlepší jednoduchá ukázka. Následující kód je zdrojový text HTML stránky, která obsahuje jeden odkaz a jeden element IFRAME. Když uživatel klikne na daný odkaz, zobrazí se odpověď ze serveru (obsah souboru server.html) do elementu IFRAME. Element IFRAME má rozměry šířku a výšku nastavenou na 0, tudíž ho uživatel nevidí. V tomto konkrétním případě, když uživatel klikne na odkaz Klikni, vypíše se do dialogového okna nápis „Ahoj“.
Výpis 4.3. Část zdrojového kódu souboru klient.html <script type="text/javascript"> function zobraz(aZprava) { alert(aZprava); } <iframe name="frame1" style="width:0px; height:0px; border: 0px"> Klikni
Výpis 4.4. Zdrojový kód souboru server.html <script type="text/javascript"> window.parent.zobraz('Ahoj');
Tento příklad ovšem trpí jedním základním problémem a to je chování tlačítek „Obnovit“ a „Zpět“. Uživatel očekává, že pokud stisknu „Obnovit“, znovunačte se mi stránka klient.html. Bohužel v tomto případě se opětovně vykoná zobrazení dialogu s nápisem. Proto musíme příklad doplnit o několik maličkostí, poté již půjde o plnohodnotný příklad techniky. Soubor server.html zůstává beze změny. Výpis 4.5. Část zdrojové kódu souboru klient2.html <script type="text/javascript"> function zobraz(aZprava) { alert(aZprava); } function zavolejServer() { var tempIFrame = document.createElement('iframe'); var IFrameObj = document.body.appendChild(tempIFrame); var IFrameDoc = IFrameObj.contentWindow.document; IFrameDoc.location.replace('server.html'); return false; } Klikni
Přibyla funkce zavolejServer(), která je vyvolána po kliknutí na odkaz. Vytvoří element IFRAME, vsadí ho do stránky a nastaví mu adresu, na kterou se má přesměrovat. V případě, že není podporován Javascript, vyvolá se adresa odkazu (zde dummy.html), nikoliv funkce zavolejServer(). Pro zjednodušení byla funkce osekaná na funkční minimum, je totiž mimo jiné nutné nastavit vlastnosti elementu IFRAME (výška, šířka), zajistit kompatibilitu mezi prohlížeči (obzvlášť v minulých dobách tato skutečnost vyžadovala nejvíce řádků kódu) a také ošetřit „recyklaci“ elementu IFRAME. Pokud totiž teď 10x klikneme na daný odkaz, vytvoří a vloží se nám 10 elementů do stránky. Pokud bychom chtěli techniku využít na odeslání formuláře, postup by nebyl již o moc složitější. Pomocí DOM bychom procházeli formulářové prvky a postupně sestavovali řetězec s názvy a hodnotami formulářových prvků. Vytvořený řetězec bychom poté připojili k volanému URL serverového skriptu. V HTML se volání logiky navěsí na formulářový element form a vyvolání nastaví pomocí atributu onsubmit. Opět je zajištěná zpětná kompatibilita s prohlížeči, které neumí Javascript zpracovat.
[- 16 -]
Výpis 4.6. Zdrojový kód souboru klient3.html function vytvorRetezec(aFormular) { formular = document.forms[aFormular]; var retezec = ''; for (i = 0; i < formular.elements.length; i++) { if (formular.elements[i].name != '') { retezec += (retezec == '') ? '?' : '&'; retezec += formular.elements[i].name+'='+ escape(formular.elements[i].value); } } return retezec; } function zavolejServer() { ... IFrameDoc.location.replace('server.html'+vytvorRetezec('form1')); ... }
4.3.2. Cookies Druhým způsobem, jak vyměňovat data se serverem a zároveň neobnovovat stránku, je využití cookies a dynamického vytvoření obrázku. Technika je opět zastaralá a již se nepoužívá. Použití budu demonstrovat opět na jednoduchém příkladu. Na stránce je jednoduchý formulář, obsahující jedno editovatelné textové políčko. Po stisku tlačítka odeslat se vyvolá javascriptová funkce zavolejServer() se jménem formuláře jako jejím argumentem. Tato funkce nejprve vymaže hodnotu cookie testcookie. Poté vytvoří obrázek a jako adresu obrázku uvede adresu serverového skriptu, který chceme vzdáleně volat. Pomocí již známé funkce vytvorRetezec() sestaví řetězec z formulářových políček (zde jediné pole s názvem hodnota) a jejich hodnot a nalepí jej za jméno serverového skriptu. V tuto chvíli je kontaktován server a paralelně dál také běží Javascript na klientovi. Je vyvolána funkce zpracujCookie(). Ta běží ve smyčce s opakováním 10 milisekund do té doby, než je hodnota cookie testcookie naplněna nějakou hodnotou (tu naplní paralelně server, který jsme kontaktovali). Hodnotu cookie získáváme pomocí funkce vratCookie(), která pro jednoduchost zde není uvedena (v přiložené ukázce samozřejmě je). Ve chvíli, kdy je v cookie již nějaká hodnota, klient ji pomocí window.alert vypíše do dialogového okna a běžící smyčku Javascriptu ukončí.
[- 17 -]
Výpis 4.7. Zdrojový kód souboru cookies-klient.html ... <script type="text/javascript"> function zpracujCookie() { var cookie = vratCookie("testcookie"); if (cookie == "") { window.setTimeout("zpracujCookie()",10); } else { window.alert(cookie.replace(/\+/g, " ")); } } function zavolejServer(aFormular) { var d = new Date(); d.setTime(d.getTime() - 1); document.cookie = "testcookie=; expires=" + d.toGMTString(); var i = new Image(); i.src = "cookies-server.php"+vytvorRetezec(aFormular); zpracujCookie(); } ...
Výpis 4.8. Zdrojový kód souboru cookies-server.php
Serverový skript je napsaný v jazyce PHP a je velice jednoduchý. Klientovi pošle cookie testcookie s nastavenou hodnotou například na „Hodnota: 4“, zadal-li uživatel do formulářového políčka hodnotu 4. 4.3.3. Ajax Technika AJAX ke komunikaci a přenosu dat využívá objekt XMLHttpRequest. Jedná se o techniku současné doby, která se hojně používá a těší se mimořádné oblibě. Vzhledem k rozsáhlosti informací bude popsána v následující kapitole.
5. Ajax 5.1.
Co je to Ajax?
Ajax (Asynchronous Javascript and XML) není specifická technologie (ačkoliv je tak někdy mylně charakterizována), nýbrž skupina technik, které jsou využity pro tvorbu interaktivních webových aplikací či RIA aplikací. S využitím těchto technik může aplikace stahovat informace ze serveru asynchronně, tj. na pozadí, bez toho aniž by uživatel musel čekat na výsledek. Během získávání dat se celá aktuální stránka nemusí aktualizovat. Data se získávají přes objekt XMLHttpRequest. Ačkoliv se ve zkratce vyskytuje slovo Javascript a XML, tyto technologie nemusejí být využity. Dokonce samotný proces nemusí nutně probíhat asynchronně, nýbrž synchronně. [- 18 -]
V následujícím textu budou všechny ukázky demonstrovány v Javascriptu.
5.2.
Historie Ajaxu
Samotný termín AJAX poprvé použil Jesse James Garrett ve svém článku [28], který byl publikován v únoru roku 2005. Samotné principy jsou ale mnohem starší. První, kdo využíval asynchronní komunikaci se stranou serveru, byly Java applety (rok 1995). O rok později byl v Internet Exploreru uveden tag IFRAME(viz předchozí kapitola). V roce 1999 společnost Microsoft představila prohlížeč Internet Explorer 5, ten obsahoval podporu již výše zmíněného objektu XMLHttpRequest jakožto ActiveX ovládacího prvku. Objekt byl v roce 2000 nasazen v programu Outlook Web Access, což je webové rozhraní emailového klienta na Microsoft Exchange Server. Masivnímu rozšíření ovšem stále bránila nulová podpora ostatních prohlížečů. Situace se dramaticky změnila v roce 2002, kdy autoři prohlížeče Mozilla ve verzi 1.0 přišli s první nativní implementací objektu XMLHttpRequest. Následoval je Apple v prohlížeči Safari ve verzi 1.2, dále Opera Software s prohlížečem Opera 8.0 a samozřejmě Microsoft, který nativní podporu přidal do Internet Exploreru 7.0. Velkou zásluhu na rozšíření má také společnost Google, která svojí aplikací Google Maps20 ukázala praktické a efektivní využití těchto technik.
5.3.
Použití objektu XMLHttpRequest
Objekt XMLHttpRequest si lze představit jako HTTP API ECMAScriptu. Jinými slovy XMLHttpRequest implementuje rozhraní, které umožňuje skriptům vykonávat HTTP funkcionalitu. Abychom mohli objekt XMLHttpRequest využívat k odeslání požadavků a zpracování odpovědí, musíme nejdříve vytvořit jeho instanci pomocí krátkého kódu v Javascriptu. Důsledkem toho, že objekt XMLHttpRequest není standard W3C, vytváří se jeho instance několika způsoby (v závislosti na použitém prohlížeči). Kód v Javascriptu musí obsahovat logiku, která určí, zdali objekt vytvořit jako nativní objekt (Firefox, Safari,…) či jako objekt ActiveX (v případě Internet Exploreru). Výsledný kód může vypadat například takto: Výpis 5.1. Vytvoření instance objektu XMLHttpRequest var xmlHttp; function createXMLHttpRequest() { if (window.ActiveXObject) { xmlHttp = new ActiveXObject(“Microsoft.XMLHTTP”); } else if (window.XMLHttpRequest) { xmlHttp = new XMLHttpRequest(); } }
Nejdříve vytvoříme globální proměnnou s názvem xmlHttp, do které uložíme ukazatel na objekt. Funkce createXMLHttpRequest() zajistí vytvoření instance objektu XMLHttpRequest. Funkce obsahuje jednoduchou rozhodovací logiku, která určí, jak bude objekt vytvořen. Volání window.ActiveXObject vrací buďto objekt nebo null, což je výrazem if vyhodnoceno jako true nebo false a je tak indikováno, jestli prohlížeč podporuje ActiveX či nikoliv. Pokud ano, je objekt XMLHttpRequest vytvořen jako nová instance objektu ActiveXObject, kde jako argument zadáme konstruktoru řetězec definující typ objektu ActiveX, který chceme vytvořit. V tomto případě konstruktoru předáme argument Microsoft.XMLHTTP. Pokud volání window.ActiveXObject neuspěje, je vyhodnoceno tělo příkazu else, které rozhodne, jestli prohlížeč implementuje objekt 20
http://maps.google.cz/
[- 19 -]
XMLHttpRequest jakožto nativní objekt Javascriptu. Pokud volání window.XMLHttpRequest uspěje, je vytvořena instance objektu XMLHttpRequest.
5.4.
Metody objektu XMLHttpRequest
V následující tabulce je vypsáno všech 6 metod, které je možné na objektu XMLHttpRequest volat. Tabulka 5.1. Metody objektu XMLHttpRequest Zjednodušená signatura metody abort() getAllResponseHeaders() getResponseHeader(‚hlavička‚) open(‚metoda‚, ‚url‚)
Popis chování metody Přeruší aktuální požadavek. Vrátí všechny hlavičky HTTP požadavku ve formě párů klíč / hodnota. Vrátí hodnotu zadané hlavičky ve formě řetězce. Nastaví parametry volání serveru. Argument metoda může nabývat například hodnot GET, POST. Argument url představuje požadované URL, které může být relativní nebo absolutní. Tato metoda má další tři nepovinné argumenty. Odešle požadavek serveru. Nastaví určenou hlavičku na zadanou hodnotu. Metoda open() musí být zavolána před jakýmikoliv pokusy o nastavování hlaviček.
5.4.1. Metoda open Začněme metodou open(). Její úplná signatura vypadá takto void open(string aMetoda, string aUrl, boolean aAsynch, string aUzivJmeno, string aHeslo)
Tato metoda nastavuje parametry volání serveru. Jako jediná je určena pro inicializaci požadavku. Má 2 povinné a 3 nepovinné argumenty. Je nutné zadat požadovanou HTTP metodu přenosu (nejčastěji GET, POST) a URL, na které budeme požadavek směřovat. Volitelně je možné zadat také argument typu boolean specifikující, jestli má být volání asynchronní (výchozí hodnota je true). Pokud zadáme hodnotu false, bude se akce provádět synchronně, to znamená, že nejprve se bude čekat na odpověď serveru, poté se bude pokračovat ve zpracování. Poslední dva argumenty umožňují zadat jméno a heslo k HTTP autentizace. Je potřeba se ujistit, zdali daný prohlížeč zvolenou HTTP metodu podporuje. Také zadávání jména a hesla není zcela ideálně podporováno u všech prohlížečů.
[- 20 -]
5.4.2. Metoda send Tato metoda provede vlastní požadavek na server. void send(aObsah)
Pokud byl požadavek deklarován jako asynchronní, vrací tato metoda řízení okamžitě, v opačném případě čeká na příchod odpovědi od serveru. Nepovinný argument může být instance objektu DOM, vstupní tok nebo řetězec. Argument předávaný metodě je odeslán jako část těla požadavku, tedy tento argument využijeme v případě, že odesíláme data metodou POST. 5.4.3. Metoda setRequestHeader Tato metoda nastavuje hodnotu specifikované hlavičky požadavku. void setRequestHeader(string aHlavicka, string aHodnota)
Jako argumenty bere řetězec reprezentující název požadované hlavičky a řetězec reprezentující hodnotu, na kterou má být hlavička nastavena. Tato metoda může být volána až po zavolání metody open(). 5.4.4. Metoda abort Metoda zruší aktuální HTTP požadavek. Navíc nastaví atribut readyState na hodnotu 0. void abort()
5.4.5. Metoda getAllResponseHeaders Metoda vrací řetězec obsahující hlavičky odpovědí. V jakém tvaru hlavičky budou a jak budou odděleny, závisí na použitém prohlížeči. string getAllResponseHeaders()
5.4.6. Metoda getResponseHeader Tato metoda je podobná předchozí metodě. Rozdíl je pouze v tom, že jako argument přijímá název hlavičky, o jejíž hodnotu máme zájem. Tuto hodnotu pak vrací jako řetězec. String getResponseHeader(string aNazev)
5.5.
Atributy objektu XMLHttpRequest
Objekt XMLHttpRequest obsahuje kromě výše popsaných metod také několik atributů, které jsou představeny v tabulce 3.2. Tabulka 5.2. Atributy objektu XMLHttpRequest Název atributu onreadystatechange
readyState responseText responseXML status statusText
Popis významu atributu Ukazatel na obslužný kód (tzv. callback), který je spouštěn při každé změně interního stavu objektu, typicky se jedná o funkci v Javascriptu. Stav požadavku. Odpověď serveru ve formě řetězce. Odpověď serveru ve formě XML. Tento objekt může být dále zpracováván a zkoumán jako DOM objekt. HTTP Stavový kód získaný od serveru. Textová verze stavového kódu. [- 21 -]
Atribut readyState může nabývat následujících hodnot: 0 (neinicializováno) 1 (načítání) 2 (načteno) 3 (interaktivní) 4 (dokončeno) Možné hodnoty atributu status odpovídají HTTP stavovým kódům. Dva nejběžnější jsou: 200 (OK, operace proběhla úspěšně) 404 (Not found, volané URL nebylo nalezeno)
5.6.
Ajax v praxi
5.6.1. Komunikace se serverem Tento příklad bude demonstrovat jednoduchou komunikaci se serverem pomocí HTTP metody GET. Veškerý kód je obsažen v souboru ajax.html, (viz Výpis 5.2). Po stisknutí tlačítka se zavolá metoda zavolejServer(). Ta nejprve vytvoří objekt XMLHttpRequest. Poté zaregistruje callback funkci callbackFunkce() a konečně vyvolá požadavek na server HTTP metodou GET na cílový soubor text.txt. Jedná se o prostý textový soubor s textem “Ahoj!”. Server je kontaktován a jako odpověď vrací obsah souboru text.txt, tedy “Ahoj!”. Tato hodnota je uložena v atributu responseText XMLHttpRequest objektu. Řízení je předáno callback metodě callbackFunkce(), neboť právě ona byla pomocí metody onreadystatechange() určena k tomu, aby byla vyvolána, až ze serveru přijde odpověď. V této metodě se již pouze testuje, zdali stav komunikace je ve stavu dokončeno (hodnota 4) a zdali stavový kód poslaný serverem zpět je ve stavu OK (hodnota 200). Pokud ano, prohlížeč zobrazí standardní výstražné okno s textem “Ahoj!” (viz Obrázek 7). Vzhledem k tomu, že metoda open byla volána pouze s dvěma povinnými argumenty, tak pro třetí argument byla použita výchozí hodnota true, která říká, že náš požadavek má probíhat asynchronně. Výpis 5.2. Zdrojový kód souboru ajax.html <script type="text/javascript"> var xmlHttp; function callbackFunkce() { if(xmlHttp.readyState == 4) { window.alert(xmlHttp.responseText); } } function zavolejServer() { if(window.ActiveXObject) { xmlHttp = new ActiveXObject("Microsoft.XMLHTTP"); } else if (window.XMLHttpRequest) { xmlHttp = new XMLHttpRequest(); } xmlHttp.open("GET", "text.txt");
Obrázek 7: Výsledek volání callback funkce callbackFunkce()
5.6.2. Asynchronní vs. synchronní volání Předpokládejme ale situaci, kdy nevoláme soubor text.txt, nýbrž soubor text.php, jehož kód vypadá následovně: Výpis 5.3. Soubor text.php umístěný na serveru
Zavoláme server. Ten bude nejprve 5 vteřin čekat, až teprve poté pošle klientovi textovou zprávu “Ahoj!”. V případě, že jsme vyvolali požadavek asynchronně (tj. metodu open jsme volali pouze s dvěma argumenty, nebo se třemi, kde třetí argument měl hodnotu true), prohlížeč na 5 vteřin “nezamrzne”. Všechno bude v normálním stavu a po 5 vteřinách na nás najednou vyskočí okno s textem “Ahoj!”. Pokud ale zavoláme metodu open synchronně (třetí argument s hodnotou false), prohlížeč po stisknutí tlačítka na 5 vteřin zamrzne, rozmrazí ho až odpověď ze serveru. 5.6.3. Asynchronní neznamená vícevláknový Je také dobré vědět, že Javascript není vícevláknový, tj. volání funkcí se řadí do FIFO fronty, první zařazená funkce bude také jako první spuštěná. Funkce jsou volány jedna po druhé. Asynchronnost může vývojáře vést k domněnce, že Javascript zavolá callback metodu v jiném vlákně. To ale není pravda! Pokud bychom tedy náš kód upravili a za metodu send() přidali volání metody sleep(), která zabere 30 sekund (je úplně jedno čím), výsledný text „Ahoj!“ se zobrazí až po ukončení této metody. Jinými slovy, metoda callbackFunkce() bude vyvolána až po kompletním dokončení metody zavolejServer(), i když odpověď ze serveru již dávno přišla.
[- 23 -]
Výpis 5.4. Upravený zdrojový kód souboru ajax.html function zavolejServer() { if(window.ActiveXObject) { xmlHttp = new ActiveXObject("Microsoft.XMLHTTP"); } else if (window.XMLHttpRequest) { xmlHttp = new XMLHttpRequest(); } xmlHttp.open("GET", "text.txt"); xmlHttp.onreadystatechange = callbackFunkce; xmlHttp.send(null); sleep(30); }
5.6.4. GET vs. POST Jak již bylo řečeno, prvním argumentem v metodě open() objektu XMLHttpRequest je typ HTTP metody, která bude při komunikace se serverem použita. Volání serveru s argumenty pomocí metody GET může vypadat například takto: Výpis 5.5. Volání serveru pomocí metody GET ... xmlHttp.open("GET", "text.php?parametr1=hodnota1¶metr2=hodnota2"); ...
Pokud využijeme HTTP metodu POST, bude řetězec s argumenty odeslán v těle požadavku. Abychom však metodu POST mohli využít, musíme nejprve nastavit hlavičku Content-Type na hodnotu application/x-www-form-urlencoded. Výsledné volání může vypadat například takto: Výpis 5.6. Volání serveru pomocí metody POST ... var retezec = "parametr1=hodnota1¶metr2=hodnota2"; xmlHttp.open("POST", "text.php"); xmlHttp.onreadystatechange = callbackFunkce; xmlHttp.setRequestHeader("Content-Type", "application/x-www-formurlencoded"); xmlHttp.send(retezec);
5.6.5. Časová známka Používáme-li k volání HTTP metodu GET a chceme zabránit cachování dotazu prostřednictvím časové známky, použijeme následující konstrukci. Výpis 5.7. Použití časové známky xmlHttp.open("GET", "text.php?parametr1=hodnota1& timestamp="+ new Date().getTime());
5.6.6. Zpracování odpovědi ze serveru Objekt XMLHttpRequest nabízí dva atributy poskytující přístup k odpovědi od serveru. První atribut, responseText, jednoduše poskytuje odpověď ve formě řetězce. Druhý atribut, reponseXML, poskytuje odpověď ve formě dokumentu XML. Pokud tedy server vygeneruje jako odpověď prostý text nebo HTML kód, můžeme tento řetězec navěsit do elementu s id „cilovyElement“ pomocí následující konstrukce:
[- 24 -]
Výpis 5.8. Navěšení odpovědi do HTML elementu document.getElementById("cilovyElement").innerHTML = xmlHttp.responseText;
Předpokládejme, že ze serveru přijde následující XML odpověď: Výpis 5.9. XML odpověď ze serveru ŠályRukaviceČepiceTrikaKraťasy
Využijeme tedy druhý atribut reponseXML. Pokud budeme chtít vypsat pouze letní kategorie, napíšeme a zaregistrujeme callback funkci, která využívá tuto logiku: Výpis 5.10.Callback funkce pro zpracování XML odpovědi function vypisLetniSortimentXML() { var odpoved = xmlHttp.responseXML; var letniUzel = odpoved.getElementsByTagName("letni")[0]; var kategorie = letniUzel.getElementsByTagName("kategorie"); var vystup = ""; for(var i = 0; i
Předpokládejme, že náš server odpoví JSON strukturou v následující podobě: Výpis 5.11. JSON odpověď ze serveru { druhy:{ zimni:{ kategorie:['Šály','Rukavice','Čepice'] }, letni:{ kategorie:['Trika','Kraťasy'] } } }
[- 25 -]
Následující funkce demonstruje zpracování předchozí odpovědi a vypsání letního sortimentu: Výpis 5.12.Callback funkce pro zpracování JSON odpovědi function vypisLetniSortimentJSON() { var odpoved = xmlHttp.responseText; var data = eval("("+odpoved+")"); for(var i = 0; i < data['druhy']['letni']['kategorie'].length; i++) { vystup += data['druhy']['letni']['kategorie'][i] + " "; } alert(vystup); }
Klíčové je volání javascriptové funkce eval(). Tímto voláním převedeme JSON řetězec do analogické datové struktury v Javascriptu a můžeme ihned odpověď zpracovávat. Je dobré přidat kulaté závorky k odpovědi, než provedeme volání funkce eval(). Specifikace ECMAScriptu totiž říká, že výraz nesmí začínat složenou závorkou, jelikož by mohla být považována za začátek bloku. Proto se doporučuje řetězec s JSON vždy obalit kulatými závorkami. JSON formát s sebou nese bezpečnostní hrozbu. V kombinaci s AJAXem je zatím spíše teoretická, nicméně pokud bude zavedena nová verze AJAXu, která bude umožňovat volat logiku AJAXem i mimo doménu, bude tato vlastnost klíčová. Pokud totiž zavoláme funkci eval() na daný řetězec, vše, co je v tomto řetězci, bude “provedeno”. Pokud tedy bude řetězec vypadat například takto: Výpis 5.13.JSON řetězec s Javascriptem [1, 2, alert('Ahoj')]
bude vyvoláno dialogové okno s pozdravem. Není těžké si představit kód, který by byl škodlivý a byl by tímto způsobem vyvolán. Proto, pokud je využit JSON formát, musíme mít jistotu, že odpovídající server je bezpečný. Pokud tuto jistotu nemáme, musíme nejprve odpověď ověřit21.
6. Návrhové vzory pro prezentační vrstvu Návrhové vzory (Design patterns) byly poprvé popsány a zdokumentovány v knize Design Patterns: Elements of Reusable Object-Oriented Software nebo zkráceně GoF Design Patterns (autoři Gamma, Helm, Johnson a Vlissides, známí také jako Gang of Four, odtud zkratka GoF). Jedná se o sadu základních návrhových vzorů. Návrhové vzory jako takové pomáhají rychle identifikovat a pojmenovat problém. Zároveň poskytují časem prověřené řešení. Vzhledem k tomu, že se vzory učí každý správný vývojář a každý architekt, jejich rozpoznání místo sáhodlouhého popisování části aplikace ušetří čas a minimalizuje komunikační šum mezi týmovými kolegy. Zároveň, když se nehodí aplikace vzoru A, může se hodit použití vzoru B, což eliminuje nedomyšlená řešení nebo znovuobjevování kola. Bylo sepsáno mnoho publikací, které popisují specifické návrhové vzory pro určitou danou oblast (i zcela mimo oblast IT). Stejně tak je tomu i v případě prezentační vrstvy. Tyto vzory jsem v následujících podkapitolách popsal a jejich použití demonstroval na příkladech.
21
První možnost je využít regulární výrazy, například výraz z RFC 4627 (více http://www.ietf.org/rfc/rfc4627.txt?number=4627 ). Druhou možností je použít JSON parser od Douglase Crockforda (http://www.json.org/json_parse.js). Parser nejen zajistí, že data neobsahují podstrčený kód, ale zároveň ověří, že se jedná o platný formát JSON. V případě problému vyvolá výjimku.
[- 26 -]
„Každý vzor je třídílné pravidlo vyjadřující vztah mezi určitou souvislostí, problémem a řešením“. (Christopher Alexander)
6.1.
Základní vzory
(Alur, Crupi a Malks, Core J2EE Patterns) popisují následující návrhové vzory jako hlavní vzory, které ovlivňují a formují prezentační vrstvu: 6.1.1. Intercepting Filter Tento vzor se hodí v situaci, kdy chceme manipulovat s požadavkem nebo s odpovědí před či po zpracování požadavku. Například v určitých situacích zpracovávání zastavíme, jindy zase připravíme data dle situace. Typické případy využití jsou: Kontrola validity klientovy session – v případě, že session vypršela, zřejmě budeme nastavovat aplikaci tak, aby reagovala jako na nepřihlášeného (nového) návštěvníka Kontrola požadované URL adresy, je korektní, má uživatel právo k jejímu přístupu – například nový návštěvník nemá právo zobrazovat údaje pouze pro registrované, zpracovávání ukončíme, nebo lépe nastavíme výchozí stránku s hlášením, že uživatel nemá právo k požadované URL Kontrola klientova prohlížeče, doplňků či operačního systému – například pokud se jedná o Internet Explorer, nastavíme jako výchozí kaskádové styly psané pro Internet Explorer, v případě Firefoxu zvolíme styly pro Firefox atd. Kontrola použitého kódování Kontrola dalších vlastností požadavku (šifrování, komprese) Logování či tracování Nastavování vlastností odpovědi (šifrování, komprese) I když se vždy testují jiná data, na úrovni programovacího jazyka se vždy jedná o sérii „IF – ELSE“ výrazů nebo o výrazy „SWITCH“, které se v řadě za sebou při každé interakci prochází (někdy třeba ne všechny kontroly). Je to tedy místo náchylné k duplikování kódu. Dále zde hrozí nebezpečí svázání logiky “preprocessingu” (před zpracováním hlavní logiky aplikace) a “postprocessingu“ (po zpracování hlavní logiky). Návrhový vzor Intercepting Filter nabízí řešení v podobě volně zapojitelných filtrů, které jsou na sebe navázány a zřetězeny za sebou jako článek za článkem. Filtry se dají volně přidávat nebo odebírat z řady. Jsou na sobě nezávislé. Filtry obvykle mají konfigurační soubor, kde je jejich definice (jméno, popis, obslužná třída), URL mapování požadavku, tj. když URL v požadavku se shoduje s URL namapovaných u daného filtru, bude logika filtru vykonána a také se zde definují parametry pro konkrétní filtry, pokud jsou potřeba.
Třída “Klient” zastupuje strukturu, která předává požadavek třídě FilterManager. Ta má na starost aktivaci všech filtrů, které budou využity a následně předá řízení třídě FilterChain. FilterChain obsluhuje filtry v daném pořadí, nejprve preprocessing. Vyvolá první filtr, ten provede svou logiku a vrací řízení. FilterChain volá druhý filtr v pořadí a tak dále. Když je preprocessing hotov, je řízení běhu předáno další aplikační komponentě, zde zastupovaná třídou Target. Když je logika v třídě Target hotova, vrací se řada zpět na FilterChain, nyní pro postprocessing. Filtry jsou vyvolávány v opačném pořadí, než v jakém byly vyvolávány u preprocessingu. Celou akci demonstruje následující sekvenční diagram (viz Obrázek 9).
6.1.2. Front Controller Front Controller popisuje situaci, kdy chceme v aplikaci jedno centrální vstupní místo, přes které budou proudit všechny uživatelovi požadavky. Je to tedy místo pro společnou logiku. V případě, že tento návrhový vzor není aplikován, vznikají mnohá místa s nutností duplicity kódu. Naopak díky jeho využití lze aplikaci mnohem snadněji rozšířit a jednotlivé části znovuvyužít díky tomu, že specifická logika mnoha volaných akcí je soustředěna právě pouze zde. Ruku v ruce s tímto jde i snadnější údržba celého celku. Typický příklad je například soubor index.php v PHP. Drtivá většina PHP aplikací je tvořena tak, že je volán tento skript, v něm se inicializují další komponenty a vytváří se tzv. Application Controllery (třídy dle návrhového vzoru Application Controller, detailně popsáno v další kapitole), které mají za úkol vyvolat správný kontroler a správné zobrazení dat (view). V případě, že aplikace není příliš rozsáhlá, může Front Controller převzít funkcionalitu Application Controlleru na svá bedra. Následující diagramy (viz Obrázek 10, 11) demonstrují aplikaci návrhového vzoru v Javě. Klient posílá požadavek, který jde přes Front Controller (Servlet). Ve Front Controlleru dochází k vytvoření Context objektů pro požadavek a odpověď (návrhový vzor Context Object je rozebrán v následující kapitole) kvůli odstínění protokolově specifickým datům. Dále je vytvořen Application Controller, kterému je také předáno řízení. Ten následně volá příslušné akce a příslušná view.
Obrázek 10: Diagram tříd Front Controlleru. [Zdroj: Core J2EE Patterns]
[- 29 -]
Obrázek 11: Sekvenční diagram Front Controlleru. [Zdroj: Core J2EE Patterns]
6.1.3. Context Object Context Object se využívá ke skrytí systémových (protokolárně závislých) dat. Představuje jakýsi transportní objekt pro data (např. v požadavku klienta a odpovědi serveru, který je nedílnou součástí Front Controlleru), pomocí kterého mohou jednotlivé části systému navzájem komunikovat. Implementován může být obyčejnou mapou (resp. asociativním polem), nebo objektem s atributy a příslušnými settery a gettery (POJO). Jako příklad bych uvedl práci s formulářovým prvkem odeslaným z klienta, implementovanou v PHP. Když nebude vzor Context Object aplikován, business logika bude vždy muset ověřovat, zdali se hodnota nachází v $_POST nebo v $_GET poli. Pokud použijeme Context Object, nastavíme hodnotu do něj a tento objekt předáváme volaným kontrolerům, ti se již o tuto věc starat nemusí. Přínos je dvojnásobný v situaci, kdy potřebujeme stávající formulář upravit, např. změna z GET na POST, nebo když budou metody využívány současně, podle aktuální situace. Context Object si lze představit jako jakousi spojku mezi komponentami v systému. Následující diagram (viz Obrázek 12) demonstruje aplikaci návrhového vzoru na požadavek klienta (Request) v Javě. Klient vznese požadavek na server. Ve Front Controlleru je vytvořen Context Object pomocí ContextFactory třídy. Context Object je předán Application Controlleru namísto původního HttpServletRequest objektu.
6.1.4. Application Controller Application Controller je návrhový vzor, který řeší 2 konkrétní úlohy aplikace: Přiřazení správné akce k uživatelskému požadavku (tzv. Action Management) Vyvolání správného zobrazení dat (tzv. View Management) Záleží na velikosti aplikace. V případě, že se jedná o menší celek, lze tuto funkcionalitu přesunout přímo do Front Controlleru. Pokud se ale aplikace bude rozrůstat, dříve nebo později narazíme na omezení. Ve Front Controlleru bude totiž logika svázaná s protokolárními daty. Pokud zvolíme oddělené řešení, jednotlivé komponenty komunikují přes Context Object. Základní logiku (session management, validace, autentizace uživatele) ponecháme v Intercepting Filtrech. Takto oddělené řešení se nám bude také lépe testovat. Jeho strukturu demonstruje následující obrázek (viz Obrázek 13). Zbývající struktura (třídy Mapper, View, Command) aplikace opět záleží na rozsáhlosti aplikace, využití aplikace a použitých technologiích.
Z klienta přijde požadavek přes Front Controller (resp. Intercepting Filtry) do Application Controlleru. Ten požádá Mapper (což je Factory) o akci a view, kterou má zavolat. Mapper tyto data vrátí. Application Controller poté volá správnou akci, následně pak také správní view (viz Obrázek 14).
6.1.5. View Helper Část aplikace, kde dochází k přípravě zobrazení dat, je tvořena soustavou view objektů. Jako příklad můžeme vzít nákupní košík. V business vrstvě jsme přidali položky do košíku a nyní přichází jejich zobrazení. Předpokládejme, že následující logika se již odehrává ve view. Je tedy potřeba získat z databáze seznam položek v košíku, projít tento seznam a vykreslit jednotlivé položky. Když ale dojde na vypsání odkazů na obrázky, zjistíme, že potřebujeme mechanismus na jejich generování. Když potřebujeme vypsat naformátovanou částku, potřebujeme zase nějaký jiný mechanismus. Pokud všechnu tuto logiku vkládáme přímo do view třídy, nejen že se neustále bude opakovat, ale hlavně se toto místo stává naprosto nepoužitelné v jiných podobných situacích a o rozšiřitelnosti či údržbě ani nemluvím. Selský rozum nám velí odsunout tuto funkcionalitu někam pryč. Ideální místo je View Helper. Tento návrhový vzor tedy odděluje logiku, která je občas potřeba v poslední fází aplikačního řízení běhu, tj. při zpracovávání zobrazování dat. Seznam položek tedy získáme v samostatné třídě, do view třídy předáme seznam skrze “Transfer Object”. Ve view procházíme tento seznam a na místě generování odkazů a cen volání pomocné třídy např. urlHelperu a currencyHelperu. Tím pádem je view nezávislé. Pokud budeme mít view tříd více (například generování HTML kódu a JSON kódu), logika v oddělených komponentách půjde s přehledem využít v obou případech. Programovací jazyky mají k aplikaci tohoto vzoru specifické mechanismy.
Například v Javě můžeme využít vlastních tagů (tzv. Custom Tags) nebo JavaBean. Obrázek (viz Obrázek 15) zachycuje situaci, kdy požadavek jde skrze Front Controller, Application Controller a dorazí do třídy AccountCommand (JavaBean), která požádá třídu AccountBO (Business Object, JavaBean) o detaily bankovního účtu. Tento objekt se spojí s objektem AccountDAO (Data Access Object), což už je objekt komunikující s datovým úložištěm. Informace jsou vráceny Application Controlleru, který je předává na view AccountView, což je klasické JSP, ve kterém je použit custom tag TableFormatter. 6.1.6. Composite View Návrhový vzor Composite View popisuje situaci, kdy určitá část zobrazovaných dat se skládá z oddělitelných oblastí, které se dají znovupoužít. Je jen otázkou implementace, jak zajistit tuto znovupoužitelnost. Například typická stránka má hlavičku (myšlena horní část např. s logem), navigační oblast, oblast pro vypsání obsahu a patičku. V každém View logicky nebude definovaná tatáž hlavička nebo patička. Vždy bude každé správné View složeno z těchto celků. V jazyku PHP můžeme View skládat pomocí prostého příkazu include, s rostoucí aplikací budeme potřebovat složitější mechanismum.
V Javě naproti tomu skládáme JSP pomocí tagu <JSP:include>, ve složitějších případech používáme POJO nebo custom tagy. Obrázek (viz Obrázek 16) zachycuje situaci, kdy vyvolané View komunikuje s třídou ViewManager, která vyčte z třídy Template, jaké má být rozvržení stránky (tzv. [- 33 -]
Layout). Podle layoutu a dalších možných okolností (například jestli je uživatel přihlášený) je výsledné View skládáno. Třídy SimpleView a CompositeView mají zdůraznit fakt, že skládání může být víceúrovňové, tj. View se skládá z dalších View, kterou jsou opět složeny z dalších menších celků. Sekvenční diagram (viz Obrázek 17) dokresluje celý proces.
6.1.7. Service to Worker Vzory Service to Worker a Dispatcher View jsou dvě různé alternativy, jak přistupovat k tomu, kdy se má provádět business logika. Service to Worker vzor popisuje situaci, kdy se business logika volá z Application Controlleru ještě před tím, než se volá View. Tento případ je typický pro situace, kdy je volané business logiky více. Typický příklad je třeba přidání, editace nebo smazání záznamu v databázi. Tento proces se vykonává ještě před tím, než začínáme vykreslovat data. Diagram tříd (viz Obrázek 18) zobrazuje rozdělení jednotlivých tříd, kde prostřednictvím Command třídy voláme business logiku. Ze sekvenčního diagramu (viz Obrázek 19) je snadno vidět oddělené dva toky řízení běhu aplikace, kdy nejprve přichází volání třídy Command, teprve až poté volání View.
Obrázek 18: Diagram tříd vzoru Server to Worker. [Zdroj: Core J2EE Patterns]
[- 34 -]
Obrázek 19: Sekvenční diagram vzoru Service to Worker. [Zdroj: Core J2EE Patterns]
6.1.8. Dispatcher View Vzor Dispatch View je alternativou ke vzoru Service to Worker. Popisuje situaci, kdy aplikace nepotřebuje volat žádnou (nebo téměř žádnou) business logiku před voláním View. Ono případné volání se děje až po vyvolání View přes View Helper třídy, dříve nikoliv. Jako typický příklad je zobrazení již existujícího záznamu v databázi. View Helper se spojí s business vrstvou, získá údaje, samotné View si tyto data zobrazí na potřebná místa. Z diagramu tříd (viz Obrázek 20) je patrné propojení Application Controlleru a View. Application Controller může být také vynechán, potom vyvolání View zajistí rovnou samotný Front Controller. Tato situace je znázorněna na následujícím sekvenčním diagramu (viz Obrázek 21).
Architektura MVC (Model-View-Controller) je nejoblíbenější architekturou dnešní doby napříč mnoha programovacími jazyky. Je potřeba ji ale chápat jako obecnou architekturu, od které je poté odvozeno několik konkrétních návrhů (Bernard, 2009). Lze říci, že MVC architektura dělí aplikaci na tři části: Model, View a Controller. Každá část má v aplikaci svůj účel, ale zároveň nepřebírá funkčnost jiné části. To je poté výhodou při údržbě aplikace (měníme pouze danou část), v rozšiřování (rozšiřujeme či měníme opět pouze danou část) a v neposlední řadě při testování aplikace (lze testovat po částech, popřípadě konkrétní časti nahradit testovací variantou). Zároveň tato architektura skrývá řadu úskalí, zaleží na konkrétním návrhu, který byl z této rodiny použit. 6.2.1. Popis MVC Uvažujme následující excelovský dokument (viz Obrázek 22), na kterém bude rozebráno, jak by se tato aplikace rozložila na jednotlivé součásti podle architektury MVC. V dispozici jsou počty žáků v jednotlivých třídách a celkový průměr žáků ve třídě. Hodnoty jsou zachyceny ve dvou různých grafech.
Obrázek 22: Excel dokument pro demonstraci MVC
Model - je datová struktura, která drží hodnoty, tj. počty žáků 28,31 a 22. Implementován může být například třídou nebo polem. Do modelu patří i operace nad těmito čísly, tj. i průměr počtu žáků 27. Operace nad daty nazýváme business logikou. Rovněž sem patří validace hodnot.
[- 36 -]
View jsou v obrázku tři, jedná se o prostou tabulku a 2 grafy. Jde o různá zobrazení totožných dat. Tyto pohledy lze různě upravovat (u tabulky například měnit podbarvení kolonek) a přidávat další prvky (například v tabulce jsou přidány popisky). Controller není z obrázku viditelný. Je to ale přesně to, co donutí zaktualizovat model (tj. změnit čísla a změnit průměr) a překreslit grafy v okamžiku, kdy změním počty žáků. Jedná se tedy o ústřední jednotku (spoušť), která se stará o celkové provázání funkčnosti aplikace. Prezentační vrstvu ovlivňuje pouze View a Controller, Model s ní nemá nic společného. Výstup aplikace (zobrazení dat) obstarává vždy View. Se vstupem je to složitější a již záleží na konkrétní použité variaci MVC architektury. U komponentových frameworků vstup řeší jednotlivé komponenty (tzv. widgety) a tím pádem tedy View. Například komponenta tlačítko reaguje na události kliknutí, textové pole zase zachytává jednotlivé znaky. U frameworků, které widgety nepoužívají, vstup zpracovává Controller. 6.2.2. Architektonický vzor MVC Návrhový vzor MVC je nejlépe aplikovatelný na platformě s odděleným vstupem a výstupem. Typicky tedy v případě obyčejných webových aplikací, kde vstup představuje URL požadavku (popřípadě včetně dat) a výstup například HTML kód. Veškerá logika je na serveru, na klientu je k dispozici pouze podpůrná funkcionalita.
Obrázek 23: vzor MVC
Uživatel nejprve vznese požadavek na aplikaci v uživatelském rozhraní (viz Obrázek 23). Ten je zachycen a zpracován Controllerem. V případě, že je to potřeba, vyvolá změnu Modelu, nebo například vyvolá změnu View. Nakonec samotné View zobrazí změny uživateli. Controller může být přitom realizován Front Controllerem a dalšími konkrétními controllery. Aplikace, které mají plně rozvinutou klientskou skriptovací část a hojně využívají Ajax, mají MVC vzor realizovaný ve skriptovacím jazyku (javascriptu) na klientovi. 6.2.3. Supervising Controller Návrhový vzor Supervising Controller patří do skupiny MVP (Model-View-Presenter) (Bernard, 2009). Tento vzor je nejlépe aplikovatelný na komponentové (widgetové) systémy. Mezi takové systémy patří například ASP.NET Web Forms, RIA aplikace (Silverlight, JavaFX) nebo třeba PHP framework PRADO.
[- 37 -]
Obrázek 24: Vzor Supervising Controller
Vzor MVP se od MVC vzoru se liší tím, že uživatelský vstup i výstup kontroluje View (viz Obrázek 24). Kromě toho má také View přímou vazbu na Presenter, v MVC totiž View o Controlleru vůbec nemusí vědět. Zobrazení dat Modelu ve View se realizuje prostřednictvím návrhového vzoru Observer nebo pomocí data bindingu. Ostatní složitější logika je v Presenteru, který s View může libovolně manipulovat. 6.2.4. Passive View Vzor Passive View je druhý vzor patřící do skupiny MVP. Od předchozího vzoru se liší pouze tím, že View nemá vazbu na Model (viz Obrázek 25). Presenter má tak daleko větší zodpovědnost, musí totiž navíc synchronizovat Model a View. Systémy aplikující tento vzor se lépe testují, neboť veškerá logika je umístěna v Presenteru a ten se dá mnohem snáze automatizovaně pokrýt než View.
Obrázek 25: Návrhový vzor Passive View
6.3.
Další vzory
(Martin Fowler, Web Presentation Patterns) zmiňuje mimojiné i tyto další návrhové vzory, které souvisí s prezentační vrstvou: 6.3.1. Template View Template View je jedním z možných přístupů, jak implementovat view v MVC architektuře. Jeho úkolem je oddělit HTML od samotného programovacího jazyka. Důvod je třeba ten, že kodér nemá znalosti vývojáře a obráceně. Aplikace tohoto vzoru je vhodná v týmovém prostředí. Základem je šablona, typicky psaná v jazyku HTML, do které jsou vloženy značky. Tyto značky jsou následně nahrazovány adekvátními daty při procesu vykreslování. To je princip vzoru.
[- 38 -]
Šablona může být psaná buď deklarativním jazykem (např. pomocí komponent a vlastních tagů) nebo imperativním jazykem (např. v PHP Smarty) (viz Obrázek 26). Deklarativní zápis je jednodušší, přehlednější. Imperativní je zase flexibilnější, ale zároveň i komplexní a šablona se může stát zcela nepřehlednou.
Obrázek 26: Imperativní (nahoře) a deklarativní zápis šablony
Taktéž povaha značek může být různá. Může se jednat o následující možnosti (nebo jejich kombinace): Prosté HTML – jednotlivé prvky jsou pak typicky rozlišovány pomocí atributu ID
1
HTML včetně vlastních atributů – do speciálních atributů lze vkládat další speciální instrukce
1
HTML včetně vlastních tagů – jsou použity vlastní tagy (custom tags), typické například pro JSP v Javě <ERRORSUMMARY name='Summary'> <list:LISTITEM> {ErrorMessage} <list:SEPARATOR>
[- 39 -]
HTML včetně zástupných hodnot (placeholder) – v HTML jsou například ve složených závorkách uvedeny názvy proměnných, kterou jsou poté v další fázi nahrazeny hodnotou proměnné, takovéto šablony jsou poměrně objemově rozsáhlé
{Username}
{Password}
Speciální šablonovací jazyk – vyžaduje nutnost naučit se tento jazyk
{section loop=users} {strip}
{users.name}
{users.email}
{/strip} {/section}
HTML včetně skriptovacích tagů – typické pro PHP jazyk, kdy HTML je prokládáno PHP výstupem
value; ?>
Šablonovací systémy lze také rozdělit podle toho, jakým způsobem předávají šablonám data: Push – všechna data, která šablona může potřebovat, jsou nejprve načtena, poté teprve dochází k samotnému vykreslování Pull – systém si tahá potřebná data během samotného vykreslování, je tedy možné, že některá data zobrazovaná v šabloně budou vynechána, pokud zrovna nejsou potřeba 6.3.2. Transform View Transform View je dalším ze způsobů, jak implementovat view v MVC architektuře. Využívá se zde transformací, které převádějí datové objekty do výsledného HTML kódu. Jako příklad transformačního jazyka lze uvést XSLT. Datové objekty nejprve převedeme do XML a pomocí XSLT transformací lze vygenerovat HTML dle našich požadavků.
[- 40 -]
7. Frameworky V této kapitole se zaměřím na 3 konkrétní frameworky a budu zkoumat, jak řeší problematiku prezenční vrstvy a ajaxové komunikace. Vybral jsem následující kandidáty: Zend Framework – zástupce klasického objektového frameworku PRADO – zástupce komponentového frameworku s netradičním přístupem Nette – zástupce frameworku, který údajně „bere z každého něco“ Postup zkoumání bude následující: 1. U každého kandidáta rozeberu jeho strukturu a vnitřní architekturu. Zkusím rozpoznat co nejvíce návrhových vzorů, které framework v daných místech aplikuje. 2. Zaměřím se na klientskou část. Vytvořím modelový příklad s jedním formulářovým tlačítkem, kterému se po odeslání formuláře změní popisek. Tuto samou úlohu poté převedu do ajaxového režimu. Z úlohy by mělo být tak patrné, co je kde potřeba nastavit k aktivaci klientské části. 3. Rozeberu nejpodstatnější klientské funkce frameworku, které daný rámec přímo podporuje. Nebudu tak rozebírat funkce, které fungují, pokud si vývojář doimplementuje to či ono. 4. Vytvořím druhý modelový příklad. Základem bude formulář s dvěma prvky typu select a jedno textové pole. Po vybrání hodnoty v prvním selectu se pošle na server ajaxový požadavek a cílem je změnit hodnotu v druhém selectu tak, aby oba elementy měly shodně zvolenou hodnotu. Čili selecty budou propojené. Navíc, při jakékoliv změně druhého selectu se odešle ajaxový požadavek na server a cílem bude zapsat tuto hodnotu do textového pole. Souhrnně, pokud dojde ke změně hodnoty prvního selectu, změní se hodnota druhého selectu a to vyvolá zápis do textového pole. Navíc, textové pole bude mít klientskou validaci hodnoty libovolného druhu. Na tomto příkladě by mělo být vidět, jak si framework dokáže poradit s jednoduchou, ale na klientské straně ne úplně triviální, úlohou. 5. Zhodnotím implementaci druhého příkladu. Zkusím najít pozitiva a nedostatky.
7.1. Zend Framework 7.1.1. Popis Název Domovská stránka projektu Počátek vývoje Současná verze Partneři Licence Autor Jazyk
Zend Framework http://framework.zend.com/ 2005 1.10.5 Adobe, Google, Microsoft New BSD Zend Technologies PHP 5
Zend Framework je open-sourcový, objektově orientovaný, webový aplikační framework pro programovací jazyk PHP 5 vyvíjený pod „New BSD“ licencí. Začátek jeho vývoje se datuje k počátku roku 2005. Jak už název napovídá, na vývoj dohlíží společnost Zend Technologies. Ta se aktivně podílí i na vývoji jazyka PHP, proto lze očekávat, že tento framework bude hrát i v budoucnu klíčovou roli.
[- 41 -]
Framework se skládá z mnoha komponent, které lze v případě potřeby jednotlivě využít. Tento přístup se označuje jako modulární architektura. Obecně se framework hodí na robustní aplikace a i v duchu této filozofie byly komponenty navrženy. Bohužel je to na úkor výkonu, který je zatím hlavní nevýhodou tohoto aplikačního rámce. 7.1.2. Architektura Zend Framework striktně dodržuje architekturu MVC, model, view i controller jsou od sebe odděleny.
Obrázek 27: Ukázka adresářové struktury Zend frameworku
Od tohoto členění se také odvíjí struktura souborů (viz Obrázek 27), kterou lze ale v konfiguračním souboru application.ini upravit, stejně tak jako další jiné parametry (například výpis chybových hlášení, cesty ke komponentám nebo nastavení databáze). Základem aplikace je třída Zend_Application (zde vytvářená v souboru public/index.php), která načítá konfigurační soubor a vytváří odvozenou třídu Bootstrap. Ta má za úkol inicializovat všechny potřebné třídy a komponenty. Jednou z nich je třída Zend_Controller_Front. Jak už její název napovídá, plní roli Front Controlleru a představuje tak centrální bod každého požadavku. Router (Zend_Controller_Router_Rewrite) zparsuje url požadavku. Díky tomu Front Controller volá správnou akci konkrétního kontroleru (třída Zend_Controller_Action) v adresáři controllers. Akce kontroleru odpovídá jeho metodě. Akce ale nejsou volány přímo, nýbrž prostřednictvím komponenty Dispatcher ( Zend_Controller_Dispatcher_Standard). Když je toto volání dokončeno, vrací se řízení na Front Controller. Pokud je ovšem nastaven příznak, že má být vyvolán další kontroler, procedura se opakuje. Jedná se tak o smyčku ve Front Controlleru a logika v akcích určuje, zda má být smyčka ukončena. Komponenty si mezi sebou předávají informace v třídách Zend_Controller_Request_Http a Zend_Controller_Response_Http, které zastřešují požadavek a odpověď.
[- 42 -]
View (Zend_View) jsou představovány šablonami s koncovkou phtml umístěnými v adresáři views. Jejich zobrazení si můžeme vynutit přímo v akci kontroleru, nebo využít pomocnou třídu ViewRenderer. Práci v šablonách nám usnadňují helper třídy. K dispozici je podpora pro formuláře, formátování měn, JSON kód, navigaci a spousta dalších. Za zmínku stojí i tzv. Placeholder helpery, pomocí kterých lze agregovat obsah šablon. Například pokud chceme vkládat typické prvky do HEAD sekce, vypisovat DocType, specifikovat značku TITLE, nebo si vytvořit vlastní úsek šablony. Podporovaná je řada dalších operací (napojování kódu, prefixy, postfixy) a jedná se o aplikaci vzoru Composite View. Další důležitou komponentou je Zend_Layout. Umožňuje efektivně spravovat části šablon, organizovat je a následně zobrazovat. Jedná se o aplikaci vzoru Two-Step View. Pro úplnost, v adresáři models jsou třídy týkající se datové vrstvy. Soubory frameworku jsou umístěny v adresáři library. Pokud aplikace používá formuláře, třídy, které reprezentují formuláře, se ukládají do adresáře forms. 7.1.3. Podpora Javascriptu Zend framework nabízí podporu dvou javascriptových frameworků, konkrétně jde o Dojo a JQuery. Než shrnu jednotlivé funkcionality, pro které nabízí Zend přímou podporu, budu demonstrovat použití knihoven na jednoduchém příkladu. Nejprve předpokládejme formulářové tlačítko, po jeho stisknutí se vyvolá požadavek na server, který změní onomu tlačítku popisek. V kontroleru IndexController nás zajímá metoda indexAction(), která je defaultní akcí tohoto kontroleru. Vytváříme zde objekt formuláře a zjišťujeme, zdali se jedná o POST nebo GET požadavek. V případě POST požadavku změníme popisek tlačítka, který má atribut ID nastaven na hodnotu tlacitko. Druhá metoda sendAction() bude využita pouze v případě Ajaxového volání, ale i tak bude její tělo prázdné. Výpis 7.1. Kompletní kód kontroleru controllers/IndexController.php class IndexController extends Zend_Controller_Action { public function init() { } public function indexAction() { $this->view->form = new Default_Form_Test(); if ($this->getRequest()->isPost()) { $this->view->form->getElement('tlacitko') ->setLabel('Kliknuto!'); } } public function sendAction() { }
} Kód šablony je velmi krátký, je pouze potřeba nastavit URL formuláře a vykreslit jej.
Formulářový soubor obsahuje definici metody a formulářového tlačítka typu submit. Nastavujeme pouze popisek na hodnotu Klikni, ostatní nastavení neměníme. Výpis 7.3. Kompletní kód formuláře forms/Test.php class Default_Form_Test extends Zend_Form { public function init() { $this->setMethod('post'); $this->addElement('submit', 'tlacitko', array( 'label' => 'Klikni' )); } }
Pokud budeme chtít tlačítko zprovoznit v Ajaxovém režimu, budeme muset změnit view a formulář a také přidat jedno view, které bude použito pro odpověď. V hlavním view musíme načíst knihovnu JQuery (framework má na to speciální funkci, bohužel v testované verzi nebyla plně funkční). Poté vykreslíme formulář, URL formuláře nenastavujeme, neboť odesílání zajistí Ajax. Následuje zápis obsluhy v javascriptu. Poté, co je plně sestavena struktura dokumentu na klientovi, zaregistrujeme našemu tlačítku na událost kliknutí Ajaxové volání. Specifikujeme metodu požadavku, tj. POST, dále adresu URL, která je v tomto případě index/send/ a nakonec akci, která se vykoná v případě úspěšného zpracování požadavku na serveru. Onou akcí nebude nic jiného, než nastavení popisku tlačítka na hodnotu, kterou odeslal server jako odpověď. Výpis 7.4. Kompletní kód view views/index/index.phtml při použití JQuery doctype() ?> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <script type="text/javascript" src="jquery.min.js"> form; ?> <script type="text/javascript"> $(document).ready(function() { $("#tlacitko").click(
Ve formuláři změníme typ prvku z hodnoty submit na hodnotu button. Výpis 7.5. Kompletní kód formuláře forms/Test.php class Default_Form_Test extends Zend_Form { public function init() { $this->setMethod('post'); $this->addElement('button', 'tlacitko', array( 'label' => 'Klikni' )); } }
Druhé view neobsahuje žádný kód, pouze text Kliknuto!. Ten bude použit jako popisek pro tlačítko. Výpis 7.6. Kompletní kód view views/index/send.phtml Kliknuto!
Pokud budeme chtít celou ukázku provést s využitím frameworku Dojo, jediné, co se změní, bude hlavní view. Stejně jako v prvním případě, musíme nejprve zinicializovat framework Dojo. Poté vykreslíme formulář. Následuje javascriptový kód, tj. zaregistrování akce na událost kliknutí. Akcí bude Ajaxové volání serveru, který vrátí text. Tento text opět použijeme ke změně popisku tlačítka. Výpis 7.7. Kompletní kód view views/index/index.phtml při použití frameworku Dojo doctype() ?> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> dojo()->setLocalPath('/js/dojo/dojo.js'); echo $this->dojo(); ?>
[- 45 -]
Jak je z příkladu patrné, podpora javascriptových frameworků je spíše doplňková. 7.1.4. JQuery a Zend Zend nabízí view helper jQuery(), který zjednodušuje práce s JQuery. Stará se o načtení všech potřebných součástí ve správném pořadí, vývojář je tak odstíněn od problému se závislostmi jednotlivých součástí. Dále pomáhá se styly (themes) a nabízí také tzv. NoConflict mód. Ten se hodí v případě, že stránka používá více javascriptových frameworků (např. Prototype) zároveň. Akce registrované na událost OnLoad (po načtení dokumentu) jsou spravovány také touto třídou. Vedle view helperu jsou k dispozici další funkcionality, které v omezené míře lze použít, aniž bychom museli psát javascriptový kód: ajaxLink – Slouží k vygenerování odkazu, který vyvolá Ajaxové volání. Lze specifikovat další efekty a akce nad odkazem, taktéž také to, co se má stát při obdržení odpovědi ze serveru. autoComplete – Textové pole s funkcí našeptávače. Nabízené hodnoty lze samozřejmě získávat ze serveru skrze Ajaxové volání. datePicker - Textové pole s možností výběru data v přehledném kalendáři. slider – podpora pro posunovací prvek („šoupátko“) dialogContainer – podpora pro dialogové okno tabContainer – podpora pro záložky accordionPane, accordionContainer – podpora pro posunovací boxy 7.1.5. DOJO a Zend Stejně jako v předchozím případě, máme k dispozici view helper, který usnadňuje práci s javascriptovým frameworkem. Jedná se o dojo(). Má na starosti cesty ke knihovnám, jejich vzájemné závislosti, styly, konfiguraci nebo třeba akce registrované na událost onLoad. Následuje výčet dalších podporovaných prvků, při jejich použití lze následně na ně uplatnit veškeré vymoženosti frameworku Dojo: AccordionPane , AccordionContainer – posunovací boxy BorderContainer – podpora pro rozmístění prvků TabContainer – podpora záložek Button – tlačítko [- 46 -]
CheckBox – checkbox ComboBox – obyčejný prvek typu select s možností zadání další hodnoty, která není v nabídce, podpora pro autodoplňování CurrencyTextBox - textové pole pro měnu s možností validace DateTextBox – textové pole datum s možností validace Editor – WYSIWYG editor s řadou editačních funkcí FilteringSelect – obyčejný prvek typu select HorizontalSlider, VerticalSlider – posunovací prvky pro výběr hodnoty z určitého rozsahu NumberSpinner – textové pole pro číselnou hodnotu s možností zvýšení nebo snížení pomocí tlačítek NumberTextBox – textové pole pro číselnou hodnotu, která může být formátována a validována podle místního nastavení PasswordTextBox – pole pro heslo RadioButton – klasický radio prvek SimpleTextarea, Textarea – formulářové textové plochy SubmitButton – formulářové tlačítko pro odeslání formuláře TimeTextBox – prvek pro volbu času 7.1.6. Zend a Ajax v praxi Implementace zadání bude demonstrována na použití frameworku Dojo. Nejprve bylo zapotřebí vytvořit formulář, který byl obohacen o Dojo elementy. To umožnil příkaz Zend_Dojo::enableForm($this). Využil jsem dva prvky typu Combobox a jeden ValidationTextBox, který zároveň zajistil validaci na straně klienta. Výpis 7.8. Kompletní kód souboru DojoForm.php setMethod('post'); $this->addElement('ComboBox', 'Combobox'); $this->addElement('ComboBox', 'Combobox2'); $this->addElement('ValidationTextBox','TextBox', array( 'required' => true, 'regExp' => '[a-zA-Z0-9]+', 'invalidMessage' => 'Pouze obyčejná písmena nebo číslice.' ) ); } }
V kontroleru je nejprve metoda indexAction(). Zde vytvoříme instanci výše definovaného formuláře, nastavíme comboboxům hodnoty (dalo by se nastavit i přímo ve formuláři) a připojíme k view. Metoda ajaxAction() je vyvolána vždy, když uživatel změní hodnotu prvního comboboxu. Na server je poslána vybraná hodnota tohoto comboboxu, metoda ji vezme a předá ji klientovi zpět. Vzhledem k tomu, že nepotřebujeme žádný grafický výstup, zablokujeme použití layoutu.
[- 47 -]
Výpis 7.9. Kompletní kód souboru IndexController.php 'Hodnota1', '2' => 'Hodnota2'); $form = new Default_Form_DojoForm(); $form->getElement('Combobox')->setAttrib('options', $array); $form->getElement('Combobox2')->setAttrib('options', $array); $this->view->form = $form; } public function ajaxAction() { $this->view->value = $this->_request->getParam('value'); $this->_helper->layout()->disableLayout(); } }
V layoutu inicializujeme framework Dojo, nastavíme cestu ke knihovně a specifikujeme použitý styl. Výpis 7.10. Kompletní kód souboru layout.phtml doctype() ?> dojo()->isEnabled()){ $this->dojo()->setLocalPath($this->baseUrl('js/dojo/dojo.js')) ->addStyleSheetModule('dijit.themes.tundra'); echo $this->dojo(); } ?> layout()->content ?>
Ve view vypíšeme formulář a nadefinujeme potřebnou klientskou funkcionalitu. Tím je zaregistrování funkcí na událost onChange na oba comboboxy. V jednom případě jde o funkci makeCall(), která vyvolá Ajaxové volání serveru, předá mu hodnotu prvního comboboxu a čeká na odpověď. Když server pošle odpověď zpět, nastaví tuto hodnotu druhému comboboxu. Druhá funkce observe() způsobí, že při změně hodnoty druhého comboboxu se jeho hodnota přepíše do textového pole. Pokud tato hodnota nevyhovuje validátoru textového políčka, rozsvítí se chybová hláška. Všechny tři prvky jsou tak propojeny a společně reagují na podněty uživatele. Výpis 7.11. Kompletní kód souboru index.phtml form->setAction($this->url()); echo $this->form; ?> <script type="text/javascript"> dojo.addOnLoad(function () { dojo.connect(dijit.byId("Combobox"), "onChange", makeCall);
[- 48 -]
dojo.connect(dijit.byId("Combobox2"), "onChange", observe); function makeCall(){ var widget = dijit.byId("Combobox"); var targetwidget = dijit.byId("Combobox2"); var postParams = { url: 'index/ajax/', postData: 'value='+widget.value, load: function(data) { targetwidget.attr('displayedValue', data); }, headers: { "X-Requested-With": "XMLHttpRequest" } }; dojo.xhrPost(postParams); } function observe(){ dijit.byId("TextBox").attr('value', dijit.byId("Combobox2").value); } });
Ve druhém view, které je využito při Ajaxové komunikaci, je pouze vypsán a hodnota předávaného parametru value. Výpis 7.12. Kompletní kód souboru ajax.phtml value; ?>
7.1.7. Zhodnocení implementace Zend framework nabízí k použití formulářové prvky, které jsem využil i v mém příkladě. Není potřeba tak řešit stylování nebo základní funkcionalitu. K dispozici je také povedená validace. Bohužel kompletní obslužnou klientskou logiku si musí vývojář naimplementovat sám. Já jsem využil Dojo, ale při použití JQuery by bylo zapotřebí zhruba stejné množství řádků. Nemůžu ale opomenout jednu vlastnost, kterou je automatické vkládání Dojo knihoven. Vzhledem k tomu, že Dojo se skládá s opravdu velkého množství různě provázaných skriptů, je tato funkcionalita zcela na místě.
7. 2. PRADO 7.2.1. Popis Název Domovská stránka projektu Počátek vývoje Současná verze Licence Autor Jazyk
PRADO je vizuální, komponentový a událostmi řízený orientovaný framework pro vývoj webových aplikací v jazyce PHP5. PRADO je zkratkou pro PHP Rapid Application Development Object-oriented. Hlavní cíl týmu autorů je znovupoužitelnost webové části aplikace. Proto na rozdíl od jiných [- 49 -]
frameworků neřeší pouze aplikační vrstvu, ale zaměřuje se na vrstvu prezentační, která bývá ve vývoji obvykle podceňována. PRADO staví vývoj na komponentách. Framework nabízí základní sadu komponent, které lze poté jednoduše rozšířit (dědičností). Systém komponent je doplněn o systém událostí. Například, když uživatel stiskne tlačítko na stránce a vyvolá událost „onClick“, je tato událost automaticky vyvolána na serveru. Na tyto události lze navěšovat metody a ty tak následně automaticky vyvolávat. Událostní model připomíná tentýž model v Javascriptu. Historicky framework vychází z Apache Tapestry22. Další inspirace byla čerpána z Borland Delphi a Microsoft ASP.NET. První verze frameworku byla napsaná v PHP4, poté byl celý projekt přepsán do PHP5. Následně projekt jednoznačně vyhrál soutěž Zend´s PHP 5 Coding Contest pořádanou společností Zend. V srpnu 2004 byl framework uvolněn jako open-source. 7.2.2. Architektura Základem frameworku jsou komponenty (viz Obrázek 28). Komponenta je instance třídy TComponent a nebo jejích potomků. Třída TComponent implementuje mechanismus pro správu vlastností a událostí. Vlastnost může být obyčejná hodnota (např. ID) nebo další komponenta. Události jsou speciální metody, které jsou automaticky vyvolány v určité fázi životního cyklu aplikace. Pro pojmenování komponent lze využít jmenné prostory (Namespaces).
Obrázek 28: Struktura komponent frameworku PRADO. [Zdroj: PRADO]
Speciální skupinou jsou kontrolní prvky. Jsou to třídy odvozené od třídy TControl. Kontrolní prvek je komponenta, ke které je připojené uživatelské rozhranní (například samotná stránka TPage nebo tlačítko TButton). Prvky mají své stavy (ViewState a ControlState), pomocí kterých lze částečně překlenout bezestavovost HTTP protokolu. Kontrolní prvky tvoří hierarchii v podobně stromu (Control Tree), kde kořenem je samotná stránka. Rodič je zodpovědný za stav svých potomků. Každý kontrolní prvek má své ID, a to jak na straně serveru, tak na straně klienta (využito v HTML v atributu ID). To umožňuje jednoduché volání prvků. 22
http://tapestry.apache.org/
[- 50 -]
Stránka (TPage) je kontrolní prvek, který stojí nejvýše v hierarchii prvků. Každá stránka musí mít svojí šablonu, což je HTML stránka obohacená o speciální PRADO tagy a značky. V šabloně jednoduše definujeme komponenty, které tvoří další stránku, definujeme události, na které mají komponenty reagovat a akce, které se mají v návaznosti na onu událost vykonat. Stránka má svůj vlastní životní cyklus, v jednotlivých fázích probíhají různé operace (vytváření komponent, nastavování stavů komponent, renderování) (viz Obrázek 29).
Obrázek 29: Životní cyklus stránky frameworku PRADO. [Zdroj: PRADO]
Moduly jsou komponenty tvořené třídami TModule implementující rozhraní IModule. Jedná je o komponenty poskytující specifickou funkcionalitu, která je připojená k PRADO aplikaci. Modul je dostupný všem komponentám. V základní sadě jsou k dispozici moduly pro požadavek (Request module), odpověď (Response module), chybové řízení (Error handler module) a řízení sezení (Session module). Dále je možné využít další volitelné moduly (cache, autentifikace, autorizace), nebo si vytvořit vlastní.
[- 51 -]
Třídy TService implementující IService se nazývají služby (Service). Ve frameworku jsou k dispozici TPageService, TJsonService (pro podporu komunikace skrze JSON), TFeedService (podpora feedů) a FSoapService (podpora Soap komunikace). TPageService zajišťuje spouštění správné stránky TPage dle uživatelova požadavku. Instance TApplication nebo jejích potomků se nazývá aplikace. Aplikace spravuje moduly, služby a parametry využívané napříč celým systémem. Životní cyklus aplikace (viz Obrázek 30) ovlivňuje jednotlivé moduly. Když aplikace vstoupí do určité fáze cyklu, všechny moduly, které jsou v této fázi zaregistrovány, jsou automaticky vyvolány.
Obrázek 30: Životní cyklus aplikace frameworku PRADO. [Zdroj: PRADO]
[- 52 -]
Na následujícím obrázku (viz Obrázek 31) jsem zachytil frameworkové součásti tak, jak odpovídají návrhovým vzorům pro prezentační vrstvu.
Obrázek 31: Aplikace návrhových vzorů ve frameworku PRADO
FrontControlleru odpovídá hlavní třída TApplication, přes kterou proudí všechny uživatelovy požadavky. TApplication spouští TPageService, která se chová jako ApplicationController. V uživatelském požadavku se snaží najít informaci, která říká, jakou stránku uživatelovi odeslat zpět. Každá stránka TPage je tvořena komponentami typu TControl, může se ale jednat opět o další stránky typu TPage. Vzhledem k tomu, že ke každé takové komponentě existuje i vlastní šablona představující View, je aplikace návrhového vzoru Composite View více než zřejmá. V každé šabloně lze využít speciálních značek a volat serverovou logiku, tj. využít funkcionalitu View Helperů. Framework neadaptoval vzor Intercepting Filter. Použité moduly, které by se nabízely jako vhodní kandidáti, jsou vyvolávány nezávisle na sobě, podle fáze životního cyklu aplikace. 7.2.3. Podpora Javascriptu Vzhledem k tomu, že PRADO je zaměřené na prezenční vrstvu, je Javascriptu k dispozici poměrně mnoho. PRADO čerpá z několika zdrojů. Použití by se dalo rozdělit následovně: Základní funkcionalita – Soubor základních funkcí, funkcionalita komponent, založeno na frameworku Prototype Vizuální efekty – Převzato z frameworku script.aculo.us Ajax – Ajaxová komunikace, callback volání, založeno na frameworku Prototype Validace – vlastní podpora pro validaci na straně klienta Logování – vlastní podpora pro logování na straně klienta Doplňky – komponenta pro výběr data, komponenta pro výběr barvy Javascript je do výsledné stránky vkládán automaticky, taktéž závislosti jednotlivých knihoven řeší framework za nás. Uvedená ukázka představuje potřebný kód k naimplementování obyčejného tlačítka a logiky, která změní jeho popisek poté, co na něj klikneme:
[- 53 -]
Výpis 7.13. Kompletní kód šablony stránky PRADO - tlačítko
Výpis 7.14. Kompletní kód stránky Text='Kliknuto!'; } }
Pokud budeme chtít celou logiku přepsat do Ajaxu, uděláme následující změny: Výpis 7.15. Kompletní kód šablony stránky při použití Ajaxu ... ...
Výpis 7.16. Kompletní kód stránky při použití Ajaxu Text='Kliknuto!'; } }
Místo komponenty TButton jsme použili komponentu TActiveButton a ve skriptu jsme uvedli cestu k této komponentě. Framework sám zajistil inicializaci na straně klienta v Javascriptu, načetl požadované knihovny a zcela nás odstínil od ajaxové komunikace. 7.2.4. Ajaxové komponenty Framework nabízí řadu komponent, které se serverem komunikují pomocí AJAXu. Vývojář definuje pouze parametry komponenty, události, na které má komponenta reagovat a akce, které mají být vyvolány. Samozřejmě lze komponenty rozšiřovat (dědičností) a doplňovat o nové funkčnosti. V základní nabídce jsou tyto komponenty: TActiveButton – již představené tlačítko TActiveCheckBox – formulářový checkbox TActiveCustomValidator – validační komponenta TActiveHyperLink – odkaz TActiveImage – obrázek TActiveImageButton – tlačítko s obrázkem na jeho pozadí TActiveLabel – popisek [- 54 -]
TActiveLinkButton – tlačítko ve formě odkazu TActivePanel – kontejner pro další kontrolní prvky na stránce TActivePager – stránkovací mechanismus, pomocí kterého lze specifikovat, jakou část dat ze seznamu má server vrátit na klienta TActiveRadioButton – formulářový radiobutton TActiveTextBox – univerzální textové pole (prostý text, heslo, víceřádkový pole) TCallbackOptions – umožňuje definovat callback akce na různé události TActiveCheckBoxList – seznam formulářových checkboxů – formulářový combobox TActiveListBox – formulářový listbox s možností výběru více položek TActiveRadioButtonList – seznam formulářových radioboxů TAutoComplete – našeptávač, rozšíření pro TActiveTextBox TCallback – podpora pro callback akce TEventTriggeredCallback – spouštěcí mechanismus callback akcí na základě DOM událostí TInPlaceTextBox – editovatelný popisek TTimeTriggeredCallback – časovaný spouštěcí mechanismus callback akce TValueTriggeredCallback – monitorovací spouštěcí mechanismus, spustí ho změna definovaného HTML prvku TDropContainer, TDraggable – podpora pro drag’n’drop a definici callbacku V dalších verzích je plánovaná například komponenta TActiveDataGrid, která umožní tabulkový výpis databázových dat a všechny související operace (stránkování, řazení, filtrování). Osobně považuji tuto komponentu jako nejdůležitější pro uplatnění v podnikové sféře. Je škoda, že dokumentace je zatím stále neúplná a aktivní komponenty nejsou zdokumentovány, chybí i praktické příklady. 7.2.5. PRADO a Ajax v praxi Splnit zadání ve frameworku PRADO nebyl vůbec žádný problém. Téměř všechna logika byla definovaná v šabloně. Použity byly kontrolní prvky TActiveDropDownList pro comboboxy a TActiveTextBox pro textové pole. U prvního comboboxu se nadefinoval atribut OnSelectedIndexChanged, jehož hodnota odpovídala metodě na serveru, která byla vyvolána vždy, když uživatel změnil vybranou hodnotu formulářového prvku (v tomto případě metoda changed()). Na serveru se jedním řádkem nastavila tato hodnota i na druhý combobox. Poté přichází ke slovu TValueTriggeredCallback, což je spoušť, která hlídá hodnotu druhého comboboxu a při jakékoliv její změně volá metodu changed2(), která změní hodnotu textového pole TActiveTextBox. Klientskou a serverovou validaci tohoto prvku zajistil prvek TRequiredFieldValidator, v tomto případě jde o kontrolu, jestli je pole neprázdné. Formulářové tlačítko odešle Ajaxem data, na serveru volá metodu process(), kde by byla vykonána další logika, samozřejmě v případě, že odeslaná data byla validní. Následuje kompletní výpis potřebného kódu obou souborů.
[- 55 -]
Výpis 7.17. Kompletní kód šablony PRADO a Ajax v praxi
Výpis 7.18. Kompletní kód php skriptu IsPostBack) { $this->bindData(); $this->TextBox->Text = $this->Combobox2->Text; } } public function bindData() { $data = array( 'Klíč 1'=>'Hodnota 1', 'Klíč 2'=>'Hodnota 2', 'Klíč 3'=>'Hodnota 3'); $this->Combobox->DataSource = $data; $this->Combobox->dataBind(); $this->Combobox2->DataSource = $data; $this->Combobox2->dataBind(); } public function changed($sender,$param) { $this->Combobox2->SelectedIndex = $sender->SelectedIndex; } public function changed2($sender,$param) { $this->TextBox->Text = $this->Combobox2->Text; } public function process($sender,$param) { if($this->Page->IsValid) { // zpracovani formulare } } } ?>
[- 56 -]
7.2.6. Zhodnocení implementace Škoda, že bylo zapotřebí využít komponenty TValueTriggeredCallback, neboť pokud by fungoval následující kód, zápis by byl ještě jednodušší. Výpis 7.19. Alternativní kód šablony
Uvedenému způsobu zápisu jinak nelze nic vytknout, neboť vývojáře zcela odstiňuje od klientského skriptování a není tak zapotřebí dalších znalostí klientského jazyka.
7.3. Nette 7.3.1. Popis Název Domovská stránka projektu Počátek vývoje Současná verze Licence Autor Jazyk
Nette je framework napsaný v PHP 5 a plně využívá objektové programování. Ačkoliv vzniká již od roku 2004, teprve v roce 2008 byl uvolněn jako open source a uvolněn veřejnosti. Mezi jeho hlavní přednosti patří rychlost, otázka bezpečnosti, malý objem zdrojového kódu a aktivní komunita. Framework nabízí i další unikátní vlastnosti (například povedená podpora ladění aplikace), které vývojářovi usnadňují práci, taktéž snad všechny základní funkcionality, které nabízejí i ostatní frameworky. 7.3.2. Architektura Nette framework podporuje architekturu MVP (viz Obrázek 32) a této architektuře také odpovídá celá struktura projektu včetně adresářové struktury. Místo Controlleru je tedy k dispozici Presenter. Následující popis vnitřního fungování patří k MVP aplikaci vytvořené v Nette.
[- 57 -]
Obrázek 32: MVC struktura frameworku Nette. [Zdroj: Grudl]
Každý projekt používající framework Nette má tři hlavní podadresáře (viz Obrázek 33): app – zde je soustředěna vlastní aplikační logiky aplikace, tj. modely, prezentery, šablony (view), šablony layoutu, dočasné soubory aplikace (podadresář temp), konfigurační soubory (config.ini, web.config, .htaccess) a zaváděcí soubor bootstrap.php document_root – veřejně dostupný adresář aplikace, zde jsou umístěny obrázky, styly, skripty a soubor index.php libs – místo pro samotný framework Nette popřípadě další frameworky a knihovny, které jsou použity
Obrázek 33: Adresářová struktura projektu využívající Nette
Všechny uživatelovy požadavky směřují na soubor index.php v podadresáři document_root. V tomto souboru se nachází definice umístění dalších součástí frameworku včetně načtení souboru bootstrap.php. Jedná se o zaváděcí soubor celé aplikace, nastavuje její prostředí, aktivuje a nastavuje funkce frameworku (debugovací mód, routování) a nakonec celou aplikaci spouští. Třída Application je typický Front Controller. Při každém požadavku nejprve připraví objekty HttpRequest,
[- 58 -]
HttpResponse. Poté přichází na řadu routování, tj. rozbor URL adresy požadavku a vyvolání správného presenteru. Presenter má svůj vlastní životní cyklus, který je možný rozdělit do několika fází: výkonná – automatické vyvolání metod startup() – vhodné místo pro zajištění připojení k databázi, a action{action} – zde by měla být veškerá logika, po které se může provést přesměrování, například validace změny vnitřních stavů – vyvolání metod handle{signal}, vhodné místo pro zpracování Ajaxových požadavků vykreslovací – vyvolání metod beforeRender() a render{view}, které mají na starosti samotné vykreslení, tj. například tvorba odkazů v šablonách nebo přiřazení proměnných do šablon ukončení – vhodné pro ukončení databázového spojení Mezi fází vykreslovací a fází ukončovací dojde k uložení vnitřních stavů a persistentních proměnných a následně na to přichází fyzické vykreslení šablony na výstup. Framework nabízí podporu layoutu, do kterého je možné šablony zanořit. Navíc, jednotlivé šablony mohou být rozsekány na menší celky, tzv. snippety, s kterými lze poté samostatně manipulovat (například při ajaxové komunikaci). Nette nabízí podporu celé řady dalších mechanismů (formulářové prvky, validace, cachování, atd.) a není tak jen jakousi knihovnou, jak se na první pohled může zdát. Framework hojně využívá reflexi, proto je důležité sledovat korektní pojmenování jednotlivých metod. 7.3.3. Podpora Javascriptu Framework Nette (stejně jako Zend) si nejlépe rozumí s javascriptovým frameworkem JQuery. Opět začnu jednoduchou úlohou, kterou poté převedu na Ajax a ukážu, co je potřeba kde nastavit, aby byla klientská část plně zaktivována. Zapotřebí je presenter ButtonPresenter a definice několika metod. První bude metoda createComponentButtonForm, ve které vytvářím formulář s jedním tlačítkem. Tlačítko samotné definuji až v druhé metodě renderDefault(), neboť zde musím nejprve ověřit, jestli již byl formulář odeslán či nikoliv a na zákládě této informace zvolit jeho příslušný popisek. Metoda processButtonForm() je vyvolána při odeslání formuláře, ale zatím nedělá nic. Výpis 7.20. Kompletní kód presenteru ButtonPresenter.php isSubmitted()) { $this->label = 'Kliknuto'; } $this['buttonForm']->addSubmit('send', $this->label); }
[- 59 -]
public function createComponentButtonForm() { $form = new AppForm; $form->onSubmit[] = array($this, 'processButtonForm'); return $form; } public function processButtonForm(Form $form) { } }
Framework Nette nabízí využití layoutu. Definoval jsem tutíž úplně základní kostru a konstrukcí ,include #content- jsem defonoval, kam se má vkládat kód šablon. Je zde také vidět odkaz na metodu presenteru, konkrétně presenter ButtonPresenter a metoda renderDefault(). Názvy musí být uvedeny přesně, aby zafungovalo volání přes reflexi. Výpis 7.21. Část kódu layoutu @layout.phtml Tlačítko {include #content}
Samotný kód šablony se skládá z pouhých dvou konstrukcí. ,block content- uvádí začátek bloku šablony, která se vloží do layoutu, druhý výraz ,widget buttonForm- definuje vložení komponenty vytvořené metodou createComponentButtonForm(). Výpis 7.22. Kompletní kód šablony default.phtml {block content} {widget buttonForm}
Pokud budeme chtít úlohu převést na Ajaxovou, bude kód potřebovat několik změn. V presenteru je zapotřebý nadefinovat, že komponenta formuláře, která je použita, má být komponentou Ajaxovou. Toho lze docílit pomocí getElementPrototype()->class('ajax'). HTML prvku je pak nastaven atribut class na hodnotu ajax. V metodě processButtonForm() přibyla definice $this>invalidateControl('ajaxform'), která říká, že po odeslání formuláře se má komponenta ajaxform zneplatnit a odeslat opět na klienta. Vzhledem k tomu, že po odeslání formuláře změníme tlačítku popisek a tento formulář se tedy celý odešle na klienta, dojde tak k efektu pouhé změny tohoto popisku. Ve skutečnosti se přepsala komponenta celá. Výpis 7.23. Kompletní kód presenteru ButtonPresenter.php isSubmitted()) { $this->label = 'Kliknuto'; } $this['buttonForm']->addSubmit('send', $this->label); }
[- 60 -]
public function createComponentButtonForm() { $form = new AppForm; $form->getElementPrototype()->class('ajax'); $form->onSubmit[] = array($this, 'processButtonForm'); return $form; } public function processButtonForm(Form $form) { $this->invalidateControl('ajaxform'); } }
V layoutu je potřeba načíst javascriptové knihovny frameworku Nette. Jedná se o základní knihovnu JQuery, 2 nadstavbové funkce pro práci se snippety a jednu vlastní javasciptovou funkci psanou konkrétně pro tento příklad. Asi by bylo jednodušší 3 soubory sloučit do jednoho, nicméně Nette návod doporučuje oddělenou formu. Druhou změnou v layoutu je symbol @ před definicí místa pro obsah šablon. Ten je potřeba uvádět vždy, když je využita Ajaxová komunikace a vkládá se obsah se snippety pomocí include. Výpis 7.24. Kompletní kód layoutu @layout.phtml <script type="text/javascript" src="{$basePath}/js/jquery.js"> <script type="text/javascript" src="{$basePath}/js/jquery.nette.js"> <script type="text/javascript" src="{$basePath}/js/jquery.ajaxform.js"> <script type="text/javascript" src="{$basePath}/js/ajax.js"> Tlačítko @{include #content}
Tento krátký javascriptový kód zajístí, že všechny formuláře s třídou ajax budou odesílány pomocí Ajaxu. Výpis 7.25. Kompletní kód skriptu ajax.js $("form.ajax :submit").live("click", function (e) { $(this).ajaxSubmit(); return false; });
Jak je vidět, v šabloně se objevuje také symbol @, neboť se musí umisťovat i před vykreslení komponenty, která obsahuje snippety. Snippet ajaxform je ohraničen párovou značkou. Výpis 7.26. Kompletní kód šablony default.phtml @{block content} {snippet ajaxform} {widget buttonForm} {/snippet}
[- 61 -]
7.3.4. Javascriptové komponenty Z předchozí ukázky s formulářem by měl být patrný princip fungování ajaxové komunikace v Nette. Formulář se označil jako Ajaxový, v šabloně se ohraničil snippety, pomocí JQuery doplnila logika a pomocí překreslování snippetů se měnil jeho stav na klientovi. K dispozici jsou další komponenty, které vyvíjí komunita. Bohužel zde není zaručená kompatibilita mezi jednotlivými verzemi frameworku, neboť tyto komponenty nejsou součástí samotného frameworku. Několik vybraných, které stojí za povšimnutí: ConfirmationDialog – podpora potvrzovacích dialogů, podpora ajaxu DataGrid – velmi povedená datová mřížka, podpora ajaxu TabControl - podpora záložek, podpora ajaxu TreeView – podpora pro vykreslování stromové (rekurzivní) struktury VisualPaginator – stránkovací komponenta DatePicker – výběr data Pokud chceme využít vizuální efekty nebo pokročilejší funkce klientského skriptování, budeme muset přímo vkládat kód JQuery. Pro Nette je ve vývoji také knihovna usnadňující spolupráci s javascriptovým frameworkem Prototype, nicméně JQuery má momentálně jasnou převahu. 7.3.5. Nette a Ajax v praxi Typový příklad lze v Nette také implementovat. V presenteru je zapotřebí definovat formulář a jeho prvky. Textovému poli lze nastavit validátor, který zajistí i klientskou validaci. Vše se děje v metodě createComponentButtonForm() a formulář tedy nese označení ButtonForm, stejně jako v předchozím příkladě. Metoda handleLoadData() je vyvolávána změnou hodnoty formulářových prvků typu select. Tato metoda vrací předanou hodnotu v argumentu a ukončuje běh zpracování. Server tak odpoví pouze předávanou hodnotou. Výpis 7.27. Kompletní kód presenteru AjaxPresenter.php getElementPrototype()->class('ajax'); $values = array(1=> 'Hodnota1', 2=> 'Hodnota2', 3=> 'Hodnota3'); $form->addSelect('select1', 'Select 1:', $values); $form->addSelect('select2', 'Select 2:', $values); $form->addText('textbox', 'Text:') ->addRule(Form::FILLED, 'Hodnota musí být vyplněna'); $form->addSubmit('send', 'Odeslat'); return $form; } public function handleLoadData($value) { echo $value; $this->terminate(); } }
[- 62 -]
Výpis 7.28. Kompletní kód šablony default.phtml {block content} {widget buttonForm}
Kód šablony je totožný s kódem prvního příkladu. Taktéž kód souboru layoutu, bylo potřeba načíst JQuery knihovnu jquery.js a klientskou logiku uloženou v souboru ajax.js. Zde došlo k registraci funkcí na událost change formulářových prvků select. Registrovaná funkce v prvním případě vyšle ajaxový požadavek na server se zvolenou hodnotou prvku, server tuto hodnotu obratem vrací. Tato hodnota se nastaví jako zvolená druhému formulářovému prvku a navíc se vyvolá opět událost change. Ta vyvolá funkci zaregistrovanou na druhém formulářovém prvku. Jde opět o ajaxový požadavek směrem na server. Server obratem zasílá hodnotu zpět a pro změnu dojde k nastavení této hodnoty do textového pole. Tím je docíleno zřetězení údálostí prvků. Výpis 7.29. Kompletní kód skriptu ajax.js $(document).ready(function() { $('#frmbuttonForm-select1').change(function(){ $.ajax( { url : "?do=loadData&value="+this.selectedIndex, success: function(data){ $('#frmbuttonForm-select2').attr('selectedIndex', data); $('#frmbuttonForm-select2').trigger('change'); } } ); }); $('#frmbuttonForm-select2').change(function(){ $.ajax( { url : "?do=loadData&value="+this.value, success: function(data){ $('#frmbuttonForm-textbox').attr('value', data); } } ); }); });
7.3.6. Zhodnocení implementace Framework nabízí velmi zajímavou možnost jednoduše aktualizovat určité části klientského kódu, téměř bez jakékoliv námahy. Bohužel tuto vlastnost jsem nemohl využít. Vzhledem k tomu, že jsem formulářovým prvkům registroval obslužné funkce na jednotlivé události, musel bych toto učinit i na vyměněný prvek, které by byl serverem odeslán a na klientu použit místo onoho starého. Na straně serveru je určitá podpora pro generování podobné funkčnosti například pomocí následující konstrukce: $form['select']->getControlPrototype()->onchange('jsFx();');
Bohužel poté zase nelze realizovat zřetězení událostí. Jedinou cestou je tedy využít unobtrusive javascript. Tím ale přicházíme o možnost využít sílu frameworku Nette a jeho specifického přístupu k ajaxové komunikaci. Proto také v příkladu odesílám na server pouze hodnotu prvků, kterou obratem vracím zpět. Mnohem zajímavější by bylo, kdyby šla celá požadovaná funkcionalita čistě [- 63 -]
nadefinovat na straně serveru. Server by obdržel hodnotu formulářového prvku select1, vytvořil by prvek select2, nastavil by ho na požadovanou hodnotu a včetně všech klientských operací by jej odeslal s překreslení zpět na klienta. Tam by došlo k překreslení a vyvolání dalších požadovaných událostí.
7.4. Závěrečný rozbor V této podkapitole bych rád shrnul několik poznatků, které jsem nabyl při seznamování se s vybranými frameworky. 7.4.1. Architektura Návrhový vzor Intercepting Filter není přímo aplikován v žádném z frameworků. Logika, která by mohla být v těchto filtrech, je vyvolávána při zavádění aplikace z front controlleru, nebo je umístěna v controllerech (resp. presenterech). Obslužné celky nejsou ale vzájemně zřetězeny způsobem, který vzor popisuje. Je to dáno také tím, že PHP nespecifikuje žádný standard, jako třeba Java a její Java Servlet Filters. Naopak vzor Front Controller implementují všechny 3 frameworky. Struktura všech aplikací postavených na těchto rámcích má své centrální vstupní místo, kam vstupuje uživatelův požadavek. Zde se provádí další nezbytné operace pro vyvolání požadované akce v konkrétním controlleru. Podle vzoru Context Object všechny frameworky zapouzdřují HTTP požadavek a HTTP odpověď do svého specifického objektu. K dispozici jsou poté metody typu isModified() a vývojář je tak zcela odstíněn od HTTP hlaviček. Tyto objekty jsou poté předávány dál a tím je celá aplikace korektně odstíněna od protokolárně závislých dat. Vzhledem k tomu, že frameworky striktně oddělují jednotlivé controllery od sebe, implementují také po vzoru Application Controller mechanismus, který vyvolává tyto controllery a k nim i příslušná view. Ve všech případech se vývojář o tuto činnost vůbec nestará, jeho povinností je pouze dodržet jmenné konvence, neboť ve všech případech bylo vyvolávání realizováno prostřednictvím reflexe. Co se týká pomocných tříd (metod) pro view dle vzoru View Helper, je zde nabízená podpora odlišná. Ve frameworcích Zend a Nette je k dispozici řada základních helperů (pro úpravy výstupu, jeho formátování atd.). Vedle nich existuje podpora pro vývoj a zapojování dalších helperů vytvořených uživatelem. Framework PRADO naopak nabízí své komponenty a také nabízí možnost vytvořit další odvozené komponenty. Pokud je potřeba specifická logika, pro kterou komponentu vytvářet nechceme, lze využít speciální značky přímo v šabloně, pomocí kterých můžeme odkazovat na libovolný PHP kód. Všechny frameworky shodně podporují vzor Composite View. Všechny rámce mají mechanismus pro definici rozvržení stránky (layout). Zde se poté definují místa, kam se má vkládat kód jednotlivých šablon. Typicky se tedy stránka rozdělí na jednotlivé logické celky (např. hlavička, navigace, levá část těla, informační část těla, patička) a ke každé této části je přiřazena šablona. Vývojář tak nemusí listovat kódem, který ho zrovna vůbec nezajímá a edituje pouze aktuální blok. Na druhou stranu, v hlavních šablonách pro definici layoutu lze definovat společnou logiku (HTML meta elementy, registrace javascriptových knihoven, definice stylů) a mít ji tak na jednom společném místě. Zend, PRADO i Nette architektura se drží principů MVC. Zend framework je typický představitel rámce, který implementuje vzor MVC. Model, View i Controller jsou tu jasně definovány a [- 64 -]
architektuře je zcela podřízeno i pojmenování jednotlivých souborů. Pro vývojáře, kteří začínají s tímto frameworkem pracovat je rozdělování jednotlivé logiky velice intuitivní. Framework PRADO je komponentový, událostně řízení framework a je to představit implementátora vzoru Supervising Controller z rodiny MVP. Zatímco rozdělení View (šablony a jednotlivé komponenty) a Presenteru (třídy odvozené od TPage) je zřejmé, Model framework zcela přesně nevymezuje a záleží na vývojáři, jak si přístup k datům a práci s nimi zorganizuje. Může však využít třídu TActiveRecord (podle vzoru Active Record), kterou framework nabízí. Framework Nette je taktéž představitel MVP vzoru. V tomto případě se ale liší od MVC pouze tím, že View mají úzkou vazbu na jednotlivé Presentery. Rozdělení logiky je jako v případě Zendu velmi intuitivní, soubory jsou také organizovány do odpovídající struktury jako architektura frameworku. Vzhledem k tomu, že všechny 3 frameworky používají šablonový zápis výstupu, je aplikace vzoru Template View samozřejmostí. Šablony v Zendu tvoří HTML, do kterého vývojář vkládá výrazy PHP jazyka. Framework PRADO doplňuje obyčejné HTML svými speciálními značkami se speciálními atributy. Navíc lze také libovolně vkládat PHP proměnné a výrazy. Nette v šablonách používá vlastní syntaxi. HTML kód lze tak doplňovat speciálními výrazy ve složených závorkách (například pro vytvoření cyklu, podmíněné výrazy atd.). Na první pohled může být zápis matoucí, nicméně pochopení zápisu je otázkou několika desítek minut. Ani jeden z frameworků nepodporuje přímo transformaci výstupu dle vzoru Transform View. Nicméně pro framework Zend existují rozšíření, které poskytují podporu pro XSLT transformace. 7.4.2. Podpora javascriptu a Ajaxu Převážnou část klientské funkčnosti frameworky přebírají z jiných, již časem prověřených, javascriptových frameworků. Je to ale pochopitelné, neboť klientský vývoj vyžaduje velké zdroje a úsilí. Navíc, tato technologická specializace nabízí rychlejší a stabilnější vývoj. Nejvíce pokrokový je určitě framework PRADO. Využívá frameworky Prototype a script.aculo.us. Navíc přidává i řadu své klientské logiky. Například velmi příjemně se programuje logiku pro obsluhu událostí, vývojář nemusí vůbec do javascriptu zasahovat. Je to ale dáno specifickou povahou frameworku. Zend využívá frameworky Dojo a JQuery. Problém ovšem je, že přináší podporu pouze velmi mála funkcí. Vývojář musí mít dobrou znalost i těchto klientských frameworků. Podpora je tak spíše v rovině integrace, než v rovině funkční. Podobně je tomu tak i v případě Nette. Nette využívá framework JQuery, pro Prototype existuje ne příliš známé rozšíření z řad Nette komunity. Když jsem se zajímal konkrétně o Ajaxovou funkčnost, vždy jsem narazil na nedostatečnou dokumentaci. Nejvíce markantní tomu bylo v případě Zendu, kde nebyl dostupný žádný adekvátní příklad a byl jsem tak odkázán na dokumentaci klientského frameworku a metodu „pokus omyl“. Lze se tak pouze domnívat, jestli framework nenabízí nějakou další skrytou ajaxovou podporu. Část ajaxových komponent frameworku PRADO je také stále nezdokumentovaná, chybí i příklady. To velmi komplikuje jejich použití v šablonách. Nette je na tom podobně, nicméně je k dispozici aktivní fórum, kde se dá dohledat řada informací. Celkově to potvrzuje fakt, že Ajaxové techniky jsou stále doplňkovou funkcionalitou, kterou frameworky pomalu adaptují. Věřím, že za rok bude situace podstatně lepší. U frameworku PRADO je sice Ajax základem, nicméně mě zarazila viditelná časová prodleva v reakcích na jednotlivé
[- 65 -]
požadavky. Dokazují to i dostupné výkonnostní testy (Daněk, 2008), framework zde má stále značné rezervy a lze pouze doufat, že další verze přinesou zvýšení výkonu.
8. Závěr V této diplomové práci jsem se snažil zmapovat prezentační vrstvu a zjistit, jak je zpracovávána v jednotlivých frameworcích. Když jsem si téma vybíral, netušil jsem, že bude takový problém celou problematiku popsat. Žil jsem v domnění, že existuje řada materiálů, které korektním způsobem zpracuji, poté vyberu z několika programovacích jazyků pár frameworků a rozeberu jeden po druhém. Poté shromáždím společné rysy, popíšu je, včetně těch zajímavých, unikátních. Když jsem začal se sběrem materiálů, zjistil jsem, že jich mnoho není, vůbec pak v českém jazyce. K dispozici byla řada internetových zdrojů, bohužel, s postupným pronikáním do problematiky jsem řadu z nich vyhodnotil jako nekorektních. Navíc jsem zjistil, že teoreticky popsat fungování a vztahy ve vrstvě také nebude úplně nejjednodušší. Musel jsem nastudovat základní návrhové vzory, které poté byly základem pro vzory složitější, přímo vztažené k prezentační vrstvě. Jakmile jsem začal praktickou část práce, narazil jsem na další problematiku. Nedostatečnou nebo nekorektní dokumentaci potřebných partií, zejména ajaxových technik. Samotné rozběhnutí frameworků a napsání jednoduché aplikace složité nebylo, teoretický popis vnitřních vztahů již ano. Když jsem chtěl napsat totožnou aplikace ve všech frameworcích, která by ověřila složitější partie, musel jsem se spokojit s velmi jednoduchou úlohou. Složitější totiž nebylo možné vyvinout, alespoň s frameworky v základní konfiguraci. Díky těmto problémům jsem musel počet frameworků radikálně omezit. V úvodní části jsem vymezil hranice prezentační vrstvy webových aplikací a porovnal ji s RIA aplikacemi. První část jsem zaměřil na popis nejznámějších a nejrozšířenějších technologií na klientovi. Technologie jsem rozdělil do skupin. Každou technologii jsem rozebral a připojil i její krátkou historickou exkurzi včetně důležitých milníků. Poté jsem se zabýval způsobem, jakým klient komunikuje s aplikační vrstvou. Přes lehký popis HTTP protokolu a formáty, kterými strany spolu komunikují, jsem se dostal k technikám komunikace. Z nich byla samozřejmě nejzajímavější technika Ajax, která je dnes velice populární. Tu jsem také velmi podrobně rozepsal, neboť je to základ dnešních moderních webových aplikací. Tím jsem měl popsanou technickou podobu prezentační vrstvy na klientovi a aktivity, které se dějí mezi klientem a serverem. Zbývala mi serverová část prezentační vrstvy. Tu jsem rozebral z teoretického hlediska podle návrhových vzorů. Jednotlivé návrhové vzory jsem popsal, nastínil jejich aplikaci na konkrétních příkladech a demonstroval obrázky a diagramy. V poslední části práce jsem si zvolil 3 PHP frameworky a snažil jsem se zmapovat jejich fungování. Konkrétně jsem byl zaměřen na tu část, která měla na starost práci s prezentační vrstvou a její generování. Snažil jsem se identifikovat aplikace návrhových vzorů, které jsem popisoval v předchozí kapitole. Když jsem měl tuto partii popsanou, zaměřil jsem se na klientské skriptování a techniku Ajax. Aby bylo srovnání v tomto bodě alespoň trochu měřitelné, zvolil jsem společné zadání, tj. napsat velmi jednoduchou, ale totožnou aplikaci, v každém z frameworků. Tato aplikace vyžadovala použití Ajaxu. Implementace poté ukázala, který framework si se zadáním poradil nejlépe. Také vyšly najevo společné implementační znaky a nedostatky frameworků. Ostatně jsem se snažil všechny tyto nabyté poznatky shrnout v závěru kapitoly. Jak jsem již zmínil, původně jsem chtěl zvolit mnohem složitější ukázkovou aplikaci. Konkrétně se mělo jednat o práci s komponentou datagrid, tj. datovou mřížkou, navíc v ajaxovém režimu. Avšak ani jeden z frameworků ji ve své základní podobě nepodporuje. Proto jsem ze svých nároků slevoval až do výsledné podoby. [- 66 -]
V diplomové práci jsem použil řadu termínů, ke kterým jsem nenašel korektní a ověřený český ekvivalent. Proto je v textu nechávám v původní podobě, u některých jsem použil i počeštěné tvary, zejména tam, kde vím, že se v IT mluvě běžně takto používají. Myslím si, že by bylo vhodné navázat na tuto práci těmito tématy: Prozkoumat frameworky v jiných programovacích jazycích, zejména ASP.NET a Java. Vzhledem k časové náročnosti ale asi nebude možné provést detailní analýzu ve více jazycích zároveň. Rozebrat javascriptové frameworky a jejich možnosti a použití. Rozebrat podobným způsobem prezentační vrstvu v RIA aplikacích.
[- 67 -]
9. Literatura 1. Asleson, Schutta. AJAX, vytváříme vysoce interaktivní webové aplikace, 1. vydání. Computer Press, a.s. 2006. ISBN 80-251-1285-3. 2. Pecinovský, Rudolf. Návrhové vzory, 1. vydání. Computer Press, a.s. 2007. ISBN 978-80-2511582-4. 3. Alur, Deepak, Crupi, John, Malks, Dan. Core J2EE Patterns: Best Practices and Design Strategies, 2. Vydání. Prentice Hall PTR. 2003. ISBN 0-13-142246-4. 4. CleverSmart. Vícevrstvá architektura: popis vrstev. [online] [cit. 20.6.2010+. Dostupný z WWW: < http://www.cleverandsmart.cz/vicevrstva-architektura-popis-vrstev/>. 5. MSDN Blogs: DiegumZone – Who Wanna be an Architect?. 3-Tier, 3-Layer, MVC : a Trio of Famous Trios. *online+, publikováno 9.10.2006 *cit. 21.6.2010+. Dostupný z WWW: < http://blogs.msdn.com/b/diegumzone/archive/2006/10/09/3_2d00_tier_2c00_3_2d00_layer_2c00_-mvc_3a00_-a-trio-of-famous-trios.aspx>. 6. James, Justin. Can presentation layer abstraction ever replace desktop and Web apps?. *online+, publikováno 3.5.2008 *cit. 14.5.2010+. Dostupný z WWW: < http://blogs.techrepublic.com.com/programming-and-development/?p=669>. 7. Moravec, Zdeněk. RIA – Rich Internet Applications. *online+, posl. změna 14.4.2009 *cit. 16.5.2010+. Dostupný z WWW: < http://programujte.com/?akce=clanek&cl=2009041200-riarich-internet-applications>. 8. Pichlík, Roman. Rich Internet Application. *online+, posl. změna 14.6.2005 *cit. 17.5.2010]. Dostupný z WWW: < http://interval.cz/clanky/rich-internet-application/>. 9. Holčík, Tomáš. Prohlížeč internetu dnes slaví 10 let. *online+, publikováno 22.4.2003 *cit. 16.4.2010+. Dostupný z WWW: < http://www.zive.cz/Clanky/Prohlizec-internetu-dnes-slavi10-let/sc-3-a-111439/default.aspx>. 10. Wikipedia. Tim Berners-Lee. [online], [cit. 4.4.2010+. Dostupný z WWW: < http://cs.wikipedia.org/wiki/Tim_Berners-Lee>. 11. Wikipedia. Robert Cailliau. [online], [cit. 7.4.2010+. Dostupný z WWW: < http://en.wikipedia.org/wiki/Robert_Cailliau>. 12. Shannon, Ross. XHTML Explained. *online+, posl. změna 8.1.2010 *cit. 12.4.2010+. Dostupný z WWW: < http://www.yourhtmlsource.com/accessibility/xhtmlexplained.html>. 13. W3C. XHTML2 Working Group Home Page. *online+, posl. změna 29.1.2009 *cit. 18.4.2010]. Dostupný z WWW: < http://www.w3.org/MarkUp/>. 14. W3C. HTML5 differences from HTML4. *online+, posl. změna 16.3.2010 *cit. 18.4.2010]. Dostupný z WWW: < http://www.w3.org/TR/html5-diff/>. 15. Hunt. A preview of HTML5 *online+, publikováno 4.12.2007 *cit. 19.4.2010+. Dostupný z WWW: < http://www.alistapart.com/articles/previewofhtml5/>. 16. Wikipedia. Cascading Style Sheets. [online], [cit. 22.4.2010+. Dostupný z WWW: < http://en.wikipedia.org/wiki/Cascading_Style_Sheets>. 17. Mozilla. About JavaScript. [online], 19.4.2010 [cit. 2.5.2010+. Dostupný z WWW: < https://developer.mozilla.org/en/About_JavaScript>. 18. Champeon, Steve. JavaScript: How did we get here ?. [online], 4.6.2001 [cit. 2.5.2010]. Dostupný z WWW: < http://www.oreillynet.com/pub/a/javascript/2001/04/06/ js_history.html>.
[- 68 -]
19. Wikipedia. VBScript. [online], [cit. 6.5.2010+. Dostupný z WWW: < http://en.wikipedia.org/wiki/VBScript>. 20. Klarr, Scott. Adobe AIR vs Flash vs Flex vs Microsoft Silverlight. [online], 15.12.2007 [cit. 26.4.2010+. Dostupný z WWW: < http://www.scottklarr.com/topic/39/adobe-air-vs-flash-vsflex-vs-microsoft-silverlight/>. 21. Redakce Interval.cz. Silverlight – co je Silverlight ?. [online], 3.11.2008 [cit. 26.4.2010]. Dostupný z WWW: < http://interval.cz/clanky/silverlight-co-je-silverlight/>. 22. Google. Stavové kódy HTTP. [online], posl. změna 30.9.2009 *cit. 8.5.2010+. Dostupný z WWW: < http://www.google.com/support/webmasters/bin/answer.py? hl=cs&answer=40132>. 23. Apple developers. Remote scripting with IFRAME. [online], [cit. 14.5.2010+. Dostupný z WWW: < http://developer.apple.com/internet/webcontent/iframe.html/>. 24. Ashley, Brent. Remote Scripting Resources. *online+, posl. změna 11.2007 *cit. 16.5.2010]. Dostupný z WWW: < http://www.ashleyit.com/rs/main.htm>. 25. Garrett, Jesse, James. Ajax: A new approach to web applications. *online+, posl. změna 18.2.2005 [cit. 20.5.2010+. Dostupný z WWW: < http://www.adaptivepath.com/ideas/essays/ archives/000385.php>. 26. Fowler, Martin. Web Presentation Patterns. [online] [cit. 17.06.2010+. Dostupný z WWW: < http://martinfowler.com/eaaCatalog/>. 27. Microsoft. Web Presentation Patterns. [online] [cit. 1.6.2010+. Dostupný z WWW: < http://msdn.microsoft.com/en-us/library/ms998516.aspx/>. 28. Web Application Component Toolkit. Template View. *online+, posl. změna 2.12.2007 *cit. 18.6.2010+. Dostupný z WWW: < http://www.phpwact.org/pattern/template_view>. 29. Web Application Component Toolkit. Intercepting filter. *online+, posl. změna 9.12.2006 *cit. 18.6.2010+. Dostupný z WWW: < http://www.phpwact.org/pattern/intercepting_filter>. 30. Web Application Component Toolkit. Front Controller. *online+, posl. změna 7.7.2007 *cit. 17.6.2010+. Dostupný z WWW: < http://www.phpwact.org/pattern/front_controller?s= front%20controller>. 31. Bernard, Borek. Seriál MVC a další prezentační vzory. [online], 15.5.2009 [cit. 4.6.2010]. Dostupný z WWW: < http://zdrojak.root.cz/serialy/mvc-a-dalsi-prezentacni-vzory/>. 32. Xue, Qiang, Zhuo, Wei. PRADO 3.1.7. Manual. [online], [cit. 26.5.2010+. Dostupný z WWW: < http://sourceforge.net/projects/prado/>. 33. Zend. Programmer’s Reference Guide. [online], [cit. 10.6.2010+. Dostupný z WWW: < http://framework.zend.com/manual/en/>. 34. Grudl, David. Seriál začínáme s Nette framework. [online], 30.6.2009 [cit. 18.6.2010]. Dostupný z WWW: < http://zdrojak.root.cz/serialy/zaciname-s-nette-framework/>. 35. Grudl, David, Nette komunita. Příručka programátora. [online], [cit. 18.6.2010+. Dostupný z WWW: < http://doc.nette.org/cs/>. 36. Daněk, Petr. Velký test PHP frameworků. [online], 11.9.2008 [cit. 28.6.2010+. Dostupný z WWW: < http://www.root.cz/clanky/velky-test-php-frameworku-zend-nette-php-a-ror/>.
[- 69 -]
10. Terminologický slovník Termín
Zkratk a
Active record
Active Server Pages
ASP
Adobe AIR
Adobe FLASH
FLASH
Adobe FLASH Player Adobe FLEX
FLEX
Application programming interface Asynchronous javascript and XML Back-end
API
AJAX
Business logika
Cache, cachování
Callback
Cascading Style Sheets
CSS
Význam [zdroj] Návrhový vzor popisující zapouzdření obsahu jednoho záznamu v tabulce relační databáze do objektu, který zároveň implementuje metody pro přístup k databázi a business logiku vztahující se k dané tabulce. [http://cs.wikipedia.org/wiki/Active_Record] skriptovací platforma společnosti Microsoft, primárně určená pro dynamické zpracování webových stránek na straně serveru. * http://cs.wikipedia.org/wiki/Active_Server_Pages] Běhové prostředí pro desktopové webové aplikace psané pomocí technologií HTML, JavaScript a Adobe FLASH a ActionScript. [http://www.adobe.com/cz/products/air/] Grafický vektorový program na vytváření FLASH aplikací (hry, reklamní bannery). Tyto aplikace lze poté přehrávat v prohlížeči, který má nainstalovaný plugin Adobe Flash Player. [http://cs.wikipedia.org/wiki/Adobe_Flash] Plugin do webového prohlížeče. Jeho instalací lze přehrávat FLASH aplikace. [http://www.adobe.com/products/flashplayer/] Sada technologií pro tvorbu RIA aplikací založených na Adobe FLASH. FLEX aplikace lze přehrávat pomocí Adobe FLASH Playeru. [http://cs.wikipedia.org/wiki/Adobe_Flex] Aplikační programové rozhraní. Sada funkcí, pomocí nichž může programátor danou knihovnu/aplikaci používat. [http://cs.wikipedia.org/wiki/API] Techniky určené ke komunikaci klienta se serverem. Nejčastěji se používá v kombinaci s JavaScriptem pro asynchronní zpracování HTTP požadavků. [http://cs.wikipedia.org/wiki/AJAX] Ta část aplikace, se kterou uživatel komunikuje zprostředkovaně. Ve webové aplikaci přes middleware. Datové úložiště (např. relační databáze) je příklad back-endu. [http://en.wikipedia.org/wiki/Front_and_back_ends] Zahrnuje klíčové výpočty, algoritmy a operace nad datovými objekty, které realizují zpracování informací mezi datovým úložištěm a uživatelským rozhraním. [http://en.wikipedia.org/wiki/Business_logic] Cache je kolekce dat, které duplikují originální data a jsou uložená ve více přístupném místě, než originální data. Cache se tedy používá pro rychlejší přístup k datům, u kterých se předpokládá, že se od uložení do cache nezměnily. Cacheování dat je proces vytvoření cache těchto dat. [http://cs.wikipedia.org/wiki/Cache] Jedná se o část kódu, která je předávána jako argument do jiné části kódu, kde je po vykonání hlavního kódu následně vyvolána. Příkladem jsou callback funkce v JavaScriptu, které jsou jako argumenty předávány po jiných funkcí. Následně, pokud je vyvolána určitá událost, je tato callback funkce automaticky zavolána. [http://en.wikipedia.org/wiki/Callback_%28computer_science%29] jazyk pro popis způsobu zobrazení stránek napsaných v jazycích HTML nebo XML [- 70 -]
Command
Cookie
Desktop
Dojo Drag and drop
Dynamické HTML
DHTM L
ECMAScript
Extensible HyperText Markup Language Extensible Markup Language
XHTM L
XML
Framework
Front-end
HTML Application
HTA
HyperText Markup Language
HTML
Hypertext Preprocessor
PHP
Hypertext
HTTP
[http://cs.wikipedia.org/wiki/CSS] Tento návrhový vzor odstiňuje klienta od zpracování jeho požadavku. Klient pouze definuje požadavek a určí zpracovatele, samotný způsob zpracování ho ale nezajímá. [http://objekty.vse.cz/Objekty/Vzory-Command] Textový soubor, který ukládá prohlížeč do počítače uživatele. Data v souboru mohou například reprezentovat stav příslušné webové aplikace v jinak bezstavovém prostředí HTTP. [http://cs.wikipedia.org/wiki/HTTP_cookie] Klasický stolní počítač. Když se hovoří o aplikaci, že je „desktopová“, je tím míněna nutnost instalace této aplikace na stolní počítač. [http://cs.wikipedia.org/wiki/Desktop] Moderní javascriptový framework. [http://www.dojotoolkit.org/] Funkčnost grafického rozhraní, kdy uživatel může klikat na virtuální objekt a následným táhnutím myši je přesunovat. [http://en.wikipedia.org/wiki/Drag-and-drop] Skupina technologií používaných k tvorbě dynamického obsahu webových aplikací. Do této skupiny patří HTML, JavaScript, CSS a DOM. [http://cs.wikipedia.org/wiki/DHTML] Skriptovací jazyk standardizovaný dle specifikace ECMA-262. Je základem pro skriptovací jazyky JavaScript a JScript. [http://en.wikipedia.org/wiki/ECMAScript] HTML stránka splňující požadavky XML dokumentu. Jedná se o sémantickou verzi HTML. [http://cs.wikipedia.org/wiki/Extensible_HyperText_Markup_Language] značkovací jazyk, který byl vyvinut a standardizován konsorciem W3C. Umožňuje snadné vytváření konkrétních značkovacích jazyků pro různé účely a široké spektrum různých typů dat [http://cs.wikipedia.org/wiki/XML] softwarová struktura, která slouží jako podpora při programování a vývoji a organizaci jiných softwarových projektů [http://cs.wikipedia.org/wiki/Framework] Ta část aplikace, se kterou přichází uživatel do přímého kontaktu. Ve webových aplikacích je front-end internetový prohlížeč. [http://en.wikipedia.org/wiki/Front_and_back_ends] Technologie společnosti Microsoft. Obyčejná HTML stránka (využívající funkce nějakého skriptovacího jazyka), která ovšem běží v zcela jiném bezpečnostním režimu. Stránka se spustí v samostatném okně a má přístup k funkcím systému (například vytváření, editace, mazání souborů, práce s registry, práce s DLL knihovnami). [http://msdn.microsoft.com/en-us/library/ms536496%28VS.85%29.aspx] značkovací jazyk pro hypertext. Je jedním z jazyků pro vytváření stránek v systému World Wide Web, který umožňuje publikaci dokumentů na Internetu. [http://cs.wikipedia.org/wiki/HTML] skriptovací programovací jazyk, určený pro programování webových apklikací, od verze 5 se jedná také o objektový jazyk [http://cs.wikipedia.org/wiki/PHP] internetový protokol určený původně pro výměnu hypertextových [- 71 -]
Transfer Protocol Javascript
Javascript object notation JQuery
JS
JSON
JScript
Java applet
Java Virtual Machine JavaFX
JVM
Microsoft Silverlight
middleware
Model-ViewPresenter
MVP
Model-ViewController
MVC
Observer
Ovládací prvky ActiveX
Parsování
dokumentů ve formátu HTML [http://cs.wikipedia.org/wiki/HTTP] Multiplatformní, objektově orientovaný, skriptovací jazyk běžící ve webovém prohlížeči. Vychází z ECMAScriptu. [http://cs.wikipedia.org/wiki/JavaScript] Jednoduchý, textový, lidsky čitelný formát pro přenos objektů a jiných datových struktur v síti. [http://www.json.org/] Lehký javascriptový framework. [http://jquery.com/] Klientský skriptovací jazyk podporovaný firmou Microsoft. Vychází z ECMAScriptu. [http://en.wikipedia.org/wiki/JScript] Applet je softwarová komponenta, která běží v kontextu jiného programu, např. webového prohlížeče. Java applet je applet nejčastěji napsaný v Javě běžící v prohlížeči pomocí JVM (Java Virtual machine). [http://en.wikipedia.org/wiki/Java_applet] Běhové prostředí nutné ke spuštění java appletů nebo JavaFX aplikací. [http://en.wikipedia.org/wiki/Java_Virtual_Machine] Platforma pro budování RIA aplikací. Aby mohl webový prohlížeč či desktop JavaFX aplikaci spustit, musí být nainstalováno JRE nebo Java ME (v případě mobilních telefonů). [http://javafx.com/] Odlehčený plugin (lightweight plugin) pro webové prohlížeče od společnosti Microsoft pro přehrávání RIA aplikací Silverlight. Konkurent Adobe FLASH. [http://www.silverlight.net/] Software, který funguje jako integrační služba mezi vrstvami, mezi které je vložen. [http://en.wikipedia.org/wiki/Middleware] Variance architektury MVC. To této rodiny vzorů patří vzory Supervising Controller a Passive View. Tento návrh je vhodný pro RIA aplikace. [http://zdrojak.root.cz/clanky/prezentacni-vzory-zrodiny-mvc/] Nejoblíbenější architektura webových aplikací. Podstata je v oddělení kódu do tří částí. Mezi jednotlivými části existují specifické vazby. Od této architektury je odvozena řada konkrétních návrhových vzorů, jeden z nich se shodně označuje MVC. [http://zdrojak.root.cz/clanky/uvod-do-architektury-mvc/] Návrhový vzor, který řeší situaci, kdy na jednom objektu je závislých několik dalších objektů a tyto objekty je potřeba kontaktovat vždy, když primární objekt k tomu dá podnět. [http://objekty.vse.cz/Objekty/Vzory-Observer] Malé programové bloky, které mohou prostřednictvím internetového prohlížeče tvořit distribuovanou aplikaci. Vkládají se do jiných aplikací. Technologie společnosti Microsoft. Ovládací prvky dokáží efektivně využívat prostředí Windows. [http://en.wikipedia.org/wiki/ActiveX] Parsování je proces, při kterém parser zpracováva nějaký řetězec či soubor. Parser si lze představit jako program, který zná strukturu předávaného řetezce a na základě určitých výskytů vykonává určité operace (například modifikuje daný řetězec). [- 72 -]
Plugin (Plugin)
Prototype
Prototypování
Renderování Rich Internet Application
RIA
Script.aculo.us
Standard Generalized_ Markup Language Strategy
SGML
Tag Uniform Resource Locator VBScript
URL
Webová aplikace World Wide Web YUI Library
WWW YUI
Zásuvný modul, software, který nepracuje samostatně, ale jako doplňkový modul jiné aplikace a rozšiřuje tak její funkčnost. Typické jsou například pluginy do webového prohlížeče. [http://cs.wikipedia.org/wiki/Plugin] Nejznámější Javascriptový framework. Řada dalších frameworků je na něm založena. [http://www.prototypejs.org/] Mechanismus užívaný např. v JavaScriptu, který nahrazuje mechanismus dědičnosti. Pomocí něj lze rozšiřovat stávající objekty. [http://www.southsearepublic.org/article/1174/read/object_oriented_jav ascript__prototyping] Proces, při kterém ze zadaných dat vzniká obraz. V případě webového prohlížeče je to webová stránka. Webové aplikace, které svojí architekturou a uživatelským rozhraním připomínají desktopové aplikace. Ke zprovoznění takové aplikace jsou zapotřebí pluginy. Nejznámější technologie jsou Adobe FLASH, Microsoft Silverlight a JavaFX. [http://en.wikipedia.org/wiki/Rich_Internet_application] Javascriptový framework postavený na frameworku Prototype. Vhodný pro visuální efekty. http://script.aculo.us/ Univerzální značkovací metajazyk, který umožňuje definovat značkovací jazyky jako své vlastní podmnožiny. [http://cs.wikipedia.org/wiki/Standard_Generalized_Markup_Language] Řeší situaci, kdy na danou problematiku je k dispozici více řešení (algoritmů) a dle situace je potřeba některé z nich vybrat. [http://objekty.vse.cz/Objekty/Vzory-Strategy] Značky, které tvoří HTML, XHTML nebo XML. [http://www.jakpsatweb.cz/enc/tag.html] řetězec znaků s definovanou strukturou, který slouží k přesné specifikaci umístění zdrojů informací na Internetu [http://cs.wikipedia.org/wiki/URL] Skriptovací jazyk vyvinutý společností Microsoft. [http://cs.wikipedia.org/wiki/VBScript] Druh aplikace, která je dostupná pomocí sítě Internet a jejíž uživatelské rozhraní je zobrazováno prohlížečem. [http://cs.wikipedia.org/wiki/Webov%C3%A1_aplikace] Soustava propojených hypertextových dokumentů. [http://cs.wikipedia.org/wiki/World_Wide_Web] Javascriptový framework vyvíjený společností YAHOO. [http://developer.yahoo.com/yui/]
[- 73 -]
11. Seznam přiložených příkladů Na přiloženém nosiči v podadresářích priklady jsou k dispozici ukázkové aplikace. Stačí je zkopírovat do aktivního adresáře aplikačního serveru. Frameworky není potřeba nijak konfigurovat, vždy je přiložen kompletní nutný kód ke spuštění celé aplikace. PHP ovšem může požadovat určitá rozšíření, které jsou nutné pro daný framework. V takovém případě je potřeba dle dostupných návodů instalaci PHP poupravit. /01-Iframe – příklady demonstrující komunikaci se serverem pomocí elementu IFRAME /02-cookies – příklady demonstrující komunikaci se serverem pomocí cookies /03-ajax – příklady ajaxové komunikace /04-zend – příklady rozebírané v diplomové práce vytvořené frameworkem Zend /05-prado – příklady rozebírané v diplomové práce vytvořené frameworkem PRADO /06-nette – příklady rozebírané v diplomové práce vytvořené frameworkem Nette