eské vysoké u£ení technické v Praze Fakulta elektrotechnická Katedra po£íta£·
Bakalá°ská práce
Elektronický obchod
Vladimír Kroupa
Vedoucí práce:
Ing. Michal Vorá£ek
Studijní program: Softwarové technologie a management, Bakalá°ský
Obor: Softwarové inºenýrství
28. kv¥tna 2010
iv
v
Pod¥kování Rád bych pod¥koval ing. Michalu Vorá£kovi za pomoc a trp¥livost p°i vedení této práce.
vi
vii
Prohlá²ení Prohla²uji, ºe jsem práci vypracoval samostatn¥ a pouºil jsem pouze podklady uvedené v p°iloºeném seznamu. Nemám závaºný d·vod proti uºití tohoto ²kolního díla ve smyslu 60 Zákona £. 121/2000 Sb., o právu autorském, o právech souvisejících s právem autorským a o zm¥n¥ n¥kterých zákon· (autorský zákon).
V Praze dne 28. 5. 2010
.............................................................
viii
Abstract The purpose of this thesis is to build a web application for an online store using the JEE platform. The application should be based on Spring application framework and should use a suitable object-relational mapping framework. The thesis rstly denes the frequently used concepts and then introduces the reader to the hiearchy of Spring framework modules. Frequently used ORM frameworks are introduced, including a discussion on their advantages and disadvantages. The next part of this thesis is concerned with requirements analysis. The requirements are collected in the form of use cases. The following part discusses issues concerning the architecture of the application and also deals with design of the individual application parts. The application design leverages several common patterns. Some of the issues arising from the use of frameworks encountered during the implementation are also detailed.
Abstrakt Cílem práce je realizovat webovou aplikace pro internetový obchod na platform¥ JEE s vyuºitím frameworku Spring a vhodného frameworku pro objektov¥-rela£ní mapování. Práce denuje n¥které pojmy podstatné pro tuto oblast a seznamuje £tená°e s frameworkem Spring a roz²í°enými ORM frameworky. V rámci práce je provedena analýza poºadavk· pomocí p°ípad· uºití, je diskutován návrh architektury a návrh jednotlivých £ástí aplikace s vyuºitím vzor·. Dále jsou zmín¥ny n¥které podstatné aspekty implementace, týkající se zejména pouºitých framework·.
ix
x
Obsah 1 Úvod
1
2 Popis problému, specikace cíle
3
2.1
Popis problému . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
3
2.2
Vymezení cíl· práce
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
3
2.3
Struktura práce . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
4
3 Vymezení pojm·
5
3.1
JEE
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
3.2
Framework
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
5
3.3
Vzor (pattern) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
6
3.4
Návrhové vzory . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
7
3.5
Impedan£ní nesoulad . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
7
3.6
Mapování na rela£ní databáze, perzistentní frameworky . . . . . . . . . . . . .
7
3.7
POJO
8
3.8
Anotace
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
4 Re²er²e
5
8
9
4.1
Framework Spring
4.2
P°ehled modul· frameworku Spring . . . . . . . . . . . . . . . . . . . . . . . .
9
4.2.1
Core . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
9
4.2.2
Context
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
10
4.2.3
Web
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
10
4.2.4
Web MVC . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
10
4.2.5
Portlet MVC
10
4.2.6
Web Framework Integration . . . . . . . . . . . . . . . . . . . . . . . .
11
4.2.7
AOP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
11
4.2.8
TX . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
11
4.2.9
JDBC
11
4.2.10 ORM
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
4.2.11 Enterprise Integration 4.2.12 Testing
11
. . . . . . . . . . . . . . . . . . . . . . . . . . .
12
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
12
4.2.13 Dal²í projekty Spring portfolio 4.3
9
. . . . . . . . . . . . . . . . . . . . . .
12
P°ehled ORM framework· . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
12
4.3.1
12
Entity Beans
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
xi
xii
OBSAH
4.4 4.5
4.3.2
Hibernate . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
4.3.3
Java Pesistence API (JPA)
4.3.4
TopLink, TopLink Essentials, EclipseLink
. . . . . . . . . . . . . . . .
13
4.3.5
JDO . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
14
4.3.6
iBatis
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
14
Google App Engine . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
14
4.4.1
. . . . . . . . . . . . . . . . . . . .
15
Re²er²e existujících implementací . . . . . . . . . . . . . . . . . . . . . . . . .
15
. . . . . . . . . . . . . . . . . . . . . . . .
Moºné vyuºití Google App Engine
5 Analýza 5.1
12 13
17
Analýza poºadavk· . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
18
5.1.1
Typy poºadavk·
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
18
5.1.2
P°ípady uºití
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
18
5.1.3
User stories . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
19
P°ípady uºití podle Alistaira Cockburna . . . . . . . . . . . . . . . . .
19
5.1.4.1
20
5.1.4
Úrove¬ cíle . . . . . . . . . . . . . . . . . . . . . . . . . . . .
5.1.5
Seznam aktér-cíl
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
21
5.1.6
Zpracované p°ípady uºití . . . . . . . . . . . . . . . . . . . . . . . . . .
21
5.1.6.1
Koupit zboºí
. . . . . . . . . . . . . . . . . . . . . . . . . . .
21
5.1.6.2
Vybrat zboºí
. . . . . . . . . . . . . . . . . . . . . . . . . . .
21
5.1.6.3
Objednat zboºí . . . . . . . . . . . . . . . . . . . . . . . . . .
22
5.1.6.4
Prohlíºet objednávky
. . . . . . . . . . . . . . . . . . . . . .
23
5.1.6.5
Vy°ídit objednávku
. . . . . . . . . . . . . . . . . . . . . . .
23
5.1.6.6
P°idat zboºí do katalogu
. . . . . . . . . . . . . . . . . . . .
24
5.1.6.7
Upravit zboºí v katalogu
. . . . . . . . . . . . . . . . . . . .
24
5.1.6.8
P°idat kategorii zboºí
. . . . . . . . . . . . . . . . . . . . . .
25
5.1.6.9
Upravit kategorii zboºí
. . . . . . . . . . . . . . . . . . . . .
25
5.1.6.10
Naskladnit zboºí . . . . . . . . . . . . . . . . . . . . . . . . .
26
5.1.7
Analýza nefunk£ních poºadavk· . . . . . . . . . . . . . . . . . . . . . .
26
5.1.8
Doménový model . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
27
6 Návrh
29
6.1
Výb¥r modul· frameworku Spring
6.2
Výb¥r vhodného persistentního frameworku
. . . . . . . . . . . . . . . . . . .
29
6.3
Návrh architektury aplikace . . . . . . . . . . . . . . . . . . . . . . . . . . . .
29
6.4
Prezenta£ní vrstva
6.3.1 6.4.1
6.5
. . . . . . . . . . . . . . . . . . . . . . . .
Vrstvy (Layers) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
29
29
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
30
Vzor Model-View-Controller . . . . . . . . . . . . . . . . . . . . . . . .
30
6.4.1.1
Model . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
31
6.4.1.2
View
31
6.4.1.3
Controller . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
31
6.4.1.4
Vzájemná interakce
32
6.4.1.5
Souvislost s vzorem Observer . . . . . . . . . . . . . . . . . .
32
Doménová vrstva . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
33
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
6.5.1
Vzor Transak£ní skript (Transaction script)
6.5.2
Vzor Doménový model (Domain Model)
. . . . . . . . . . . . . . .
33
. . . . . . . . . . . . . . . . .
34
xiii
OBSAH
6.5.3 6.6
6.7
35
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
35
6.6.1
Vzor Data access object (DAO) . . . . . . . . . . . . . . . . . . . . . .
36
6.6.2
Interakce integra£ní vrstvy s doménovou vrstvou
. . . . . . . . . . . .
36
. . . . . . . . . . . . . . . . . . . . . .
37
Podrobn¥j²í návrh jednotlivých vrstev 6.7.1
6.7.2
. . . . . . . . . . . . . . . . . . . . . . . . . . . . .
37
6.7.1.1
Prezenta£ní vrstva
ivotní cyklus poºadavku . . . . . . . . . . . . . . . . . . . .
37
6.7.1.2
Rozd¥lení prezenta£ní vrstvy do balí£k· . . . . . . . . . . . .
38
Doménová vrstva . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
39
6.7.2.1
Aktualizace doménových objekt· . . . . . . . . . . . . . . . .
40
6.7.2.2
e²ení typu pull
6.7.2.3
Modikace pull °e²ení
. . . . . . . . . . . . . . . . . . . . . .
43
6.7.2.4
e²ení typu push . . . . . . . . . . . . . . . . . . . . . . . . .
44
6.7.2.5
Dal²í varianta °e²ení typu pull
. . . . . . . . . . . . . . . . . . . . . . . . .
41
. . . . . . . . . . . . . . . . .
45
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
46
Integrace vrstev . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
48
6.7.3 6.8
Volba vzoru pro £len¥ní doménové logiky . . . . . . . . . . . . . . . . .
Integra£ní vrstva
Integra£ní vrstva
7 Implementace
51
7.1
Controllery
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
51
7.2
Validace . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
52
7.2.1
Balí£ek validation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
52
7.2.2
Knihovna Spring Modules . . . . . . . . . . . . . . . . . . . . . . . . .
53
7.2.3
JSR 303 Bean Validation API . . . . . . . . . . . . . . . . . . . . . .
54
7.3
Lazy Load . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
54
7.4
Pouºití Hibernate jako implementace JPA
. . . . . . . . . . . . . . . . . . . .
55
7.5
Zabezpe£ení aplikace . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
55
7.6
Struktura databáze . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
56
8 Testování
59
8.1
Testování jednotek (Unit testing) . . . . . . . . . . . . . . . . . . . . . . . . .
59
8.2
Frameworky pro testování
. . . . . . . . . . . . . . . . . . . . . . . . . . . . .
60
8.3
Testování v rámci práce
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
60
9 Záv¥r
63
Literatura
65
A Instala£ní a uºivatelská p°íru£ka
69
A.1
Instalace . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
69
A.2
Uºivatelská p°íru£ka
69
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
A.2.1
Zákaznická £ást . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
69
A.2.2
Administrátorská £ást
69
B Obsah p°iloºeného CD
. . . . . . . . . . . . . . . . . . . . . . . . . . .
71
xiv
OBSAH
Seznam obrázk· 4.1
Moduly frameworku Spring [Mak08]
. . . . . . . . . . . . . . . . . . . . . . .
10
5.1
Typy úrovní p°ípad· uºití [Coc01]
. . . . . . . . . . . . . . . . . . . . . . . .
20
5.2
Model problémové domény . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
27
6.1
Vzor MVC v kontextu t°ívrstvé architektury . . . . . . . . . . . . . . . . . . .
31
6.2
Interakce jednotlivých rolí ve vzoru MVC [BMR 98]
6.3
+
. . . . . . . . . . . . . .
32
Vzor Transak£ní skript [Fow03]
. . . . . . . . . . . . . . . . . . . . . . . . . .
34
6.4
Vzor Doménový model [Fow03]
. . . . . . . . . . . . . . . . . . . . . . . . . .
35
6.5
Rozhraní UserDAO . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
36
6.6
Pouºití DAO t°ídy [java] . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
37
6.7
Zpracování HTTP poºadavku frameworkem Spring MVC [Mak08] . . . . . . .
38
6.8
Balí£ky prezenta£ní vrstvy . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
39
6.9
Balí£ky doménové vrstvy . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
40
6.10 T°ída transak£ních skript· . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
40
6.11 Doménový objekt . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
41
6.12 Sekven£ní diagram interakce t°íd ze v²ech vrstev
. . . . . . . . . . . . . . . .
50
Struktura databáze . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
57
7.1
xv
xvi
SEZNAM OBRÁZK
Seznam tabulek 5.1
Seznam aktér· a jejich cíl·
. . . . . . . . . . . . . . . . . . . . . . . . . . . .
xvii
21
xviii
SEZNAM TABULEK
Kapitola 1
Úvod Dlouhodobým trendem posledních let je rostoucí roz²í°ení aplikací s webovým rozhraním na úkor klasických desktopových aplikací. V oblasti podnikových systém· p°evládají °e²ení postavená na platform¥ Java EE a Microsoft .NET. Pokud se ale zam¥°íme na webové aplikace men²ího rozsahu, jako jsou nap°íklad content management systémy (CMS) nebo ecommerce aplikace, zjistíme, ºe v této oblasti v oblasti p°evaºují °e²ení postavená na jazyce PHP (tato platforma se také ozna£uje jako LAMP podle sady typicky pouºitých technologií: Linux, Apache, MySQL a PHP). Je moºné, ºe tento stav je zp·soben tím, ºe platforma Java EE byla dlouho vnímána jako sloºitá a t¥ºkopádná, za coº vd¥£í nejspí²e historickým verzím technologie Enterprise Javabeans (EJB) nebo relativn¥ komplikovaným webovým framework·m, jako je p·vodní verze Apache Struts. V posledních letech pro platformu Java EE ale vzniklo velké mnoºství framework·, které významn¥ zvy²ují efektivitu práce a p°itom jsou relativn¥ snadné na pouºití a nesvazují programátora mnoºstvím omezení. Tento trend z°ejm¥ odstartoval framework Spring, který nabídl jako jeden z prvních pouºitelnou alternativu k technologi EJB. V dne²ní dob¥ jiº není d·vod, aby platforma JEE byla vnímána pouze jako °e²ení velkého kalibru, vhodné výhradn¥ pro aplikace rozsahu bankovních systém· nebo podnikových intranet·.
1
2
KAPITOLA 1.
ÚVOD
Kapitola 2
Popis problému, specikace cíle 2.1
Popis problému
V eské republice je velké mnoºství ºivnostník·, kte°í se zabývají maloobchodním prodejem zboºí a jejich jediným distribu£ním kanálem je internet. Kaºdý z t¥chto podnikatel· musí °e²it otázku získání aplikace pro internetový prodej. Mezi jejich moºnosti pat°í koup¥ licence na hotový (krabicový) software nebo pouºití n¥kterého z opensource °e²ení, jejichº instalaci nabízí °ada student· za velmi nízké ceny. Poslední moºností je vytvo°ení °e²ení kompletn¥ na zakázku u n¥které ze softwarových rem. Vytvo°ení aplikace kompletn¥ na zakázku je pro malého ºivnostníka málokdy nan£n¥ dostupné, zejména pokud s podnikáním za£íná. V¥t²ina z nich tedy volí n¥kterou z prvních dvou moºností. Problém nastává, pokud se podnikatel na trhu uchytí a jeho podnik roste. V tomto moment¥ velmi £asto pot°ebuje do své aplikace pro internetový prodej p°idat funkce, které mu umoºní efektivn¥ spravovat rostoucí agendu, nap°íklad napojení na systémy pro správu ú£etnictví. M·ºe také pot°ebovat novou funkcionalitu pro své zákazníky, nap°íklad podporu pro velkoobchodní prodej nebo internacionalizaci aplikace a s tím související podporu pro více m¥n. Firmy nabízející licence na krabicový software jsou p°ipraveny p°izp·sobit jejich produkty zákazník·m na míru, ale cena t¥chto sluºeb je velmi vysoká. Open source °e²ení zase £asto svým návrhem nedovolují snadno aplikaci roz²i°ovat.
2.2
Vymezení cíl· práce
Cílem práce je implementovat aplikaci pro internetový obchod s vyuºitím frameworku Spring a vhodného frameworku pro objektov¥-rela£ní mapování. D·leºitým aspektem práce je dobrý návrh aplikace, který neu£iní aplikaci p°íli² závislou na zvolených technologiích a který umoºní její snadné roz²i°ování do budoucna. V rámci aplikace bude krom¥ £ásti pro zákazníky zpracována neve°ejná £ást pro prodejce, jejíº sou£ástí bude evidence skladových zásob. Podrobn¥j²í poºadavky na aplikaci budou zji²t¥ny analýzou. Práce se nezabývá °e²ením problém· spojených s návrhem uºivatelského rozrhraní, jako je pouºitelnost nebo gracké zpracování.
3
4
KAPITOLA 2.
2.3
POPIS PROBLÉMU, SPECIFIKACE CÍLE
Struktura práce
Kapitola 3 se v¥nuje vysv¥tlení netriviálních pojm·, které se v práci £asto vyskytují. V rámci kapitoly 4 jsou p°edstaveny jednolivé £ásti frameworku Spring, dále jsou zde popsány roz²í°ené frameworky pro objektov¥-rela£ní mapování a diskutovány výhody a nevýhody jejich pouºití. Je zde zmín¥na platforma Google App Engine a nakonec jsou diskutovány existující implementace. Kapitola 5 se zabývá analýzou poºadavk· a analýzou problémové domény. Analýze poºadavk· p°edchází seznámení s pouºitými metodami analýzy poºadavk· a analýzy domény. Funk£ní poºadavky na aplikaci jsou zde zachyceny pomocí p°ípad· uºití. V kapitole 6 je °e²en návrh aplikace. Jsou zde také uvedeny zvolené frameworky a d·vody, které vedly k jejich výb¥ru. Dále je diskutována volba architektury aplikace. Poté jsou diskutovány zásadní otázky návrhu, týkající se jednotlivých £ástí aplikace. Nakonec jsou zmín¥ny detailn¥j²í aspekty návrhu jednotlivých £ástí aplikace. Kapitola 7 se zabývá popisem n¥kterých implementa£ních detail· aplikace, souvisejících s pouºitými technologiemi. Kapitola 8 popisuje testování aplikace.
Kapitola 3
Vymezení pojm· 3.1
JEE
Java Enterprise Edition je platforma pro vývoj podnikových informa£ních systém· (ozna£ovaných n¥kdy anglicismem enterprise aplikace). Zkrácené ozna£ení platformy je Java EE, p°ípadn¥ JEE. asto je moºné se setkat se zkratkou J2EE, která byla pro tuto platformu ociáln¥ pouºívána do verze 1.4 v£etn¥. JEE obsahuje °adu technologií, které jsou denovány sadou specikací JSR (Java Specication Request), které vznikají v rámci Java Community Process. JCP umoº¬uje rmám a odborné ve°ejnosti podílet se na vývoji. V rámci JCP probíhá i vývoj ostatních verzí jazyka Java - JSE, JME a Java Card. Specikace jsou realizovány referen£ními implementacemi, které pocházejí £asto od rmy Sun Microsystems. Dal²í implementace jsou vytvá°eny jinými rmami a organizacemi. Technologie implementující JSR jsou realizovány nej£ast¥ji jako open source (software s otev°eným kódem) pod n¥kterou z tzv. free software licencí, výjimkou nejsou ale ani produkty s komer£ními licencemi. Jako komer£ní implementace JSR byly vytvo°eny n¥které aplika£ní servery (nap°. Websphere od rmy IBM), které poskytují JEE aplikacím nutné prost°edí pro jejich b¥h. Alternativu k platform¥ JEE v sou£asné dob¥ p°edstavuje zejména .NET Framework od rmy Microsoft.
3.2
Framework
[GHJV95] denuje framework jako sadu spolupracujících t°íd, které vytvá°í návrh, opakovateln¥ pouºitelný pro aplikaci konkrétního typu. [Lar05] zavádí tento pojem jako koherentní sadu rozhraní a t°íd, které spolupracují za ú£elem poskytování sluºeb pro základní, nem¥nnou £ást logického podsystému. Jako typickou vlastnost dále uvádí p°ítomnost konkrétních a abstraktních t°íd, které mají p°esn¥ denované rozhraní ve smyslu kontrakt·, které musí dodrºovat. Framework je podobný softwarové knihovn¥ v tom, ºe jde o hotový, dob°e dokumentovaný kód, který programátor vyuºívá ve své aplikaci. Zásadní rozdíl frameworku oproti knihovn¥ je ten, ºe framework ur£uje architekturu aplikace, ve které je pouºit. [GHJV95] Frameworky
5
6
KAPITOLA 3.
VYMEZENÍ POJM
jsou zaloºeny na tzv. Hollywood Principle. Tento princip vystihuje v¥ta Don't call us, we'll call you. V praxi to znamená, ºe uºivatelem (vývojá°em) denované t°ídy p°ijímají zprávy od t°íd denovaných frameworkem. U knihoven je tomu naopak, programátorem vytvo°ené t°ídy posílají zprávy p°edp°ipraveným t°ídám knihovny. Alternativním a více formálním ozna£ením pro tento princip je
Inversion of Control
(zkratka IoC).
ádaným efektem pouºití frameworku je stejn¥ jako u knihoven usnadn¥ní práce programátora a z toho plynoucí rychlej²í vývoj aplikace. Programátor nemusí vytvá°et znovu °e²ení problému, který jiº n¥kdo d°íve uspokojiv¥ vy°e²il. [GHJV95] uvádí, ºe pouºití frameworku má za následek podobnou strukturu aplikací, coº usnad¬uje jejich udrºovatelnost. Aplikace vytvo°ené pomocí jednoho frameworku se jeví jako konzistentní. [GHJV95] zárove¬ zmi¬uje, ºe aplikace vytvo°ené pomocí frameworku jsou s ním velmi provázány, coº je £iní citlivé na zm¥ny v n¥m. Jak je framework vyvíjen jeho autory, musí se tomu p°izp·sobovat i aplikace, která jej vyuºívá. Není samoz°ejm¥ vºdy nutné p°echázet na nov¥j²í verze frameworku, pokud stará verze neobsahuje zásadní chyby nebo omezení, které nová odstra¬uje. Podmínkou úsp¥²ného pouºití frameworku je jeho dostate£ná znalost. Framework za£ne usnad¬ovat vývoj aº v moment¥, kdy je s ním programátor dostate£n¥ seznámen. Zpo£átku m·ºe efektivitu práce spí²e sníºit. Nasadit neznámý framework na projekt, který je výrazn¥ omezen £asem, m·ºe být pom¥rn¥ riskantní. Je nutné podotknout, ºe my²lenka frameworku není objevem posledních let. P°íkladem m·ºe být MacApp, framework pro opera£ní systém MacOS rmy Apple z 90. let, který byl poprvé zve°ejn¥n v roce 1985. [Dra] Slovo framework nemá v £e²tin¥ ustálený ekvivalent, stejn¥ jako °ada dal²ích pojm· v této oblasti.
3.3
Vzor (pattern)
Pod pojmem vzor si lze p°edstavit obecné, ustálené °e²ení £asto se vyskytujícího problému, jehoº pouºití se opakovan¥ osv¥d£ilo. [Lar05] vysv¥tluje pojem pattern takto: Most simply, a good pattern is a named and well-known problem/solution pair that can be applid in new contexts, with advice on how to apply it in novel situations and discussion of its trade-os, implementations, variations, and so forth. Vzory reprezentují léty prov¥°ené postupy a techniky, které se neváºí na konkrétní technologii. Nelze vymyslet nový vzor. Vzor je pouze moºné objevit, pokud se £asto objevuje v existujících °e²eních a vykazuje dobré kvality ve v²ech sm¥rech, které umoº¬ují, aby byl pouºit i v odli²ných kontextech. The point of design patterns is not to express new design ideas. [Lar05] Vzory mají n¥kolik funkcí. Usnad¬ují pochopení správných technik a postup· pro £lov¥ka, který s nimi zatím není seznámen. Zárove¬ usnad¬ují komunikaci mezi programátory tím, ºe denují terminologii. Poukazem na název vzoru lze vyjád°it velké mnoºství informace.
3.4.
7
NÁVRHOVÉ VZORY
3.4
Návrhové vzory
Návrhové vzory byly popsány v knize [GHJV95]. asto se lze setkat s ozna£ením GoF vzory, vzniklé podle p°ezdívky Gang of Four £tve°ice autor·. Návrhové vzory mohou p°i správné aplikaci zvý²it znovupouºitelnost kódu, sníºit provázanost jednotlivých £ástí a celkov¥ p°isp¥t ke správnému objektov¥-orientovanému návrhu aplikace. Porozum¥ní jednotlivým vzor·m obvykle nesta£í pro jejich efektivní pouºívání. Velká £ást vzor· se týká problém·, u kterých je v praxi £asto obtíºné rozpoznat stejnou podstatu a tedy moºnost aplikace vzoru. U nezku²ených programátor· m·ºe snaha vylep²it návrh aplikace pomocí návrhových vzor· dosp¥t k jejich nepromy²lenému aplikování. Softwarové frameworky velmi £asto vyuºívají návrhové vzory ve své struktu°e. Pokud jsou ve frameworku vhodn¥ pouºity, m·ºe jejich výhody srkze framework vyuºít i programátor, který s nimi není obeznámen. Vývojá°i, který návrhové vzory zná, naopak usnad¬ují pochopení, jak framework funguje. [GHJV95]
3.5
Impedan£ní nesoulad
V¥t²ina aplikací pro sv·j chod pot°ebuje n¥jakou formu datového úloºi²t¥. V oblasti podnikových informa£ních systém· je tímto úloºi²t¥m dat typicky rela£ní databáze. I p°es existenci objektových roz²í°ení pro rela£ní model stále siln¥ p°evaºují £ist¥ rela£ní databáze. Aplikace, které k dat·m p°istupují, jsou naproti tomu vyvíjeny v objektov¥-orientovaných jazycích. Mezi objektovým paradigmatem a rela£ním paradigmatem jsou zásadní rozdíly, které neumoº¬ují bezproblémové propojení t¥chto dvou sv¥t·. Tento problém je ozna£ován jako emphimpedan£ní nesoulad (Impedance Mismatch). Jedním z nejpatrn¥j²ích rozdíl· mezi zmín¥nými paradigmaty jsou zásadní odli²nostech v pouºívaných typových systémech. Rela£ní model nezná pojem ukazatele, vztahy mezi entitami jsou zachyceny pomocí relací (vycházející z relace jakoºto podmnoºiny kartézského sou£inu). Koncept nadtyp· a podtyp· z objektového sv¥ta a s tím související d¥di£nosti lze do rela£ního modelu p°eloºit je²t¥ obtíºn¥ji.
3.6
Mapování na rela£ní databáze, perzistentní frameworky
Programáto°i se museli s problémem mapování objekt· na rela£ní databáze v praxi n¥jakým zp·sobem vypo°ádat. Objevila se °ada °e²ení, p°i£emº málokteré z nich p°iná²í tolik jednozna£ných výhod oproti ostatním, aby jej bylo moºné prohlásit za jediné správné. Tyto ustálená °e²ení byly popsány formou vzor· v [Fow03]. Postupn¥ vznikla °ada hotových °e²ení pro mapování objekt· na rela£ní databáze. Tyto nástroje jsou ozna£ovány jako
tentní frameworky.
objektov¥ rela£ní mapova£e, ORM frameworky
nebo
perzis-
V¥t²ina ORM framework· v podstat¥ funguje jako vrstva nad rela£ní
databází, která umoº¬uje s touto databází pracovat, jako kdyby ²lo o objektovou databázi.
8
3.7
KAPITOLA 3.
VYMEZENÍ POJM
POJO
POJO je zkratka pro
plain old java object, oby£ejný objekt, na který nejsou kladeny ºádné
poºadavky jako nutnost implementovat rozhraní (frameworku) nebo d¥dit z p°edepsané t°ídy. [Fow03]
3.8
Anotace
Anotace je konstrukt jazyka Java, zavedený ve verzi 1.5, který umoº¬uje do zdrojového kódu vkládat metadata vztahující se k t°ídám, metodám a parametr·m metod.
Kapitola 4
Re²er²e 4.1
Framework Spring
Auto°i frameworku Spring ho ozna£ují jako platformu pro komplexní podporu vývoje aplikací v jazyce Java. Spring pomáhá °e²it infrastrukturu aplikace, aby se programátor mohl soust°edit na programování aplika£ní logiky. Je alternativou k platform¥ Enterprise JavaBeans, ale zárove¬ poskytuje podporu pro integraci mnoha jiných framework· a °e²ení, v£etn¥ t¥ch konkuren£ních, jako jsou EJB. To umoº¬uje nasadit Spring i na projekty, kde z n¥jakého d·vodu není velká volnost ve výb¥ru knihoven a framework·. asto se pouºívá pro webové aplikace, ale jeho uplatn¥ní zdaleka není omezeno na tuto oblast. Základem frameworku Spring je tzv. IoC kontejner, který je pojmenován podle principu Inversion of Control, který vyuºívá. (Princip Inversion of Control je diskutován v kapitole 3.2, viz Holywood principle). Dal²ím klí£ovým pojmem pro framework Spring je injekce závislostí - Dependency Injection. [Mak08] denuje Dependency Injection jako konkrétní techniku realizující princip Inversion of Control. Podstatou DI je, ºe objekt nezískává reference na t°ídy, na kterých závisí, pomocí aktivního vyhledání. Pouze zp°ístupní mechanismus (setter metoda nebo konstruktor), kterým mu je moºné reference na tyto t°ídy p°edat.
4.2
P°ehled modul· frameworku Spring
Framework Spring se skládá z °ady modul·, z nichº kaºdý poskytuje podporu pro °e²ení problém· v konkrétní oblasti. Moduly mají mezi sebou omezenou, dob°e denovanou provázanost, coº umoº¬uje vývojá°i vybrat si pro sv·j projekt pouze ty moduly, které v aplikaci vyuºije. Na obrázku 4.1 je p°ehled modul·, platný pro verze 2.5 a 3.0. Obrázek také ilustruje vzájemnou závislost modul·. Kaºdý modul je závislý na modulech, nacházejících se pod ním.
+
Nap°íklad modul Web MVC je závislý na modulech Web, Context a Core. [Mak08] [JHD ]
4.2.1
Core
Modul Core je základní £ást frameworku. Realizuje princip Dependency Injection pomocí komponenty BeanFactory, která vyuºívá návrhového vzoru Factory.
9
10
KAPITOLA 4.
REERE
Obrázek 4.1: Moduly frameworku Spring [Mak08]
4.2.2
Context
Modul Context poskytuje implementaci IoC kontejneru nazvanou ApplicationContext. Ta roz²i°uje funkcionalitu modulu Core, p°idává nap°íklad podporu internacionalizace. Modul Context je závislý na modulu Core.
4.2.3
Web
Modul Web poskytuje základní integraci s webovým prost°edím a slouºí primárn¥ jako podpora pro dal²í moduly webového prost°edí. Modul Web závisí na modulu Context.
4.2.4
Web MVC
Modul Web MVC je reprezentován webovým frameworkem Spring MVC. Ten je zaloºenen na architektonickém vzoru Model-View-Controller. Modul Web MVC závisí na modulu Web.
4.2.5
Portlet MVC
Modul Portlet MVC je tzv. portlet framework.
Portlety
jsou komponenty, které tvo°í obsah
webových portál· s vyuºitím portletového kontejneru dle specikace Java Portlet Specication. Dobrou p°edstavu dává sluºba iGoogle rmy Google, p°estoºe není postavena na
4.2.
11
PEHLED MODUL FRAMEWORKU SPRING
Java Portletech. Zde pouºívané
gadgety
se portlet·m velmi podobají a funkcionalita sluºby
iGoogle odpovídá portálu ve smyslu Java Portlet Specication. Modul Portlet MVC závisí na modulu Web.
4.2.6
Web Framework Integration
Tento modul poskytuje podporu pro integraci frameworku Spring s jinými webovými frameworky. Podporovány jsou pro frameworky JavaServer Faces, Apache Struts, Apache Struts 2, OpenSymphony WebWorks a Apache Tapestry. Modul Web Framework Integration závisí na modulu Web.
4.2.7
AOP
Tento modul p°edstavuje framework pro podporu aspektov¥ orientovaného programování. Aspektov¥ orientované programování je pom¥rn¥ nové programovací paradigma, komplementární k objektovému paradigmatu. Jeho cílem je umoºnit abstrakci problém·, které se vyskytují skrze celou aplikaci (typicky ve více vrstvách) a které souvisejí spí²e s infrastrukturou, neº s doménovou logikou (nap°. logování). Tento modul je pouºit v n¥kolika dal²ích modulech frameworku Spring. Závisí na modulu Core.
4.2.8
TX
Modul TX umoº¬uje správu transakcí. Transakce se denují zcela nezávisle na pouºitém perzistentním frameworku (z t¥ch, které jsou podporovány). Transakce je také moºné °ídit deklarativn¥, nap°íklad pomocí anotací. Deklarativní p°ístup umoº¬uje metody oby£ejných POJO t°ídy provád¥t transak£n¥ bez nutnosti psát kód pro obsluhu transakcí. Modul TX závisí na modulu AOP.
4.2.9
JDBC
Tento modul usnad¬uje práci s JDBC API pouºitím p°ipravených vzor· (templates), které redukují £asto se opakující obsluºný kód (tzv.
boilerplate code ).
Dále konvertuje chybové
kódy t°ídy SQLException, závislé na pouºitém JDBC driveru, do vlastní hierarchie výjimek. Modul JDBC závisí na modulu TX.
4.2.10
ORM
Modul ORM poskytuje integraci s ORM frameworky JPA, Hibernate, Ibatis a JDO. ORM modul umoº¬uje vyuºívat pro v²echny podporované perzistentní frameworky °ízení transakcí modulem TX. Odpadne tak závislost zp·sobu °ízení transakcí na pouºitého perzistentního frameworku. Modul ORM závisí na modulu JDBC.
12
KAPITOLA 4.
4.2.11
REERE
Enterprise Integration
Modul Enterprise Integration umoº¬uje ve Frameworku Spring pouºít technologie Java EE jako jsou Enterprise JavaBeans (EJB), Java Messaging Service (JMS), Java Management Extensions (JMX) nebo zasílání e-mail·. Modul Enterprise Integration závisí na modulu Context.
4.2.12
Testing
Spring TestContext Framework zavádí podporu pro jednotkové testování. Vytvá°í abstrakci nad frameworky JUnit 3.x, JUnit 4.x a TestNG.
4.2.13
Dal²í projekty Spring portfolio
Projekt Spring za²ti´uje °adu dal²ích projekt·, které framework dále roz²i°ují. Za zmínku stojí zejména Spring Security (d°íve Acegi Security), Spring Web Flow a Spring Modules. Spring Security je framework pro podporu zabezpe£ní aplikací. Spring Web Flow je nadstavba nad webovým frameworkem Spring MVC, která umoº¬uje denovat controllery pomocí doménov¥ specického jazyka (DSL). Spring Modules obsahuje °adu nástroj· a modul· a umoº¬uje nap°íklad deklarativní denice validátor·.
4.3
4.3.1
P°ehled ORM framework·
Entity Beans
Entity Beans se poprvé objevily jako sou£ást specikace Enterprise Javabeans (EJB) verze 1.1. Entity Beans mapují t°ídy v Jav¥ na tabulky v datovém úloºi²ti (ne nutn¥ rela£ní databáze) a vyºadují nasazení na aplika£ní server s EJB kontejnerem. Entity Beans byly £asto kritizovány pro velkou reºii a p°íli²nou komplikovanost, viz nap°íklad [Joh03]. Entity Beans byly soub¥ºn¥ s vydáním specikace EJB 3.0 nahrazeny technologií JPA, takºe nemá význam uvaºovat jejich pouºití na novém projektu.
4.3.2
Hibernate
Projekt Hibernate vznikl jako reakce na technologii Entity Beans. Záhy získal velkou popularitu a vývojový tým Hibernate byl najat rmou JBoss, aby pracoval na projektu pod jejich hlavi£kou. Hibernate umoº¬uje mapovat t°ídy v Jav¥ na tabulky v rela£ní databázi. Mapování se denuje pomocí XML soubor· a od verze Hibernate 3.2 lze pro mapování vyuºít anotací. Narozdíl od Entity Beans Hibernate není závislý na sluºbách kontejneru aplika£ního serveru. Pro konguraci Hibernate (v£etn¥ kongurace mapování jednotlivých objekt·) se uplat¬uje princip
conguration by exception.
Ten spo£ívá v tom, ºe pro kaºdou poloºku kongurace
u které je to moºné existuje implicitní hodnota, která pro v¥t²í £ást p°ípadu vyhovuje. Programátor tedy musí v kongura£ním souboru vyplnit jenom ty poloºky, u kterých mu implicitní hodnota nevyhovuje. Jednou z výhod tohoto p°ístupu je to, ºe konguraci zvládne
4.3.
13
PEHLED ORM FRAMEWORK
pom¥rn¥ snadno i za£áte£ník. Na druhou stranu tento p°ístup na první pohled zakrývá sloºitost problému, který se pak jeví jako jednodu²²í, neº ve skute£nosti je. S mapovanými objekty je moºné provád¥t standardní
CRUD
operace (create, retrieve,
update, delete) pomocí p°ipravených metod. Pro sloºit¥j²í operace lze vyuºít dotazovacího jazyka HQL, který je velmi podobný jazyku SQL, ale umoº¬uje nap°íklad vytvá°et polymorfní dotazy. V p°ípad¥ pot°eby lze p°es API Hibernate také provád¥t nativní dotazy p°ímo v SQL. Hibernate umoº¬uje z mapovaných objekt· automaticky vygenerovat schéma rela£ní databáze. To v kombinaci s metodami pro CRUD operace umoº¬uje odstín¥ní programátora od rela£ní databáze, coº má mimo jiné za d·sledek nezávislost na pouºitém databázovém stroji. V praxi je ale obvykle provázání s konkrétní databází nevyhnutelné, stejn¥ tak je nutná znalost rela£ních databází.
4.3.3
Java Pesistence API (JPA)
Java Persistence API vzniklo p°i vytvá°ení specikace EJB 3.0. Projekt JPA nahrazuje Entity Beans a není jiº sou£ástí EJB. JPA není zp¥tn¥ kompatibilní s technologií Entity Beans a podle [javb] vychází z technologií Hibernate, Toplink a JDO. S jistou mírou zjednodu²ení lze JPA ozna£it za podmnoºinu Hibernate. V²e v odstavci 4.3.2 platí tedy i pro JPA. V prosinci 2009 byla schválena specikace JPA 2.0, která navazuje na p·vodní specikaci a roz²i°uje ji, více viz [Kei08].
4.3.4
TopLink, TopLink Essentials, EclipseLink
Po£átek vývoje ORM nástroje TopLink sahá p°ekvapiv¥ hluboko do historie. P·vodn¥ byl vyvíjen v 90. letech rmou The Object People v jazyce Smalltalk. V roce 1996 rma The Object People za£ala pracovat na nové verzi TopLinku pro jazyk Java, který byl tehdy relativn¥ neznámý. TOPLink for Java se stal úsp¥ným produktem, narozdíl od Entity Beans umoº¬oval pouºití b¥ºných Java t°íd (POJO) pro mapování na rela£ní databáze. V roce 2000 byl Projekt TopLink odkoupen rmou WebGain spolu s vývojovým týmem a záhy poté v roce 2002 rmou Oracle. Po nástupu specikace JPA (rok 2006) Oracle z komer£ního produktu Oracle TopLink od²t¥pil verzi TopLink Essentials s otev°eným kódem. TopLink Essentials byl implementací specikace JPA a neobsahoval n¥které pokro£ilé vlastnosti Oracle TopLink. Sun Microsystems poté vybral TopLink Essentials jako referen£ní implementaci specikace JPA. Oracle TopLink soub¥ºn¥ pokra£oval jako samostatný produkt.[Smi] V roce 2007 rma Oracle vstoupila do nadace Eclipse (Eclipse Foundation). Vznikl nový projekt EclipseLink, do n¥hoº v¥noval Oracle zdrojové kódy produktu TopLink. EclipseLink je vyvíjen jako opensource a v roce 2008 byl vybrán jako referen£ní implementace specikace JPA 2.0. Podle hlavního produktového manaºera Oracle pro perzistentní technologie [Cla08] bude ve²kerý vývoj Oracle Toplink pokra£ovat v projektu EclipseLink. EclipseLink v sou£asné dob¥ £ist¥ implementací specikace JPA 1.0 a JPA 2.0. Nezavádí vlastní funkcionalitu mimo rámec t¥chto specikací, jako nap°íklad Hibernate.
14
KAPITOLA 4.
4.3.5
REERE
JDO
JDO je specikace, vytvá°ená v rámci Java Community procesu soub¥ºn¥ se specikací EJB a JPA. Zásadní rozdíl oproti JPA je ten, ºe technologie JDO není zam¥°ena pouze na mapování na rela£ní databáze, ale °e²í perzistenci objekt· do datových úloºi²´ obecn¥ (nap°. objektové databáze). [Joh03] zmi¬uje, ºe JDO by se mohlo stát standardním API pro p°ístup k objektovým databázím v Jav¥. To se nenaplnilo. JDO se nedo£kalo ²ir²ího roz²í°ení a Sun pozastavil jeho vývoj. Pozd¥ji ale Sun v¥noval specikaci JDO Apache Software Foundation, která v jeho vývoji pokra£uje. [jdo]
4.3.6
iBatis
Ibatis je perzistentní framework, který °e²í objektov¥-rela£ne mapování jiným zp·sobem. Nepouºívá se v n¥m mapování t°íd na tabulky v databázi, ale mapují se výsledky SQL dotaz· na t°ídy (typicky z doménové vrstvy) a SQL dotazy na metody (metody DAO t°íd). SQL dotazy se v denují v XML souborech nebo pomocí anotací. Existuje i moºnost denovat SQL dotazy pomocí doménov¥ specického jazyka, ale jde o zcela odli²ný p°ístup neº u JPA/Hibernate, kde dotazy primárn¥ generuje framework. Pouºití iBatis typicky vypadá tak, ºe programátor napí²e rozhraní DAO t°ídy, v XML souborech nadenuje mapování a iBatis podle mapování vygeneruje implementaci rozhraní. Výhodou tohoto p°ístupu je plná kontrola vývojá°e nad p°ístupem do databáze. Odpadnou tak n¥které problémy vzniklé automatickým generováním dotaz·, nap°íklad jejich obtíºná optimalizace. Proto se framework iBatis hodí zejména na aplikace, které vyuºívají sloºit¥j²í dotazy do databáze, neº jsou klasické CRUD operace. Výhodou p°i pouºití iBatis oproti pouºití holého JDBC je, ºe související SQL dotazy jsou shromáºd¥ny na jednom míst¥ a jsou odd¥lené od kódu aplikace. P°ípadný databázový expert má tak lep²í podmínky k jejich optimalizaci. IBatis dále automatizuje správu zdroj· jako jsou spojení do databáze, £ímº redukuje moºnost programátorských chyb spojených se správou zdroj·. Nevýhodou je niº²í produktivita práce ve srovnání s frameworky jako Hibernate nebo JPA.
4.4
Google App Engine
Google App Engine je platforma pro nasazení aplikací napsaných v jazyce
Python
a Java. S
podporou Javy se váºe také podpora jazyk·, které se p°ekládají na bytekód Javy, nap°íklad
Groovy
nebo
Scala.
GAE vyuºívá jako perzistentní úloºi²t¥
Bigtable
+
[CDG 06], které je vyuºívano °adou
aplikací z portfolia Google. Bigtable je distribuovaný databázový systém, který není zaloºen na rela£ním modelu. Pro p°ístup do Bigtable lze v prost°edí GAE pouºít technologie JDO a JPA. Vzhledem k tomu, ºe specikace JPA je zaloºena na rela£ním modelu, není dostupné celé API JPA. GAE nabízí pom¥rn¥ zajímavé moºnosti, nap°íklad automatickou ²kálovatelnost aplikací nebo snadný p°ístup k API r·zných aplikací Google, jako je GMail API, Google Accounts API nebo Google Talk API. Na druhou stranu má GAE °adu omezení, nap°íklad v²echny
4.5.
REERE EXISTUJÍCÍCH IMPLEMENTACÍ
15
zde nasazené aplikace musí být jednovláknové a není moºné p°istupovat na lesystém. Dále není moºné pouºít v²echny knihovny JRE; je denován whitelist [gooa], který explicitn¥ povoluje jednotlivé t°ídy. V p°ípad¥ pouºití framework· je obvykle nutné framework v¥t²í £i men²í m¥rou p°izp·sobit t¥mto omezením. Google udrºuje p°ehled kompatility roz²í°ených framework· s App Engine, viz [goob].
4.4.1
Moºné vyuºití Google App Engine
Omezení dané platformou GAE by byly potenciální komplikací zejména pro frameworky pouºité v aplikaci. Framework Spring a jeho modul Spring MVC by bylo moºné pouºít, jsou v seznamu kompatility ozna£eny jako podporované. [goob] Framework Spring Security, který je v aplikaci vyuºit, je ozna£en pouze jako £áste£n¥ podporovaný. P°i pouºití Spring Security by byly problematické SQL dotazy, pomocí kterých se provádí autentizace uºivatel· proti existujícímu databázovému schématu aplikace. Perzistentní úloºi²t¥ pouºité v GAE jazyk SQL nepodporuje, proto by existující zp·sob autentizace nebylo moºné pouºít.
4.5
Re²er²e existujících implementací
Pokud vezmeme v úvahu platformu Java EE, zjistíme, ºe open source aplikací pro internetový prodej existuje ve srovnání s platformou jazyka PHP velmi malé mnoºství. Poda°ilo se mi objevit projekty
JFire [j] a Apache OFBiz
[ofb]. Spole£nou vlastností t¥chto projekt· je, ºe
nenabízí aplikaci pouze pro realizaci internetového obchodu. V p°ípad¥ JFire jde o pom¥rn¥ rozsáhlý systém, který implementuje podporu pro oblasti remních proces· jako jsou Supply chain management, Customer relationship management, Supplier relationship management a dal²í. Apache OFBiz je více zam¥°en na internetové obchodování, ale stále jde o rozsáhlý systém, který nap°íklad nabízí podporu pro projektový management nebo podporu terminál· pro p°ímý prodej zboºí (pokladny). Nevýhodou existujících open source °e²ení je, ºe se ob¥ snaºí podporovat rozsáhlé spektrum £inností. V p°ípad¥ projektu JFire se jedná v podstat¥ o kompletní podnikový systém, jako je nap°íklad SAP. Projekt Apache OFBiz odpovídá p°edstav¥ aplikace pro realizaci internetového obchodu lépe, ale rozsah podporovaných £inností je i tak velmi rozsáhlý. Domnívám se, ºe °e²ení postupn¥ vystav¥né z malé aplikace by mohlo více odpovídat specik·m internetového obchodování v eské republice.
16
KAPITOLA 4.
REERE
Kapitola 5
Analýza Analýza jako disciplína vývoje software se zabývá zkoumáním problému a zji²´ováním poºadavk·. Nezabývá se °e²ením problému. V rámci analýzy je nutné zjistit, jaké mají budoucí uºivatelé na systém poºadavky a v £em má usnad¬ovat jejich práci. Tímto se zabývá analýza poºadavk·. Druhým úkolem analýzy je p°ipravit podklad pro návrh °e²ení zmapovat kontext, do kterého jsou zasazeny poºadavky uºivatel· a cíle, kterých jim má systém pomáhat dosahovat. Tento kontext se typicky ozna£uje jako problémová doména. Popis problémové domény spolu s poºadavky na systém tvo°í spole£n¥ vstup pro dal²í disciplíny vývoje, p°eváºn¥ pro návrh, který se zabývá zp·sobem °e²ení problému. Rozdíl mezi analýzou a návrhem je výstiºn¥ shrnut v anglických v¥tách Do the right thing pro analýzu a Do the thing right pro návrh. [Lar05] Zp·sob návrhu je velmi ovlivn¥n paradigmatem zvoleného programovacího jazyka. Pro objektov¥ orientované programování se hodí jiné postupy návrhu, neº pro procedurální nebo funkcionální programování. Mohlo by se zdát, ºe analýza na pouºitém paradgimatu závislá není, protoºe se °e²ením problému nezabývá a logicky by m¥la p°edcházet fázi návrhu. Snad v²echny metodiky vývoje softwaru ale zavrhují cyklus vývoje, kdy je nejd°íve provedena kompletní analýza problému, poté je s pouºitím výsledk· analýzy systém navrºen a podle návrhu naimplementován. Tento p°ístup je £asto ozna£ován pojmenováním
Front. Známý je také jako vodopádový model.
Roz²í°ené metodiky vývoje softwaru (zejména tzv.
Big Design Up
agilní metodiky ) tedy po£ítají s tím,
ºe analýza probíhá více £i mén¥ v soub¥hu s ostatními disciplínami vývoje software. Proto je výhodné, aby mezi popisem problému v analýze a popisem návrhu problému nebyly velké rozdíly ve zp·sobu vyjad°ování (tzv. sémantická mezera). Jeden postup, který tuto výhodu má, uvádí [Lar05] a nazývá ho objektov¥-orientovaná analýza. Ta spo£ívá v hledání a popisování objekt· (koncept·) v problémové domén¥. Tento princip se podobá d°íve pouºívanému vytvá°ení konceptuálních model· pomocí E-R diagram·. Model vytvo°ený p°i objektov¥-orientované analýze se obvykle nazývá
doménový
model. Objektov¥-orientovaná analýza ne°e²í analýzu poºadavk·, tu je nutné provést pomocí n¥které z metod pro sb¥r poºadavk·.
17
18
KAPITOLA 5.
5.1
ANALÝZA
Analýza poºadavk·
5.1.1
Typy poºadavk·
Poºadavky na software se nej£ast¥ji rozd¥lují na
funk£ní, kam pat°í v²echny ostatní.
funk£ní,
týkající se chování aplikace a
ne-
FURPS+ model. Ten je pojmenován podle prvních písmen jednotlivých kategorií poºadavk·: Functionality, Usability, Reliability, Performance a Supportability. Toto rozd¥lení není v koniktu s p°echozím rozd¥lením [Lar05] doporu£uje pro £len¥ní poºadavk· pouºívat tzv.
na funk£ní a nefunk£ní poºadavky, pouze je podrobn¥j²í.
Functionality
Kategorie
Usability
odpovídá funk£ním poºadavk·m zmín¥ném vý²e.
(pouºitelnost) bere v potaz lidský faktor jak navrhnout uºivatelské rozhraní
aplikace tak, aby s ním uºivatel·m dob°e pracovalo, p°ípadn¥ zohled¬uje pot°eby konkrétních skupin lidí se specickými omezeními (nap°. lidé s poruchami zraku, d¥ti, senio°i). Zkoumáním pouºitelnosti se zabývá obor HCI (Humancomputer interaction).
Reliability
(spolehlivost) obsahuje poºadavky na spolehlivost systému, nap°. poºadavek
na nep°etrºitý b¥h aplikace po stavenou dobu. V této souvislosti se £asto objevují zkratky 24/7, znamenající provoz 24 hodin denn¥, 7 dní v týdnu, nebo ve nines, znamenající dostupnost 99,999% £asu za stanovenou dobu (podobn¥ four nines, six nines, atd.). Tato kategorie m·ºe také obsahovat poºadavky na schopnost systému zotavit se z chybových stav·.
Performance
(výkon) obsahuje poºadavky na výkon aplikace, typicky vyjád°ené pomocí
pojm· jako je propustnost (throughput), doba odezvy, kapacita, ²kálovatelnost a dal²ích, viz [Fow03].
Supportability (podporovatelnost) zahrnuje poºadavky na lokalizaci, testovatelnost, p°izp·sobitelnost, kongurovatelnost a udrºnovatelnost. Plus v názvu FURPS+ zahrnuje dal²í poºadavky, neza°aditelné do ºádné z p°edchozích kategorií. Jde nap°íklad o omezení na zdroje, vymezení pouºitelných nástroj· a programovacích jazyk·, omezení daná rozhraními externích systém·, právní náleºitosti jako je licencování a dal²í. Model FURPS+ je sou£ástí n¥kterých roz²í°ených metodik vývoje software, nap°íklad metodiky Unied Process.
5.1.2
P°ípady uºití
Velmi roz²í°enou metodou pro sb¥r a zaznamenávání poºadavk· jsou
p°ípady uºití (use stakeholdery
cases). P°ípady uºití jsou psané p°íb¥hy denující kontrakt mezi systémem a
(zainteresované osoby nebo organizace). P°ípad uºití popisuje chování systému v reakci na
primární aktér. Hlavní £ástí scéná°, coº je sekvence akcí aktér· a systému a popisu interakcí mezi nimi.
poºadavek jednoho ze stakeholder·, který je ozna£ován jako p°ípadu uºití je
P°íkladem jednoho scéna°e m·ºe být popis situace, kdy zákazník banky chce vybrat peníze z bankomatu a systém nevydá hotovost, protoºe z·statek na ú£t¥ je niº²í, neº poºadovaná £ástka, nebo popis úsp¥²ného výb¥ru hotovosti. Pomocí v²ech moºných variant se scéná°i denuje poºadované chování systému. Pro p°ípady uºití je v jazyce UML podpora ve form¥ diagramu p°ípad· uºití.
5.1.
ANALÝZA POADAVK
19
P°ípady uºití jsou ur£eny pro funk£ní poºadavky. Nejsou p°íli² vhodné pro zaznamenávání nefunk£ních poºadavk·.
5.1.3
User stories
Extrémní programování (XP) zavádí pro sb¥r poºadavk· metodu user stories. Spo£ívá v psaní krátkých denic poºadavk· na systém z pohledu stakeholdera
Metodika vývoje software
(typicky budoucího uºivatele systému). P°íklad: Jako zákazník chci zaplatit zboºí pomocí sluºby PayPal, protoºe je to rychlý a bezpe£ný zp·sob. User stories by m¥li psát lidé zainteresovaní na projektu, jeho p°ípadní budoucí uºivatelé. User stories by nem¥li vytvá°et vývojá°i sami. Aby byly user stories krátké, £asto se doporu£uje psát je rukou na malé kartotékové karti£ky, na které se velké mnoºství textu ani nevejde. Narozdíl od p°ípad· uºití nejsou user stories samy o sob¥ plnohodnotnou metodou sb¥ru poºadavk·. Jednotlivé karti£ky p°edstavují spí²e p°ipomínky, k jakému poºadavku provést podrob¥j²í analýzu práv¥ v£as. To je umoºn¥no díky jiné praktice metodiky Extrémního programování, kterou je trvalá p°ítomnost zástupce zákazníka u vývojá°· (on-site customer). Vývojá°i mohou kdykoliv konzultovat s £lov¥kem od zákazníka (tzv. business expertem) detaily n¥kterého z poºadavk·. Sespané user stories jim slouºí jako základní p°ehled poºadavk·. Bez £asté p°ítomnosti zákazníka tedy tuto metodu sb¥ru poºadavk· nelze úsp¥²n¥ pouºít. [Coc01] [Amb] [Coh] navrhuje pouºití user stories i pro sb¥r nefunk£ních poºadavk·. Uvádí p°íklad: Jako CTO chci, aby systém vyuºíval existující databázi objednávek, abychom nemuseli spravovat databázi navíc.
5.1.4
P°ípady uºití podle Alistaira Cockburna
Pro analýzu funk£ních poºadavk· jsem zvolil p°ípady uºití. Absence uceleného textového výstupu diskvalikuje user stories pro pouºití v této práci. P°i psaní p°ípad· uºití jsem vycházel z knihy Writing Eective Use Cases od Alistaira Cockburna. Jeho podoba p°ípad· uºití roz²i°uje model Ivara Jacobsona, p·vodního autora konceptu p°ípad· uºití. [Coc01] navrhuje pro psaní p°ípad· zp·sob, kdy se v sekci pro hlavní úsp¥²ný scéná° popí²e pouze nejjednodu²²í scéna° bez jakýchkoliv chyb nebo moºností v¥tvení. V²echny ostatní scéná°e vzniklé v¥tvením hlavního scéna°e se popisují v sekci ro²í°ení. Událost, která vede k alternativnímu pr·chodu scéná°e, se stru£n¥ popí²e, ozna£í se £íslem kroku, ke kterému p°edstavuje alternativu a za toto £íslo se p°idá pro odli²ení písmeno. Poté následuje posloupnost krok·, které reprezentují alternativní pr·chod scéná°em. Pro p°íklad viz libovolný p°ípad uºití v sekci 5.1.6
- Zpracované p°ípady uºití.
asto nastane situace, kdy se v popisované v¥tvi scéná° v¥tví znovu. V takovém p°ípad¥
se v¥tvení popí²e v míst¥, kde vzniká, viz následující p°íklad. Bod 6a Pro zadanou po²tovní adresu není denován ºádný zp·sob p°epravy popisuje událost, vedoucí na alternativní pr·chod bodu 6 hlavního scéna°e. Krok 6a2a Zákazník nechce objednávku realizovat s jinou adresou podobn¥ popisuje událost, která vede na alternativní pr·chod bodu 6a2.
Roz²í°ení: 6a. Pro zadanou po²tovní adresu není definován ºádný zp·sob p°epravy:
20
KAPITOLA 5.
ANALÝZA
6a1. Systém informuje zákazníka. 6a2. Zákazník se vrátí na výb¥r doru£ovací adresy a zvolí jinou adresu. 6a2a. Zákazník nechce objednávku realizovat s jinou adresou: 6a2a1. Zákazník ukon£í práci s aplikací.
5.1.4.1 Úrove¬ cíle [Coc01] denuje pro p°ípady uºití kritérium úrovn¥ cíle. Motivací pro zavedení tohoto kritéria je, ºe cíle aktéra se skládají z men²ích cíl· a naopak n¥kolika cíl·m £asto odpovídá jeden
user
vy²²í cíl. P°ípady uºití d¥lí podle úrovn¥ cíl· na t°i hlavní skupiny: uºivatelský cíl (
goal ), souhrnný cíl (summary goal ) a podfunkce (subfunction ), viz obrázek 5.1.
Obrázek 5.1: Typy úrovní p°ípad· uºití [Coc01]
Uºivatelský cíl odpovídá velikostí tzv. elementárnímu business procesu (EBP). Je obtíºné
boss testu. Ten spo£ívá v p°edstav¥ nad°ízeného, který se svého pod°ízeného ptá: co jste d¥lal celý ho exaktn¥ denovat, ale ºe se jedná o cíl této úrovn¥, lze snadno odhalit pomocí tzv.
den? Pokud by ho uspokojila odpov¥¤ v podob¥ cíle, na který tento test aplikujeme (nap°. p°idával jsem do nabídky nové produkty), jedná se o uºivatelský cíl. Pokud by odpov¥¤ nad°ízeného neuspokojila (nap°. p°ihla²oval jsem se do systému), z°ejm¥ se jedná o cíl niº²í úrovn¥ (podfunkce). [Lar05] Zárove¬ musí p°ípad uºití této úrovn¥ spl¬ovat to, aby jej aktér mohl dosáhnout b¥hem jednoho sezení. P°ípady uºití této úrovn¥ jsou nejd·leºit¥j²í, protoºe reprezentují jednotlivé funk£ní poºadavky na systém. Jednotlivé kroky t¥chto p°ípad· uºití je moºné rozloºit na podfunkce. Vytvá°ení p°ípad· uºití popisujících podfunkce má smysl tehdy, pokud je p·vodní p°ípad uºití p°íli² dlouhý (doporu£uje se p°ibliºn¥ 3-9 krok· v hlavním úsp¥²ném scéná°i) a shrnutím n¥kolika krok· do samostatného p°ípadu uºití se stane srozumiteln¥j²ím. Vytvo°ení p°ípadu uºití na této niº²í úrovni je také vhodné, pokud se v n¥kolika p°ípadech uºití opakují stejné kroky. Z t¥chto
5.1.
21
ANALÝZA POADAVK
Aktér
Cíl
Zákazník
Vybrat zboºí
Zákazník
Objednat zboºí
Zákazník
Prohlíºet objednávky
Prodejce
Vy°ídit objednávku
Prodejce
P°idat zboºí
Prodejce
Upravit zboºí
Prodejce
P°idat kategorii zboºí
Prodejce
Upravit kategorii zboºí
Prodejce
Naskladnit zboºí
Tabulka 5.1: Seznam aktér· a jejich cíl·
krok· se vytvo°í nový p°ípad uºití typu podfunkce a v p·vodních p°ípadech uºití se na n¥j odkáºe. Tomu odpovídá vazba
include
v UML diagramu p°ípadu uºití.
Souhrnný cíl se skládá z n¥kolika uºivatelských cíl·. P°ípady uºití tohoto typu lze pouºít pro zachycení souvislostí více p°ípad· uºití. P°íkladem p°ípadu uºití se souhrným cílem je 5.1.6.1
- Koupit zboºí. Ten se odkazuje na jeden p°ípad uºití typu podfunkce a dva p°ípady
uºití typu uºivatelský cíl.
5.1.5
Seznam aktér-cíl
Seznam aktér· a jejich cíl· v tabulce 5.1 slouºí jako hrubý p°ehled funkcionality, kterou by m¥la aplikace poskytovat. Podrobný p°ehled poskytují p°ípady uºití.
5.1.6
Zpracované p°ípady uºití
Zpracované p°ípady uºití reprezentují funk£ní poºadavky na aplikaci.
5.1.6.1 Koupit zboºí Primární aktér: Zákazník Rozsah: aplikace elektronického obchodu Úrove¬: souhrnný cíl Hlavní úsp¥²ný scéná°: Kroky 1-2 mohou prob¥hnout v libovolném po°adí. 1. Zákazník se p°ihlásí do systému. 2. Zákazník si vybere zboºí. [5.1.6.2] 3. Zákazník vybrané zboºí objedná. [5.1.6.3]
5.1.6.2 Vybrat zboºí Rozsah: aplikace elektronického obchodu
22
KAPITOLA 5.
ANALÝZA
Úrove¬: uºivatelský cíl Primární aktér: Zákazník Hlavní úsp¥²ný scéná°: 1. Zákazník si p°eje vybrat zboºí z nabídky. 2. Systém zobrazí katalog zboºí a seznam kategorií zboºí. 3. Zákazník zvolí n¥kterou z kategorií zboºí. 4. Systém zobrazí zboºí ve zvolené kategorie a seznam podkategorií této kategorie. U kaºdého zboºí zobrazí popis, dostupné mnoºství a komentá°e uºivatel· k tomuto zboºí. 5. P°ípad uºití kon£í, kdyº si uºivatel nep°eje v procházení zboºí pokra£ovat.
Roz²í°ení: ∗a.
Systém detekuje interní chybu znemoº¬ující pokra£ování:
∗a1.
Systém zobrazí uºivateli jednoduchou zprávu o chyb¥, zapí²e podrobnou zprávu do logu.
4a. Zákazník chce vloºit komentá° £i dotaz ke zboºí: 4a1. Zákazník vyplní text komentá°e. 4a2. Systém uloºí komentá° se jménem zákazníka. 4a1a. Zákazník není p°ihlá²en do systému: 4a1a1. Systém zobrazí výzvu k [P°ihlá²ení do systému].
5.1.6.3 Objednat zboºí Rozsah: aplikace elektronického obchodu Úrove¬: uºivatelský cíl Primární aktér: Zákazník Hlavní úsp¥²ný scéná°: 1. Zákazník má vybráno zboºí z katalogu. Zvolí poºadované zboºí a zadá poºadovaný po£et kus·. 2. Systém vloºí zboºí do zákazníkova nákupního ko²íku a zobrazí potvrzení. Kroky 1-2 se opakují, dokud zákazník neur£í jinak. 3. Zákazník vybere moºnost sestavení objednávky. 4. Systém zobrazí seznam zákazníkových po²tovních adres. 5. Zákazník vybere ze seznamu adresu pro doru£ení a faktura£ní adresu. 6. Systém zobrazí moºné zp·soby doru£ení pro vybranou doru£ovací adresu v£etn¥ cen za doru£ení. 7. Zákazník vybere n¥který ze zp·sob· doru£ení. 8. Systém zobrazí rekapitulaci objednávky a výzvu k odeslání objednávky. 9. Zákazník potvrdí odeslání objednávky. 10. Systém uloºí objednávku a zobrazí potvrzení o odeslání objednávky.
Roz²í°ení: ∗a.
Zákazník chce zm¥nit po£et kus· zboºí v ko²íku:
∗a1. ∗a2. ∗b.
Zákazník zvolí v ko²íku poloºku, u které chce zm¥nit po£et kus·. Zadá nové mnoºství. Systém uloºí nové mnoºství (a zobrazí potvrzení).
Systém detekuje interní chybu znemoº¬ující pokra£ování:
∗b1.
Systém zobrazí uºivateli jednoduchou zprávu o chyb¥, zapí²e podrobnou zprávu do logu.
1a. Zákazník není p°ihlá²en: 1a1. Systém zobrazí výzvu k [P°ihlá²ení do systému]. 1b. Zákazník zadá neplatné mnoºství. b1. Systém zobrazí informaci o chyb¥ a poloºí nový dotaz na mnoºství.
5.1.
ANALÝZA POADAVK
23
2a. V nákupním ko²íku zákazníka uº se poºadované zboºí nachází: 2a1. Systém navý²í po£et kus· zboºí v ko²íku o nov¥ zadaný po£et kus·. 2b. Zákazník chce odstranit z ko²íku poloºku: 2b1. Zákazník zvolí v ko²íku poloºku k odstran¥ní. 2b2. Systém odstraní poloºku z ko²íku (a zobrazí potvrzení). 3a. Zákazník nechce v tuto chvíli sestavit objednávku: 3a1. Systém uloºí obsah zákazníkova nákupního ko²íku pro pozd¥j²í pouºití. 3a2. Zákazník ukon£í práci s aplikací. 5a. Zákazník·v seznam po²tovních adres je prázdný: 5a1. Systém informuje zákazníka a nabídne [P°idání po²tovní adresy] 6a. Pro zadanou po²tovní adresu není denován ºádný zp·sob p°epravy: 6a1. Systém informuje zákazníka. 6a2. Zákazník se vrátí na výb¥r doru£ovací adresy a zvolí jinou adresu. 6a2a. Zákazník nechce objednávku realizovat s jinou adresou: 6a2a1. Zákazník ukon£í práci s aplikací. 9a. Zákazník zamítne odeslání objednávky: 9a1. Systém uloºí obsah zákazníkova nákupního ko²íku pro pozd¥j²í pouºití a smaºe objednávku.
5.1.6.4 Prohlíºet objednávky Rozsah: aplikace elektronického obchodu Úrove¬: podfunkce P°edpoklady: Zákazník je p°ihlá²en do systému. Primární aktér: Zákazník Hlavní úsp¥²ný scéná°: 1. Zákazník zvolí moºnost zobrazení svých objednávek. 2. Systém zobrazí objednávky tohoto zákazníka v£etn¥ jejich stavu.
Roz²í°ení: ∗a.
Systém detekuje interní chybu znemoº¬ující pokra£ování:
∗a1.
Systém zobrazí uºivateli jednoduchou zprávu o chyb¥, zapí²e podrobnou zprávu do logu.
5.1.6.5 Vy°ídit objednávku Rozsah: aplikace elektronického obchodu Úrove¬: uºivatelský cíl Primární aktér: Prodejce P°edpoklady: Prodejce je p°ihlá²en do systému. Hlavní úsp¥²ný scéná°: 1. Prodejce zvolí moºnost spravovat objednávky. 2. Systém zobrazí seznam nevy°ízených objednávek. 3. Prodejce vybere objednávku a aktualizuje objednávku. 4. Systém uloºí nový stav objednávky a zobrazí potvrzení.
Roz²í°ení: ∗a.
Systém detekuje interní chybu znemoº¬ující pokra£ování:
24
KAPITOLA 5.
∗a1.
ANALÝZA
Systém zobrazí zprávu o chyb¥, obsahující její p°í£inu. Zapí²e podrobnou zprávu do logu.
1a. Prodejce zvolí moºnost spravovat vy°ízené objednávky: 1a1. Systém zobrazí seznam vy°ízených objednávek. 3a. Prodejce zm¥ní po£et kus· zboºí v poloºce objednávky: 3a1. Systém zvaliduje zadané údaje. 3a2. Systém uloºí zm¥ny v objednávce a zobrazí potvrzení. 3a1a: Systém zjistí, ºe zadané mnoºství je záporné nebo nula: 3a1a1. Systém vrátí údaje k oprav¥ a zobrazí chybu. 3b. Prodejce odstraní poloºku objednávky: 3b1. Systém uloºí zm¥ny v objednávce a zobrazí potvrzení.
5.1.6.6 P°idat zboºí do katalogu Rozsah: aplikace elektronického obchodu Úrove¬: uºivatelský cíl Primární aktér: Prodejce Preconditions: Prodejce je p°ihlá²en do systému. Hlavní úsp¥²ný scéná°: 1. Prodejce vybere kategorie, do kterých produkt spadá a zadá následující údaje: - název výrobku - popis - prodejní cenu 2. Systém zvaliduje zadané údaje. 3. Prodejce zvolí existující produkty, které souvisejí s nov¥ zadávaným produktem. Vybere 0, 1, nebo více produkt·. 4. Systém uloºí nový produkt a zobrazí potvrzení.
Roz²í°ení: ∗a.
Systém detekuje interní chybu znemoº¬ující pokra£ování:
∗a1.
Systém zobrazí zprávu o chyb¥, obsahující její p°í£inu. Zapí²e podrobnou zprávu do logu.
2a. Systém detekuje chyb¥jící nebo nesprávné údaje: 2a1. Systém vrátí údaje k oprav¥ a zobrazí seznam chyb.
5.1.6.7 Upravit zboºí v katalogu Rozsah: aplikace elektronického obchodu Úrove¬: uºivatelský cíl Primární aktér: Prodejce P°edpoklady: Prodejce je p°ihlá²en do systému. Hlavní úsp¥²ný scéná°: 1. Prodejce vybere zboºí, které chce upravit. 2. Systém zobrazí údaje o zboºí v editovatelné podob¥. 3. Prodejce upraví údaje o zboºí. 4. Systém zvaliduje zadané údaje. 5. Systém uloºí zm¥ny a zobrazí potvrzení.
5.1.
ANALÝZA POADAVK
25
Roz²í°ení: ∗a.
Systém detekuje interní chybu znemoº¬ující pokra£ování:
∗a1.
Systém zobrazí zprávu o chyb¥, obsahující její p°í£inu. Zapí²e podrobnou zprávu do logu.
3a. Prodejce chce zboºí smazat: 3a1. Prodejce zvolí moºnost smazání produktu. 3a2. Systém smaºe produkt. 4a. Systém detekuje chyb¥jící nebo nesprávné údaje: 4a1. Systém vrátí údaje k oprav¥ a zobrazí seznam chyb.
5.1.6.8 P°idat kategorii zboºí Rozsah: aplikace elektronického obchodu Úrove¬: uºivatelský cíl Primární aktér: Prodejce P°edpoklady: Prodejce je p°ihlá²en do systému. Hlavní úsp¥²ný scéná°: 1. Prodejce zadá název nové kategorie a p°ípadn¥ vybere kategorii, která je rodi£ovskou kategorií nové kategorie. 2. Systém zvaliduje zadané údaje. 3. Systém uloºí novou kategorii a zobrazí potvrzení.
Roz²í°ení: ∗a.
Systém detekuje interní chybu znemoº¬ující pokra£ování:
∗a1.
Systém zobrazí zprávu o chyb¥, obsahující její p°í£inu. Zapí²e podrobnou zprávu do logu.
2a. Systém detekuje chyb¥jící nebo nesprávné údaje: 2a1. Systém vrátí údaje k oprav¥ a zobrazí seznam chyb.
5.1.6.9 Upravit kategorii zboºí Rozsah: aplikace elektronického obchodu Úrove¬: uºivatelský cíl Primární aktér: Prodejce P°edpoklady: Prodejce je p°ihlá²en do systému. Hlavní úsp¥²ný scéná°: 1. Prodejce vybere kategorii zboºí, kterou chce upravit. 2. Systém zobrazí údaje o kategorii v editovatelné podob¥. Zobrazí: - jméno kategorie - rodi£ovskou kategorii 3. Prodejce upraví údaje o kategorii. 4. Systém zvaliduje zadané údaje. 5. Systém uloºí zm¥ny a zobrazí potvrzení.
Roz²í°ení: ∗a.
Systém detekuje interní chybu znemoº¬ující pokra£ování:
∗a1.
Systém zobrazí zprávu o chyb¥, obsahující její p°í£inu. Zapí²e podrobnou zprávu do logu.
3a. Prodejce chce kategorii smazat:
26
KAPITOLA 5.
ANALÝZA
3a1. Prodejce zvolí moºnost smazání kategorie. 3a2. Systém smaºe kategorii. 4a. Systém detekuje chyb¥jící jméno kategorie nebo je jako rodi£ovská kategorie zvolena kategorie sama: 4a1. Systém vrátí údaje k oprav¥ a zobrazí seznam chyb.
5.1.6.10 Naskladnit zboºí Rozsah: aplikace elektronického obchodu Úrove¬: uºivatelský cíl Primární aktér: Prodejce P°edpoklady: Prodejce je p°ihlá²en do systému. Hlavní úsp¥²ný scéná°: 1. Prodejce zvolí moºnost naskladnit zboºí. 2. Systém zobrazí seznam zboºí v katalogu. 3. Prodejce vybere zboºí, které chce naskladnit a zadá mnoºství. 4. Systém zvý²í evidované mnoºství o mnoºství zadané prodejcem a zobrazí potvrzení.
Roz²í°ení: ∗a.
Systém detekuje interní chybu znemoº¬ující pokra£ování:
∗a1.
Systém zobrazí zprávu o chyb¥, obsahující její p°í£inu. Zapí²e podrobnou zprávu do logu.
3a. Systém zjistí, ºe zadané mnoºství je záporné, nula, nebo není £íslo: 3a1. Systém vrátí údaje k oprav¥ a zobrazí chybu.
5.1.7
Analýza nefunk£ních poºadavk·
Usability
Jelikoº se práce pouºitelností ani návrhem uºivatelského rozhraní nezabývá,
nemá p°íli² smysl denovat poºadavky tohoto typu. P°íkladem poºadavku z této kategorie by mohlo být Rozhraní aplikace bude spl¬ovat zásady p°ístupnosti webových stránek pro t¥ºce zrakov¥ postiºené uºivatele Blind Friendly Web 2.3 nebo V²echna menu v uºivatelském rozhraní budou sou£asn¥ zobrazovat nejvý²e 10 poloºek.
Reliabilitym, Performance
Vzhledem k tomu, ºe v rámci práce se ne°e²í nasazení ap-
likace a její podpora, chybí zde kontext, do kterého by byly zasazeny poºadavky na spolehlivost.
Supportability
•
Aplikace bude snadno lokalizovatelná do dal²ích jazyk·.
Ostatní •
Aplikace bude implementována v Jazyce Java.
•
Aplikace bude postavena na frameworku Spring.
•
Aplikace nebude vyºadovat k b¥hu EJB kontejner.
•
Aplikaci bude moºné provozovat v rámci aplika£ního serveru s volnou licencí.
5.1.
27
ANALÝZA POADAVK
5.1.8
Doménový model
UML diagram na obrázku 5.2 zachycuje významné koncepty z domény elektronického obchodování. Vznikal na improvizované tabuli a byl postupn¥ zjem¬ován aº do aktuální podoby. Zám¥rn¥ neobsahuje atributy, které jsou z°ejmé, nap°íklad atributy u t°ídy Adresa. Model domény je uºite£ný zejména tehdy, pokud jej lze pouºít jako vizuální pom·cku pro pochopení vztah· mezi významnými koncepty z problémové domény. Z tohoto d·vodu by nem¥l být zbyte£n¥ detailní. Jednotlivé koncepty lze podrobn¥ji popsat a vysv¥tlit ve slovní£ku pojm·.
nachází se v > 1..*
Stav název
1
Osoba
1
jméno 0..*
Dodavatel Objednávka
zadal > 1
obsahuje >
< dodává 1
1
0..*
0..*
0..*
Adresa
Položka 0..*
množství
Role
0..*
1
cena název popis
náleží do > 0..*
1
0..* vztahuje se na
1
Zákazník
0..* Sleva
1
míra 1 < patří
Obrázek 5.2: Model problémové domény
0..* vztahuje se na 0..* Daň název sazba
Kategorie
0..* název
Košík obsahuje >
Prodejce
Produkt
reprezentuje >
0..*
název
jméno
28
KAPITOLA 5.
ANALÝZA
Kapitola 6
Návrh 6.1
Výb¥r modul· frameworku Spring
Protoºe aplikace má mít webové rozhraní, pouºil jsem modul Spring MVC. S perzistentním frameworkem jsem zpo£átku pracoval p°ímo, pozd¥ji jsem vyuºil modulu Spring ORM. Modul Spring TX jsem vyuºil pro vymezení transakcí na úrovni perzistentní vrstvy pro zaji²´ení atomicity n¥kterých metod. V prezenta£ní vrstv¥ je dále vyuºita knihovna Spring Modules pro validaci objekt·, reprezentujících uºivatelem vypln¥né formulá°e.
6.2
Výb¥r vhodného persistentního frameworku
P°i výb¥ru perzistentního frameworku jsem se rozhodoval mezi pouºitím JPA a frameworku Hibernate. Framework JDO jsem zavrhl pro jeho nízkou roz²í°enost a tedy men²í dostupnost podpory (tutoriály, diskuzní fóra). Spring nabízí stejné moºnosti integrace pro JPA i Hibernate (skrze modul ORM), pro JPA jsem se nakonec rozhodl pouze z toho d·vodu, ºe jsem se s touto technologií jiº d°íve setkal. Jako implementaci JPA (tzv.
persistence provider ) jsem
pouºil Hibernate, nicmén¥ výb¥r implementace JPA není z hlediska návrhu podstatný. Pozd¥ji b¥hem vývoje aplikace jsem se dozv¥d¥l o frameworku iBatis, který m¥ velmi zaujal pro jeho jednoduchost a míru kontroly, kterou programátorovi nabízí. V této fázi se mi ale uº necht¥lo perzistentní framework m¥nit, protoºe jsem strávil nezanedbatelné mnoºství £asu zkoumáním n¥kterých aspekt· JPA (zejména Lazy loadingu) a obával jsem se, ºe bych se pouºití frameworku iBatis také neobe²lo zcela bez komplikací.
6.3
Návrh architektury aplikace
Základní £len¥ní aplikace je realizováno pomocí
6.3.1
vrstev.
Vrstvy (Layers)
Velmi roz²í°enou technikou pro uspo°ádání sloºitého systému nebo aplikace je rozd¥lení do vrstev. N¥které zdroje uvád¥jí rozd¥lení do vrstev jako techniku [Fow03], jiné zmi¬ují vrstvy
29
30
KAPITOLA 6.
NÁVRH
+
jako konkrétní architektonický vzor [BMR 98]. Nejznám¥j²ím p°íkladem rozd¥lení do vrstev je z°ejm¥ protokolový stack TCP/IP z oblasti po£íta£ových sítí. Podstatou vrstvené architektury je hrubé rozd¥lení aplikace na n¥kolik £ástí, podsystém·, kde prvky kaºdé £ásti mají spole£nou odpov¥dnost za n¥kterou z hlavních funkcí (nap°. p°ístup k dat·m nebo uºivatelské rozhraní). Vrstvy si lze p°edstavit jako patra budovy, vrstvy jsou logicky umíst¥né jedna na druhé. P°edstava vertikálního uspo°ádání vrstev umoº¬uje snadno pochopit vzájemnou závislost vrstev na sob¥. Vrstva vºdy vyuºívá sluºeb vrstvy pod sebou, ale neví nic o vrstv¥ nad sebou. asto vrstva skrývá vrstv¥ nad sebou p°ítomnost niº²ích vrstev, v takovém p°ípad¥ mluvíme o striktní vrstvené architektu°e. Pokud vrstva m·ºe p°ímo volat sluºby i jiných niº²ích vrstev, neº je vrstva bezprost°edn¥ pod ní, mluvíme o relaxované vrstvené architektu°e. [Lar05] V informa£ních systémech se typicky vyskytují t°i základní vrstvy: prezenta£ní vrstva, doménová vrstva a vrstva pro p°ístup k dat·m. asto se tedy hovo°í o
t°ívrstvé architektu°e.
Prezenta£ní vrstva zprost°edkovává sluºby aplikace uºivatel·m, poskytuje tedy uºivatelské rozhraní aplikace. Doménová vrstva obsahuje vlastní logiku aplikace, která se týká problémové domény (tzv. business logika nebo doménová logika). Typicky jde o n¥jakou formu manipulace s daty (výpo£et úroku, zji²t¥ní aktuálního stavu na ú£tu a podobn¥). Uºivatel vyuºívá funkcionalitu této vrstvy nep°ímo p°es uºivatelské rozhraní v prezenta£ní vrstv¥.
integra£ní nebo perzistentní vrstva (pojem perzistentní vrstva nazna£uje spí²e manipulaci s daty v trvalém úloºi²ti
Poslední vrstvou je vrstva pro p°ístup k dat·m, ozna£ovaná také jako
jako je databáze, zatímco pojem integra£ní vrstva evokuje dal²í moºné zdroje dat, nap°íklad jiné aplikace). Tato vrstva nezahrnuje samotné úloºi²t¥ dat, pouze obsahuje logiku pro manipulaci s daty v tomto úloºi²ti. Základní výhodou vrstvené architektury je nízká vzájemná závislost vrstev. Pokud jsou vrstvy striktn¥ odd¥leny, je moºné nahradit implementaci jedné vrstvy jinou bez toho, aby musely být ostatní vrstvy modikovány. Takto lze nap°íklad zm¥nit zp·sob ukládání dat nebo vym¥nit uºivatelské rozhraní typu rich client (nap°. Java Swing API) za webové rozhraní. P°estoºe vrstvy mají mezi sebou omezenou závislost, nedokáºí kompletn¥ zamezit propagaci zm¥n po aplikaci. Pokud se má p°idat do aplikace nová funkce, musí se £asto p°idat nový kód do v²ech vrstev. Zm¥nu musí reektovat uºivatelské rozhraní, doménová logika a £asto i vrstva pro p°ístup k dat·m. Dal²í nevýhodou vrstev je zvý²ená reºie zp·sobená voláním jednotlivých vrstev mezi sebou, coº o n¥co sniºuje výkon aplikace. Ve v¥t²in¥ p°ípad· ale pozitiva vrstvené architektury p°evaºují nad jejími nevýhodami.
6.4
Prezenta£ní vrstva
Prezenta£ní vrstva je zaloºena na modulu Spring MVC a s ním souvisejících modul· frameworku Spring. Spring MVC implementuje architektonický vzor Model-View-Controller.
6.4.1
Vzor Model-View-Controller
Podstatou vzoru MVC je rozd¥lení odpov¥dností uºivatelského rozhraní do t°í rolí:
view
a
controller.
model,
6.4.
31
PREZENTANÍ VRSTVA
Prezentační vrstva
View
Controller
Doménová vrstva Model
Integrační vrstva
Obrázek 6.1: Vzor MVC v kontextu t°ívrstvé architektury
6.4.1.1 Model Model zapouzd°uje data a chování aplikace související s její doménou. Neobsahuje data samotného uºivatelského rozhraní (velikost okna, barva pozadí), ani chování uºivatelského rozhraní (obsluha stisku tla£ítka, zpracování HTTP poºadavku). V kontextu vrstvené architektury je model objektem z doménové vrstvy. Podstatné pro správné pochopení vzoru MVC je, ºe model nezapouzd°uje pouze data aplikace, ale také aplika£ní logiku.
6.4.1.2 View View p°edstavuje pohled na model (zobrazení modelu) v uºivatelském rozhraní. P°íkladem m·ºe být tabulka v HTML dokumentu nebo komponenta knihovny Swing, zobrazující údaje o osob¥. Pohled· (view) na jeden model m·ºe být n¥kolik, r·zné pohledy mohou nap°íklad zobrazovat stejná data jiným zp·sobem.
6.4.1.3 Controller Controller obsluhuje vstup od uºivatele. V reakci na vstup od uºivatele controller provede zm¥ny pohledu (nap°. situace, kdy uºivatel zm¥ní kritérium pro °azení dat v tabulce) nebo zm¥ny modelu - typicky pomocí delegace zodpov¥dnosti na model (p°íklad - uºivatel stiskne
32
KAPITOLA 6.
NÁVRH
tla£ítko pro smazání uºivatele, controller událost zachytí a zavolá odpovídající metodu modelu, která implementuje mazání uºivatel·). Controller také zaji²´uje aktualizaci pohledu po provedení zm¥n.
6.4.1.4 Vzájemná interakce ásti view a controller jsou závislé na modelu. View získává z objekt· modelu data, která sám zobrazuje. Controller na model deleguje volání sluºeb. Controller je také závislý na view, protoºe s ním manipuluje. Model by ideáln¥ nem¥l v¥d¥t o existenci controlleru ani view. Je ale pot°eba, aby model mohl n¥jakým zp·sobem oznámit view, ºe má obnovit pohled na model, protoºe do²lo k zm¥n¥ dat a pohled view na model je neaktuální. (P°íkladem m·ºe být situace, kdy uºivatel má otev°en souborový manaºer opera£ního systému, v n¥m má otev°en pohled na adresá° a v jiné aplikaci vytvo°í v tomto adresá°i nový soubor.) Stejná situace m·ºe nastat ve vztahu model-controller a to v p°ípad¥, kdy chování controlleru n¥jakým zp·sobem závisí na stavu modelu. (P°íkladem mohou být dva typy controlleru pro jeden view jeden umoº¬uje editaci, druhý je pouze pro £tení a informace o tom, zda je editace povolena, je uloºena v modelu.) V b¥ºn¥ pouºívaných objektov¥-orientovaných jazycích (Java, C++) je tento problém °e²en pomocí návrhového vzoru
+
Observer.
Jeho souvislost se vzorem MVC
ilustruje obrázek 6.2. [BMR 98]
0..*
calls update >
«interface» Observer «realize» update() «realize»
Model data 1 observers
View
notifyObservers() register(o : Observer) 1 detach(o : Observer) getData() service() 1
< gets data
model 1 controller
Controller 1
< manipulates display
update() adjustDisplay() display()
1 model view update() handleEvent()1
< calls service
+
Obrázek 6.2: Interakce jednotlivých rolí ve vzoru MVC [BMR 98]
6.4.1.5 Souvislost s vzorem Observer Vzor Observer umoº¬uje, aby model závisel pouze na rozhraní (Observer), které p°edepisuje abstraktní metodu pro aktualizaci (update). V kontextu vzoru MVC tuto metodu imple-
6.5.
33
DOMÉNOVÁ VRSTVA
mentuje view a p°ípadn¥ controller. Zdroj událostí (zde model) drºí seznam ukazatel· na typ Observer a v p°ípad¥ zm¥ny svého stavu zavolá na v²ech Observerech ze svého seznamu metodu update. Pro registraci a odhla²ování observer· musí mít zdroj událostí p°íslu²né dv¥ metody. Vyuºití vzoru Observer sniºuje závislost modelu na view a controlleru na rozumnou míru, je pouze pot°eba p°idat do modelu dv¥ ve°ejné metody, které mají jako parametr rozhraní. U aplikací s webovým rozhraním problém aktualizace view z modelu zcela odpadá. Protokol HTTP neumoº¬uje, aby aplikace na serveru volala webový prohlíºe£ klienta, m·ºe pouze zasílat odpov¥di na jeho dotazy. Server si tedy nem·ºe vynutit aktualizaci view na klientovi, coº moºnosti webového uºivatelského rozhraní pom¥rn¥ omezuje. Tento problém °e²í technologie
AJAX
Periodic Refresh ) HTTP Streaming ).
pomocí periodických dotaz· z klienta na server (
nebo podrºením otev°eného HTTP spojení na server ze strany klienta ( Technologií AJAX se tato práce nezabývá.
6.5
Doménová vrstva
Logika v doménové vrstva je uspo°ádána podle vzoru
Transak£ní skript (Transaction script ).
Jednotlivé t°ídy s transak£ními skripty pracují s daty v doménových objektech. Doménové objekty slouºí pro reprezentaci dat a mají pouze metody pro manipulaci s jejich atributy.
6.5.1
Vzor Transak£ní skript (Transaction script)
Transak£ní skript je jeden ze vzor· pro organizaci doménové logiky které popisuje [Fow03]. Kaºdý transak£ní skript odpovídá jedné akci, kterou m·ºe uºivatel na aplikaci vyvolat. Na rozdíl od vzoru
Doménový model,
kde se zpracování poºadavku realizuje skládáním
díl£ích zodpov¥dností jednotlivých doménových objekt· a díl£í zodpov¥dnosti objekt· jsou znovupouºitelné, kaºdý transak£ní skript zpracovává sám jeden typ poºadavku. Znovupouºitelnosti lze u transak£ního skriptu do jisté míry dosáhnout vy£len¥ním podobného kódu do spole£né metody, kterou budou vyuºívat více transak£ních skript·. Transak£ní skripty lze sdruºovat do t°íd podle podobnosti zodpov¥dností (nap°. t°ída OrderService s metodami makeOrder, combineOrders, cancelOrder atd.) Výhodou transak£ního skriptu je snadné vymezení transakcí. Logika v jednom transak£ním skriptu typicky odpovídá jedné transakci, transakci lze tedy zahájit na za£átku metody transak£ního skriptu a ukon£it ji na jejím konci. Odtud také pochází název tohoto vzoru. Dal²í výhodou tohoto vzoru je jeho jednoduchost. Rozd¥lení zodpov¥dností mezi transak£ní skripty je výrazn¥ snaº²í, neº správné p°i°azení zodpov¥dností jednotlivým kooperujícím doménovým objekt·m. Zásadní nevýhoda tohoto p°ístupu se projeví s rostoucí sloºitostí aplikace. U aplikace se sloºitou doménovou logikou je obtíºné vyhnout se duplicitám v jednotlivých transak£ních skriptech. Moºnosti tohoto vzoru jsou v tomto sm¥ru omezené, zásadn¥j²í snahy o refaktorování duplicit d°íve nebo pozd¥ji povedou na p°echod k rozd¥lení zodpov¥dností mezi kooperující objekty, coº v podstat¥ znamená p°echod na vzor Doménový model.
34
KAPITOLA 6.
6.5.2
NÁVRH
Vzor Doménový model (Domain Model)
Vzor Doménový model spo£ívá v rozd¥lení doménové logiky aplikace na díl£í zodpov¥dnosti jednotlivým objekt·m, které odpovídají významným koncept·m z modelované domény (odpovídají t°ídám zji²t¥ným p°i pouºití objektov¥-orientované analýzy). Podstatné na tomto vzoru je, ºe doménové objekty nesou krom¥ dat z modelované domény také chování, nejsou to pouze obálky na atributy. Jak jiº bylo zmín¥no, jednotlivé objekty spolupracují za ú£elem zpracování poºadavku (typicky z vy²²í vrstvy). [Fow03] zmi¬uje dva typy Doménového modelu: jednodu²²í, kdy kaºdý doménový objekt odpovídá jedné tabulce v databázi, a sloºit¥j²í, u kterého je v doménovém modelu °ada dal²ích t°íd, které jsou pouºity nap°íklad pro implementaci návrhových (GoF) vzor·, pouºívá se d¥di£nost a celkov¥ je mapování na databázi sloºit¥j²í, neº v prvním p°ípad¥. Výhodou pouºití vzoru Doménový model je, ºe takto strukturovaný kód doménové vrstvy lze snadno znovupouºívat p°i implementaci nové funkcionality. Proto je vhodný pro aplikace s rozsáhlou doménovou vrstvou. U aplikací s jednoduchou doménovou logikou se jeho výhody p°íli² neprojeví. [Fow03] Správná aplikace tohoto vzoru vyºaduje dobrou schopnost objektového návrhu um¥t správn¥ p°i°azovat odpov¥dnosti objekt·m. patn¥ navrºená doménová vrstva snadno ztratí v¥t²inu výhod tohoto vzoru, ale ponechá si v²echna negativa. Jedním z negativ je sloºit¥j²í mapování na tabulky rela£ní databáze. Pro mapování se v poslední dob¥ velmi £asto pouºívají hotové nástroje perzistentní frameworky. Ty dokáºí vy°e²it velkou £ást problém· spojených s mapováním objekt· Doménového modelu, vzhledem ke sloºitosti objektov¥-rela£ního mapování se ale p°i jejich pouºití mohou objevit problémy nové, nap°íklad obtíºná optimalizace dotaz· do rela£ní databáze.
Obrázek 6.3: Vzor Transak£ní skript [Fow03]
Na obrázcích 6.3 a 6.4 je ilustrován rozdíl mezi Transak£ním skriptem a Doménovým modelem. V p°ípad¥ Transak£ního skriptu zpracovává poºadavek objekt Recognition Service a jediný dal²í objekt, se kterým p°i tom spolupracuje, je objekt pro p°ístup do databáze (Data Gateway). Od toho získá pot°ebná data, s nimi sám manipuluje a výsledek p°edá
6.6.
35
INTEGRANÍ VRSTVA
objektu Data Gateway, aby jej op¥t uloºil do databáze.
Obrázek 6.4: Vzor Doménový model [Fow03]
Na diagramu 6.4 je vid¥t kooperace objekt· Doménového modelu. Za zpracování poºadavku odpovídá objekt Contract, který tuto zodpov¥dnost £áste£n¥ deleguje na objekt Product. Objekt Product op¥t p°edá °ízení objektu Recognition Strategy (jedná se o implementaci návrhového GoF vzoru Strategy). Objekt Strategy vrací jako výsledek op¥t doménový objekt a ten je postupn¥ op¥t vrácen objektu Contract.
6.5.3
Volba vzoru pro £len¥ní doménové logiky
V aplikaci zpracovávané v rámci této práce p°evaºují v doménové logice CRUD operace. Jedná se o £ty°i základní operace s daty vytvo°ení (Create), vyzvednutí dat (Retrieve), aktualizace (Update) a smazání (Delete). Tyto operace nevedou na sloºitou doménovou logiku a z tohoto d·vodu jsem se rozhodl pouºít vzor Transak£ní skript. V doménové vrstv¥ se dále vyskytují doménové objekty, které obsahují pouze metody pro manipulaci s jejich atributy a jsou pomocí perzistentního frameworku specikace JPA mapovány na tabulky databáze. Tyto jednotlivé objekty odpovídají jednotlivým tabulkám databáze. S postupným roz²i°ováním aplikace se za£aly vyskytovat v kódu duplicity, které byly vy°e²eny tím, ºe n¥které objekty transak£ních skript· (nap°. t°ída OrderService) pouºívají jednodu²²í transak£ní skripty v jiných objektech (nap°. t°ída UserService a její metoda getCustomerRoleForUser). V sou£asné podob¥ toto nep°edstavuje velký problém, pozornost by si zasluhoval spí²e kód v controllerech v prezenta£ní vrstv¥, který se ukazuje jako náchylný k duplicitám. Nelze ale vylou£it, ºe se p°i dal²ím roz²i°ování aplikace volba vzoru Transak£ní skript ukáºe jako nevhodná.
6.6
Integra£ní vrstva
Integra£ní vrstva vyuºívá pro komunikaci s rela£ní databází Java Persistence API. Rozhraní integra£ní vrstvy je denováno pomocí vzoru
Data access object (DAO). To zaji²´uje nezávis-
36
KAPITOLA 6.
NÁVRH
lost doménové vrstvy na pouºité perzistentní technologii. Technologii JPA by bylo moºné vym¥nit nap°íklad za framework iBatis beze zm¥n v doménové vrstv¥.
6.6.1
Vzor Data access object (DAO)
Vzor Data access object denuje rozhraní pro p°ístup k perzistentnímu úloºi²ti. Kód psaný proti tomuto rozhraní není závislý na konkrétní implementaci. Rozhraní jednotlivých DAO t°íd obsahuje typicky pouze metody typu CRUD. V p°ípad¥, ºe úloºi²t¥ dat neumoº¬uje p°ímé ukládání objekt· (objektová databáze), musí t°ída implementující p°edepsané DAO rozhraní provád¥t mapování z objekt· na neobjektové úloºi²t¥.
«interface» UserDAO create(person : User) : void findById(personId : Long) : User findByLogin(login : String) : User findAll() : Collection<User> update(person : User) : void delete(personId : Long) : void
Obrázek 6.5: Rozhraní UserDAO
Sekven£ní diagram na obrázku 6.6 nazna£uje zp·sob pouºití DAO t°ídy. Objekt z doménové vrstvy zde volá na objektu implementujícím rozhraní DAO t°ídy (dále DAO objekt) metodu pro získání dat. Ten vyzvedne data z datového úloºi²t¥ a vytvo°í objekt, do kterého data uloºí. Tímto objektem m·ºe být instance t°ídy z doménové vrstvy nebo objekt ur£ený pouze k p°esunu dat mezi vrstvami. Objekt doménové vrstvy poté m·ºe s objektem reprezentující data v úloºi²ti manipulovat a následn¥ jej op¥t p°edat DAO objektu do integra£ní vrstvy, aby jej znovu uloºil (provedl jeho aktualizaci v úloºi²ti), jak nazna£uje diagram. Vzor Data access object odpovídá obecn¥j²ímu Fowlerovu vzoru
6.6.2
Gateway. [Fow03]
Interakce integra£ní vrstvy s doménovou vrstvou
Rozhodl jsem se v integra£ní vrstv¥ pro p°ístup, kdy jednotlivé metody DAO t°íd p°ijímají a vrací doménové objekty z doménové vrstvy. To má za následek v¥t²í provázanost t¥chto vrstev, coº je z hlediska návrhu tém¥° vºdy neºádoucí. Pokud ale vezmeme v potaz fakt, ºe není pravd¥podobné, ºe by se integra£ní vrstva dala jako celek znovupouºít, pak se tato nevýhoda nejeví jako zásadní. Výhodou je naopak niº²í sloºitost aplikace, protoºe kaºdá vrstva nezavádí vlastní sadu objekt· pro stejné doménové koncepty. Doménové objekty jsou v integra£ní vrstv¥ mapovány jedna ku jedné na tabulky v databázi pomocí Java Persistence API. Mapované doménové objekty jsou také vyuºívány view komponentami v prezenta£ní vrstv¥ jako zdroj dat pro zobrazování. Zatím tento zp·sob nep°iná²í problémy, ale je t°eba si p°iznat, ºe £istý návrh by m¥l mít d·kladn¥j²í odd¥lení zodpov¥dností.
6.7.
37
PODROBN
JÍ NÁVRH JEDNOTLIVÝCH VRSTEV
Obrázek 6.6: Pouºití DAO t°ídy [java]
6.7
6.7.1
Podrobn¥j²í návrh jednotlivých vrstev
Prezenta£ní vrstva
6.7.1.1 ivotní cyklus poºadavku Pro popis rozd¥lení zodpov¥dností v prezenta£ní vrstv¥ je nutné p°iblíºit, jak pracuje modul Spring MVC, kolem kterého je prezenta£ní vrstva vystav¥na. Tento modul p°edstavuje webový framework a je tedy zaloºen na modelu komunikace
request-response
protokolu HTTP.
Obrázek 6.7 ilustruje posloupnost událostí p°i zpracování poºadavku. [Spring Recipes] Centrálním prvkem Springu MVC je t°ída DispatcherServlet. Ta implementuje vzor
Controller
Front
[Fow03], který spo£ívá v tom, ºe v²echny poºadavky od klient· proudí do aplikace
p°es jeden objekt Front Controller. Ten rozhoduje, kterému konkrétnímu controlleru se má vy°ízení poºadavku p°edat, ale je²t¥ p°edtím m·ºe nad poºadavkem vykonat sám n¥jakou logiku, která je spole£ná pro v²echny controllery. Po p°ijetí poºadavku DispatcherServlet vybere odpovídající controller (ve Spring MVC t°ída, implementující rozhraní Controller). Pro výb¥r se pouºije mapování poºadavk· na Controllery. To je denováno pomocí t°ídy, implementující rozhraní HandlerMapping. Spring
38
KAPITOLA 6.
NÁVRH
Obrázek 6.7: Zpracování HTTP poºadavku frameworkem Spring MVC [Mak08]
MVC poskytuje n¥kolik implementací tohoto rozhraní, které nabízejí odli²né zp·soby mapování. Pokud pro poºadavek DispatcherServlet najde odpovídající Controller, p°edá mu poºadavek. Controller po p°ijetí poºadavku poºadavek zpracuje, p°i£emº podle vzoru MVC zodpov¥dnosti související s doménovou logikou aplikace deleguje na model. Controller po zpracování poºadavku vrátí DispatcherServletu objekt modelu a název view, který se má pouºít pro zobrazení odpov¥di. Implementaci jednotlivých controller· musí zajistit programátor. DispatcherServlet po p°ijetí modelu a názvu view vyhledá odpovídající view. K tomu vyuºije t°ídu, implementující rozhraní ViewResolver. V tomto je funkce ViewResolveru podobná funkci HandlerMappingu. Spring MVC op¥t poskytuje n¥kolik implementací rozhraní ViewResolver, které lze pouºít. Kdyº ViewResolver vrátí DispatcherServletu odpovídající view (reprezentovaný ve Spring MVC t°ídou, implementující rozhraní View), DispatcherServlet mu po²le zprávu, aby se vykreslil a p°edá mu pro tento ú£el model, který p°edtím získal od controlleru. View poté zobrazí data v modelu uºivateli. View m·ºe být realizován jako JSP stránka, nebo to m·ºe být nap°íklad objekt, který zobrazení modelu realizuje vygenerováním PDF souboru. [Mak08]
6.7.1.2 Rozd¥lení prezenta£ní vrstvy do balí£k· web. Ten je rozd¥len na balí£ky controllers, validacommandobjects, viz obrázek 6.8. Balí£ek controllers obsahuje t°ídy (con-
Prezenta£ní vrstvu p°edstavuje balí£ek
tors, typeeditors
a
trollery), které jsou odpov¥dné za zpracování poºadavk·. T°ídy v tomto balí£ku vyuºívají sluºeb t°íd v ostatních balí£cích (validators, typeeditors a commandobjects). Controllery jsou rozd¥leny podle uºivatelských rolí na balí£ky
customer
a
admin.
Balí£ek commandobjects obsahuje tzv. form objekty, ve Spring MVC také nazývané command objekty (nesouvisí nijak s návrhovým vzorem Command). Tyto objekty reprezentují
6.7.
PODROBN
JÍ NÁVRH JEDNOTLIVÝCH VRSTEV
39
web
controllers admin
validators
customer
typeeditors
commandobjects
Obrázek 6.8: Balí£ky prezenta£ní vrstvy
parametry HTTP poºadavku, m·ºe jít nap°íklad o hodnoty uºivatelem vypln¥ného formulá°e. Spring umoº¬uje jako form objekt pouºít jakýkoliv POJO objekt. Zpo£átku jsem pouºíval jako form objekty p°ímo doménové objekty z doménové vrstvy. Záhy se ale ukázalo, ºe tato technika je vhodná jenom pro extémn¥ jednoduché p°ípady a ºe doménové objekty £asto neodpovídají sad¥ dat ve formulá°ích, které se t¥chto objekt· týkají. Formulá°e £asto obsahují n¥jakou informaci navíc, která neslouºí k uloºení do doménového objektu, ale pouze pro controller. Také se vyskytly p°ípady, kdy data z formulá°e na stránce odpovídala více neº jednomu doménovému objektu. Z toho d·vodu jsem jako form objekty za£al pouºívat objekty specializované pouze pro tento ú£el. Balí£ek validators obsahuje validátory (t°ídy implementující rozhraní Validator), které umoº¬ují validovat stav objekt·. Kaºdý validátor umí validovat práv¥ jednu t°ídu. Tyto t°ídy se v aplikaci primárn¥ vyuºívají pro kontrolu formulá°· vypln¥ných uºivatelem. Balí£ek typeeditors obsahuje t°ídy, implementující rozhraní PropertyEditor. Toto rozhraní je sou£ástí Java API a slouºí k usnadn¥ní transformace objekt· (obvykle jde o doménové objekty) na textové hodnoty a zp¥t, £asto pot°ebné p°i implementaci uºivatelských rozhraní.
6.7.2
Doménová vrstva
Doménové vrstv¥ odpovídá balí£ek domain. Ten obsahuje balí£ky service, model a propertyproviders, viz obrázek 6.9. Balí£ek service obsahuje jednotlivé t°ídy transak£ních skript·. Kaºdá t°ída obsahuje metody, které se týkají jedné oblasti. Jako p°íklad je uvedeno rozhraní t°ídy UserService
40
KAPITOLA 6.
NÁVRH
domain service
propertyproviders
model
Obrázek 6.9: Balí£ky doménové vrstvy
na obrázku 6.10. Tyto t°ídy operují nad doménovými objekty z balí£ku model. P°íkladem doménového objektu je t°ída Order na obrázku 6.11.
«interface» shop::domain::service::UserService createUser(user : User) : void getUserById(userId : Long) : User findUser(user : User) : User findUserByEmail(email : String) : User findUserByLogin(login : String) : User getAllUsers() : Collection<User> updateUser(user : User) : void addCustomerRole(userLogin : String,customerPP : CustomerPropertyProvider) : void getCustomerRoleForUser(userLogin : String) : Customer addCustomerAddress(userLogin : String,address : Address) : void removeCustomerAddress(userLogin : String,addressId : Long) : void updateCustomerAddress(userLogin : String,address : Address) : void
Obrázek 6.10: T°ída transak£ních skript·
6.7.2.1 Aktualizace doménových objekt· Balí£ek propertyproviders °e²í problém s p°esunem dat mezi doménovými objekty a jim odpovídajících objekt· v jiných vrstvách. Tento problém se projevuje v prezenta£ní vrstv¥, kde je pot°eba p°id¥lit zodpov¥dnost za reprezentaci vstupu od uºivatele. Tomu odpovídá
6.7.
PODROBN
JÍ NÁVRH JEDNOTLIVÝCH VRSTEV
41
shop::domain::model::Order id : Long orderItems : Collection
shippingAddress : Address billingAddress : Address shippingMethod : ShippingMethod shippingPrice : Double currentState : OrderState states : Collection «create» Order() changeState(state : OrderState) : void getTotalPrice() : Double getBillingAddress() : Address setBillingAddress(billingAddress : Address) : void getId() : Long setId(id : Long) : void getOrderItems() : Collection setOrderItems(orderItems : Collection) : void getShippingAddress() : Address setShippingAddress(shippingAddress : Address) : void getShippingMethod() : ShippingMethod setShippingMethod(shippingMethod : ShippingMethod) : void getShippingPrice() : Double setShippingPrice(shippingPrice : Double) : void getCurrentState() : OrderState setCurrentState(currentState : OrderState) : void getStates() : Collection setStates(states : Collection) : void
Obrázek 6.11: Doménový objekt
ve Springu MVC role command objektu a m·ºe jím být libovolná POJO t°ída. Jak jiº bylo diskutováno, objekty z doménové vrstvy jsou pro tento ú£el nevhodné. Nejjednodu²²í °e²ení je zavést specializovanou t°ídu pro reprezentaci dat z formulá°e. Framework objekt této t°ídy (dále command objekt) p°edá do controlleru a ten pot°ebuje takto získaná data p°edat doménové vrstv¥. Nechceme, aby doménová vrstva byla závislá na prezenta£ní vrstv¥, proto do ní command objekt nem·ºeme p°edávat p°ímo. Je pot°eba p°evést command objekt na odpovídající objekt doménové vrstvy uº v prezenta£ní vrstv¥.
6.7.2.2 e²ení typu pull len vývojového týmu frameworku Spring Colin Yates navrhuje °e²ení v podob¥ rozhraní, reprezentujících aktualizaci (zm¥nu) objektu. Tyto rozhraní denují getter pro kaºdou prom¥nnou doménového objektu, který má být m¥nitelný. Rozhraní pojmenovává jako RequestToEdit nebo PropertyProvider. [Yat] P°íklad rozhraní pro zm¥ny doménového objektu Product:
42
KAPITOLA 6.
package
NÁVRH
shop . domain . p r o p e r t y p r o v i d e r s ;
interface public public public public public public
ProductPropertyProvider Boolean
{
getActive () ;
C o l l e c t i o n String
getDescription () ;
String
getName ( ) ;
Double
getSalePrice () ;
C o l l e c t i o n
getCategories () ;
getRelatedProducts () ;
}
Listing 6.1: Rozhraní ProductPropertyProvider, °e²ení typu pull T°ída doménového objektu musí mít metodu, která jako parametr p°ijímá objekt typu ProductPropertyProvider, podle kterého zm¥ní sv·j stav.
package
shop . domain . model ;
class
Product
{
...
void
update (
ProductPropertyProvider
pp
)
{
... } }
Listing 6.2: T°ída Product, °e²ení typu pull T°ída v prezenta£ní vrstv¥, jejíº instance se pouºije jako command objekt pro reprezentaci formulá°e, bude implementovat odpovídající rozhraní PropertyProvider.
package
s h o p . web . c o m m a n d o b j e c t s ;
c l a s s ProductCommand implements P r o d u c t P r o p e r t y P r o v i d e r private Boolean a c t i v e ; p r i v a t e S t r i n g name ; private String d e s c r i p t i o n ; p r i v a t e Double s a l e P r i c e ; p r i v a t e C o l l e c t i o n
c a t e g o r i e s ; p r i v a t e C o l l e c t i o n
r e l a t e d P r o d u c t s ; public
ProductCommand ( )
categories
=
new
relatedProducts
=
{
A r r a y L i s t
() ;
new
A r r a y L i s t
() ;
}
/∗ g e t t e r y a s e t t e r y ∗/
public Boolean g e t A c t i v e ( ) return a c t i v e ; }
{
{
6.7.
43
PODROBN
JÍ NÁVRH JEDNOTLIVÝCH VRSTEV
public void s e t A c t i v e ( Boolean this . active = active ;
active
)
{
} ... }
Listing 6.3: T°ída ProductCommand, °e²ení typu pull Jedno rozhraní typu PropertyProvider m·ºe být samoz°ejm¥ implementováno více t°ídami. Implementující t°ída navíc m·ºe mít více dvojic getter/setter pro reprezentaci dal²ích parametr· poºadavku. Toho lze vyuºít v p°ípad¥, ºe formulá° svázaný s command objektem má poloºky navíc, které typicky slouºí jako informace pro controller (p°íkladem m·ºe být checkbox pro odsouhlasení registra£ních podmínek). Velkou výhodou tohoto p°ístupu pro aktualizace doménových objekt· je, ºe nenutí doménové objekty zp°ístup¬ovat svojí vnit°ní reprezentaci poskytnutím setter·.
6.7.2.3 Modikace pull °e²ení asto nastává situace, kdy command objekt v prezenta£ní vrstv¥ p°edstavuje zm¥nu jenom £ásti z atribut· doménového objektu a se zbytkem atribut· v·bec nepracuje. Stále ale musí implementovat v²echny metody odpovídajícího rozhraní PropertyProvider. Nejd°íve jsem toto omezení obe²el tak, ºe metody v implementující t°íd¥, které nem¥ly hodnotu k vrácení, vracely null. To ale zna£n¥ zkomplikovalo metodu update na doménových objektech, které musely u kaºdé návratové hodnoty zji²´ovat, zda není null.
package class
shop . domain . model ;
Product
{
...
public void Boolean
if
(
update (
ProductPropertyProvider
pp
)
{
n e w A c t i v e = pp . g e t A c t i v e ( ) ;
newActive
active
null
!=
)
{
= newActive ;
} C o l l e c t i o n
if
(
newCategories
categories
=
null
!=
newCategories )
= pp . g e t C a t e g o r i e s ( ) ;
{
newCategories ;
} String
if
(
newDescription
newDescription
description
=
= pp . g e t D e s c r i p t i o n ( ) ;
!=
null
)
{
newDescription ;
} String
if
(
newName = pp . getName ( ) ;
newName
!=
null
)
{
name = newName ; } Double
newSalePrice
= pp . g e t S a l e P r i c e ( ) ;
44
KAPITOLA 6.
if
(
newSalePrice
salePrice
=
!=
null
)
NÁVRH
{
newSalePrice ;
} C o l l e c t i o n
n e w R e l a t e d P r o d u c t s = pp . g e t R e l a t e d P r o d u c t s ( ) ;
if
(
newRelatedProducts
relatedProducts
null
!=
)
{
= newRelatedProducts ;
} } ... }
Listing 6.4: T°ída Product, metoda update Toto °e²ení umoº¬uje, aby objekt typu PropertyProvider m¥l mén¥ atribut·, neº má doménový objekt, který aktualizuje. Vznikl ale nový problém. N¥které view komponenty knihovny tag· HTML formulá°· ve Spring MVC pouºívají null jako hodnotu nap°íklad tehdy, kdyº uºivatel neza²krtne v HTML formulá°i ani jedno polí£ko elementu radiobutton. Doménový objekt v metod¥ update ale hodnoty null ignoruje a proto n¥které zm¥ny hodnot neprob¥hnou.
6.7.2.4 e²ení typu push V dal²í fázi jsem se rozhodl p°evést zodpov¥dnost za aktualizaci doménového objektu na objekty jiných vrstev. Rozhraní PropertyProvider se zjednodu²²í na jednu metodu update.
package
shop . domain . p r o p e r t y p r o v i d e r s ;
public interface public void
ProductPropertyProvider
update (
Product
product
{
) ;
}
Listing 6.5: Rozhraní ProductPropertyProvider, °e²ení typu push Doménový objekt místo metody update musí umoºnit p°ístup ke svým atribut·m pomocí setter·. Objekt nesoucí data pro aktualizaci v metod¥ update (command objekt) zavolá pouze ty settery, které je schopen zm¥nit.
package
s h o p . web . c o m m a n d o b j e c t s ;
public class
ProductCommand
implements
ProductPropertyProvider
...
public void
update (
Product
product . setActive (
active
product . s et C at eg o ri e s (
product
...
{
) ;
categories
product . setRelatedProducts ( }
)
) ;
relatedProducts
) ;
{
6.7.
45
PODROBN
JÍ NÁVRH JEDNOTLIVÝCH VRSTEV
}
Listing 6.6: T°ída ProductCommand, °e²ení typu push Toto °e²ení je odolné v·£i pouºívání null ve významu platné hodnoty. Jeho zásadní nevýhodou je, ºe nutí doménové objekty zp°ístupnit svoji vnit°ní reprezentaci.
6.7.2.5 Dal²í varianta °e²ení typu pull První variantu typu pull by bylo moºné p°epracovat tak, aby doménový objekt v metod¥ update nekontroloval návratové hodnoty na null. Nabízí se dv¥ moºné °e²ení: místo null vyhazovat vyjímku, nebo zavést v rozhraních PropertyProvider pro kaºdý getter dal²í metodu typu boolean. Tato metoda by udávala, zda t°ída v p°íslu²né getter metod¥ vrací nové hodnoty. Vyjímky by m¥ly obecn¥ signalizovat chybový stav, proto není úpln¥ vhodné je zde pouºít. Jako vhodn¥j²í se tedy jeví p°idání metod (hasActive apod.)
package
shop . domain . p r o p e r t y p r o v i d e r s ;
public interface
ProductPropertyProvider
public Boolean g e t A c t i v e ( ) ; p u b l i c boolean h a s A c t i v e ( ) ; p u b l i c C o l l e c t i o n
p u b l i c boolean h a s C a t e g o r i e s ( ) ;
{
getCategories () ;
... }
Listing 6.7: Rozhraní ProductPropertyProvdider, druhá varianta pull °e²ení
package
s h o p . web . c o m m a n d o b j e c t s ;
public class
ProductCommand
implements
ProductPropertyProvider
...
p u b l i c boolean h a s A c t i v e ( ) return f a l s e ;
{
}
public Boolean g e t A c t i v e ( ) return n u l l ;
{
}
p u b l i c boolean h a s C a t e g o r i e s ( ) return true ;
{
}
p u b l i c C o l l e c t i o n return c a t e g o r i e s ;
} ... }
getCategories ()
{
{
46
KAPITOLA 6.
NÁVRH
Listing 6.8: T°ída ProductCommand, druhá varianta pull °e²ení Doménový ubjekt v metod¥ update pomocí t¥chto metod zjistí, které svoje atributy má aktualizovat.
package class
shop . domain . model ;
Product
{
...
public void if
(
update (
ProductPropertyProvider
pp . h a s A c t i v e ( )
active
)
pp
)
{
{
= pp . g e t A c t i v e ( ) ;
}
if
(
pp . h a s C a t e g o r i e s ( )
categories
)
{
= pp . g e t C a t e g o r i e s ( ) ;
} ... } ... }
Listing 6.9: T°ída Product, druhá varianta pull °e²ení Tento zp·sob má z°ejm¥ nejmén¥ nevýhod. Stále to ale není elegantní °e²ení. Oproti °e²ení typu push je nutné napsat pom¥rn¥ velké mnoºství kódu na n¥kolika místech, pokud chceme t°íd¥ doménového objektu p°idat nový atribut. Dal²í nevýhodou je rozt°í²t¥ní zodpov¥dnosti za vrácení atributu do dvou metod. M·ºe tedy snadno dojít k nekonzistenci, pokud programátor zapomene zm¥nit ob¥ metody.
6.7.3
Integra£ní vrstva
Návrh integra£ní vrstvy je pom¥rn¥ jednoduchý. Balí£ek
dao obsahuje rozhraní jednotlivých
DAO t°íd. Tyto rozhraní obsahují metody odpovídající CRUD operacím. Ostatní balí£ky obsahují implementace rozhraní z balí£ku dao. Tyto implementující balí£ky vznikly postupn¥ t°i. P·vodní balí£ek dao.fake byl pouºíván ze za£átku vývoje a p°edstavoval fale²nou implementaci £ásti DAO t°íd pomocí t°ídy HashMap z knihovny Java Collections a n¥které metody implementoval pouze vrácením xních p°ednastavených hodnot. Balí£ek
dao.jpa
ob-
sahuje implementace DAO t°íd pomocí Java Persistence API, p°i£emº ovládání transakcí a získávání objekt· API JPA probíhá ru£n¥ v kódu. Balí£ek
dao.springJPA
obsahuje imple-
mentace DAO t°íd vyuºívající pomocných vzor· (templates) pro JPA , které nabízí modul Spring ORM. Dále vyuºívá °ízení transakcí kontejnerem, které zaji²´uje modul Spring TX. Zastaralé balí£ky by bylo moºné z projektu zcela odstranit, jejich zachování bylo nutné pouze b¥hem p°echod· mezi jednotlivými zp·soby implementace integra£ní vrstvy, které probíhaly postupn¥ a po ur£itou dobu spolu vºdy koexistovaly dva typy implementace (JPA a SpringJPA).
6.7.
47
PODROBN
JÍ NÁVRH JEDNOTLIVÝCH VRSTEV
Pro srovnání uvádím metodu create rozhraní ProductDAO implementovanou ob¥ma zp·soby. V prvním p°ípad¥ se s JPA pracuje p°ímo a transakce se vymezuje ru£n¥ voláním metod getTransaction, commit a rollback. Ve druhém p°ípad¥ je vyuºit template Spring ORM v kombinaci se Spring TX, který umoº¬uje denovat transakce deklarativn¥ pomocí anotací.
package
shop . dao . j p a ;
public class private
EntityManagerFactory
public void
create (
EntityManager
Product
ProductDAO
{
emFactory ; product
)
{
manager = emFactory . c r e a t e E n t i t y M a n a g e r ( ) ;
EntityTransaction
try
implements
JPAProductDAO
t x = manager . g e t T r a n s a c t i o n ( ) ;
{ tx . begin () ; manager . p e r s i s t (
product
) ;
t x . commit ( ) ;
}
catch
(
RuntimeException
e
)
{
tx . r o l l b a c k () ;
throw e ; finally
}
{
manager . c l o s e ( ) ; } } ...
Listing 6.10: Implementace rozhraní ProductDAO bez vyuºití Spring ORM
package
shop . dao . s p r i n g j p a ;
public class
SpringJPAProductDAO
ProductDAO
@Transactional (
public void
extends
implements
JpaDaoSupport
{ propagation
create (
Product
getJpaTemplate () . p e r s i s t (
= P r o p a g a t i o n . REQUIRED product product
)
)
{ ) ;
} ...
Listing 6.11: Implementace rozhraní ProductDAO s vyuºitím Spring ORM Do n¥kterých DAO t°íd bylo postupn¥ p°idáno n¥kolik specializovan¥j²ích metod. Nap°íklad metoda ndOrdersOfACustomer ve t°íd¥ OrderDAO, jejíº chování je v podstat¥ jiº realizováno obecn¥ji v metod¥ ndAll ve stejné t°íd¥. D·vodem pro vznik t¥chto metod je, ºe metoda pro vyhledání v²ech objednávek jednoho zákazníka implementovaná v doménové vrstv¥ by byla potenciáln¥ výpo£etn¥ náro£ná objednávek se m·ºe nahromadit v databázi velké mnoºství a tyto v²echny by se musely z databáze vyzvednout a prohledat v doménové
48
KAPITOLA 6.
NÁVRH
vrstv¥. Vyhledání objednávek lze na úrovni integra£ní vrstvy provést výrazn¥ rychleji, zejména pokud vyuºíváme rela£ní databázi. Otázkou z·stává, jestli se do rozhraní integra£ní vrstvy tímto nezaná²í implementa£ní detail (p°edpokládáme rela£ní databázi jako úloºi²t¥, p°estoºe rozhraní vrstvy by m¥lo být obecné). Lze ale p°edpokládat, ºe integra£ní vrstva bude tém¥° vºdy schopná provést tyto operace rychleji, neº doménová vrstva, nap°íklad p°i pouºití objektové databáze nebo XML databáze. B¥hem vývoje se v rozhraních n¥kterých DAO t°íd objevily jiné nedostatky týkající se zanesení implementa£ních detail·. JPA umoº¬uje uloºit do databáze naráz celý strom mapovaných objekt· (entit) p°edáním pouze ko°enového objektu (za p°edpokladu, ºe je toto chování p°edem nadenováno). Tato vlastnost je ozna£ována jako kaskádování perzistentních operací. Této vlastnosti bylo na n¥kolika místech v integra£ní vrstv¥ vyuºito, coº se projevilo tím, ºe CRUD operace s n¥kterými entitami nebyly v rozhraní integra£ní vrstvy denovány a spoléhalo se p°i jejich perzistenci na kaskádování. V¥t²ina t¥chto kaskádních operací byla pozd¥ji odstran¥na, ale £ást z nich m·ºe stále v kódu p°etrvávat.
6.8
Integrace vrstev
Zpracování jednoho poºadavku, na kterém spolupracují objekty v²ech vrstev, lze vid¥t na sekven£ním diagramu 6.12. P°i integraci jednotlivých vrstev je pot°eba uspokojit vzájemné závislosti t°íd t°ídy z vy²²ích vrstev pot°ebují reference na instance t°ídy z niº²ích vrstev. Pokud bychom ve t°íd¥, která závisí na jiné t°íd¥, poºadavnou t°ídu p°ímo vytvá°eli, byl by výsledný kód neexibilní. Nastavení jiné kongurace aplikace £asto znamená vyuºití jiné t°ídy (se stejným rozhraním) na n¥kterém míst¥ v aplikaci. Kaºdá takováto zm¥na kongurace by vyºadovala zásahy do kódu. Existuje n¥kolik vzor·, které tento problém °e²í. Jedná se o návrhové GoF vzory
Method/Abstract Factory
v kombinaci s J2EE vzorem
Service Locator.
Factory
Spring Framework
nabízí alternativu v podob¥ IoC kontejneru, který vyuºívá princip Dependency Injection. Pouºitím XML soubor· lze p°edepsat, které objekty mají být pod správou IoC kontejneru (v terminologii frameworku Spring se objekt pod správou kontejneru ozna£uje jako
bean ).
Kontejner zajistí vytvo°ení beans a podle p°edepsané kongurace vy°e²í jejich závislosti injekcí p°es setter, konstruktor nebo p°es rozhraní. Následuje p°íklad konfugrace v XML. Nejprve je denován objekt (bean) userService jako instance t°ídy UserServiceImpl, který má dostat p°es settery odkaz na instance t°íd UserDAO, userRoleDAO a addressDAO. Dále jsou denovány beans od t¥chto t°íd. Tyto beans je²t¥ vyºadují injekci objektu entityManagerFactory z Java Persistence API, op¥t pomocí metody (setteru). Na po°adí denic beans nezáleºí.
...
< bean id = " userService " class = " shop . domain . service . UserServiceImpl " > < property name = " userDAO " ref = " userDAO " / > < property name = " userRoleDAO " ref = " userRoleDAO " / > < property name = " addressDAO " ref = " addressDAO " / >
6.8.
49
INTEGRACE VRSTEV
...
< bean id = " addressDAO " class = " shop . dao . springJPA . SpringJPAAddressDAO " > < property name = " entityManagerFactory " ref = " entityManagerFactory " /> < bean id = " userDAO " class = " shop . dao . springJPA . SpringJPAUserDAO " > < property name = " entityManagerFactory " ref = " entityManagerFactory " /> < bean id = " userRoleDAO " class = " shop . dao . springJPA . SpringJPAUserRoleDAO " > < property name = " entityManagerFactory " ref = " entityManagerFactory " />
Listing 6.12: XML soubor pro konguraci IoC kontejneru Springu V jednotlivých t°ídách, jejichº instance mají být spravovány kontejnerem, je pot°eba pouze doplnit kód pro injekci, v tomto p°ípad¥ jsou pouºity setter metody. O zbytek se jiº postará IoC kontejner.
public class private private private
UserServiceImpl
AddressDAO UserDAO
implements
UserService
{
addressDAO ;
userDAO ;
UserRoleDAO
userRoleDAO ;
...
p u b l i c v o i d s e t U s e r D A O ( UserDAO t h i s . userDAO = userDAO ;
userDAO
)
{
}
p u b l i c v o i d s e t U s e r R o l e D A O ( UserRoleDAO t h i s . userRoleDAO = userRoleDAO ;
userRoleDAO
)
}
p u b l i c v o i d s e t A d d r e s s D A O ( AddressDAO t h i s . addressDAO = addressDAO ;
addressDAO
)
{
} }
Listing 6.13: T°ída vyuºívající Dependecy Injection
{
50
KAPITOLA 6.
Obrázek 6.12: Sekven£ní diagram interakce t°íd ze v²ech vrstev
NÁVRH
Kapitola 7
Implementace 7.1
Controllery
Pro implementaci controller· v prezenta£ní vrstv¥ byl p·vodn¥ pouºit Spring MVC ve verzi 2, ale pozd¥ji byla aplikace p°epracována s vyuºitím moºností nov¥j²í verze 2.5. Ve verzi 2 je standardním postupem p°i psaní controlleru zd¥dit z odpovídající t°ídy a p°etíºit poºadované metody. Níºe je uveden p°íklad controlleru, který zpracovává poºadavek na vypsání v²ech produkt·.
public class protected
extends
ListProductsController ProductServiceImpl
AbstractController
{
productService ;
@Deprecated @Override
public
ModelAndView
handleRequestInternal (
HttpServletResponse C o l l e c t i o n Map<S t r i n g , model . put (
r e t u r n new
hsr1
)
throws
products
Object > model = " products " ,
=
new
products
ModelAndView (
HttpServletRequest
Exception
hsr ,
{
productService . getAllProducts () ; HashMap<S t r i n g ,
O b j e c t >() ;
) ;
" catalog " ,
model
) ;
} ... }
Listing 7.1: Controller ve Spring MVC verze 2 Ve Spring MVC verze 2.5 lze jako Controller pouºít libovolnou POJO t°ídu. T°ída se ozna£í anotací @Controller a pomocí anotace @RequestMapping lze na metody t°ídy namapovat HTTP poºadavky.
package
s h o p . web . c o n t r o l l e r s . c u s t o m e r ;
@Controller
public class
ProductsController
{
51
52
KAPITOLA 7.
private private
ProductService
productService ;
ProductCategoryService
@RequestMapping (
IMPLEMENTACE
productCategoryService ;
"/ c a t a l o g . html "
)
p u b l i c S t r i n g l i s t P r o d u c t s ( ModelMap m o d e l , @ R e q u e s t P a r a m ( = f a l s e , v a l u e = " c a t e g o r y I d " ) Long c a t e g o r y I d ) { C o l l e c t i o n
if
(
c a t e g o r y I d == products
}
else
required
products ;
null
)
{
=
productService . getAllProducts () ;
=
productService . getAllProductsInCategory (
{
products
categoryId
) ;
} model . put ( " p r o d u c t s " ,
products ) ;
model . put ( " t o p L e v e l C a t " ,
productCategoryService .
getTopLevelCategories () ) ;
return
" Catalog " ;
} ... }
Listing 7.2: Controller ve Spring MVC verze 2.5
7.2
Validace
7.2.1
Balí£ek validation
Aplikace vyºaduje validovat objekty v perzistení vrstv¥, které reprezentují vstup od uºivatele (typicky vypln¥ný formulá°). Framework Spring nabízí funkcionalitu pro validaci stavu objekt· v balí£ku validation. Pomocí rozhraní Validator z tohoto balí£ku lze vytvá°et t°ídy validátory, p°i£emº kaºdý validátor je ur£en pro validaci objekt· jedné t°ídy. Ve t°íd¥ implementující toto rozhraní lze vyuºívat statické metody ze t°ídy ValidationUtils. Pomocí t¥chto metod lze programov¥ nadenovat, jaký je p°ípustný stav validovaného objektu.
package
s h o p . web . v a l i d a t o r s ;
public class
ProductValidator
implements
Validator
p u b l i c boolean s u p p o r t s ( C l a s s c l a z z ) { r e t u r n ProductCO . c l a s s . i s A s s i g n a b l e F r o m (
{
clazz
) ;
}
public void
validate (
Object
target ,
Errors
errors
V a l i d a t i o n U t i l s . rejectIfEmptyOrWhitespace ( ,
" required . productDescription "
) ;
)
{
errors ,
"description"
7.2.
53
VALIDACE
V a l i d a t i o n U t i l s . rejectIfEmptyOrWhitespace ( r e q u i r e d . productName "
errors ,
" name " ,
"
errors ,
"salePrice" ,
) ;
V a l i d a t i o n U t i l s . rejectIfEmptyOrWhitespace ( " required . productSalePrice "
) ;
} }
Listing 7.3: T°ída implementující rozhraní Validator Nap°íklad první volání metody rejectIfEmptyOrWhitespace zajistí kontrolu, zda prom¥nná description ve t°íd¥ ProductCO (typu String) není prázdná nebo sloºená pouze z bílých znak·. Pokud je, p°idá o tom informace do objektu errors v£etn¥ chybového kódu required.productDescription. Chybové kódy a chybová hlá²ení jsou nadenovány v tzv. message source, který jsem v aplikaci realizoval pomocí property souboru. P°i pouºití toho p°ístupu je moºné p°idat podporu internacionalizovaných chybových hlá²ení bez zásahu do kódu validátor·.
7.2.2
Knihovna Spring Modules
Alternativní p°ístup pro validaci nabízí Bean Validation Framework z projektu Spring Modules. Bean Validation Framework nabízí deklarativní p°ístup k validaci objekt·. Poºadovaný stav se denuje pomocí anotací p°ímo ve t°íd¥, jejíº instance chceme validovat. [Whe08]
package
s h o p . web . c o m m a n d o b j e c t s ;
public class
ProductCO
implements
ProductPropertyProvider
{
@NotBlank
private
String
name ;
@NotBlank
private
String
@Min ( v a l u e
description ;
= 0)
@NotNull
private private private
Double
salePrice ;
C o l l e c t i o n
C o l l e c t i o n
categories ;
relatedProducts ;
... }
Listing 7.4: Deklarace validního stavu pomocí anotací Tento zp·sob validace v aplikaci p°evaºuje. Jako p°íklad je uvedena relevantní £ást t°ídy ProductCO. Z názv· anotací lze snadno odvodit, jakým pravidl·m odpovídají. Bean Validator Framework implementuje standardní rozhraní Validator frameworku Spring. Jediný rozdíl oproti p°edchozímu °e²ení je ten, ºe chybové kódy nedenujeme sami, ale jsou p°edepsané podle názvu t°ídy, prom¥nné a pouºité anotace. Ukázka z property souboru:
ProductCO . name [ not . blank ]= Jmeno nesmi byt prazdne . ProductCO . description [ not . blank ]= Popis nesmi byt prazdny .
54
KAPITOLA 7.
IMPLEMENTACE
ProductCO . salePrice [ not . null ]= Cena nesmi byt prazdna . ProductCO . salePrice [ min ]= Minimalni cena je 0. Listing 7.5: Denice chybových hlá²ení v property souboru
7.2.3
JSR 303 Bean Validation API
Ve Spring Frameworku verze 3 je podporována validace pomocí nového Bean Validation API, které je denováno v Java Specication Request 303. Bean Validation API vyuºívá op¥t deklarativní p°ístup pomocí anotací a jeho referen£ní implementací je Hibernate Validator verze 4.x.
7.3
Lazy Load
P°i na£ítání objektu z databáze je pro napln¥ní prom¥nných referencí pot°eba na£íst z databáze dal²í data pro vytvo°ení objekt·, na který reference ukazují. Pokud tento objekt má také referen£ní prom¥nné, dostáváme se do stejné situace a postupn¥ bychom byli nuceni nahrát z databáze kompletní graf objekt·. Technika Lazy Load °e²í tuto situaci tím, ºe se do prom¥né místo kompletního objektu umístí pouze zástupná zna£ka a samotný objekt se na£te z databáze aº v moment¥, kdy je na tuto zna£ku p°istoupeno. JPA umoº¬uje ozna£it u mapovaných t°íd (entit) libovolný atribut jako Lazy, coº zp·sobí odloºení jeho na£tení do doby, kdy je na n¥j p°istoupeno. Lazy loading má význam p°eváºn¥ u prom¥nných základajících vztah s jinou entitou, proto jsou v JPA v²echny vztahy mezi entitami implicitn¥ denovány jako lazy. Problém nastává, pokud je t°eba pomocí lazy loadu nahrát z databáze objekt po skon£ení databázové transakce. Pokud je aplikace navrºená tak, ºe sluºby JPA jsou volány p°ímo v aplika£ní logice (doménová logika a kód pro p°ístup do databáze není odd¥lený), tak tento problém nastat nemusí. Metoda obsahující doménovou logiku m·ºe ukon£it transakci aº na svém konci a b¥hem jejího b¥hu mohou být pot°ebná data získávána v rámci transakce z databáze. P°i pouºití vzoru Data Access Object ale musí konec transakce vyvolat metoda v DAO t°íd¥ nejpozd¥ji na svém konci p°ed vrácením °ízení do doménové vrstvy. V doménové vrstv¥ nebo v prezenta£ní vrstv¥ pak m·ºe entita nahraná lazy zp·sobem vyºadovat p°ístup do databáze, ale nemá jiº k dispozici otev°enou transakci. Framework Spring nabízí °e²ení ur£ené pro perzistentní framework Hibernate. Pouºívá vzor
Open Session In View, který je realizován t°ídami OpenSessionInViewFilter a OpenS-
essionInViewInterceptor. Jediný rozdíl mezi nimi je, ºe interceptory jsou spravovány v rámci kontejneru, zatímco ltry stojí mimo framework Spring a kongurují se pomocí souboru web.xml. Podstatou vzoru OpenSessionInView je, ºe s kaºdým novým HTTP poºadavkem se automaticky otev°e Hibernate Session (ta vymezuje za£átek a konec databázové transakce) a uzav°e se aº po vyrenderování odpov¥di pro klienta, p°ed samotným odesláním opov¥di na poºadavek. B¥hem toho, co je Session (a tím pádem transakce) otev°ená, mohou view komponenty skrze Hibernate poºadovat nahrání pot°ebných dat z databáze. Toto °e²ení je velmi jednoduché na implementaci, zejména v p°ípad¥ pouºití Springu v kombinaci s Hibernate a s pouºitím moºností, které nabízí Spring ORM. Alternativou je
7.4.
POUITÍ HIBERNATE JAKO IMPLEMENTACE JPA
55
p°ipravit v²echna pot°ebná data (a pouze tyto, jinak by ne²lo o lazy loading) uº v perzistentní vrstv¥. Je pot°eba zavést v perzistentní vrstv¥ (v DAO t°ídách) alternativní metody pro brzké na£tení. Dále je nutné zjistit, které sady objekt· bude doménová vrstva pro zpracování konkrétního poºadavku pot°ebovat a v prezenta£ní vrstv¥ pouºívat pouze tyto objekty. Pomocí voláních metod pro brzké na£tení v perzistentní vrstv¥ se pot°ebná £ást grafu objekt· na£te najednou. V p°ípad¥ JPA lze v perzistení vrstv¥ metody pro brzké na£tení implementovat pomocí tzv. JOIN FETCH spojení, nebo jednodu²e u lín¥ na£teného objektu p°istoupit na poºadované prom¥nné. Open Session In View m·ºe fungovat jako záloºní °e²ení v p°ípad¥, ºe by nedo²lo k na£tení v²ech poºadovaných objekt·. Pokud pouºijeme Open Session In View jako jediný zp·sob °e²ení lazy loadingu, dojde k zanesení závislosti integra£ní (perzistentní) vrstvy na prezenta£ní vrstv¥. Pokud bychom vym¥nili implementaci prezenta£ní vrstvy, p°estane na£ítání objekt· z databáze za b¥hu fungovat. Na druhou stranu je optimalizace dotaz· v perzistentní vrstv¥ za ú£elem poskytování v²ech pot°ebných dat pro vy²²í vrstvy pom¥rn¥ sloºitá. Je moºné si usnadnit práci pouºitím OSIW b¥hem vývoje a po stabilizování poºadavk· p°ejít na pouºití optimalizovaných dotaz·. [Pat]
7.4
Pouºití Hibernate jako implementace JPA
Jako implementace JPA jsem zvolil framework Hibernate. Neplánoval jsem pouºít ºádné funkcionality specické pro Hibernate, aby nebyl problém p°ípadn¥ p°ejít na jinou implementaci JPA. Svázání s Hibernate ale nastalo pouºitím OpenSessionInViewInterceptoru pro °e²ení lazy loadingu. Protoºe pouºití OSIW interceptoru zaná²í do aplikace °adu necht¥ných závislostí, bylo by vhodné zváºit p°echod na jiný zp·sob °e²ení lazy loadingu.
7.5
Zabezpe£ení aplikace
Pro zabezpe£ení aplikace je vyuºita knihovna Spring Security ve verzi 2.0.1. Z moºností, které tato knihovna nabízí, je vyuºito podpory pro autentizace uºivatel· a funkce restrikce p°ístupu na URL. Autorizace (p°id¥lování práv) je ve Spring Security zaloºeno na uºivatelských rolích. Zdrojem pro autentizaci (ov¥°ování identity) uºivatel· m·ºe být nap°íklad LDAP server, rela£ní databáze nebo property soubor. V p°ípad¥ pouºití databáze lze specikovat SQL dotazy pro získání údaj· pro autentizaci. Toho je v aplikaci vyuºito k integraci s existujícími t°ídami reprezentující role, které se nacházejí v doménové vrstv¥. Následující £ást XML souboru pro kongurace Spring Security denuje zmín¥né SQL dotazy:
< authentication - provider > < jdbc - user - service data - source - ref = " dataSource " users - by - username - query = " SELECT login as username , password , ' true ' as enabled FROM users WHERE login = ? " authorities - by - username - query = " SELECT users . login as username , shoprole . dtype as authorities FROM users , users_shoprole , shoprole WHERE users . login = ? AND users . id = users_shoprole . users_id AND shoprole . id = users_shoprole . roles_id " / >
56
KAPITOLA 7.
IMPLEMENTACE
Listing 7.6: Kongurace SQL dotaz· pro autentizaci Omezení p°ístupu k jednotlivým URL (které jsou mapovány na controllery a jsou vstupním bodem do aplikace) op¥t vyuºívá rolí. URL, které neodpovídají ºádnému ze záznam· jsou p°ístupné bez p°ihlá²ení. Pro p°ístup na URL v sekci /admin/ je poºadováno, aby p°ihlá²ený uºivatel m¥l mezi svými rolemi roli administrátora. ást URL vyºaduje, aby p°ihlá²ený uºivatel m¥l roli zákazníka.
< intercept - url < intercept - url < intercept - url > < intercept - url > < intercept - url < intercept - url < intercept - url < intercept - url < intercept - url /> < intercept - url
pattern = " / addtocart . html * " access = " ROLE_CUSTOMER " / > pattern = " / addaddress . html * " access = " ROLE_CUSTOMER " / > pattern = " / listaddresses . html * " access = " ROLE_CUSTOMER " / pattern = " / deleteaddress . html * " access = " ROLE_CUSTOMER " / pattern = " / editaddress . html * " access = " ROLE_CUSTOMER " / > pattern = " / checkout . html * " access = " ROLE_CUSTOMER " / > pattern = " / listorders . html * " access = " ROLE_CUSTOMER " / > pattern = " / showorder . html * " access = " ROLE_CUSTOMER " / > pattern = " / removefromcart . html * " access = " ROLE_CUSTOMER " pattern = " / showcart . html * " access = " ROLE_CUSTOMER " / >
< intercept - url pattern = " / admin /* " access = " ROLE_ADMIN " / > Listing 7.7: Kongurace omezení p°ístupu k URL
7.6
Struktura databáze
Databázové schéma na obrázku 7.1 vzniklo vygenerováním z mapovaných t°íd (entit), coº umoº¬uje JPA. Je to jednodu²²í varianta, neº mapovat na entity existující schéma databáze. Ze schématu je vid¥t, ºe JPA (potaºmo Hibernate, který je pouºit jako implementace JPA) vyuºívá v implicitním nastavení vztahové tabulky jak pro vztahy typu M:N, tak pro vztahy typu 1:N. Jména vztahových tabulek byla nadenována ru£n¥, aby bylo schéma srozumiteln¥j²í. Diagram vznikl pomocí nástroje DbVisualizer, který umoº¬uje zkoumat strukturu databázového schématu p°ipojením se k b¥ºící databázi p°es JDBC.
7.6.
STRUKTURA DATABÁZE
Obrázek 7.1: Struktura databáze
57
58
KAPITOLA 7.
IMPLEMENTACE
Kapitola 8
Testování 8.1
Testování jednotek (Unit testing)
Testování jednotek je zaloºeno na testování nejmen²ích testovatelných £ástí software jednotek. Tomu v objektov¥-orientovaného programování odpovídají jednotlivé t°ídy.
1 Klí£ové
pro testování jednotek je, ºe jednotlivé t°ídy se testují izolovan¥. To znamená, ºe výsledek testu závisí pouze na vlastnostech jedné testované t°ídy a ne na dal²ích t°ídách, které tato t°ída vyuºívá. Protoºe v typické aplikace v¥t²ina t°íd není izolovaná a vyuºívá jiné t°ídy, není obvykle jednoduché úplné izolace testovaných t°íd dosáhnout. K izolování testované t°ídy se pouºívá nahrazení t°íd které testovaní t°ída vyuºívá zástupnými objekty. [Fow] denuje £ty°i typy zástupných objekt· -
Dummy, Fake, Stub
a
Mock.
Dummy objekt slouºí typicky jako výpl¬ nepot°ebného parametru metody, je to prázdná implementace rozhraní. S dummy objektem se b¥hem testu nijak nepracuje, slouºí pouze k tomu, aby bylo moºné test zkompilovat. Fake objekt imituje funkcionalitu jiného objektu, ale jeho implementace je podstatn¥ jednodu²²í, neº implementace skute£ného objektu stejného typu. P°íkladem m·ºe být fake objekt DAO t°ídy, který imituje databázi vhodnou datovou strukturu v pam¥ti. Stub je objekt, který implementuje v¥t²inu svého chování pomocí pro ú£ely konkrétního testu p°ipravených opov¥dí na volání svých metod. ást metod stub objektu, která není pro test pot°ebná, nemusí být v·bec implementovaná (metoda nic neprovede, jako návratovou hodnotou vrátí null). Mock objekt jsou speciální objekty, které jsou schopny zaznamenávat, jakým zp·sobem s nimi bylo interagováno (nap°. jaké metody s jakými parametry na nich byly volány) a také dokáºí ov¥°it, zda tento zp·sob odpovídá specikaci, která do mock objektu byla p°ed spu²t¥ním testu vloºena. 1 Lze namítnout, ºe nejmen²í testovatelnou £ástí software je metoda, p°ípadn¥ blok kódu. Protoºe pojem jednotky (unit) v oblasti testování nemá jednozna£nou denici, navrhuje [Rai05] alternativní termín testování objekt· (Object Testing).
59
60
KAPITOLA 8.
8.2
TESTOVÁNÍ
Frameworky pro testování
Testování jednotek hraje nejvýznamn¥j²í roli p°i vývoji aplikace, kdy pomáhá programátor·m ov¥°ovat správnost jimi produkovaného kódu. Pokud se testování jednotek provádí £asto a testy jsou opakovatelné, dávají tak programátorovi v£as zp¥tnou vazbu o tom, jak jeho zm¥ny existujícího kódu ovlivnily funk£nost aplikace. Testy jednotek (unit testy) vytvá°í obvykle sám programátor. Aby mohly být testy jednotek provád¥ny £asto a byly opakovatelné, je zapot°ebí, aby byly automatizované. To zaji²´ují testovací frameworky, které umoº¬ují automaticky spou²t¥t testy a zaji²´ují jejich vyhodnocení. Nejroz²í°en¥j²í je pravd¥podobn¥ framework
xUnit,
pro který existuje implementace prakticky na kaºdé platform¥ (v Jav¥
JUnit). Krom¥ framework· pro psaní automatizovaných unit test·, jako je xUnit, existuje °ada framework· pro usnadn¥ní práce s mock objekty. Tyto frameworky umoº¬ují vygenerovat pro rozhraní p°íslu²ný mock objekt a nastavit na tomto objektu specikaci p°ípustné interakce s ním. Vygenerovaný mock objekt p°i poru²ení této specikace vyhodí výjimku, která zp·sobí selhání b¥ºícího testu. Mock objekt·m lze pomocí frameworku také nastavit, jak má na o£ekávané volání metod reagovat vzhledem k volajícímu objektu, coº spo£ívá typicky v denování návratové hodnoty. Díky tomuto lze vygenerovaný mock objekt pouºít také v roli stub objektu (pomocí frameworku se nadenují odpov¥di objektu pro ú£ely testu). Také je moºné vyuºít framework pouze k vygenerování objektu poºadovaného typu a pouºít ho jako dummy objekt. Mezi testovací frameworky tohoto typu pat°í nap°íklad
8.3
EasyMock
nebo
jMock.
Testování v rámci práce
Pro jednotkové testování aplikace bylo pouºito frameworku EasyMock. Pomocí n¥j byly otestovány t°ídy transak£ních skript· v doménové vrstvy (balí£ek shop.domain.service). Tyto t°ídy závisí na DAO t°ídách, které bylo nutné nahradit zástupnými objekty. Pro tento ú£el by bylo moºné pouºít n¥jakou formu databáze v pam¥ti, realizované nap°íklad t°ídou HashMap z Java API, ale takto vytvo°ený fake objekt by mohl sám obsahovat necht¥nou chybu ve své implementaci. Testování pomocí mock/stub objekt· s vyuºitím frameworku EasyMock je proto vhodn¥j²í.
@Test public void testfindNonExistentUserByLogin () throws Exception { expect ( udMock . findByLogin ( unkownUserLogin ) ) . andReturn ( null ) ; replay ( udMock ) ; try { userService . findUserByLogin ( unkownUserLogin ) ; fail ( " UserService didn ' t throw exception when asked to find unknown user " ) ; } catch ( EshopException e ) { // OK } verify ( udMock ) ;
8.3.
TESTOVÁNÍ V RÁMCI PRÁCE
} Listing 8.1: P°íklad jednoduchého unit testu s pouºitím frameworku EasyMock
61
62
KAPITOLA 8.
TESTOVÁNÍ
Kapitola 9
Záv¥r V rámci práce byla prozkoumána °ada technologií a s jejich pouºitím byla realizována funk£ní implementace, která je pom¥rn¥ dob°e p°ipravena na dal²í roz²i°ování v °ad¥ ohled·. Analýza funk£ních poºadavk· byla provedena s vyuºitím p°ípad· uºití. Sepsané p°ípady uºití jsou pom¥rn¥ detailn¥ zpracované, takºe na nich lze stav¥t v dal²ích iteracích vývoje aplikace. Zárove¬ jsou psané stylem, který umoº¬uje jejich pochopení bez p°edchozích znalostí této metody. Toho by bylo moºné dále vyuºít p°i p°ípadném zp°es¬ování poºadavk· na aplikaci odborníkem na doménu elektronického obchodování. P°i návrhu aplikace bylo pouºito roz²í°ených architektonických a návrhových vzor·, coº usnad¬uje p°ípadnou diskuzi nad modikacemi aplikace. Pouºitím vzor· se také dosáhlo relativn¥ snadné roz²i°itelnosti aplikace a zvolená architektura umoº¬uje vym¥nit pouºité technologie za jiné relativn¥ bez v¥t²ích komplikací. Práce vyuºívá framework Spring, který je hodn¥ roz²í°en a neustále se vyvíjí. Je velmi nepravd¥podobné, ºe by se jeho vývoj v brzké budoucnosti zastavil, v tomto ohledu jsou moºnosti aplikace otev°ené. Zvolený framework JPA pro objektov¥-rela£ní mapování se ukázal jako významný pro usnadn¥ní výoje perzistentní vrstvy, na druhou stranu ale p°inesl do vývoje n¥kolik komplikací. Komplexní automatické testování aplikace je vzhledem k pouºitým technologiím netriviální, ale byl identikován vhodný testovací framework, který £ást problém· odstra¬uje. Pro dal²í roz²i°ování aplikace by bylo vhodné zvý²it podílu automatizovaných test· a zváºit p°echod na mén¥ komplikovaný perzistentní framework, jako zajímavá alternativa se nabízí v práci zmi¬ovaný framework iBatis. Osobní p°ínos pro m¥ práce p°edstauje v tom, ºe jsem se p°i jejím zpracovávání detailn¥ji seznámil s pokro£ilými technologiemi, které jsem d°íve pokládal za obtíºn¥ proniknutelné.
63
64
KAPITOLA 9.
ZÁV
R
Literatura [Amb]
Scott W. Ambler. Introduction to user stories.
http://www.agilemodeling.com/artifacts/userStory.htm, stav z 25. 5. 2010. +
[BMR 98] Frank Buschmann, Regine Meunier, Hans Rohnert, Peter Sornmerlad, and Michael Stal.
Pattern-oriented software architecture : A system of patterns, vol-
ume 1. Wiley-Academy, 1st edition, 1998.
+
[CDG 06] Fay Chang, Jerey Dean, Sanjay Ghemawat, Wilson C. Hsieh, Deborah A. Wallach, Mike Burrows, Tushar Chandra, Andrew Fikes, and Robert E. Gruber.
OSDI'06: Seventh Symposium on Operating System Design and Implementation, 2006. Bigtable: A distributed storage system for structured data.
[Cla08]
Doug Clarke. Oracle Technology Network Forums, 2008.
http://forums.oracle.com/forums/thread.jspa?threadID=673888,
stav
z
25. 5. 2010. [Coc01] [Coh]
Alistair Cockburn.
Writing eective use cases. Addison-Wesley, 1st edition, 2001.
Mike Cohn. Non-functional requirements as user stories.
http://blog.mountaingoatsoftware.com/non-functional-requirements-as-user-stori stav z 25. 5. 2010. [Dra]
Richard Drake. Mac App.
http://c2.com/cgi-bin/wiki?MacApp, [Fow]
stav z 25. 5. 2010.
Martin Fowler. Mocks aren't Stubs.
http://martinfowler.com/articles/mocksArentStubs.html,
stav
z
25. 5. 2010. [Fow03]
Martin Fowler.
Patterns of enterprise application architecture.
Addison-Wesley,
1st edition, 2003. [GHJV95]
Erich Gamma, Richard Helm, Ralph Johnson, and John Vlissides. Design Patterns: Elements of reusable object-oriented software. Addison-Wesley, 1st edition, 1995.
[gooa]
The JRE class white list.
http://code.google.com/intl/cs/appengine/docs/java/jrewhitelist. html, stav z 26. 5. 2010.
65
66
LITERATURA
[goob]
Will it play in App Engine.
http://groups.google.com/group/google-appengine-java/web/ will-it-play-in-app-engine, stav z 26. 5. 2010. [java]
Core J2EE patterns - Data Access Object.
http://java.sun.com/blueprints/corej2eepatterns/Patterns/ DataAccessObject.html, stav z 25. 5. 2010. [javb]
Java Persistence API FAQ.
http://java.sun.com/javaee/reference/faq/persistence.jsp,
stav
z
25. 5. 2010. [jdo]
JDO - JPA Frequently Asked Questions.
http://www.datanucleus.org/products/accessplatform/jdo_jpa_faq. html, stav z 25. 5. 2010. [j]
jre.org - Free / Open Source ERP.
http://www.jfire.org, +
[JHD ]
stav z 26. 5. 2010.
Rod Johnson, Juergen Hoeller, Keith Donald, Colin Sampaleanu, Rob Harrop, Alef Arendsen, Thomas Risberg, Darren Davison, Dmitriy Kopylenko, Mark Pollack, Thierry Templier, Erwin Vervaet, Portia Tung, Ben Hale, Adrian Colyer, John Lewis, Costin Leau, Mark Fisher, Sam Brannen, Ramnivas Laddad, Arjen Poutsma, Chris Beams, and Tareq Abedrabboand Andy Clement. Spring framework reference documentation.
http://www.springsource.org, [Joh03]
Rod Johnson.
stav z 25. 5. 2010.
Expert one-on-one J2EE design and development.
Wrox, 1st
edition, 2003. [Kei08]
Mike Keith. Looking forward to JPA 2.0, 2008.
http://java.dzone.com/articles/looking-forward-jpa-20,
stav
z
25. 5. 2010. [Lar05]
[Mak08]
Applying UML and patterns: An introduction to object-oriented analysis and design and iterative development. Prentice Hall, 3rd edition, 2005. Craig Larman.
Gary Mak.
Spring Recipes: A problem-solution approach.
Apress, Oval Road,
London, UK, 1st edition, 2008. [ofb]
OFBiz, The Apache Open For Business Project.
http://ofbiz.apache.org, [Pat]
stav z 26. 5. 2010.
Anthony Patricio. Open Session in View - JBoss community.
http://community.jboss.org/wiki/OpenSessioninView, [Rai05]
J.B. Rainsberger. ning, 2005.
stav z 25. 5. 2010.
JUnit recipes : practical methods for programmer testing. Man-
67
LITERATURA
[Smi]
Donald Smith. A brief history of TopLink.
http://www.oracle.com/technology/tech/java/newsletter/articles/ toplink/history_of_toplink.html, stav z 25. 5. 2010. [Whe08]
Willie Wheeler.
Annotation-based validation with the Spring bean validation
framework, 2008.
http://wheelersoftware.com/articles/spring-bean-validation-framework. html, stav z 25. 5. 2010. [Yat]
Colin Yates.
Spring Community Forums - Using domain objects as command
objects.
http://forum.springsource.org/showthread.php?p=60758#post60758, z 25. 5. 2010.
stav
68
LITERATURA
P°íloha A
Instala£ní a uºivatelská p°íru£ka A.1
Instalace
Rozbalte archívy
apache-tomcat.tar
a
hsqldb.tar.
Pokud pouºijete dodaný server Apache Tomcat, aplikace je v n¥m jiº p°ipravena. (P°i pouºití vlastní instalace Apache Tomcat zkopírujte WAR archív
Shop.war do adresá°e webapps
ve va²í instalaci.)
hsqldb (cd hsqldb) a spus´te z p°íkazové °ádky databázi java -cp lib/hsqldb.jar org.hsqldb.Server -database.0 file:mydb -dbname.0 jshop Spus´te z p°íkazové °ádky server Apache Tomcat p°íkazem apache-tomcat-6.0.26/bin/startup.sh (v p°ípad¥ OS Windows apache-tomcat-6.0.26/bin/startup.bat) Otev°ete webový prohlíºe£ va²eho OS a zadejte adresu http://localhost:8080/Shop Nastavte jako aktuální adresá°
HSQL p°íkazem
A.2
A.2.1
Uºivatelská p°íru£ka
Zákaznická £ást
Pro p°ihlá²ení do zákaznické £ásti se v pravém horním rohu p°ihla²te s t¥mito údaji: uºivatel:
user, heslo: user.
Druhou moºností je vybrat v pravém horním rohu moºnost
Registrace
a vytvo°it nového
uºivatele. Takto vytvo°ený uºivatel dostane automaticky práva pro vstup do sekce pro registrované zákazníky.
A.2.2
Administrátorská £ást
P°ihlásit se a p°ihla²te s t¥mito údaji: uºivatel: admin, heslo: admin. Poté vyberte záloºku Administrace. P°ípadn¥ m·ºete p°istoupit na záloºku Administrace rovnou a systém vás vyzve k p°ihPro p°ihlá²ení do administrátorského £ásti vyberte v pravém horním rohu moºnost
lá²ení.
69
70
PÍLOHA A.
INSTALANÍ A UIVATELSKÁ PÍRUKA
P°íloha B
Obsah p°iloºeného CD • apache-tomcat.tar
webový server/servletový kontejner Apache Tomcat
• hsqldb.tar
databázový systém HyperSQL
• README.txt
návod na instalaci a spu²t¥ní aplikace
• Shop
NetBeans projekt aplikace
• Shop.war • text
archív aplikace pro nasazení na webový server
tento text
71