načítání...
nákupní košík
Košík

je prázdný
a
b

Návrhové vzory v PHP - Marian Böhmer

-6%
sleva

Elektronická kniha: Návrhové vzory v PHP
Autor:

Pracujete s PHP a potřebujete dát svému vývoji větší řád? Řešíte opakovaně podobné typy problémů? Hledáte možnosti, jak vyvíjet rychleji, efektivněji a s menším úsilím? ...
Titul je skladem - ke stažení ihned
Médium: e-kniha
Vaše cena s DPH:  249 Kč 234
+
-
7,8
bo za nákup

ukázka z knihy ukázka

Titul je dostupný ve formě:
elektronická forma tištěná forma

hodnoceni - 69.2%hodnoceni - 69.2%hodnoceni - 69.2%hodnoceni - 69.2%hodnoceni - 69.2% 80%   celkové hodnocení
2 hodnocení + 0 recenzí

Specifikace
Nakladatelství: » Computer press
Dostupné formáty
ke stažení:
PDF
Upozornění: většina e-knih je zabezpečena proti tisku
Počet stran: 320
Rozměr: 23 cm
Úprava: ilustrace
Vydání: 1. vyd.
Spolupracovali: překlad Lukáš Krejčí
Jazyk: česky
Médium: e-book
Téma: návrhové vzory
ADOBE DRM: bez
ISBN: 978-80-251-3338-5
Ukázka: » zobrazit ukázku
Popis

Pracujete s PHP a potřebujete dát svému vývoji větší řád? Řešíte opakovaně podobné typy problémů? Hledáte možnosti, jak vyvíjet rychleji, efektivněji a s menším úsilím? Začleňte do své praxe použití návrhových vzorů a předežeňte konkurenci perfektními softwarovými produkty.

Zkušený autor vás provede 23 návrhovými vzory a u každého vás seznámí nejen s jeho klíčovými přednostmi, ale ukáže vám i ukázkovou implementaci a upozorní vás na skryté problémy. To vše na příkladech z praxe s řadou vlastních zkušeností, které v běžných příručkách nenajdete. Každému vzoru se věnuje samostatná kapitola vždy se stejnou strukturou, knihu tak můžete číst od začátku do konce, nebo ji použít jako katalog vzorů.

S knihou se mimo jiné naučíte:
* Správně přistoupit k návrhu softwaru
* K čemu jsou jednotlivé vzory vhodné
* Využít přednosti jazyka UML
* Opakovaně použít již vytvořený kód
* Zvolit vhodný vzor pro daný problém
* Jak každý ze vzorů implementovat


O autorovi:
Marian Böhmer vystudoval obor Komunikační a informační technologie na Akademii ozbrojených sil v Liptovském Mikuláši. Je zkušeným programátorem v PHP a autorem řady projektů založených na Zend Frameworku. V době vydání knihy působil jako vedoucí IT oddělení a garant IT projektů.

Předmětná hesla
Zařazeno v kategoriích
Marian Böhmer - další tituly autora:
Zend Framework Zend Framework
Böhmer, Marian
Cena: 427 Kč
Návrhové vzory v PHP Návrhové vzory v PHP
Böhmer, Marian
Cena: 429 Kč
 
Recenze a komentáře k titulu
Zatím žádné recenze.


Ukázka / obsah
Přepis ukázky
Marian Böhmer Návrhové vzory v PHP Computer Press Brno 2012 Návrhové vzory v PHP Marian Böhmer Překlad: Lukáš Krejčí Obálka: Martin Sodomka Odpovědný redaktor: Martin Herodek Technický redaktor: Jiří Matoušek Objednávky knih: http://knihy.cpress.cz www.albatrosmedia.cz eshop@albatrosmedia.cz bezplatná linka 800 555 513 ISBN 978-80-251-3338-5 Vydalo nakladatelství Computer Press v Brně roku 2012 ve společnosti Albatros Media a. s. se sídlem Na Pankráci 30, Praha 4. Číslo publikace 15 935. © Albatros Media a. s. Všechna práva vyhrazena. Žádn á část této publikace nesmí být kopírována a rozmnožována za účelem rozšiřování v jakékoli formě či jakýmkoli způsobem bez písemného souhlasu vydavatele. 1. vydání Obsah 3 Obsah ÚVODEM . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .11 Struktura knihy . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12 Komu je kniha určena . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13 Zpětná vazba od čtenářů . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14 Errata . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14 ČÁST I ÚVOD DO NÁVRHU SOFTWARU KAPITOLA 1 ZÁKLADNÍ PRAVIDLA PŘI NÁVRHU SOFTWARU . . . . . . . . . . . . .17 Pravidla softwarového návrhu . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18 Zapouzdření údajů . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19 Aktéři . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .22 Implementace procesů půjčování. . . . . . . . . . . . . . . . . . . . . . . . . .24 Ladění aplikace . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31 Znovupoužitelnost kódu . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .34 Rozměnit na drobné . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .36 Kompozice místo dědění . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .38 Volná vazba místo závislostí . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .41 Shrnutí . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44 4 Obsah ČÁST II TVOŘIVÉ VZORY KAPITOLA 2 NÁVRHOVÝ VZOR SINGLETON . . . . . . . . . . . . . . . . . . . . . . . . . . . .49 Problém . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 49 Účel návrhového vzoru . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 50 Implementace . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 51 Skryté problémy . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .53 Definice . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 55 Shrnutí . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 56 Další využití . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 57 Variace návrhového vzoru Singleton . . . . . . . . . . . . . . . . . . . . . . .57 KAPITOLA 3 NÁVRHOVÝ VZOR FACTORY METHOD . . . . . . . . . . . . . . . . . . . . .61 Problém . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 61 Účel návrhového vzoru . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 62 Implementace . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 62 Definice . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 65 Shrnutí . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 66 Další využití . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 67 Statická Factory Method a Singleton . . . . . . . . . . . . . . . . . . . . . . .68 KAPITOLA 4 NÁVRHOVÝ VZOR ABSTRACT FACTORY . . . . . . . . . . . . . . . . . . . .71 Problém . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 71 Účel návrhového vzoru . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 72 Implementace . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 73 Implementace tabulky HTML . . . . . . . . . . . . . . . . . . . . . . . . . . . . .75 Implementace tabulky pro příkazový řádek . . . . . . . . . . . . . . . . . .82 Definice . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 85 Shrnutí . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 87 Další využití . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 87 Obsah 5 KAPITOLA 5 NÁVRHOVÝ VZOR BUILDER . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .89 Problém . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 89 Účel návrhového vzoru . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 90 Implementace . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 90 Definice . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 95 Shrnutí . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 96 KAPITOLA 6 NÁVRHOVÝ VZOR PROTOTYPE . . . . . . . . . . . . . . . . . . . . . . . . . . .99 Problém . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 99 Účel návrhového vzoru . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 100 Implementace . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 100 Definice . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 105 Shrnutí . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 106 Skryté problémy . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 107 ČÁST III STRUKTURÁLNÍ VZORY KAPITOLA 7 NÁVRHOVÝ VZOR COMPOSITE . . . . . . . . . . . . . . . . . . . . . . . . . .113 Problém . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 113 Účel návrhového vzoru . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 114 Implementace . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 114 Odstranění listů . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .118 Definice . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 119 Shrnutí . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 120 KAPITOLA 8 NÁVRHOVÝ VZOR ADAPTER . . . . . . . . . . . . . . . . . . . . . . . . . . . . .121 Problém . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 121 Účel návrhového vzoru . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 122 Implementace . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 122 Definice . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 129 Shrnutí . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 130 Další využití . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 131 6 Obsah KAPITOLA 9 NÁVRHOVÝ VZOR BRIDGE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .133 Problém . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 133 Účel návrhového vzoru . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 134 Implementace . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 134 Definice . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 142 Shrnutí . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 143 KAPITOLA 10 NÁVRHOVÝ VZOR DECORATOR . . . . . . . . . . . . . . . . . . . . . . . . . .145 Problém . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 145 Účel návrhového vzoru . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 146 Implementace . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 147 Definice . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 153 Shrnutí . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 154 Další využití . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 155 Test existence metody . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .158 KAPITOLA 11 NÁVRHOVÝ VZOR PROXY . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .159 Problém . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 159 Účel návrhového vzoru . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 160 Implementace . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 161 Definice . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 165 Shrnutí . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 167 Další využití . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 167 KAPITOLA 12 NÁVRHOVÝ VZOR FACADE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .171 Problém . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 171 Účel návrhového vzoru . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 174 Implementace . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 175 Definice . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 177 Shrnutí . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 178 Další využití . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 179 Obsah 7 KAPITOLA 13 NÁVRHOVÝ VZOR FLYWEIGHT . . . . . . . . . . . . . . . . . . . . . . . . . . .181 Problém . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 181 Účel návrhového vzoru . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 184 Implementace . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 185 Definice . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 193 Shrnutí . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 194 ČÁST IV VZORY CHOVÁNÍ KAPITOLA 14 NÁVRHOVÝ VZOR OBSERVER . . . . . . . . . . . . . . . . . . . . . . . . . . .197 Problém . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 197 Účel návrhového vzoru . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 199 Implementace . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 200 Definice . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 207 Shrnutí . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 209 Další využití . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 209 KAPITOLA 15 NÁVRHOVÝ VZOR MEDIATOR . . . . . . . . . . . . . . . . . . . . . . . . . . . .211 Problém . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 211 Účel návrhového vzoru . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 212 Implementace . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 212 Definice . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 217 Shrnutí . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 218 KAPITOLA 16 NÁVRHOVÝ VZOR TEMPLATE METHOD . . . . . . . . . . . . . . . . . . .219 Problém . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 219 Účel návrhového vzoru . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 220 Implementace . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 220 Definice . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 225 Shrnutí . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 227 Další využití . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 227 8 Obsah KAPITOLA 17 NÁVRHOVÝ VZOR COMMAND . . . . . . . . . . . . . . . . . . . . . . . . . . .231 Problém . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 231 Účel návrhového vzoru . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 233 Implementace . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 233 Definice . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 239 Shrnutí . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 240 Další využití . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 240 KAPITOLA 18 NÁVRHOVÝ VZOR MEMENTO . . . . . . . . . . . . . . . . . . . . . . . . . . . .241 Definice . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 241 Shrnutí . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 241 KAPITOLA 19 NÁVRHOVÝ VZOR VISITOR . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .243 Problém . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 243 Účel návrhového vzoru . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 245 Implementace . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 246 Definice . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 253 Shrnutí . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 254 KAPITOLA 20 NÁVRHOVÝ VZOR ITERATOR . . . . . . . . . . . . . . . . . . . . . . . . . . . .255 Problém . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 255 Účel návrhového vzoru . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 258 Implementace . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 259 Definice . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 263 Shrnutí . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 264 KAPITOLA 21 NÁVRHOVÝ VZOR STATE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .265 Problém . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 265 Účel návrhového vzoru . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 271 Implementace . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 271 Definice . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 282 Obsah 9 Shrnutí . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 283 Další využití . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 284 KAPITOLA 22 NÁVRHOVÝ VZOR STRATEGY . . . . . . . . . . . . . . . . . . . . . . . . . . . .285 Definice . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 285 Shrnutí . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 286 KAPITOLA 23 NÁVRHOVÝ VZOR CHAIN OF RESPONSIBILITY . . . . . . . . . . . . .287 Problém . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 287 Účel návrhového vzoru . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 288 Implementace . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 289 Definice . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 296 Skryté problémy . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 297 KAPITOLA 24 NÁVRHOVÝ VZOR INTERPRETER . . . . . . . . . . . . . . . . . . . . . . . . .299 Definice . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 299 Shrnutí . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 299 ČÁST V PŘÍLOHY PŘÍLOHA A JAZYK UML. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .303 PŘÍLOHA B VKLÁDÁNÍ ZÁVISLOSTÍ A PŘEVRÁCENÉ ŘÍZENÍ . . . . . . . . . . . .307 PŘÍLOHA C MODERNÍ APLIKAČNÍ ROZHRANÍ S PLYNULÝMI ROZHRANÍMI . . . . . . . . . . . . . . . . . . . . . . . . . . . . .309 REJSTŘÍK . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .315 Úvodem 11 Úvodem Návrhové vzory nabízejí postupy řešení často se vyskytujících problémů při návrhu softwaru. Často jsou považované za velmi komplikované, asociované s komplexními diagramy jazyka UML a obtížně pochopitelnými architekturami. Tato kniha vám ukáže, že návrhové vzory a jejich implementace v jazyce PHP nejsou až tak komplikované, jak se mohou někomu jevit po prvním přečtení jejich definice. Na praktických příkladech se seznámíte s  různými návrhovými vzory, které vám pomohou při každodenní práci a kvůli nimž už nebudete muset organizovat velká pracovní střetnutí nebo vytvářet vícestranné diagramy. Pomocí návodů v této knize se pro vás návrhové vzory stanou nástrojem, který vám ulehčí a obohatí chvíle při vývoji aplikací v jazyce PHP. Jazyk PHP 5 přinesl množství novinek, například kompletně přepracovanou podporu pro XML nebo jednodušší použití webových služeb přes protokol SOAP, který je automaticky podporovaný v jazyce PHP. Přístup k různým typům databází lze nyní díky PHP 5.1 a PDO provádět přes jednotné rozhraní. Naproti tomu tato aplikační rozhraní sama o sobě zatím neumožňovala realizovat profesionální aplikace. O to se postaral až Zend Engine 2 s kompletně přepracovaným objektovým modelem, který nabízí viditelnost pro atributy a metody, rozhraní, výjimky, ale i abstraktní a finální třídy. To vám, jakožto vývojářům v jazyce PHP, umožňuje navrhovat softwarové architektury, které nebudou v ničem zaostávat za architekturami vývojářů v jazyce Java. Tato kniha vám ukáže, jak můžete při návrhu softwaru využít prvky jazyka PHP 5.3 k tomu, aby váš software splňoval moderní standardy a bylo jej možné bez problémů rozšířit v případě, že se změní požadavky na aplikaci. 12 Úvodem Dále se seznámíte s pravidly, která byste měli dodržovat při návrhu aplikace. Kromě toho vám návrhové vzory nabízejí jazyk, pomocí něhož můžete řešit problémy s ostatními kolegy vývojáři, aniž abyste museli každý detail podrobně vysvětlovat. Struktura knihy Celá kniha je rozdělená do pěti částí a lze ji číst dvěma způsoby. Buď ji budete číst postupně, od začátku do konce, a přitom se naučíte krok za krokem jednotlivé návrhové vzory, nebo ji použijete jako katalog, v němž si vyhledáte přesně ten návrhový vzor, jehož implementací se chce zabývat. Každý návrhový vzor představuje jednu kapitolu. V některých kapitolách se setkáte s odkazy na jiné návrhové vzory – můžete je však použít i nezávisle na sobě. Jiné kapitoly naopak nemusí být rozepsané dopodrobna, a to zvláště v případě, že popisovaný návrhový vzor lze nahradit jiným návrhovým vzorem, který řeší stejný problém. V úvodní části (kapitola 1 – Základní pravidla při návrhu softwaru) si na příkladu vyzkoušíte, jakým chybám byste se měli vyhnout při návrhu architektury softwaru. Vyvodí se z nich všeobecně platná pravidla, jež se stanou základem návrhových vzorů probíraných v této knize. Druhá část (kapitoly 2–6) pojednává o návrhových vzorech týkajících se tvorby objektů. V  třetí části knihy (kapitoly 7–13) se představí návrhové vzory, které se zabývají kompozicí různých objektů. V této části se navíc seznámíte se strategiemi, které umožňují rozšiřitelnost daných kompozic. Čtvrtá část (kapitoly 14–24) se zabývá poslední skupinou klasických návrhových vzorů. Tyto vzory řeší problémy, které se mohou často vyskytnout při interakci různých objektů. V poslední, páté části (Příloha) na jdete krátký úvod do jazyka UML, díky němuž nebudete mít problém pochopit diagramy jazyka UML v jednotlivých kapitolách. Kromě toho v této části najdete i techniky nazývané vkládání závislostí (angl. Depencency Injection), které staví na filozofii převráceného řízení (angl. Inversion of Control – IoC), a také se naučíte vytvářet aplikační rozhraní s Fluent Interfaces. Úvodem 13 Ve všech výpisech v knize budou vynechané počáteční a koncové značky (<?php a ?>) a bude uvedený jen kód jazyka PHP. Pro označení názvů jednotlivých tříd, metod a atributů budeme používat anglické pojmy, což je způsob, který doporučuji i pro vaše projekty, protože tyto pojmy se lépe hodí k nativním názvům tříd a funkcí jazyka PHP. Pro lepší přehlednost nebudou uváděné komentáře. U reálných projektů byste však měli myslet alespoň na popis aplikačního rozhraní pomocí nástroje PHPDoc (http://www.phpdoc.org). Všechny příklady jsou napsané pro jazyk PHP ve verzi 5.3. Chcete-li je použít se starší verzí jazyka PHP, musíte je patřičně upravit – vzdát se používání jmenných prostorů a odstranit z výpisů klíčová slova namespace a use. Komu je kniha určena Tato kniha je určená vývojářům, kteří už mají zkušenosti s  programováním v jazyce PHP. V ideálním případě se už při realizaci projektu střetli s objektově orientovaným programováním (OOP) v jazyce PHP 4 nebo PHP 5, avšak žádné hluboké znalosti OOP v jazyce PHP 5 nejsou podmínkou. Pro vysvětlení a pochopení jednotlivých návrhových vzorů probíraných v této knize nejsou vyžadované žádné hluboké znalosti jazyka UML (Unified Modeling Language). Kromě krátkého úvodu do tohoto jazyka, který najdete v  příloze, nabízí tato kniha diagramy, jejichž obsah pro vás bude srozumitelný i se základy jazyka UML. Kniha Návrhové vzory v  PHP je napsaná pro programátory, kteří chtějí při vytváření profesionálních architektur využívat vlastnosti OOP. Jejím těžištěm je přitom architektura softwaru. Věci, které v knize nebudou probírané, se týkají oblasti nízkoúrovňové logiky, jako je například přístup k souborům, analyzování dokumentů XML nebo přístup k údajům v databázi pomocí jazyka SQL. Máte-li málo zkušeností s  jazykem PHP, avšak pojem návrhové vzory vám je známý z jiných programovacích jazyků, můžete se pomocí této knihy seznámit s implementací různých vzorů, jejichž realizace uvedeným způsobem je možná jen v jazyce PHP. Ú v o d e m 14 Zpětná vazba od čtenářů Nakladatelství a vydavatelství Computer Press, které pro vás tuto knihu připravilo, stojí o zpětnou vazbu a bude na vaše podněty a dotazy reagovat. Můžete se obrátit na následující adresy: redakce PC literatury Computer Press Spielberk Office Centre Holandská 3 639 00 Brno nebo sefredaktor.pc@cpress.cz Computer Press neposkytuje rady ani jakýkoli servis pro aplikace třetích stran. Pokud budete mít dotaz k programu, obraťte se prosím na jeho tvůrce. Errata Přestože jsme udělali maximum pro to, abychom zajistili přesnost a správnost obsahu, chybám se úplně vyhnout nedá. Pokud v některé z našich knih najdete chybu, ať už chybu v textu nebo v kódu, budeme rádi, pokud nám ji nahlásíte. Ostatní uživatele tak můžete ušetřit frustrace a pomoci nám zlepšit následující vydání této knihy. Veškerá existující errata zobrazíte na adrese http://knihy.cpress.cz/K1886 po klepnutí na odkaz Soubory ke stažení. Úvodem 15 ČÁST I Úvod do návrhu softwaru 17 KAPITOLA 1 Základní pravidla při návrhu softwaru Máloco podléhá tak častým změnám jako právě software. Ve většině projektů se na něj nakládají stále nové požadavky a stejně rychle odpadají požadavky dosud implementované – nebo v lepším případě jsou často pozměněné. Jako softwarový vývojář musíte jednotlivé komponenty své aplikace navrhnout takovým způsobem, abyste mohli relativně rychle a flexibilně reagovat na měnící se požadavky. V této kapitole se dozvíte, jak lze vyvíjet flexibilní aplikace, a také to, že je důležité zamyslet se nad návrhem aplikace ještě před vlastní implementací. Tím se vyhnete situaci, kdy náhle stojíte před problémem, kdy musíte přepsat velké části aplikace, aby bylo možné reagovat na změněné požadavky. Jestliže tomu nezabráníte, může každý změněný požadavek na software znamenat zvýšené náklady, čímž se prodlouží čas nutný k dokončení projektu nebo se do softwaru nestihnou zapracovat všechny požadavky. Na příkladu v této kapitole si osvojíte základy návrhu softwaru a naučíte se, jak sestavit aplikaci skládající se z více tříd, jež splňují požadavky na rozšiřitelnost a flexibilitu. Na konci kapitoly se dozvíte, jak lze co nejrychleji najít vhodný návrhový vzor pro řešení budoucích problémů. Vyzbrojeni těmito vědomostmi můžete použít následující kapitoly jako encyklopedii, když narazíte v jednom ze svých projektů na problémy, které budete chtít vyřešit pomocí návrhových vzorů. Část I Úvod do návrhu softwaru 18 Protože hlavním cílem této knihy je blíže vás seznámit se správnou architekturou aplikací, výklad nebude zacházet až do detailů a nebude se věnovat perzistentnímu ukládání údajů nebo grafickému uživatelskému rozhraní. Místo toho budeme klást důraz na rozhraní, která vám dané třídy nabízejí, a na to, jak jednotlivé třídy mezi sebou komunikují. Pravidla softwarového návrhu K objasnění základních pravidel softwarového návrhu využijete následující příklad. Představte si, že byste měli implementovat aplikaci, pomocí níž bude knihovna spravovat své publikace. Na konci této kapitoly budete mít za sebou vývoj funkční aplikace, s níž bude možné tyto publikace půjčovat a každé takovéto půjčení přesně protokolovat. V  reálné knihovně bude správce chtít jistě ukládat o každé publikaci více informací a půjčování nebude nefungovat přesně tak, jako to bude uvedené zde, ale jako příklad probírané problematiky to stačí. Pokud jste se už nějakým způsobem zabývali objektově orientovaným programováním, jsou vám pojmy třída (angl. Class), objekt (angl. Object) a možná i rozhraní (angl. Interface) docela dobře známé. Koncepce tříd představuje pokus přenést věci z reálného světa, s nimiž má aplikace něco společné, do světa programování. Každý typ publikace má samozřejmě jiné vlastnosti, ale určitým způsobem se všechny vzájemně podobají, z čehož lze odvodit následující rozhraní: namespace czk1886example; interface Publication { public function open(); public function close(); public function setPageNumber($page); public function getPageNumber(); } Reprezentace libovolné knihy by potom mohla vypadat následovně: namespace czk1886example; class Book implements Publication { protected $category; protected $pageCount; protected $pageNumber = 0; protected $closed = true; Kapitola 1 Základní pravidla při návrhu softwaru 19 public function __construct($category, $pageCount) { $this->category = $category; $this->pageCount = $pageCount; } public function open() { $this->closed = false; } public function setPageNumber($page) { if ($this->closed !== false || $this->pageCount < $page) { return false; } $this->pageNumber = $page; return true; } public function getPageNumber() { return $this->pageNumber; } public function close() { $this->setPageNumber(0); $this->closed = true; } public function __destruct() { if (!$this->closed) { $this->close(); } } // další metody pro čtení atributů } Reprezentace knihy má čtyři atributy: kategorii, do níž náleží, počet stran, konkrétní stranu, na níž je právě otevřená, a příznak udávající, zda je otevřená nebo zavřená. Zapouzdření údajů Třídy a objekty vám umožňují omezit přístup k údajům, čehož byste měli využívat. Díky tomu totiž můžete změnit vnitřní strukturu třídy, aniž by se to dotklo jiných tříd nebo metod, které dotyčnou třídu používají. Takové změny mohou být kromě jiného způsobené i následujícími důvody: Část I Úvod do návrhu softwaru 20  Změnily se požadavky na aplikaci, přičemž je nutné změnit algoritmy. Pokud se změny provedou v rámci jedné třídy, neovlivní to žádnou z tříd, jež upravenou třídu volají.  Implementované algoritmy jsou velmi pomalé, protože aplikaci používá stále větší počet uživatelů. Tyto algoritmy můžete přepsat, povedou-li ke stejnému výsledku.  Je zapotřebí změnit úložiště údajů. K tomu může dojít například v situaci, když zjistíte, že aktuální úložiště je vzhledem k objemu údajů nevhodné, a je tedy nutné použít místo souboru databázi. Pro objasnění znovu využijeme příklad knihovny. Vzhledem k  tomu, že půjčování publikací není zadarmo, musí být někde uložená denní sazba pro jednu publikaci. Je-li tato hodnota zpočátku stále stejná, může vás napadnout použít globální proměnnou nebo nějaký podobný způsob konfigurace: $dailyRate = 10; Co se ale stane, přijde-li požadavek, aby se denní sazba pro dětské knihy lišila od sazby pro knihy vědecké nebo aby celková částka závisela na délce vypůjčení. Tím by velmi vzrostl počet konfiguračních možností a  museli byste v  příslušných místech své aplikace implementovat logiku, pomocí níž byste načítali správnou konfiguraci. Z těchto důvodů je lepší zapouzdřit přístup k denní sazbě hned od začátku. Protože se předpokládá, že výška této sumy se bude lišit v závislosti na vypůjčené publikaci, představuje rozhraní Publication dobré místo pro tuto logiku. Toto rozhraní totiž implementují všechny publikace (knihy, časopisy apod.). Rozšiřte tedy toto rozhraní o jednu metodu a tu pak implementujete v příslušných třídách. Příklad metody pro třídu Book by mohl vypadat následovně: namespace czk1886example; class Book implements Publication { // ... atributy a metody public function getDailyRate() { return 10; } } Kapitola 1 Základní pravidla při návrhu softwaru 21 Má-li být pro jiný typ knihy účtovaná jiná denní sazba, pak stačí jen přepsat tuto metodu a nový požadavek máte implementovaný. Tím jste se seznámili s prvním pravidlem návrhu softwaru u objektově orientované architektury: PRAVIDLO Přístup k údajům vždy v rámci třídy zapouzdřete a poskytněte metody, pomocí nichž lze dané údaje získat. Stejně jednoduchá je implementace požadavku, aby denní sazba byla nižší v případě vypůjčení knihy na déle než dva týdny. V tomto případě stačí také změnit jen jednu metodu: namespace czk1886example; class Book implements Publication { // ... atributy a metody public function getDailyRate($days = 1) { if ($days >= 14) { return 7.50; } return 10; } } S tím také samozřejmě souvisí úprava tříd, jež volají metodu getDailyRate(), protože tato metoda musí od nynějška předávat počet dní. Této dodatečné změně se můžete vyhnout, pokud jste se při návrhu rozhraní pokusili stanovit, jaké údaje by byly eventuálně potřebné při výpočtu denní sazby. Nikdy však nebude možné zohlednit všechny budoucí požadavky hned při první implementaci rozhraní. V takovém případě byste museli metodě předávat všechny dostupné údaje, čímž byste rozbili zapouzdření údajů. Pokuste se najít zlatou střední cestu a metodu navrhnout tak, aby byla v budoucnosti jednoduše rozšiřitelná – jak jsme si to ukázali v tomto příkladu. Tím jste se naučili už druhé pravidlo objektově orientovaného návrhu softwaru: PRAVIDLO Svá rozhraní navrhujte tak, aby je bylo možné později rozšířit. PRAVIDLO Přístup k údajům vždy v rámci třídy zapouzdřete a poskytněte metody, pomocí nichž lze dané údaje získat. PRAVIDLO Svá rozhraní navrhujte tak, aby je bylo možné později rozšířit. Část I Úvod do návrhu softwaru 22 Na začátku návrhu softwaru provedete vždy stejné kroky: musíte se zamyslet nad spravovanými údaji a nad tím, jak lze tyto údaje zahrnout do entit. Z toho pak vyplynou jednotlivé třídy a metody. Aktéři V  příkladu knihovny se nacházejí následující aktéři, kteří musí být částí vaší aplikace:  jednotlivé knihy, které jsou částí knihovny a lze je půjčovat,  členové knihovny, kteří si knihy půjčují,  samotná knihovna, která spravuje jednotlivé publikace a stará se o půjčování. Z těchto představitelů můžete hned odvodit potřebné třídy a rozhraní. Pro knihy jste to už provedli, zůstávají už jen členové a  knihovna. Implementujte proto třídu Member, která bude reprezentovat jednoho člena knihovny: namespace czk1886example; class Member { protected $id; protected $name; public function __construct($id, $name) { $this->id = $id; $this->name = $name; } public function getId() { return $this->id; } public function getName() { return $this->name; } } Daný člen se skládá z jedinečného identifikátoru, jímž se v systému identifikuje, a ze svého jména, což pro jednoduchou demonstraci úplně stačí. Informace, které jsou přiřazené členovi, se předají prostřednictvím konstruktoru a uloží se do atributů objektu. Přístup k těmto údajům je možný pomocí metod getId() a getName(). Kapitola 1 Základní pravidla při návrhu softwaru 23 Po vytvoření tříd pro členy a knihy nastal čas věnovat se samotné knihovně, kterou reprezentuje třída Library: namespace czk1886example; class Library { protected $library = array(); public function addToLibrary($id, Publication $p) { $this->library[$id] = $p; } public function rentPublication(Publication $p, Member $m) { } public function returnPublication(Publication $p) { } } Knihovna má jeden atribut, do něhož se ukládají všechny publikace určené k vypůjčení, a také tři metody:  Metoda addToLibrary() se používá k přiřazení nové publikace do knihovny. Tato publikace se jednoduše uloží do pole $library.  Pomocí metody rentPublication() si může člen knihovny vypůjčit konkrétní publikaci. Tuto metodu jste zatím neimplementovali, neboť nejdříve je nutné definovat, v jaké formě se budou údaje ukládat.  Pro vrácení publikace se používá metoda returnPublication(). V tomto případě není nutné předat objekt člena, který publikaci vrací. Koneckonců knihovna přece musí vědět, kdo měl danou publikaci vypůjčenou. V následujících krocích budete deklarovat metody naplněné skutečnou logikou. Metody rentPublication() a returnPublication() mají vždy něco společné s vypůjčením publikace. Buď proces vypůjčení začal, nebo byl vrácením publikace zpět do knihovny ukončený. Tohoto procesu se vždy účastní dva aktéři: publikace, která má být vypůjčena, a osoba, která si ji vypůjčila. Dále jsou důležité časové údaje, kdy byla publikace vypůjčená a také kdy byla vrácená, aby tak bylo možné vypočítat cenu za vypůjčení. Ve  skutečné knihovně to většinou funguje jinak, ale jako příklad postačí i  tato varianta. Podle pravidel zapouzdřování, která jste se právě naučili, se pokuste dostat tyto informace do jedné třídy. Část I Úvod do návrhu softwaru 24 Implementace procesů půjčování Nová třída RentalAction musí obsahovat následující informace:  osoba, která si publikaci půjčuje,  publikace, která se půjčuje,  datum, kdy byla publikace vypůjčena,  datum, kdy byla publikace vrácena a proces ukončen. Implementace této třídy může vypadat následovně: namespace czk1886example; class RentalAction { protected $publication; protected $member; protected $rentDate; protected $returnDate = null; function __construct(Publication $p, Member $m, $date = null) { $this->publication = $p; $this->member = $m; // v případě neuvedení data použít aktuální if (null === $date) { $date = date('Y-m-d H:i:s'); } $this->rentDate = $date; } public function getPublication() { return $this->publication; } public function getMember() { return $this->member; } public function getRentDate() { return $this->rentDate; } public function getReturnDate() { return $this->returnDate; Kapitola 1 Základní pravidla při návrhu softwaru 25 } } Konstruktoru třídy musíte při vytvoření nového procesu předat jako parametry publikaci, která má být vypůjčena, a dále osobu, která si ji půjčuje. Volitelně můžete uvést datum a čas, kdy byla daná publikace vyzvednuta. V případě neuvedení data se použije aktuální datum. Tyto hodnoty se uloží v příslušných atributech třídy. Dále se ve třídě nacházejí čtyři metody pro čtení atributů, které vám umožňují přistupovat k atributům třídy. Pokud si nyní přijde nějaký člen vaší knihovny vypůjčit určitou publikaci, můžete vytvořit odpovídající proces vypůjčení takto: use czk1886exampleBook; use czk1886exampleMember; use czk1886exampleRentalAction; $book = new Book('PC', 100); $mabo = new Member(1, 'Marian Böhmer'); $rentalAction = new RentalAction( $book, $mabo, '2011-08-22 16:00:00' ); V této chvíli je sice možné knihu vypůjčit, avšak zatím není možné zaznamenat, že už byla i vrácena. Pro tento účel jste si v této třídě už předem rezervovali atribut $returnDate. K jeho nastavení je nutné vložit do třídy RentalAction následující metodu: namespace czk1886example; class RentalAction { // ... atributy a metody třídy public function markPublicationReturned($date = null) { // v případě neuvedení data použít aktuální if (null === $date) { $date = date('Y-m-d H:i:s'); } $this->returnDate = $date; } } Bude-li publikace přinesena zpět do knihovny, pak pro uložení této informace do objektu stačí zavolat příslušnou metodu: Část I Úvod do návrhu softwaru 26 $rentalAction->markPublicationReturned('2011-08-30 13:00:00'); Výsledek této operace je zobrazený na obrázku 1.1. Obrázek 1.1: Proces vypůjčení knihy z knihovny Pokud si chcete ověřit, zda byla kniha vrácena a tím daný proces ukončen, můžete k tomu využít hodnotu, kterou vrací metoda getReturnDate(): if (null !== $rentalAction->getReturnDate()) { print 'Publikace byla vrácená'; } Tento kód se však neimplementuje jednoduše, a proto je vhodné zapouzdřit jej do další metody: namespace czk1886example; class RentalAction { // ... atributy a metody třídy public function isReturned() { return null !== $this->returnDate; } } Kapitola 1 Základní pravidla při návrhu softwaru 27 Tuto metodu můžete nyní využít ke zjištění, zda už byla publikace vrácena: if ($rentalAction->isReturned()) { print 'Publikace byla vrácená'; } Tím jste se naučili další pravidlo vývoje softwaru: PRAVIDLO V metodách tříd nezapouzdřujte jen údaje, ale také algoritmy, díky čemuž budou komplexní operace implementované centrálně na jednom místě. Zavedení metody isReturned() vám v budoucnosti umožní na základě podmínky určit, zda už byl proces vypůjčení ukončen a kniha vrácena zpět do knihovny. Pomocí nové třídy RentalAction je možné implementovat chybějící metody ve třídě Library. Nejdříve je nutné vložit do uvedené třídy nový atribut $rentalActions, v němž budou v podobě objektů uložené jednotlivé procesy vypůjčení. Nejjednodušším datovým typem použitelným k tomuto účelu je pole. Následující implementace metody pro vypůjčení publikace musí splňovat následující kritéria:  otestovat, zda je požadovaná publikace součástí knihovny,  otestovat, zda je požadovaná publikace aktuálně vypůjčená (v takovém případě ji nelze znovu vypůjčit),  pomocí nové instance třídy RentalAction vytvořit nový proces vypůjčení. Implementace metody rentPublication() může vypadat následovně: namespace czk1886example; class Library { protected $rentalActions = array(); // ... atributy a metody třídy public function rentPublication(Publication $p, Member $m) { $publicationId = array_search($p, $this->library); if (false === $publicationId) { throw new UnknownPublicationException(); } if (!$this->isPublicationAvailable($p)) { throw new PublicationNotAvailableException(); PRAVIDLO V metodách tříd nezapouzdřujte jen údaje, ale také algoritmy, díky čemuž budou komplexní operace implementované centrálně na jednom místě. Část I Úvod do návrhu softwaru 28 } $rentalAction = new RentalAction($p, $m); $this->rentalActions[] = $rentalAction; return $rentalAction; } } Pomocí funkce array_search() jazyka PHP můžete zjistit, zda se publikace nachází v nabídce knihovny. Vrátí-li hodnotu false, pak signalizuje chybu vyvoláním výjimky. Test, zda je daná publikace právě vypůjčená, je trochu komplikovanější, a proto je jeho logika přesunuta do další metody. Díky tomu mohou tuto logiku použít i  jiné metody třídy. Tímto způsobem opět zapouzdřujete určitý algoritmus do jedné metody. Konkrétní implementace této metody bude probrána později. V případě, že publikace není vypůjčená, vytvoří se nová instance třídy RentalAction, které předáte půjčovanou publikaci a člena, který si ji půjčuje. Tuto instanci potom uložíte do k tomu určeného atributu, kde jsou uložené i všechny ostatní procesy vypůjčení. Metoda rentPublication() vrací objekt RentalAction. Vrácení tohoto objektu sice není v současnosti pro knihovnu důležité, protože neobsahuje žádné další informace než ty, které už obdržela, avšak v budoucnosti může objekt RentalAction obsahovat i další informace, například číslo objednávky, které budete chtít poskytnout aplikaci. Ještě před tím, než začnete ve vypůjčené publikaci listovat, je nutné podívat se na implementaci pomocné metody isPublicationAvailable(). Pro  zjištění, zda je daná publikace právě vypůjčená, stačí jen otestovat, zda atribut $rentalActions obsahuje proces vypůjčení pro hledanou publikaci, který ještě nebyl ukončen. K tomuto účelu vám dobře poslouží metody pro čtení atributů třídy RentalAction: public function isPublicationAvailable(Publication $p) { foreach ($this->rentalActions as $rentalAction) { if ($rentalAction->getPublication() !== $p) { continue; } if ($rentalAction->isReturned()) { continue; } return false; } return true; } Kapitola 1 Základní pravidla při návrhu softwaru 29 Ve funkci isPublicationAvailable() probíhá iterace přes všechny prvky v poli $rentalActions (všechny procesy vypůjčení). Pokud aktuální proces nepatří hledané publikaci nebo už je ukončený, pokračuje se s další iterací. Pokud daný proces náleží k hledané publikaci a ještě není ukončen, nemůže být daná publikace znovu vypůjčena, což se signalizuje vrácením hodnoty false. Neexistuje-li pro hledanou publikaci žádný proces, který ještě nebyl ukončen, vrátí se hodnota true. V  tomto okamžiku lze třídu Library použít k  půjčování publikací a  navíc je zaručené, že jedna publikace může být vypůjčená jen jednou, jak to ukazuje následující příklad: use czk1886exampleLibrary; use czk1886exampleBook; use czk1886exampleMember; $library = new Library(); $book = new Book('PC', 100); $mabo = new Member(1, 'Marian Böhmer'); $luigi = new Member(2, 'Luigi Valentino'); $library->addToLibrary('pc1', $book); $library->rentPublication($book, $mabo); $library->rentPublication($book, $luigi); Po jeho provedení reaguje knihovna následující výjimkou: Fatal error: Uncaught exception 'czk1886example PublicationNotAvailableException' in ch01Library.php:24 Tuto výjimku můžete ve frontendu své aplikace změnit na chybové hlášení. Aby bylo možné i  vrácení vypůjčených publikací, musíte dále implementovat metodu returnPublication(). Tato metoda musí najít aktuální proces vypůjčení, který náleží k dané publikaci, a označit jej jako ukončený. Kód této metody se podobá tomu v metodě isPublicationAvailable(). I v tomto případě procházíme přes všechny procesy vypůjčení, dokud nenajdeme proces pro hledanou publikaci, který ještě nebyl ukončen. Tento proces potom označíme pomocí metody markPublicationReturned() jako ukončený. Kompletní implementace vypadá takto: namespace czk1886example; class Library { Část I Úvod do návrhu softwaru 30 // ... atributy a metody t řídy public function returnPublication(Publication $p) { foreach ($this->rentalActions as $rentalAction) { if ($rentalAction->getPublication() !== $p) { continue; } if ($rentalAction->isReturned()) { continue; } $rentalAction->markPublicationReturned(); return true; } return false; } } V tomto okamžiku mohou být vypůjčené publikace znovu vráceny a připraveny na své další vypůjčení: use czk1886exampleLibrary; use czk1886exampleBook; use czk1886exampleMember; $library = new Library(); $book = new Book('PC', 100); $mabo = new Member(1, 'Marian Böhmer'); $luigi = new Member(2, 'Luigi Valentino'); $library->addToLibrary('pc1', $book); $library->rentPublication($book, $mabo); $library->returnPublication($book); $library->rentPublication($book, $luigi); Při provedení tohoto kódu nedošlo k  vyvolání žádné výjimky. Místo toho se vytvořily dva procesy vypůjčení, z nichž jeden byl i ukončený. U této implementace vás možná napadne, proč není proces po jeho ukončení z  pole vymazán? Jednoduše proto, že byste v  takovém případě ztratili historii procesů vypůjčení. Představte si, že by chtěl správce knihovny zjistit, které publikace se nejvíce půjčují nebo kdo je nejaktivnějším členem knihovny. Pomocí procesů uložených v poli $rentalActions lze tyto údaje snadno poskytnout. Je nutné si uvědomit, že v tomto příkladu nešlo o uchovávání údajů ani o jeho výkonnost, ale o vytvoření architektury aplikace. Místo pole s objekty typu Ren- Kapitola 1 Základní pravidla při návrhu softwaru 31 talAction byste v reálné aplikaci použili pro jejich uložení databázovou tabulku. Databázové systémy už nabízejí nástroje, jak lokalizovat záznam k aktuálnímu procesu vypůjčení konkrétní publikace. Ladění aplikace V této chvíli máte za sebou základy aplikace a jste schopni půjčovat publikace a přijímat je zpět. V této podkapitole si na příkladu části aplikace ukážeme, jaká další pravidla návrhu softwaru byste měli ve svých aplikacích zohlednit. Třebaže funkce pro ladění (angl. debugging) aplikací v  jazyce PHP lze zlepšit pomocí externích nástrojů, skoro každý vývojář v jazyce PHP využívá k výpisu nezbytných informací při tomto kroku příkaz print nebo echo. Tyto příkazy se během vývoje jednoduše vloží do zdrojového kódu a před tím, než se aplikace nasadí do provozu, se zase odstraní. V rámci této části budete takovýto ladicí kód postupně, kroku za krokem vylepšovat, při čemž se seznámíte s  různými pravidly, která byste měli zohlednit i v dalších softwarových projektech. Při dalším vývoji softwaru knihovny můžete do zdrojového kódu následujícím způsobem vložit hlášení používané při ladění: namespace czk1886example; use czk1886exampleRentalAction; class Library { protected $library = array(); protected $rentalActions = array(); public function addToLibrary($id, Publication $p) { $this->library[$id] = $p; print 'Nová publikace v knihovně: ' . $p->getCategory() . " "; } public function rentPublication(Publication $p, Member $m) { $publicationId = array_search($p, $this->library); if (false === $publicationId) { throw new UnknownPublicationException(); } if (!$this->isPublicationAvailable($p)) { throw new PublicationNotAvailableException(); } Část I Úvod do návrhu softwaru 32 $rentalAction = new RentalAction($p, $m); $this->rentalActions[] = $rentalAction; print $m->getName() . ' si vyp ůjčil publikaci: ' . $p->getCategory() . " "; return $rentalAction; } public function returnPublication(Publication $p) { foreach ($this->rentalActions as $rentalAction) { if ($rentalAction->getPublication() !== $p) { continue; } if ($rentalAction->isReturned()) { continue; } $rentalAction->markPublicationReturned(); print $rentalAction->getMember()->getName() . ' vrátil publikaci: ' . $p->getCategory() . " "; return true; } return false; } // ... ostatní metody } Pokud nyní znovu zavoláte příkazy z předchozího testovacího skriptu s pozměněnou třídou Library, můžete přesně sledovat, kdy se která metoda volá: Nová publikace v knihovně: PC Marian Böhmer si vypůjčil publikaci: PC Marian Böhmer vrátil publikaci: PC Luigi Valentino si vypůjčil publikaci: PC V závislosti na tom, jakou část aplikace chcete ladit, se bude měnit i množství ladicích informací. Před přesunem aplikace na produkční server jednoduše tyto řádky kódu vymažete. Co se ale stane, pokud objevíte problém, který se vyskytuje jen v produkčním prostředí, protože souvisí například s množstvím paralelních dotazů na aplikaci? Tato hlášení nemůžete jednoduše zobrazit koncovému uživateli. V takovém případě používá většina vývojářů protokolovací soubor, do něhož přesměrují veškerá hlášení. Často je tedy ladicí kód rozšířený o příkazy if/else nebo switch, Kapitola 1 Základní pravidla při návrhu softwaru 33 pomocí nichž lze přepínat mezi laděním v produkčním nebo vývojovém prostředí. V případě knihovny by to vypadalo následovně: namespace czk1886example; class Library { protected $library = array(); protected $rentalActions = array(); public function addToLibrary($id, Publication $p) { $this->library[$id] = $p; switch(DEBUG_MODE) { case 'echo': print 'Nová publikace v knihovně: ' . $p->getCategory() . " "; break; case 'log': error_log('Nová publikace v knihovně: ' . $p->getCategory() . " ", 3, './library.log'); break; } } public function rentPublication(Publication $p, Member $m) { $publicationId = array_search($p, $this->library); if (false === $publicationId) { throw new UnknownPublicationException(); } if (!$this->isPublicationAvailable($p)) { throw new PublicationNotAvailableException(); } $rentalAction = new RentalAction($p, $m); $this->rentalActions[] = $rentalAction; switch(DEBUG_MODE) { case 'echo': print $m->getName() . ' si vypůjčil publikaci: ' . $p->getCategory() . " "; break; case 'log': error_log($m->getName() . ' si vypůjčil publikaci: ' . $p->getCategory() . " ", 3, './library.log'); Část I Úvod do návrhu softwaru 34 break; } return $rentalAction; } // ... ostatní metody t řídy } Pomocí konstanty DEBUG_MODE můžete přepínat mezi jednoduchými hlášeními vypisovanými na obrazovku a zapisovanými do protokolovacího souboru funkcí error_log(). K tomu je nutné přidat do skriptu následující řádek, umožňující centrální řízení způsobu ladění: define('DEBUG_MODE', 'log'); Co však na prvý pohled vypadá jako komfortní řešení, je v konečném důsledku jen velká slabina aplikace. Na každém místě, kde chcete vložit ladicí kód, musíte vložit devět řádků kódu. Tím bude zdrojový kód vaší aplikace o něco delší, a aplikace se tak stane pomalejší a obtížně udržovatelná. Na tomto místě přichází na řadu základní pravidlo znovupoužitelnosti kódu. Znovupoužitelnost kódu Určitě vás napadlo, že byste se měli vyhýbat duplicitnímu kódu, který často vzniká při postupu ve stylu „Copy & Paste“. Při každé změně tohoto kódu (například při změně názvu souboru nebo při přidání třetího ladicího režimu) je nutné provést změnu na mnoha místech kódu. Zabránit tomu můžete tím, že duplicitní kód přesunete do samostatné metody, kterou na potřebných místech jen zavoláte. Nová metoda třídy Library bude vypadat následovně: protected function debug($message) { switch(DEBUG_MODE) { case 'echo': print $message . " "; break; case 'log': error_log($message . " ", 3, './library.log'); break; } } Kapitola 1 Základní pravidla při návrhu softwaru 35 Nové metodě debug() je nutné předat řetězec se zprávou, která se má nějak zpracovat. Tato metoda na základě konstanty DEBUG_MODE rozhodne, zda se zadaná informace vypíše na obrazovku nebo se zapíše do protokolovacího souboru. Následně je zapotřebí upravit i metody, které mají novou metodu debug()využívat. namespace czk1886example; class Library { protected $library = array(); protected $rentalActions = array(); public function addToLibrary($id, Publication $p) { $this->library[$id] = $p; $this->debug( 'Nová publikace v knihovně: '


       

internetové knihkupectví ABZ - online prodej knih


Knihy.ABZ.cz - knihkupectví online -  © 2004-2018 - ABZ ABZ knihy, a.s. TOPlist