Mendelova univerzita v Brně Provozně ekonomická fakulta
Využití přístupů založených na modelu MVC pro tvorbu aplikací Diplomová práce
Vedoucí práce: Ing. David Procházka Ph.D.
Bc. Lukáš Kubíček
Brno 2011
Rád bych poděkoval Ing. Davidovi Procházkovi, Ph.D., za vedení a cenné rady, které mi velmi pomohly. Také bych chtěl poděkovat Ing. Janu Přichystalovi, Ph.D., za vytvoření a provoz systému TeXonWeb, ve kterém jsem práci psal. V neposlední řadě chci poděkovat rodině, která mě podporovala nejen při psaní práce, ale při celém studiu.
Prohlašuji, že jsem tuto diplomovou práci vypracoval samostatně a uvedl jsem všechny literární prameny a publikace, ze kterých jsem čerpal.
V Brně, dne 26. 5. 2011
....................................................
4
Abstract Kubíček, L. Use of design patterns based on MVC model in application development. Diploma thesis. Brno, 2011. This diploma thesis describes MVC (Model-View-Controller ), MVP (ModelView-Presenter ) and MVVM (Model-View-ViewModel) design patterns. In the first part I focus on theoretical aspects and compare these design patterns. I provide a key to decide which pattern to use or how to identify them in source code. The second part, in the form of a tutorial, describes application development process with the use of design patterns. The last part shows implementation details of MVVM pattern in a more complex application and discusses the consequences.
Abstrakt Kubíček, L. Využití přístupů založených na modelu MVC pro tvorbu aplikací. Diplomová práce. Brno, 2011. Práce popisuje návrhové vzory MVC (Model-View-Controller ), MVP (ModelView-Presenter ) a MVVM (Model-View-ViewModel ). První část práce zkoumá tyto návrhové vzory po teoretické stránce. Výsledkem je shrnutí usnadňující rozhodnutí, kdy který vzor použít nebo jak rozlišit implementované vzory v kódu. Druhá část popisuje formou tutoriálu proces vývoje aplikací s využitím návrhových vzorů. Poslední část práce se věnuje nasazení vzoru MVVM u složitějších aplikací, poskytuje implementační detaily a diskutuje následky.
5
OBSAH
Obsah 1 Úvod a cíl práce 1.1 Úvod . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1.2 Cíl práce . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2 Teorie návrhových vzorů 2.1 Alternativní přístupy k tvorbě 2.2 Model-View-Controller . . . . 2.3 Model-View-Presenter . . . . 2.4 Model-View-ViewModel . . . 2.5 Shrnutí . . . . . . . . . . . . . 2.6 Další kroky v tvorbě aplikace 3 Metodika návrhu aplikací 3.1 Demo aplikace . . . . . . 3.2 Navrhujeme aplikaci . . 3.3 Implementujeme aplikaci 3.4 Shrnutí . . . . . . . . . .
. . . .
. . . .
. . . .
aplikací . . . . . . . . . . . . . . . . . . . . . . . . .
. . . .
. . . .
4 Analýza a návrh případové studie 4.1 Specifikace požadavků . . . . . . 4.2 Scénáře užití . . . . . . . . . . . . 4.3 Objektový a datový model . . . . 4.4 Uživatelské rozhraní . . . . . . .
. . . .
. . . .
5 Implementace případové studie 5.1 Použité technologie . . . . . . . . . 5.2 Více o implementaci vzoru MVVM 5.3 Implementační detaily View . . . . 5.4 Propojení View a ViewModelu . . . 5.5 Implementační detaily ViewModelu 5.6 Implementační detaily Modelu . . .
. . . .
. . . .
. . . . . .
. . . .
. . . .
. . . . . .
. . . . . .
. . . .
. . . .
. . . . . .
. . . . . .
. . . .
. . . .
. . . . . .
. . . . . .
. . . .
. . . .
. . . . . .
. . . . . .
. . . .
. . . .
. . . . . .
. . . . . .
. . . .
. . . .
. . . . . .
. . . . . .
. . . .
. . . .
. . . . . .
. . . . . .
. . . .
. . . .
. . . . . .
. . . . . .
. . . .
. . . .
. . . . . .
. . . . . .
. . . .
. . . .
. . . . . .
. . . . . .
. . . .
. . . .
. . . . . .
. . . . . .
. . . .
. . . .
. . . . . .
. . . . . .
. . . .
. . . .
. . . . . .
. . . . . .
. . . .
. . . .
. . . . . .
. . . . . .
. . . .
. . . .
. . . . . .
. . . . . .
. . . .
. . . .
. . . . . .
. . . . . .
. . . .
. . . .
. . . . . .
6 6 6
. . . . . .
8 8 9 12 15 17 18
. . . .
21 21 21 29 33
. . . .
34 34 35 36 37
. . . . . .
41 41 42 43 45 46 47
6 Závěr
49
7 Literatura
51
1
ÚVOD A CÍL PRÁCE
1 1.1
6
Úvod a cíl práce Úvod
Návrh a tvorba počítačových aplikací je netriviální záležitost, která může zasahovat do mnoha různorodých disciplín. Na vývoji větších softwarových programů dnes často pracují velké týmy, složené z odborníků na různé oblasti. Ale i menší projekty, mají-li být konkurenceschopné, se musí snažit vyvíjet software, který je kvalitní a jehož vývoj netrvá zbytečně dlouho. V 70. letech se objevilo softwarové inženýrství, nová vědní disciplína, která do tvorby počítačových programů vnesla systematický přístup a inženýrské metody. V polovině 90. let se potom staly populární objektově orientované programovací jazyky. S objektově orientovaným programováním (OOP) souvisí návrhové vzory. Programátoři si všimli, že některé složitější problémy se při návrhu a implementaci programů v OOP často opakují. Návrhové vzory se snaží na některé známé problémy poskytnout ověřené a vhodné řešení. Návrhový vzor popisuje jak vytvořit objekty a jak mají tyto objekty spolu komunikovat. Návrhové vzory mohou snížit čas a úsilí potřebné k navržení systému, který je přehledný, robustný, dobře udržovatelný a jehož dílčí části jsou znovupoužitelné. Jedním z typů aplikací, které jsou velmi úzce spojeny s OOP, jsou aplikace s grafickým uživatelským rozhraním (GUI). Jedním z možných přístupů jak tyto aplikace navrhovat je pomocí třívrstvé architektury, ve které je aplikace rozdělená na tři vrstvy: datovou, logickou a prezentační. S tímto přístupem souvisí návrhový vzor MVC (Model-View-Controller ), který byl používaný už při psaní programů s GUI v jazyce Smalltalk a je používaný a oblíbený i dnes. Použití MVC nebo jeho odvozené varianty MVP (Model-View-Presenter ) a MVVM (Model-View-ViewModel ) je doporučováno většinou velkých a významných platforem pro tvorbu aplikací jako je Java, .NET, Ruby on Rails, Qt a další. Nasazení těchto návrhových vzorů přináší již zmíněné výhody. Kód může být přehlednější, protože program je rozdělen do samostatnějších celků. To umožňuje snadnější vytvoření komponent, tedy znovupoužitelných bloků, ale také snadnější udržování a případný refaktoring. V oblibě jsou tyto návrhové vzory i proto, že usnadňují práci větším týmům. Specialista na grafiku a návrh uživatelského rozhraní se může věnovat prezentační vrstvě, zatímco odborník na databáze se může věnovat datové vrstvě a programátoři potom zajistí společnou komunikaci pomocí logické vrstvy.
1.2
Cíl práce
Cílem této práce je prozkoumat možnosti nasazení návrhových vzorů využívaných pro tvorbu aplikací, v kontextu moderních programovacích jazyků a technologií. V první části práce se budu zabývat návrhovými vzory MVC (Model-ViewController ), MVP (Model-View-Presenter ) a MVVM (Model-View-ViewModel )
1.2
Cíl práce
7
z teoretické stránky. Provedu rešerši a porovnám tyto návrhové vzory mezi sebou a ukážu, čím se liší, jaký je jejich historický kontext, jak souvisí s použitím různých technologií a programovacích jazyků a jaké mají vlastnosti. Shrnutí této části by čtenáři mělo umožnit snadnější rozlišení mezi těmito návrhovými vzory a rozhodnutí kdy se který používá. V druhé části vytvořím ucelený návod pro ty, kteří si přejí začít vytvářet aplikace s využitím návrhových vzorů. Návod bude popisovat proces vývoje a návrhu ukázkové demo aplikace na správu receptů. Návod bude určený pro programátory se znalostmi OOP. Poslední část práce bude popisovat implementační detaily jednoho z diskutovaných návrhových vzorů na praktické aplikaci. Případovou studií je aplikace pro podporu nutričního poradenství určená pro reálné nasazení. Aplikaci vytvořím s použitím zvolené platformy a jednoho z návrhových vzorů. Tato část práce by měla ukázat jaké výhody a nevýhody přináší použití vybraného návrhového vzoru na větší aplikaci. Případná úskalí a důsledky, které mohou vzniknout, budou zmíněny v diskuzi v závěru.
2
TEORIE NÁVRHOVÝCH VZORŮ
2
8
Teorie návrhových vzorů
Dvořák chápe návrhový vzor jako obecný popis řešených problémů. Nejedná se o konkrétní kus kódu nebo implementaci, ale o abstraktní popis řešení, které se pro daný problém ukázalo jako vhodné. Takovéto použití návrhových vzorů lze vysledovat i v jiných oborech než jen v informatice. Zejména v architektuře, odkud tento pojem také pochází (Dvořák, 2003). Termín návrhový vzor (anglicky design pattern) publikoval poprvé stavební architekt Christopher Alexander. Ten popisuje návrhový vzor takto: „Každý návrhový vzor popisuje problém, který se vyskytuje znovu a znovu v našem prostředí a popisuje jádro řešení tohoto problému takovým způsobem, že můžeme použít toto řešení mnohokrát, aniž bychom dělali stejnou věc dvakrátÿ (Alexander, 1964). V informatice se návrhové vzory objevily v roce 1987 na konferenci OOPSLA (Object-Oriented Programming, Systems, Languages Applications). Ale skutečnou popularitu jim získala až kniha Design Patterns: Elements of Reusable ObjectOriented Software publikovaná v roce 1991 od autorů Erich Gamma, Richard Helm, Ralph Johnson a John Vlissides. Pro tuto čtveřici se také uchytil název Gang of Four (GoF). Jejich dílo je i dnes relevantní a uznávané. Gang of Four popisuje čtyři základní elementy, které tvoří návrhový vzor (Gamma a kol., 1995): 1. Název (Pattern name). Krátký název, který pokud možno dobře vystihuje podstatu návrhového vzoru. Umožňuje odkazovat se na návrhový vzor při komunikaci, v dokumentaci ale i v uvažování. Název umožňuje s návrhovým vzorem pracovat na vyšší úrovni abstrakce. 2. Popis problému (Problem). Vysvětluje problém a jeho kontext. Někdy může obsahovat také seznam podmínek, které musí být splněny, aby mělo smysl návrhový vzor použít. 3. Popis řešení (Solution). Vysvětluje jaké prvky vytvořit, jejich vztah, odpovědnost a spolupráci. Řešení nepopisuje konkrétní implementaci, protože návrhový vzor je jako šablona, která může být použita v různých situacích. Místo toho poskytuje abstraktní popis návrhu a obecné uspořádání prvků (v našem případě tříd a objektů), které daný problém řeší. 4. Důsledky (Consequences). Důsledky hrají důležitou roli při hodnocení a výběru vzorů. Důsledky pro software často zahrnují prostorové a časové kompromisy. Mohou se týkat otázek implementace v konkrétním jazyce a technologii. Mohou zahrnovat dopad na flexibilitu, rozšiřitelnost a přenositelnost softwarového systému na který mají být aplikovány.
2.1
2.1
Alternativní přístupy k tvorbě aplikací
9
Alternativní přístupy k tvorbě aplikací
Jak uvádí Gang of Four, to jakou technologii, programovací jazyk a paradigma zvolíme, hraje důležitou roli. Co v jednom jazyce může být řešeno pomocí návrhového vzoru, může být v jiném triviální konstrukt. Pokud bychom například pracovali s procedurálními jazyky typu Pascal nebo C, potom by i problémy jako dědičnost, zapouzdřenost a polymorfismus mohli být řešeny pomocí návrhových vzorů (Gamma a kol., 1995). Tato práce popisuje použití návrhových vzorů z pohledu programovacích jazyků typu C++, Java nebo C#. Tento úhel pohledu jsem zvolil proto, že s nimi mám nejvíce zkušeností a také jsou to v současnosti jedny z nejpopulárnějších programovacích jazyků. Tyto jazyky umožňují použití objektově orientovaného paradigmatu s prvky procedurálního programování (např. použití primitivních typů). Odlišný by byl také přistup z prostředí dynamičtějších objektových jazyků (CLOS, Self) nebo čistě objektových jazyků (Smalltalk). Návrhové vzory ve své podstatě se dají využít i ve zcela neobjektových paradigmatech jako je třeba funkcionální programování (Lisp, Haskell).
2.2
Model-View-Controller
Nejstarší z trojice zkoumaných návrhových vzorů je vzor MVC (Model-ViewController ). Autorem původního článku, dokumentujícího použití MVC pro programátory jazyka Smalltalk, s názvem Applications Programming in Smalltalk–80: How to use Model–View–Controller je Steve Burbeck. Základní koncept Podle Burbecka je vhodné vstup od uživatele, doménový model dat a grafické znázornění zpětné vazby rozdělit do tří samostatných a specializovaných objektů. View (pohled) je zodpovědný za grafický nebo textový výstup, se kterým může uživatel interagovat. Controller (v českých překladech se používá řadič nebo kontrolér) interpretuje vstup z klávesnice a myši od uživatele a informuje model a pohled jak se mají aktualizovat. Model (model) se stará o chování (behavior) a doménově specifická data, reaguje na dotazy na stav (obvykle se ptá View ) a také na požadavky na změnu stavu (obvykle posílá Controller ). Jak Burbeck konstatuje, formální rozdělení těchto tří úkolů je důležitým aspektem MVC přístupu a velmi vhodné pro Smalltalk, kde může toto být realizováno s pomocí abstraktních objektů: View, Controller, Model a Object (Burbeck, 1992, Basic Concepts). Burbeck dále dodává, že View i Controller obsahují obecnou logiku, která se často opakuje. Naopak modelem může být jakýkoliv objekt. Desetinné číslo může být Model pro View zobrazující rychlost. Textový řetězec (String) by mohl být plnohodnotným modelem pro jednoduchý textový editor (Burbeck, 1992, Basic Concepts).
2.2
Model-View-Controller
10
Komunikace mezi objekty Správné propojení trojice objektů View, Controller a Model je klíčové pro ucelenou interakci aplikace s uživatelem. Zatímco první dva spolu komunikují přímo, model může být do interakce zapojen různými způsoby. Pasivní model V nejjednodušším případě se Model vůbec nemusí zabývat komunikací se zbývajícími objekty. Jednoduchý textový editor je dobrým příkladem. Ústřední vlastností takové aplikace je řetězec reprezentující právě editovaný text. Modelem může být tedy textový řetězec (String). View musí vědět o každé změně textu, aby jej mohl správně zobrazovat na obrazovce. Avšak zodpovědnost za informování o těchto změnách nemá Model, nýbrž Controller, který zpracovává vstup od uživatele a provádí změny v textu. Zde má Controller dvě možnosti. Může pouze pro View oznámit, že se něco změnilo (a View si vyžádá aktuální stav Modelu) nebo může poslat i informace o tom co bylo změněno. Model v tomto případě vůbec nemusí vědět o existenci View ani Controlleru (Burbeck, 1992, The Passive Model). Informující model Ale ne vždy může Model fungovat takto pasivně. Někdy se stav Modelu mění i nezávisle na Controlleru a View, tedy jako reakce na zprávy od jiných objektů. V tom případě musí být View informován o změnách Modelu. Protože jen Model ví o všech změnách, leží tato zodpovědnost na něm (Burbeck, 1992, The Model’s Link to the Triad). Burbeck dále popisuje způsob jak je toto realizováno ve Smalltalku. Pomocí mechanismu nazvaného DependentFields, který umožňuje objektu dostat zprávu pokaždé, když se změní sledovaná vlastnost jiného objektu. View se zaregistruje, že chce být informován o změnách na Modelu. Když ke změně dojde, tak Model všem, kteří se zaregistrovali, pošle informaci o změně. View si po obdržení této informace vyžádá aktuální data a zobrazí změny uživateli (Burbeck, 1992, The Model’s Link to the Triad). Tento mechanismus je podobný událostem (events) v jazyce C# nebo Java. Jeden objekt může sloužit jako Model pro více zobrazení současně. Vazba mezi objekty Controller a View Na rozdíl od modelu, který může být do trojice MVC zapojen nepřímo, každý View je asociován s jediným konkrétním Controllerem a naopak. Oba si udržují vzájemně na sebe referenci a oba mají referenci na Model. Ten neobsahuje odkaz ani na jeden z nich. Model jen pomocí události informuje, že se změnil.
2.2
Model-View-Controller
11
Obr. 1: Vazby objektů vzoru MVC; plné čáry představují přímou referenci (tzn. možnost volání metod), čárkované znázorňují nepřímou vazbu realizovanou pomocí událostí
Vazba mezi objekty Model a View Model a View spolu souvisí a musí být nevyhnutelně nějakým způsobem propojeny. View zprostředkovává data uživateli a umožňuje mu s nimi interagovat. Hansen a Fossum ve své práci Refactoring Model-View-Controller míní, že jsou dobré důvody pro to, aby tato vazba byla co nejvolnější a umožňovala snadné rozpojení a nezávislost objektů Model a View. Uvádí pro to dva důvody. Prvním je snazší mixování a párování dat a jejich zobrazení. V moderních aplikacích často jeden Model bývá zobrazován různými způsoby. Dalším důvodem je vývoj a údržba aplikace. Když jsou Model a View rozpojeny (decoupled), může za každý z nich mít zodpovědnost jiný člen (Hansen a Fossum, 2005, s. 125). Implementace MVC v prostředí webových aplikací MVC je v současnosti oblíbenou volbou při návrhu a tvorbě webových aplikací. Svědčí o tom i počet webových MVC frameworků pro všechny významné platformy. Zde jsou pouze vybrané příklady1 těch populárnějších: • Java: Java Server Faces, Spring MVC Framework, Play; • PHP: Zend Framework, Symfony Framework; • .NET: ASP.NET MVC Framework; • Python: Django; • Ruby: Ruby on Rails. Využití MVC přístupu při tvorbě webových aplikací usnadňuje správné oddělení a komunikaci datové a prezentační vrstvy, tedy části aplikace na serveru a části aplikace u klienta. View představuje HTML stránka (včetně javascriptu), která je odeslaná klientovy. Model jsou opět doménově specifická data (na serveru) a Controller je ta část aplikace, která zpracovává požadavky (vstup) od uživatele. Tyto 1
Rozsáhlejší výčet lze najít na http://en.wikipedia.org/wiki/Model-view-controller
2.3
Model-View-Presenter
12
jsou aplikaci předávány pomocí HTTP requestů (URL a parametry). Stejně jako v prostředí Smalltalku, uživatelský vstup dostává a zpracovává jako první Controller, nikoliv View. Implementace MVC v prostředí desktopových aplikací Zatímco v prostředí Smalltalk-80 vstup od uživatele jako první dostane Controller a ten potom obstarává další změny, mnoho desktopových platforem pro vývoj GUI aplikací dnes funguje jinak. Uživateli jsou zobrazeny grafické komponenty, takzvané widgety. Ty také jako první dostanou možnost zpracovat událost od uživatele (gesta myši, zmáčknutí klávesy). Toto platí například pro Swing (Java) nebo Winforms (.NET). Amy Fowler popisuje architekturu Swing komponent, která vychází z MVC přístupu, ale slučuje View a Controller do jednoho objektu nazvaného Delegate (Fowler Amy). „Brzy jsme si však uvědomili, že toto [MVC] rozdělení u nás nebude v praxi dobře fungovat, protože View a Controller v rámci komponenty vyžadují silnou vazbu (bylo například obtížné napsat obecný Controller, který by nepracoval se specifickými vlastnostmi View ). Proto jsme sloučili tyto dvě entity do jedno UI objektu.ÿ Swing architektura vychází z MVC. Model je zcela nezávislý na jeho reprezentaci, avšak zbylé dva objekty jsou nahrazeny jedním společným. Ten je nazvaný Delegate, protože je navržený tak, aby umožňoval delegovat vykreslování komponenty různým look-and-feel objektům.
2.3
Model-View-Presenter
Jak píše Martin Fowler, MVP (Model-View-Presenter ) se poprvé objevil v roce 1990 v IBM jako architektonický vzor pro vývoj aplikací odvozený od MVC (Fowler, 2006). Původní referencí je často citovaný článek MVP: Model-View-Presenter The Taligent Programming Model for C++ and Java (Potel, 1996). Potel popisuje využití MVC při tvorbě desktopových aplikací s uživatelským rozhraním. Z trojice Model, View, Controller, postupně obměňuje a doplňuje vlastnosti třetího objektu, pro který potom navrhuje nový název – Presenter. Potel analýzou dochází ke dvěma základním oblastem, kterým je potřeba věnovat pozornost při vývoji komplexních aplikací. První je Data Management a druhou User Interface. U každé z těchto potom rozvíjí dílčí úkoly a reprezentuje je otázkami, na které musí programátor odpovědět při vývoji MVP aplikace. Předkládá tak šest otázek, které odpovídají šesti základním elementům v MVP aplikaci (Potel, 1996, s. 7): 1. Co jsou data (Model ); 2. Jak lze data specifikovat (Selection); 3. Jak lze data měnit (Commands);
2.3
Model-View-Presenter
13
4. Jak jsou data zobrazena (View ); 5. Jak události odpovídají změnám v datech (Interactor ); 6. Jak je to vše propojené (Presenter ). Model a View mají stejný význam jako v MVC. Selection Potel popisuje jako to, která část dat je uživateli zprostředkována a jaké transformace jsou na ně aplikovány. Uživatel si může například ve formě grafu prohlížet finanční výsledky firmy za uplynulý rok. Při kliknutí na konkrétní měsíc se mu zobrazí v téže komponentě pro kreslení grafu detailní graf pro daný měsíc. Data Modelu zde odpovídají datům uloženým například v databázi, zatímco data konkrétně vybraná (v paměti), se kterými se pracuje, označuje Potel jako Selection. Commands jsou příkazy, kterými lze data modifikovat. Vymazat hodnoty pro poslední měsíc, přidat data pro nový měsíc atd. Interactor zodpovídá za namapování událostí vyvolaných uživatelem (gesta myši, vstup z klávesnice) na konkrétní příkazy (Commands). Tyto události jsou vyvolány přímo na formulářové komponentě (tj. View ), ale ta na ně nereaguje, pouze jejich zpracování deleguje dále. Presenter je potom zastřešujícím prvkem. Je to prostředník mezi daty a jejich uživatelskou reprezentací. Je zodpovědný za interpretaci uživatelských gest, jejich namapování na správné příkazy pro manipulaci s daty a aktualizaci grafických komponent. Potel dále diskutuje jaké jsou výhody takovéhoto rozdělení a zda tyto stojí za vynaloženou námahu (Potel, 1996, s. 13). Rozlišení Model /View přináší výhodu nezávislosti zobrazení. Např. různá zobrazení programu Kalkulačka (rozdílné množství funkcí, jiné uspořádání tlačítek) mohou být naprogramována jako nezávislé View nad jedním výpočetním modelem pro simulaci kalkulačky. Rozlišení Selection/Model poskytuje výhodu nezávislosti uložení dat. To znamená, že programátoři mohou upravovat datové struktury v jakých jsou data uložena (např. změnit způsob uložení z databáze na soubory) aniž by museli měnit jak jsou data zobrazena nebo zpracována ve zbytku programu. Toto rozlišení také usnadňuje perzistenci, vzdálený přístup k datům a sdílení. Rozlišení Command /Selection umožňuje znovupoužití příkazů. Jeden příkaz může být aplikován na různé selekce dat v rámci jedné aplikace. Jednou naimplementovaný příkaz je možné také znovu použít i v jiné aplikaci, pokud je to vhodné. Odlišení Interactor /View přináší výhodu univerzálnosti vstupu. Bez nutnosti měnit aplikační logiku nebo způsob vykreslování dat, může aplikace podporovat různá menu, dialogy, klávesové zkratky, gesta nebo vstup z tabletu. Potel dodává, že vyčlenění Commands a Interactors v rámci Presenteru, usnadňuje znovupoužitelnost implementovaného kódu v jiných aplikacích s minimální námahou.
2.3
Model-View-Presenter
14
Komunikace mezi objekty Role Modelu zůstává stejná jako v MVC. Model nemá referenci ani na View ani na Presenter. Pokud se stav Modelu může měnit i vlivem objektů mimo triádu, pak může o těchto změnách informovat nepřímo pomocí událostí. Presenter si udržuje referenci na Model, stejně jako v MVC, za účelem modifikace dat jako reakce na uživatelský vstup. V případě složitější architektury, může být Model dále rozdělen na Commands a Selection (Potel, 1996) a Presenter může komunikovat s jejich instancemi. Presenter má také referenci na View. Častý je přístup, kdy tato přímá vazba je nahrazena rozhraním. View implementuje rozhraní (Interface) a Presenter pracuje s View pouze přes toto rozhraní. Boodhoo tuto variantu vyzdvihuje, protože umožňuje znovupoužitelnost Presenteru v rozličných UI technologiích a usnadňuje testování (Boodhoo, 2006).
Obr. 2: Vazby objektů vzoru MVP; plné čáry představují přímou referenci (tzn. možnost volání metod), čárkované znázorňují nepřímou vazbu realizovanou pomocí událostí
Protože uživatelský vstup je vyvolán na grafických komponentách (widgets), tedy na View, musí tento dát o události vědět Presenteru. Boodhoo doporučuje toto realizovat pomocí událostí, tedy nepřímě vazby, tak aby View nemusel mít odkaz na Presenter (Boodhoo, 2006). Potel ukazuje, jak tuto vazbu rozložit přes více objektů v souladu s rozdělením View/Interactor/Presenter (Potel, 1996). Podle toho jestli spolu přímo komunikují View a Model a jakou roli hraje v triádě Presenter, rozlišuje Fowler dvě možnosti implementace MVP. Supervising Presenter Tato varianta je podobnější MVC přístupu. Fowler polemizuje a váhá mezi pojmenováním Supervising Presenter a Supervising Controller. View má referenci na Model a sám se aktivně dotazuje na data a udržuje si stav. Úkolem Presenteru je zpracování uživatelského vstupu (který je předán od View ) a částečná synchronizace View /Model. Esencí tohoto přístupu je, že Presenter má na starosti jen minimum operací, zatímco View obsahuje tolik aplikační logiky, kolik je potřeba. Presenter vstupuje mezi komunikaci View /Model pouze pokud toto zahrnuje složitější logiku (Fowler, 2006).
2.4
Model-View-ViewModel
15
Passive View Zde Fowler popisuje variantu, ve které je View zcela pasivní. Nemá referenci na Model a sám se o žádnou synchronizaci nestará. Veškerou aplikační logiku obsahuje Presenter. View je chápán jako deklarativní část uživatelského rozhraní, která obsahuje jen minimum logiky. Jako důvod k takovémuto uspořádání uvádí Fowler především snadnou testovatelnost programu (Fowler, 2006).
Obr. 3: Vazby objektů vzoru MVP ve variantě Passive View ; plné čáry představují přímou referenci (tzn. možnost volání metod), čárkované znázorňují nepřímou vazbu realizovanou pomocí událostí
Presenter First Občas je možné setkat se s přístupem nazvaným Presenter First. Jedná se o techniku vývoje softwarových aplikací, která kombinuje využití návrhového vzoru MVP s metodikami Test Driven Development a Feature Driven Development. Tento přístup byl představen na konferenci Agile (Kolektiv autorů, 2006). Při vývoji aplikace je věnována napřed pozornost Presenteru, který je implementován jako první. View i Model mohou být díky komunikaci přes rozhraní (Interface) z počátku nahrazeny Mockupy (zástupnými objekty, které pouze simulují chování skutečného objektu). Podle autorů je nejvýhodnější začít z triády MVP právě prací na Presenteru, protože tímto může aplikace vyjít z uživatelských scénářů a využít dobré praktiky Test Driven Developmentu. Psaní takovýchto testů je ekonomické a méně náročné než testování GUI vrstvy. Specifikace pro zbylé dva objekty (které navazují na již fungující Presenter ) tak vzejdou přirozeně z uživatelských scénářů a tím se sníží riziko tvorby zbytečně komplikovaného kódu, který je častý pro tyto třídy. Presenter First vynucuje oddělení uživatelského rozhraní od aplikační logiky a tím umožňuje snadnou změnu grafické vrstvy (Kolektiv autorů, 2006).
2.4
Model-View-ViewModel
Historii tohoto návrhového vzoru shrnuje Josh Smith takto (Smith, 2009, The Evolution of Model-View-ViewModel): V roce 2004 publikoval Martin Fowler článek o návrhovém vzoru nazvaném Presentation Model (PM) (Fowler, 2004). PM je podobný MVP v tom, že odděluje View od chování (behavior) a stavu (state). V tomto vzoru je pro View vytvořená abstrakce nazvaná Presentation Model. View se potom víceméně stává jen vykreslením Presentation Modelu. Fowler vysvětluje, že Presentation Model často aktualizuje View, aby zůstaly synchronizovány. Tato synchronizační logika je realizována jako kód ve třídě Presenatation Modelu.
2.4
Model-View-ViewModel
16
O rok později John Gossman, jeden z architektů WPF (Windows Presentation Foundation) a Silverlightu, představil vzor Model-View-ViewModel (MVVM). Ten je identický s Fowlerovým Presentation Modelem v tom, že oba vzory zavádějí abstrakci pro View, která obsahuje jeho stav a chování. Fowler představil Presentation Model jako způsob vytváření abstrakce pro View nezávisle na platformě, zatímco Gossman představil MVVM jako standardizovanou cestu k využití výhod základních funkcí WPF ke zjednodušení vytváření uživatelských rozhraní na této platformě. Smith chápe MVVM jako specializaci obecného vzoru Presentation Model, uzpůsobenou pro platformy WPF a Silverlight (Smith, 2009). Windows Presentation Foundation Podobně jako originální MVC je spjaté se Smalltalkem v tom smyslu, že některé aspekty tohoto návrhového vzoru závisí na konkrétních možnostech této platformy2 , je návrhový vzor MVVM (Model–View–ViewModel ) spjatý s technologií WPF (Windows Presentation Foundation). Výraznou funkcí WPF, která je též nezbytná pro pochopení MVVM, je mechanismus nazvaný data binding. Smith popisuje data binding jako možnost automatického přesunu datových objektů z jednoho místa na druhé. Programátor může specifikovat kdy, jak a proč budou hodnoty přesunuty ze zdrojového objektu na cílový. Je možné bindovat vlastnost jednoho UI elementu na vlastnost na jiném UI elementu, případně může být jeden element bindován sám na sebe. Je možné také použít převodníky hodnot (value convertors) k bindování dvou vlastností různých typů. Bindování může být vytvořeno a specifikováno v kódu nebo značkovacím jazyce XAML (Smith 2010, s. 7). Uživatelské rozhraní ve WPF je většinou deklarováno ve značkovacím jazyce XAML3 , což je akronym pro Extensible Application Markup Language. XAML je deklarativní jazyk založený na XML, vhodný pro vytváření stromu UI elementů, nastavování jejich vlastností a určení metod reagujících na události. XAML soubor je často asociován s code behind souborem, který obsahuje kód, např. metody na zpracování událostí vyvolaných na komponentách deklarovaných v XAMLu (Smith 2010, s. 7). Některé komponenty, jako například Button a MenuItem umožňují úplně se vyhnout psaní kódu v code-behind souboru, díky jejich vlastnosti Command. Pokud je tlačítku do vlastnosti Command přiřazen nějaký objekt implementující rozhraní ICommand, potom při stisku tlačítka je tento příkaz automaticky proveden (Smith 2010, s. 7). Komunikace mezi objekty Smith popisuje trojici objektů v MVVM takto (Smith 2010, s. 8): 2 3
Způsob zpracování uživatelského vstupu, notifikační mechanismy Výslovnost [zaml]
2.5
Shrnutí
17
Model obsahuje data konzumovaná a modifikovaná uživatelem. Může také obsahovat věci známé jako business rule processing, input validation, change tracking a další, které souvisí se doménovými daty v aplikaci. Naproti tomu View je pouze záležitost vizuální stránky. View je UI komponenta, která zobrazuje data, umožňuje uživateli modifikovat stav programu skrze vstupní zařízení, zobrazuje videa, obrázky nebo cokoliv mají uživatelé vidět na obrazovce. Třetí objekt popisuje Smith jako prostředníka a definuje jej takto: ViewModel je modelem View. ViewModel je abstrakcí uživatelského rozhraní. Neměl by mít žádnou znalost o UI elementech na obrazovce. Kód, který pracuje se specifickými elementy na konkrétním View by měl být v code-behind souboru toho konkrétního View. Na rozdíl od Presenteru v MVP, ViewModel nepotřebuje mít referenci na View. View se binduje na vlastnosti ViewModelu, který zpřístupňuje data Modelu a stav specifický pro View. Bindování mezi View a ViewModelem je jednoduché vytvořit, protože View má vlastnost DataContext do které je nastaven příslušný ViewModel. Když se změní hodnoty vlastností na ViewModelu, jsou tyto automaticky propagovány pomocí data bindingu na View. Když uživatel ve View klikne na tlačítko, spustí se příkaz (Command ) na ViewModelu a vykoná požadovanou akci. Pouze ViewModel, nikdy View, provádí změny na datech Modelu (Smith, 2009).
Obr. 4: Vazby objektů vzoru MVVM; plné čáry představují přímou referenci, čárkované znázorňují nepřímou vazbu realizovanou pomocí událostí a mechanismu data binding
View neví o existenci Modelu. ViewModel a Model zase nevědí o existenci View.
2.5
Shrnutí
Hlavní motivací všech tři popsaných návrhových vzorů je poskytnout programátorům dobré a ověřené řešení, jak oddělit v aplikaci to, co je uživateli zobrazováno (View ), od dat, která toto zobrazení zprostředkovává (Model ). Nejstarším návrhovým vzorem je MVC (Model-View-Controller ), který má svůj původ v prostředí Smalltalk. Dnes se často nasazuje při vývoji webových aplikací. Z něho přímo vychází následující vzor MVP (Model-View-Presenter ), který vznikl v kontextu objektových jazyků C++ a Java. MVP existuje v několika variantách a bylo popsáno i několik odvozených vzorů. Jedním z nich je i PM (Presentation Model ). MVVM se vyvinul jako specializace PM pro platformu WPF (Windows Presentation Foundation), kde je tento vzor velmi populární. Všechny tři vzory popisují objekty View a Model podobně. To, čím se liší, jsou klíčové vlastnosti třetího objektu a jejich vzájemné propojení.
2.5
Shrnutí
18
Model-View-Controller: Controller jako první zpracovává vstup od uživatele. Controller provádí změny Modelu a informuje o nich View, který se potom aktualizuje. Model obsahuje stav i chování. Controller i View mají vzájemnou referenci. V případě použití MVC v prostředí webu se Controller stará o navigaci a může reagovat na požadavky od více View. Model-View-Presenter: View dostává vstup od uživatele jako první, ale většinou jej pouze předá Presenteru ke zpracování. Presenter má referenci na View, tedy každý View má svůj Presenter. Presenter funguje buď jako částečný nebo úplný koordinátor komunikace mezi Modelem a View. Presenter obsahuje chování, Model uchovává stav. Model-View-ViewModel: View dostává vstup od uživatele jako první, ale podobně jako v MVP jej většinou jen přesměruje na ViewModel. ViewModel je abstrakcí uživatelského rozhraní a obsahuje stav i chování. ViewModel nemá referenci na View. Proto je možné aby více View využívalo jeden ViewModel i když tato praxe není častá a obvykle jednomu View odpovídá jeden ViewModel. View a Model spolu nekomunikují. Hlavním rozdílem mezi MVP a MVVM je směr reference mezi View a koordinátorem. V MVP má Presenter referenci na View, zatímco v MVVM má View referenci na ViewModel. Kdy který vzor použít Použití je do značné míry dáno platformou, na které je aplikace vyvíjena. MVC, tak jak je originálně popsáno ve Smalltalku, je velmi obtížné realizovat na většině moderních platforem pro vývoj desktopových aplikací, protože na nich vstup od uživatele jako první dostane View. V tom případě se používá MVP. MVC lze uplatnit při tvorbě webových aplikací. MVVM je oblíbený při vývoji aplikací na platformě WPF, která k tomuto poskytuje několik ulehčujících mechanismů. Návrhový vzor, architektura nebo přístup? Autoři používají v literatuře různá označení. Burbeck představil MVC jako paradigma či přístup k vývoji aplikací. Při popisu konkrétní trojice propojených objektů používá Burbeck označení triáda (Burbeck, 1992). Gang of Four využívá MVC jako příklad, na kterém ilustruje jaké konkrétní návrhové vzory lze při implementaci MVC využít. Vzor Observer, může sloužit k rozpojení (decoupling) objektů a jejich nezávislé notifikaci o změnách. Vzor Composite zase umožňuje zanořené View. A vzor Strategy je zobecněním vztahu mezi Controller a View (Gamma a kol., 1995). Samotný MVC však v seznamu návrhových vzorů neuvádí. V tomto smyslu lze o MVC uvažovat jako o vzoru složeném z jiných vzorů. Potel hovoří o návrhovém vzoru, ale také o přístupu. Při popisu MVP používá téměř výhradně slovní spojení programming model (Potel, 1996), což lze v kontextu článku chápat jako způsob návrhu aplikace. Hansen a Fossum popisují MVC jako architektonický
2.6
Další kroky v tvorbě aplikace
19
návrhový vzor (Hansen a Fossum, 2005). Toto označení, které dobře vystihuje podstatu těchto vzorů, se ujalo a dnes je při popisu MVC, MVP a MVVM používáno často.
2.6
Další kroky v tvorbě aplikace
Volba architektonického vzoru je jen jednou z částí návrhu a tvorby aplikace. Podle Procházky je nutné nejprve zjistit účel aplikace a poznat cílového uživatele, tedy kdo a proč bude aplikaci používat (Procházka, 2010). Seznámení s cílovým uživatelem by mělo zahrnovat: • zjištění čeho chce uživatel dosáhnout použitím aplikace; • jaké úkony musí ke splnění cíle učinit; • jaký jazyk a slova tuto činnost charakterizují; • schopnosti uživatele a kolik času je ochoten věnovat naučení se práce s nástrojem; • postoj uživatele k aplikaci. Uživatelské rozhraní Následně, když známe typické scénáře užití, víme pro jakou platformu budeme vyvíjet (desktop, web, mobilní aplikace,. . . ), víme jaký typ nebo idiom rozhraní chceme použít (formulářová aplikace, e-shop, editor,. . . ), lze přistoupit k návrhu konkrétnějších částí uživatelského rozhraní (Tidwell, 2010, s. 25). I zde však Jenifer Tidwell doporučuje napřed popsat okna nebo stránky v obecných abstraktnějších pojmech. Většina obrazovek či stránek obsahuje zejména některé z těchto čtyř věcí (Tidwell, 2010, s. 26): • zobrazení jednoho hlavního objektu jako např. mapa, kniha, video nebo hra; • zobrazení seznamu nebo skupiny položek; • poskytnutí nástrojů k vytvoření něčeho; • prostředek umožňující vykonat nějakou činnost nebo úkol. Důležitou otázkou je také rozhodnutí základního rozvržení aplikace. Tedy jestli bude aplikace zobrazena pomocí více oken, jednoho okna měnícího obsah, jednoho rozděleného okna, případně kombinací těchto přístupů. Přičemž volba implementace by neměla být dána vkusem programátora ale podstatou aplikace (Procházka, 2010). Při návrhu GUI lze využít některé z existujících vzorů pro tvorbu uživatelských rozhraní a interakce s uživatelem. Mnoho z těchto vzorů je dobře rozebráno v knize Designing Interfaces (Tidwell, 2010), kde jsou popsány nejen vzory řešící strukturu rozložení obsahu, navigaci, práci se seznamy, příkazy, komplexními daty,
2.6
Další kroky v tvorbě aplikace
20
uživatelským vstupem, ale také vzory zabývající se chováním uživatelů, sociálními sítěmi a problémy typickými pro mobilní zařízení. Existují i volně přístupné webové knihovny těchto vzorů4 . Datová vrstva I pro část aplikace, která se zabývá Modelem a datovou vrstvou existují doporučené praktiky a vzory, které usnadní její dobrou implementaci. Zde velmi záleží na konkrétní použité technologii, jestli bude aplikace uchovávat data v souborech nebo v databázi nebo bude využívat vzdálené webové služby atd. Např. při návrhu datové základny pro relační databáze je dobré vyjít ze tří úrovní návrhu (konceptuální, logická, implementační) jak popisuje Šimůnek a znát proces normalizace databáze (Šimůnek, 1999). Dnes však existuje i velké množství alternativních databází, které umí uchovávat data přímo ve formě objektů, grafů, dokumentů a dalších5 .
4 5
např. http://ui-patterns.com/ nebo http://quince.infragistics.com viz http://nosql-database.org/ nebo http://en.wikipedia.org/wiki/NoSQL
3
METODIKA NÁVRHU APLIKACÍ
3
21
Metodika návrhu aplikací
Tato kapitola tvoří ucelený, samostatně použitelný tutoriál pro začínající. Ten na jednoduchém příkladě ilustruje a vysvětluje postupy a praktiky popsané v druhé kapitole této práce. Účel tohoto tutoriálu Tento tutoriál Vás provede procesem návrhu a tvorby počítačové aplikace. Cílem je naučit se jak postupovat, aby činnosti při návrhu a implementaci počítačové aplikace byly systematické, využívali dobrých praktik a návrhových vzorů. Celý proces bude vykládán na příkladě. V první části bude popsána analýza a návrh aplikace. Tato část bude čerpat zejména z knihy Designing User Interfaces (Tidwell, 2010) a z materiálů k předmětu Pokročilá Uživatelská Rozhraní (Procházka, 2010). Druhá část se bude zabývat implementací. Pro koho je tento tutoriál určen Předpokladem k použití tohoto návodu je dobrá znalost programování, zejména Objektově orientovaného programování (OOP). Předpokládá se, že čtenář má zkušenost s některým z moderních objektových jazyků (Java, C#, C++,. . . ). Tento tutoriál si neklade za cíl naučit programovat, ale osvojit si používání dobrých praktik a návrhových vzorů při tvorbě aplikací.
3.1
Demo aplikace
Naším úkolem bude vytvořit program pro správu receptů (kuchařku). Aplikace bude pro domácí a příležitostné kuchaře, kteří si chtějí uchovávat recepty. Máme využít i možností, které nabízí moderní přenosná zařízení (chytré telefony, tablety) a nabídnout uživateli možnost díky těmto zařízením využít aplikaci jako asistenta při vaření.
3.2
Navrhujeme aplikaci
Před tím než začneme programovat, je vždy dobré vědět co, proč a pro koho budeme vytvářet. Nejprve aplikaci analyzujeme jako obecný nástroj. Využijeme k tomu těchto kroků: 1. analýza uživatele, 2. zjištění podstaty a smyslu nástroje, 3. definování konkrétních cílů a nutných kroků k jejich splnění, 4. vymezení funkcionality a rozbor datových objektů.
3.2
Navrhujeme aplikaci
22
Následně určíme typ aplikace a na základě předchozího vytvoříme grafický návrh uživatelského rozhraní, vybereme konkrétní technologii, zvolíme architektonický vzor a popíšeme objektovou a datovou základnu. Cílový uživatel a smysl aplikace Čeho chce uživatel dosáhnout použitím aplikace? Kdy ji bude používat? Jaké alternativní možnosti existují? Jaké jsou obdobné aplikace a jak se liší? Seznam receptů, čili kuchařka, není záležitost specifická pro počítačový svět. Naopak je to něco, co existovalo dlouho před tím, než se počítače rozmohly do domácností běžných lidí. Toho je možné s výhodou využít a podívat na vlastnosti a použití těchto papírových kuchařek. Toto je dobré udělat vždy, když má navrhovaný program k dispozici nějaký protějšek ve skutečném světě. Rychlým průzkumem můžeme zjistit, že lze najít seznamy receptů dvojího druhu: • recepty tištěné, vydávané ve formě knih; • ručně sbírané a zapisované seznamy receptů. Ty první bývají většinou tematicky zaměřené kuchařky, které kromě samotného seznamu receptů často obsahují i další informace o vaření, surovinách, ingrediencích, správné výživě nebo i o kuchyňském vybavení a jeho použití. V obchodech je k dostání široká nabídka. Kuchařky zaměřené na různé kuchyně (česká, portugalská, indická,. . . ), diety (vegetariánská, bezlepková,. . . ), ale i velmi obsáhlé tradiční kuchařky. Pro nás je důležité, že tyto kuchařky jsou neměnné – obsahují seznam receptů od autora, rozdělený a seřazený podle nějakého systému o kterém rozhodl autor. Druhý typ kuchařek jsou recepty sbírané. Jde často o sešity, zápisníky nebo svazky volných papírů, které obsahuji recepty, které si majitel kuchařky přál uchovat. Kdo bude nástroj využívat? Jak je starý? Jaké má zvyky? Jaké má zkušenosti a dovednosti? K lepšímu poznání cílového uživatele, je potřeba položit otázku, čeho chce uživatel použitím naší aplikace dosáhnout. Každý člověk, který používá dobrovolně nějaký nástroj, má pro to svůj důvod. Například (Tidwell, 2010, s. 2): • nalezení informace nebo objektu; • něco se naučit; • vykonat operaci;
3.2
Navrhujeme aplikaci
23
• něco ovládat nebo hlídat; • vytvořit něco; • komunikovat s někým; • pobavit se. V případě kuchařky jde na prvním místě pravděpodobně o nalezení informace nebo objektu. Uživatel bude často potřebovat najít recept a potom provést jednu z možných akcí (uvařit jídlo, nakoupit ingredience, poslat recept známému,. . . ). Druhým účelem kuchařky je uložení nebo vytvoření receptu – uživatel chce, aby si kuchařka zapamatovala nový recept a později mu ho umožnila vyhledat. Na tomto přichází čas se poprvé vydat za uživatelem. „Každý uživatel je jedinečný. Rozhodně není jako Vy!ÿ(Procházka, 2010, Poznáváme uživatele). Co se může zdát jako ideální z Vašeho pohledu, nemusí být ideální pro uživatele. Programování je činnost, která má vysoké nároky na abstraktní myšlení, dobrou paměť a pozornost k detailům (Summit, 1995). Lze tyto vlastnosti očekávat od uživatele? Pro získání lepší představy, se lze vydat např. za někým kdo si recepty zapisuje a kuchařku používá. Nabízí se metoda dotazování a přímého pozorování 6 . Jaké recepty si zapisuje? Kam? Kdy je používá? Jaký systém organizace využívá? Jak probíhá vyhledání receptu? Jaké činnosti předcházejí použití? Jaké následují? Ze zjištěných informací budou vycházet jednotlivé scénáře užití. Scénáře užití Scénáře popisují příklady situací, ve kterých bude uživatel aplikaci používat. Vychází z předchozí analýzy a rozhovorů s uživateli. Pomohou definovat strukturu aplikace, základní funkce a jejich návaznosti. V jakých situacích bude uživatel aplikaci používat? Jaké konkrétní funkce náš uživatel očekává? Jaké kroky povedou k naplnění cíle?
Scénář: Příprava pokrmu podle receptu Cíl: vyhledat recept z existující databáze receptů a zobrazit jej ve formě vhodné pro použití při přípravě pokrmu. Kdy: před a v průběhu přípravy pokrmu. 6
Další metody k poznání uživatele jsou případové studie, persony, hromadné dotazníky a další
3.2
Navrhujeme aplikaci
24
Úkoly: zadání parametrů pro vyhledávání, procházení výsledků vyhledávání, zobrazení receptu, další akce s receptem. Z rozhovorů s uživateli vyplynuly dva způsoby vyhledávání. 1. Vyhledání konkrétního receptu. Uživatel ví co hledá. Chce najít recept, aby podle něj připravil jídlo, zjistil ingredience (a jejich množství) nebo se o recept s někým podělil. Hledání bude nejčastěji probíhat podle jména pokrmu, základních surovin nebo kategorií do kterých recept patří. 2. Procházení receptů podle kritérií. Uživatel má hrubou představu o tom, co chce najít, ale nezná konkrétní recept. Například „bezmasé jídlo, podle indické kuchyně, s rýžíÿ. Vyhledání bude nejčastěji probíhat podle kombinace kategorií jako jsou dietní omezení, typ jídla, kuchyně, použité suroviny, atd. Zobrazení receptu ve formě vhodné pro použití při přípravě pokrmu lze realizovat několika způsoby: • vytištění receptu na papír; • zobrazení na celé obrazovce, tak aby byl recept dobře čitelný; • zobrazení na mobilním zařízení; • využití hlasového syntetizátoru ke čtení receptu. Scénář: Zjištění ingrediencí a jejich případný nákup Cíl: vyhledat recept a zobrazit seznam ingrediencí včetně množství. Kdy: před vlastní přípravou pokrmu; v terénu za pomoci mobilního zařízení. Úkoly: zadání parametrů pro vyhledávání, procházení výsledků vyhledávání, zobrazení seznamu ingrediencí receptu, možnost využít mobilní zařízení. Vyhledávání probíhá stejně jako v předchozím scénáři. Další práce se seznamem ingrediencí usnadňující jejich shromáždění může například být realizována odškrtávacím seznam, tento seznam může být zobrazen přímo v aplikaci nebo může být vytištěn nebo odeslán jako email nebo zpráva. Scénář: Práce s databází receptů Cíl: aplikace uchovává databázi receptů a ingrediencí. Tuto databázi může uživatel libovolně rozšiřovat a upravovat. Kdy: rozšiřovat a upravovat recepty lze např. při prvním spuštění při získání receptů z jiných zdrojů (import z jiných programů, získání z online databáze) nebo později kdykoliv v průběhu používání aplikace. Úkoly: přidání receptu, editace receptu zahrnující editaci všech údajů včetně kategorizace, odebrání receptu, sdílení receptů s přáteli, import receptů z jiného zdroje, export receptů.
3.2
Navrhujeme aplikaci
25
Typ aplikace Jakého typu bude aplikace? Webová, desktopová, mobilní nebo nějaká kombinace? Jaký idiom bude aplikace využívat? Formulářová aplikace, grafická aplikace,. . . ? Na základě předchozí analýzy a popsaných scénářů by aplikace pro malé dotykové tablety mohla jevit jako ideální. Snadné procházení a zobrazení receptů i mimo pracovní prostředí, možnost vzít tablet do kuchyně s receptem, do obchodu s ingrediencemi, to vše je velikou výhodou. Z rozboru aplikace ale také vychází požadavek na zadávání a editaci nových receptů a na různé způsoby vyhledávání. Zapsání nového receptu vyžaduje poměrně hodně psaní a práci s textem. Mobilní dotyková zařízení nejsou pohodlná pro delší psaní (Tidwell, 2010, s. 443), pro tento úkol je lepší aplikace na desktopu, který disponuje větší obrazovkou a klávesnicí. Aplikace pro desktop může být realizována jako nativní nebo webová. Každá z těchto variant přináší nějaké výhody i nevýhody. Zvolíme tedy kombinaci desktopové a mobilní (na tablety zaměřené) aplikace. Těžiště desktopové aplikace bude v podrobném vyhledávání, práci s databází receptů, včetně editování, přidávání a organizování receptů. Mobilní aplikace bude určená především pro rychlé nalezení receptu, zobrazení ve formě vhodné pro asistenci při přípravě pokrmu a možnost zobrazovat ingredience ve formě nákupního seznamu. Funkcionalita, úkoly, data Základním objektem naší aplikace je recept. Z předchozího rozboru (např. studium papírových kuchařek, rozhovory s uživateli) můžeme popsat z čeho se skládá a jaká data chceme u receptu uchovávat: • název receptu; • seznam ingrediencí včetně množství; • počet porcí; • celková doba přípravy; • postup přípravy; • kategorie do kterých recept patří; • fotografie nebo obrázek. Zvláštní pozornost z těchto údajů si zaslouží položka kategorie. Aplikace bude uchovávat recepty uživatelů a pro lepší organizaci a snadnější vyhledávání jim bude
3.2
Navrhujeme aplikaci
26
umožňovat tyto recepty kategorizovat. Existují dvě možnosti jak ke kategorizaci a organizaci objektů přistoupit. 1. Pevně daná ontologie. Seznam kategorií je vytvořený autorem programu a uživatel pouze rozhoduje o zařazení. 2. Volná organizace. Nechat uživatele vytvářet si vlastní způsob kategorizování např. pomocí štítků (tagů). Clay Shirky popisuje první možnost jako vhodnější, pokud je množství objektů menší, lze popsat formální kategorie, objekty se v čase nemění, a existují jasné hranice. Tento přístup je vhodný pro odborné uživatele, koordinované uživatele a tam, kde existuje rozhodující autorita. Druhý způsob má výhody u velkého počtu objektů, když nelze popsat formální kategorie, objekty se mění v čase nebo nejsou jasné hranice. Druhý přístup je vhodný pro amatérské uživatele, nespolupracující uživatele a tam kde neexistuje rozhodující autorita (Shirky, 2005). Naše aplikace je určená pro amatérské uživatele. Z analýzy vyplynulo, že uživatelé si recepty organizují různě. Někdo podle zdroje (od koho recept pochází), někdo podle kuchyní atd. Na druhou stranu jsme zjistili existenci jasných všeobecně známých kategorií (typ jídla, dietní omezení). Důležitou otázkou je také to, jestli aplikace bude po instalaci prázdná a bude sloužit pouze na správu receptů, které do ní uživatel vloží nebo jestli bude aplikace již při prvním spuštění obsahovat nějaké recepty nebo možnost recepty nějak získat. Definice logické struktury aplikace Jaká bude struktura aplikace? Jaké jsou návaznosti jednotlivých úkolů? Hierarchie ovládacích prvků? Desktop: po spuštění aplikace nabídne možnost přidat nový recept a zobrazí seznam existujících receptů s možností procházení dle kategorií a vyhledávání. Při výběru receptu zobrazí jeho podrobnosti a nástroje pro práci s receptem (editace jednotlivých hodnot, tisk, odebrání). Dílčí ovládací prvky budou zejména tyto: nástroje pro práci se všemi recepty, seznam kategorií, seznam receptů, detail jednoho receptu, nástroje pro práci s jedním receptem. Tablet: po spuštění aplikace nabídne hlavní akce, které lze vykonat. Najít recept podle názvu, procházet recepty podle kategorií, zobrazit nákupní seznam. Každá akce uživatele zavede na další obrazovku s možností bezpečného návratu. Návrh uživatelského rozhraní Nyní máme definovanou strukturu aplikace a víme jaké ovládací prvky chceme uživateli nabídnout k definovaným úkolům. Rozhodli jsme, že budeme vytvářet desktopovou aplikaci a doplňkovou aplikaci na tablety a jiná mobilní zařízení. Jeden z dalších
3.2
Navrhujeme aplikaci
27
kroků, které je potřeba udělat, je navrhnout konkrétní podobu uživatelského rozhraní. To co jsme zatím popisovali poměrně abstraktně vyjádřit v podobě widgetů a elementů uživatelského rozhraní rozmístěných na jednotlivé obrazovky. Jednou možností je vzít papír a tužku a začít kreslit návrhy obrazovek na papír. Alternativou je využít nějaký software na vytváření skic uživatelského rozhraní (těmto návrhům se říká wireframes nebo mockups). Návrhy v tomto tutoriálu jsou vytvořeny v programu Basamiq Mockups 7 . Někteří designéři preferují grafické bitmapové editory typu Photoshop. Čím jednodušší grafické provedení komponent v návrhu, tím lépe. Grafické detaily nejsou podstatné a odvádí pozornost od toho, co mají mockupy komunikovat. Tím je funkcionalita a struktura uživatelského rozhraní. Grafický design přijde později. Proto není příliš vhodné tyto návrhy obrazovek vytvářet z konečných komponent ve vývojových prostředích typu Visual Studio nebo Eclipse. Systémově animovaná tlačítka, podbarvení vybraných položek v ListBoxech a podobné detaily rozptylují při vyhodnocování a posuzování návrhu v této fázi. Na základě předchozího může návrh naší desktopové aplikace vypadat například takto:
Obr. 5: Mockup uživatelského rozhraní hlavního okna desktopové aplikace pro správu receptů
Vše je zobrazeno v jednom děleném okně s panely. Hlavní tok informací a akcí je organizován zleva doprava a shora dolů. To je běžné uspořádání (v západní kultuře) a uživatelé jsou na něj zvyklí. V horní části obrazovky je globální menu, zejména pro přidávání nebo získávání receptů. V případě prvního spuštění aplikace je také jasným vstupním bodem kde má uživatel začít. Může být navíc při prvním spuštění (nebo kdykoliv když bude seznam receptů prázdný) zvýrazněno pomocí tooltipu 7
http://balsamiq.com
3.2
Navrhujeme aplikaci
28
nebo dialogu, který uživateli naznačí, kde může přidat nové recepty (Clear Entry Points). Při procházení nebo hledání v již existujícím seznamu receptů uživatel postupuje zleva, výběrem kategorií nebo jiných položek, které zužují výběr. Vhodné recepty jsou potom zobrazeny v seznamu formou tlustých řádků (Fat Rows). Je tak rychle vidět nejen název, ale i náhled (obrázek, foto), kategorie a další informace které mohou být důležité při procházení a hledání. Detail vybraného receptu je potom zobrazen v pravé části obrazovky. Akční prvky (tlačítka, menu) jsou seskupeny podle logických funkcí (Button Groups) a umístěny k elementům, ke kterým se vztahují. Na horním panelu jsou tlačítka ke globálním funkcím, akce pro vybraný recept jsou v panelu s detailem. V pravé horní části globálního menu je také informace o přihlášeném uživateli. Tam je také zobrazena informace, že recepty jsou synchronizovány. V aplikaci pro tablet nemáme k dispozici tolik prostoru jako na velkém monitoru stolního počítače. Tomu je přizpůsobeno rozložení aplikace. Po výběru ze seznamu, se vybraný recept zobrazí na celém okně. Tomuto způsobu se říká One– Window Drilldown. Uživatel se každou volbou proklikává hlouběji na vlastní obrazovku. K zachování přehledu o tom, kde se uživatel nachází, může sloužit prvek pro bezpečný návrat na první obrazovku (Escape Hatch) nebo drobečková navigace (Breadcrumbs). Při návrhu pro mobilní zařízení musíme zohlednit změny, které s jejich používáním přicházejí. Mobilní zařízení mají menší displeje, nelze si dovolit luxus postranních panelů, uživatelské rozhraní musí být omezeno na esenciální elementy, které poskytují základní funkcionalitu. Navíc různá zařízení můžou mít různou šířku obrazovek, je potřeba počítat s variabilním designem. Uživatelé ovládají tablety a chytré telefony pomocí doteků, je vhodné vyvarovat se malých tlačítek a využít možností gest. Psát text je obtížnější bez plnohodnotné klávesnice. Uživatel často věnuje aplikaci menší pozornost, než při práci s aplikací na desktopu. Toto všechno jsou výzvy, se kterými se vývojář musí vypořádat (Tidwell, 2010). Výše zmíněné problémy respektuje i návrh úvodní obrazovky. Tlačítka jsou dostatečně velká pro použití na dotykové obrazovce a zároveň rozvíjejí dialog s uživatelem tím, že zobrazují doplňující informace. Např. tlačítko pro nákupní seznam zobrazuje i počet aktuálních položek. Při přechodu na další obrazovku je v horní části zobrazena drobečková navigace, která slouží také jako tlačítka pro přechod na některou z předchozích úrovní. Další detaily, jako je například tlačítko na vymazání vloženého textu, zjednodušují práci na zařízení s dotykovým vstupem. Mockupy jsou důležitým krokem v průběhu návrhu aplikace. Na jejich tvorbě se podílí designéři i programátoři. Ve větších týmech jsou opěrným bodem pro zodpovědné osoby a mohou být také důležité pro klienta, který chce být informován nebo se chce podílet na vývoji aplikace. Mockupy můžeme také použít ke kontrole a vyhodnocování použitelnosti uživatelského rozhraní. Ověřit si, že návrh je v souladu se známými vzory chování uživatelů (popsanými např. v Designing Interfaces).
3.3
Implementujeme aplikaci
29
Obr. 6: V mobilní aplikaci je pro zobrazení seznamu receptů využit nekonečný seznam (Infinite List) a recepty se otevírají na celé obrazovce (One–Window Drilldown)
Ví uživatel kde má začít? Bude při provádění této akce vědět jak postupovat, jak se vrátit a kde se nachází? Co zaručuje bezpečný průzkum dalších funkcí? Co se stane, když uživatel v průběhu provádění této akce bude potřebovat proces přerušit? Jak si uživatel může tuto funkci přizpůsobit? Které kroky se u vykonání tohoto úkolu vždy opakují?
3.3
Implementujeme aplikaci
Někdy je volba programovacího jazyka a technologie dána volbou zákazníka nebo samotným charakterem aplikace a nemáme na výběr. Jindy je to otázka zdrojů nebo preferencí vedení. Dnes má programátor k dispozici rozmanitou škálu programo-
3.3
Implementujeme aplikaci
30
Obr. 7: Úvodní obrazovka uživateli nabízí seznam akcí, které může vykonat
vacích jazyků pro mnoho různých prostředí. Jako první je důležité určit pro jakou platformu budeme aplikaci vyvíjet. Jestli bude aplikace desktopová, webová, mobilní nebo aplikace pro sociální sítě. V analýze a návrhu jsme rozhodli, že naše aplikace na správu receptů bude využívat kombinace desktopové a mobilní aplikace. Lehce si představíme, jak tuto kombinaci rozšířit o využití webového prvku, který by synchronizoval recepty na centrálním serveru. Ve skutečnosti je tato možnost naznačena v návrzích uživatelského rozhraní, informací o přihlášeném uživateli. U desktopové části aplikace hraje důležitou roli rozhodnuti pro jaký operační systém chceme vyvíjet. Má být aplikace provozována na více operačních systémech? Pokud ano, jakých? Mezi populární volby pro vývoj multiplatformních aplikací patří Java nebo framework Qt od Nokie. V případě, že potřebujeme aplikaci provozovat pouze na jednom operačním systému, je možné zvolit technologie specifické. Ty nabízí často lepší integraci s operačním systémem a umožňují větší uživatelskou přívětivost. Například ani Java ani Qt, neposkytuje prostředky pro automatické
3.3
Implementujeme aplikaci
31
upgrady aplikací bez uživatelova zásahu. To však pro demo aplikaci není podstatné a jakákoliv ze zmíněných multiplatformních možností je dobrou volbou. U mobilních zařízení je situace podobná. Buď se lze zaměřit na konkrétní systém a vyvíjet nativně nebo využít multiplatformních frameworků. Mezi ty patří například Titanium 8 nebo Particle Code 9 . Titanium funguje tak, že developer vytváří aplikaci pomocí HTML a javascriptu, které jsou skrze API zprostředkované další možnosti zařízení (přístup k souborům, senzorům, informace o poloze). Naproti tomu při využití Particle Code, vytváří programátor aplikaci v objektovém jazyce (Java nebo ActionScript3 ), která je potom kompilována do nativního kódu. Pro graficky intenzivní aplikace, jakými mohou být třeba hry, je výhodný framework Corona 10 , postavený na OpenGL, OpenAL a Lua. Volba architektury a návrhového vzoru Chceme aby naše aplikace byla spolehlivá a dobře fungovala. Toho dosáhneme snadněji, pokud kód bude přehledný, dobře udržovatelný, a zodpovědnost za dílčí úkoly bude rozdělená do logických částí, které spolu budou vhodně komunikovat. Detailnější motivace k použití návrhových vzorů a jejich podrobnější popis je v druhé kapitole zabývající se teorií návrhových vzorů. Volba návrhového vzoru je hodně závislá na použité technologii a zvoleném programovacím jazyce. Například architektonický vzor MVVM (Model-View-ViewModel ) je praktické nasadit ve WPF (Windows Presentation Foundation), zatímco v Javě bude snadnější implementovat vzor MVP (Model-Veiw-Presenter ). Pro další práci, zvolíme návrhový vzor MVP a jeho implementaci popíšeme na příkladu desktopové aplikace. Implementace návrhového vzoru V projektu vytvoříme tři balíčky pojmenované Models, Views a Presenters. Program dále rozdělíme do hierarchické struktury komponent (podle předchozí analýzy), které mohou zasahovat přes všechny tři balíčky. Takže komponenta pro zobrazení jednoho receptu se může skládat ze tříd RecipeView v balíčku Views, RecipeModel v balíčku Models a třídy RecipePresenter v balíčku Presenters. Statická třída Program je vstupním bodem při spuštění aplikace, je zodpovědná za inicializaci dat, uživatelského rozhraní a jejich propojení. Možností jak toto realizovat je několik. V návrhovém vzoru MVP, má Presenter ukazatel jak na View, tak na Model. Můžeme tedy vytvořit třídu MainPresenter, která bude spojnicí hlavního okna (MainWindow ) a seznamu receptů. Ta může tyto objekty inicializovat buď sama (jak je to naznačeno v diagramu dále) nebo jí mohou být předány jako parametry v konstruktoru. Třídy v balíčku Views představují vlastní uživatelské rozhraní. Jednotlivé třídy jsou komponenty složené z elementů jakými jsou textová pole, tlačítka a další. Dále 8
http://www.appcelerator.com http://www.particlecode.com/ 10 http://www.anscamobile.com/corona/ 9
3.3
Implementujeme aplikaci
32
Obr. 8: Diagram tříd demo aplikace; plné čáry představují přímou referenci, čárkované znázorňují nepřímou vazbu realizovanou pomocí událostí obsahují metody, které se volají jako reakce na vstup od uživatele (co se stane při zmáčknutí tlačítka, vyplnění textového pole,. . . ). V těchto metodách jsou řešeny pouze záležitostí týkající se grafické odezvy. Všechny logické operace s daty jsou přesměrovány na Presenter. Způsobů jak rozvrhnout třídy v balíčku Presenters je opět více. V demo aplikaci je zvolena jedena hlavní třída MainPresenter, která má jako atributy kolekci receptů (objekty RecipePresenter ), kolekci kategorií, informaci o právě vybraném receptu, zvolené kategorii a aplikovaném filtru. Její metody budou reagovat na nástroje na globálním panelu nástrojů (přidání receptu, import, export,. . . ), změnu vybrané kategorie, změnu filtru a změnu vybraného receptu. Deklarace třídy MainPresenter : c l a s s MainPresenter { // c o n s t r u c t o r s : MainPresenter ( MainWindow window , R e c i p e s data ) ; MainPresenter ( ) ; // a t r i b u t e s : Recipes r e c i p e s ; L i s t <S t r i n g > c a t e g o r i e s ; RecipePresenter selectedRecipe ; Int selectedCategory ; String f i l t e r ; MainWindow view ; // methods : R e c i p e P r e s e n t e r addRecipe ( ) ; L i s t
i m p o r t R e c i p e s ( ) ; L i s t c h a n g e S e l e c t e d C a t e g o r y ( S t r i n g c a t e g o r y ) ; boolean changeSelectedRecipe ( RecipePresenter r e c i p e ) ;
3.4
Shrnutí
33
L i s t a p p l y F i l t e r ( S t r i n g f i l t e r ) ; } V balíčku Models vytvoříme dvě třídy. RecipeModel je klasický business object reprezentující recept. Jeho atributy jsou dány předchozím rozborem a zahrnují název, seznam ingrediencí, postup přípravy, dobu přípravy, počet porcí a kategorie. Třída Recpipes představuje seznam všech uživatelových receptů. Oproti jednoduché kolekci, má navíc metody pro práci s recepty jako je přidání, uložení, práce s databází a další. Vzájemnou komunikaci mezi třídami jedné logické komponenty popíšeme na příkladě zobrazení detailu receptu. Grafická komponenta pro zobrazení detailu receptu je vidět v sekci návrhu uživatelského rozhraní. Jedná se o pravý panel v hlavním okně zobrazující obsah receptu. Tento panel, včetně nástrojů pro práci s receptem (tlačítka vpravo dole) je součástí třídy RecipeView. Při kliknutí na tlačítko Editovat se jednotlivé položky receptu změní na editovatelné TextBoxy (změní se styl, tak aby uživatel viděl, že políčka jsou nyní zapisovatelná a povolí se změna hodnot). Tato změna se týká pouze View, proto tento kód bude v metodě třídy RecipeView reagující na událost stisknutí tlačítka Editovat. Po uložení změn vyvolá RecipeView událost RecipeChanged, kterou zachytí a zpracuje metoda ve třídě RecipePresenter. RecipePresenter oznámí MainPresenteru, že hodnoty tohoto receptu se změnily a aktualizuje data Modelu. MainPresenter aktualizuje ostatní části uživatelského rozhraní (například v seznamu receptů zobrazí nový název) a zajistí, že změny se ve vhodný okamžik uloží také do databáze (skrze využití metod třídy Recipes).
3.4
Shrnutí
Existuje mnoho metodik pro vývoj software. Ty se od sebe liší jednotlivými fázemi životního cyklu aplikace, jejich trváním, celkovým uspořádáním, délkou iteračního cyklu atd. Tento návod ukazuje jednu z možností, jak vytvářet aplikace s využitím vzorů. Jednotlivé fáze návrhu zde popsané je potřeba přizpůsobit požadavkům aplikace i zákazníka. Jinak by například vypadal vývoj webové služby nebo konzolové aplikace. Pokud bychom vyvíjeli stejnou aplikaci se stejným návrhovým vzorem, ale rozhodli se pro přístup Presenter First (popsaný v druhé kapitole), tak by pořadí jednotlivých kroků bylo také jiné. Tento tutoriál popsal proces tvorby do stavu vytvoření funkčního prototypu aplikace. Zde samozřejmě proces nekončí, ale následují další kroky, kterými budou zejména testování, tvorba designu, případně prezentace klientovi.
4
ANALÝZA A NÁVRH PŘÍPADOVÉ STUDIE
4
34
Analýza a návrh případové studie
4.1
Specifikace požadavků
Analýza a návrh Aplikace vychází ze specifikace požadavků, která popisuje případy užití, motivaci k vytvoření Aplikace a také cílového uživatele. Podrobná specifikace požadavků včetně funkčních i nefunkčních požadavků je rozepsána jako samostatný dokument. Základní popis programu Program by měl být kvalitní software pro nutriční poradce, který jim snadno umožní vést evidenci klientů a jejich kontrol, orientovat se v databázi surovin, jídel, jídelníčků a celých sestav, vyhodnocovat stávající návyky klientů a sestavovat jim optimalizované jídelníčky dle zamýšleného cíle. Výstupem programu jsou tiskové sestavy. Příklad použití K lékaři přijde obézní pacient, lékař mu zřídí kartu s osobními údaji (jméno, kontakt, narození, populační kategorie), zaznamená k návštěvě aktuální údaje (váha, tlak, cholesterol atd.), zanalyzuje a vyhodnotí stávající jídelníčky za týden (analýza probíhá porovnáním doporučených denních dávek pro danou populační kategorii), sestaví přesný program na týden, předá klientovi vyhodnocení stávajícího jídelníčku, nový program na týden, případně graficky znázorněné rozdíly mezi nimi. Po týdnu kontrola, opět vyhodnotí skutečnost, zaznamená aktuální hodnoty klienta a sestaví nový program dle aktuálních potřeb. Po několika návštěvách může vytisknout pacientovi trendovou zprávu s grafickým vyjádřením. Přehled hlavních funkcí Hlavní funkce aplikace jsou: • evidence klientů a jejich návštěv, • sestavování jídelníčků a sestav z databáze surovin, • přiřazení sestav nebo jídelníčků klientům, • tisk reportů a jídelníčků. Důležité objekty Ze specifikace požadavků vyplývají tyto důležité objekty, se kterými bude uživatel pracovat v Aplikaci: • databáze potravin a nutrientů; • jídelníčky a sestavy jídelníčků;
4.2
Scénáře užití
35
• doporučené denní dávky; • klienti a jejich údaje; • návštěvy klientů (kontroly) a sledované hodnoty (váha, cholesterol,. . . ).
4.2
Scénáře užití
Scénáře popisují příklady situací, ve kterých bude uživatel aplikaci používat. Tyto pomohou k lepšímu porozumění užití aplikace a mohou být využity zejména při návrhu uživatelského rozhraní. Scénář: Práce s databází (kartotékou) klientů Cíl: aplikace uchovává databázi klientů nutričního poradce a jejich údaje. Tuto databázi může uživatel libovolně rozšiřovat a upravovat. Kdy: rozšiřovat a upravovat data o klientech lze např. přepisováním klientů z papírové kartotéky, nebo při první návštěvě klienta může být vytvořen jeho záznam a vyplněny údaje. Úkoly: přidání klienta, editace klienta, odebrání klienta. Scénář: Sestavování a práce s databází jídelníčků Cíl: umožnit vytváření a editaci anonymních jídelníčků, tj. jídelníčků, které nejsou svázány s žádným klientem a mohou být využity později. Kdy: Sestavovat nové jídelníčky lze kdykoliv. Úkoly: vytváření, editace a odebírání jídelníčků. Jejich kategorizování do skupin např. podle dietních omezení (bezlepkové, vegetariánské,. . . ). Práce s databází potravin a nutrientů. Scénář: Návštěva klienta Kdy: klient přijde na návštěvu k nutričnímu poradci. Cíl: zaevidovat návštěvu klienta a s tím spojená data. Úkoly: 1. Nalezení klienta v databázi (pokud je to nový klient, tak vytvoření nového). 2. Vytvořit novou návštěvu a vyplnění sledovaných údajů k této návštěvě (váha, cholesterol,. . . ). 3. Volitelně vyhodnocení přineseného jídelníčku. 4. Vytvoření nebo přiřazení jídelníčku nebo sestavy jídelníčků. 5. Tisk sestavy nebo reportu pro klienta.
4.3
4.3
Objektový a datový model
36
Objektový a datový model
Datový model Vychází z důležitých objektů a vztahů mezi nimi. Základním prvkem je potravina (Eatable) a její nutrienty. Z potravin se mohou skládat recepty (Recipe) nebo jídelníčky (Diet), přičemž jídla v jídelníčku jsou rozdělena podle jídel (Meal ). Z více jídelníčků se skládá sestava (Program), která může být svázána s konkrétní návštěvou (CheckUp) jako vyhodnocení nebo návrh. Návštěva je svázána s klientem (Client). Tyto entity tvoří základ datového schématu, pro uložení objektů v databázi. U každé entity jsou sledovány relevantní atributy.
Obr. 9: Datové entity a vztahy mezi nimi
Architektura aplikace Architektura aplikace je založena na třívrstvém modelu oddělujícím datovou, aplikační a prezentační vrstvu. Jako programovací jazyk pro implementaci byl zvolen objektový jazyk C# na platformě .NET, proto entitám z datové vrstvy mohou odpovídat třídy resp. objekty v aplikační vrstvě a ty budou interagovat s uživatelem
4.4
Uživatelské rozhraní
37
skrze prezentační vrstvu (uživatelské rozhraní). Za tímto účelem využijeme varianty návrhového vzoru MVC (Model-View-Controller ), vzor MVVM (Model-ViewViewModel ).
4.4
Uživatelské rozhraní
Cílový uživatel Účel a hlavní funkce aplikace jsou popsány ve specifikaci. Předpokládaný cílový uživatel aplikace je lékař specialista – nutriční poradce. Budeme předpokládat tyto vlastnosti cílového uživatele aplikace: • vyšší vzdělání a s tím související schopnost pracovat s odborným názvoslovím ze svého oboru; • základní počítačová gramotnost. Rozhodně nelze od uživatele očekávat nadprůměrné technické a počítačové znalosti. Základní procesy a funkcionalita Toto jsou podstatné úkoly, ke kterým bude aplikace uživateli sloužit: • vyhledání správného klienta (ze seznamu klientů); • zobrazení nebo editace údajů klienta; • vytvoření nového klienta; • vyhledání návštěvy u vybraného klienta; • založení nové návštěvy a vyplnění sledovaných hodnot; • prohlížení zadaných sestav jídelníčku u vybrané návštěvy; • zadání nových sestav jídelníčků k vybrané návštěvě; • porovnání stravovacích návyků s doporučenými plány; • tvorba jídelníčku nebo sestavy (nesvázané s návštěvou); • kontrola jídelníčku oproti doporučeným denním dávkám (DDD); • tisk vybraných jídelníčků a sestav. Tyto úkoly lze seskupit tematicky podle objektů, kterých se týkají zhruba do tří hlavních skupin: • úkoly spojené s klientem; • úkoly spojené s návštěvou; • úkoly spojené s jídelníčky a jejich vyhodnocováním.
4.4
Uživatelské rozhraní
38
Návaznosti Některé úkony navazují na jiné. Například návštěvu je možní vybrat až po té, co je vybrán klient a až po výběru návštěvy je možné zadávat sestavy. Naproti tomu nesvázané sestavy je možno zadávat rovnou nezávisle na stavu klientů a návštěv. Zjednodušeně lze tedy říci, že uživatel se na začátku může rozhodnout, jestli chce pracovat s klientem nebo nesvázaným jídelníčkem. Pokud se rozhodne pracovat s klientem, provede výběr, poté vybere nebo založí návštěvu a k té může přiřadit některý jídelníček nebo sestavu. Funkcionalita a komponenty Nyní se pokusíme každou z těchto tří skupin charakterizovat pomocí abstraktních komponent. Pro práci s klientem je potřeba mít k dispozici: • seznam klientů (s nástroji pro výběr); • seznam nástrojů (akcí), které lze s klientem provést. Pro práci s návštěvou: • seznam návštěv (s nástroji pro výběr); • hodnoty návštěvy (zobrazení a zadání); • seznam nástrojů (akcí) pro práci s návštěvou. Pro práci s jídelníčkem: • seznam potravin v daném jídelníčku (seskupených do jídel); • seznam potravin a jídel, která lze přidat; • informace o celkovém součtu nutrientů (porovnání oproti DDD); • seznam nástrojů (akcí), pro práci s jídelníčkem. Rozložení aplikace Uvážíme tři možnosti, jak lze výše popsané úkoly a jim přiřazené abstraktní komponenty rozložit do aplikace: 1. Rozložení do více oken: každý úkon by byl v samostatném okně. a) Výhody: uživatel by si mohl rozložení aplikace (oken) přizpůsobit dle svých představ. b) Nevýhody: Vzhledem k počtu dílčích úkolů by to znamenalo dohromady více jak 12 oken. Nároky na uživatelovu schopnost organizovat si prostor a rozumět aplikaci by tak byly velmi vysoké.
4.4
Uživatelské rozhraní
39
2. Jedno okno měnící obsah: všechny úkoly by probíhaly v jednom okně. Vzhledem k množství úkolů by to znamenalo mnoho „klikání sem a tamÿ a uživatel by si musel udržovat dobrou orientaci v „cestáchÿ mezi jednotlivými úkoly. 3. Jedno dělené okno s panely: a) Výhody: oproti druhé možnosti umožňuje vidět více věcí paralelně (např. vybraného uživatele a zároveň jídelníčky) a oproti první možnosti nezatěžuje uživatele s nutností vytváření organizace b) Nevýhody: Pro všechny úkoly je i tak množství panelů v jednom okně poměrně velké. Jako nejlepší se tedy jeví kombinace třetího a prvního přístupu. Z návaznosti úkolů a jejich tematického seskupení (viz předchozí kapitoly) se zdá jako dobrý přístup rozdělit aplikaci na dva hlavní okruhy, které seskupují akce, které spolu tematicky souvisí. Jeden nabízející akce pro práci s klientem a návštěvou, druhý nabízející akce pro práci s jídelníčkem. Každé toto tematické seskupení může být implementováno jako vlastní dělené okno s panely. Okno klienti a návštěvy Na základě výše popsané funkcionality a úkolů bude toto okno obsahovat: 1. Seznam klientů. 2. Pro vybraného klienta seznam návštěv. 3. Pro vybranou návštěvu její hodnoty. Všechny tyto (klienty, návštěvy a jejich hodnoty) lze vytvářet nové, procházet existující, upravovat a mazat. Ke konkrétní návštěvě lze přidat sestavu jídelníčků jako vyhodnocení nebo návrh. Okno jídelníčky a sestavy Na základě výše popsané funkcionality a úkolů bude toto okno sloužit k prohlížení, vytvoření nebo editaci jídelníčku nebo sestavy. Obsahuje jednotlivé dny sestavy, jejich denní jídla (snídaně, oběd,. . . ) a v nich jednotlivé potraviny s množstvím a nutrienty. Při editaci a prohlížení jídelníčku svázaného s klientem zobrazuje vyhodnocení oproti doporučeným denním dávkám. Okno by mělo umožňovat rychle vyhledávat a vkládat potraviny do jídelníčku. Návrhy obrazovek Toto jsou návrhy obrazovek, které zobrazují jednu z možností, jak mohou být implementovány abstraktní komponenty z kapitoly Funkcionalita a komponenty, respektující navržené rozložení aplikace.
4.4
Uživatelské rozhraní
Obr. 10: Návrh obrazovky Klienti a Návštěvy
Obr. 11: Návrh obrazovky Sestavy a Jídelníčky
40
5
IMPLEMENTACE PŘÍPADOVÉ STUDIE
5
41
Implementace případové studie
Tato kapitola popisuje implementaci návrhového vzoru MVVM v případové studii. Implementace vychází z analýzy a návrhu popsaného v předchozí kapitole. Aplikace je realizována na platformě .NET 4.0 v programovacím jazyce C# verze 4.0. Uživatelské rozhraní je postaveno na technologii WPF 4.0 a je vytvořeno v deklarativním jazyce provádět.
5.1
Použité technologie
V dokumentaci je .NET Framework popsán jako součást systému Windows, umožňující vytváření a spouštění aplikací a webových služeb. Framework obsahuje dvě hlavní komponenty: modul CLR (Common Language Runtime) a knihovnu tříd. Modul CLR spravuje kód v době provádění programu, poskytuje základní služby, jako je například správa paměti, správa vláken a vzdálená komunikace. Knihovna tříd, druhá hlavní komponenta .NET Frameworku je všeobecná, objektově orientovaná kolekce opakovaně použitelných tříd, které lze použít pro vývoj aplikací. (Dokumentace MSDN, 2010) K práci s .NET Frameworkem lze využít všech CLI11 jazyků jako jsou například C# a F#. Jazyk C# vznikl jako objektově orientovaný jazyk vyšší úrovně určený pro programovaní v .NET Frameworku. Dnes, v jeho čtvrté verzi, je popisován jako multiparadigmatický programovací jazyk, umožňující imperativní, deklarativní, funkcionální, generické a objektově orientované programování. Pro porozumění dalšího textu je nezbytné znát základy objektově orientovaného programování a alespoň základy syntaxe jazyka C#. Klíčové prvky jazyka, které se mohou lišit od jiných OOP jazyků jsou tyto: Property jsou jedním ze dvou druhů atributů, které třídy a objekty v C# mohou mít. Prvním jsou klasické Fields, udržující hodnotu zvoleného datového typu. Přistupuje se k nim pomocí tečkové notace objekt.vlastnost = hodnota. Druhým jsou Properties, které také udržují hodnotu zvoleného datového typu, krom toho ale při čtení a při zápisu této hodnoty mohou vykonat nějaký kód. Syntaxe zůstává stejná jako u práce s jednoduchými atributy tedy objekt.Property = hodnota. Je dobrým zvykem Property pojmenovávat s prvním písmenem velkým a Fields s prvním písmenem malým. Property lze přirovnat k používání Getterů a Setterů v Javě s tím rozdílem, že Property není metodou ale syntakticky se s ní pracuje jako s jednoduchým atributem. Events neboli události umožňují třídě nebo objektu dát na vědomí jiné třídě nebo objektu, že nastala nějaká změna. Třída, která událost oznamuje (raises) se nazývá Publisher a třída, která na událost reaguje (handles) se nazývá Subscriber. Při zpracování událostí se využívá Delegátů, což jsou ukazatele na funkce. 11
Common Language Infrastructure
5.2
Více o implementaci vzoru MVVM
42
LINQ neboli Language Integrated Query je součástí .NET Frameworku a rozšíření jazyka C# od jeho třetí verze. LINQ umožňuje provádět dotazy a operace nad daty, podobným způsobem jako SQL, přímo v programovacím jazyce. LINQ je obecný nástroj, data mohou pocházet z kolekcí objektů, relačních databází, XML souborů a dalších. WPF (Windows Presentation Foundation) je Microsoftem vyvinutý grafický subsystém pro vykreslování uživatelského rozhraní. WPF je postavené na vektorovém renderovacím enginu, využívajícím DirectX místo GDI12 a umožňuje tak snadno provádět grafické operace jako jsou přibližování, posunování a rotace s prvky uživatelského rozhraní bez ztráty kvality. WPF je navržené tak, aby využívalo možností moderního hardwaru pro grafickou akceleraci. WPF existuje jako součást frameworku .NET a nabízí mnoho prvků a funkcí usnadňujících vývoj aplikací, jsou jimi zejména XAML (Extensible Application Markup Language), připravené UI komponenty, data binding, práce s layoutem 2D a 3D grafiky, animace, styly, šablony, funkce pro práci s dokumenty, multimédii, textem a typografií. (Dokumentace MSDN, 2010)
5.2
Více o implementaci vzoru MVVM
Návrhový vzor MVVM se objevil v roce 2005 (Smith, 2009). Od té doby vzniklo relativně velké množství frameworků usnadňujících jeho použití. Prvním důvodem je fakt, že při implementaci aplikace podle vzoru MVVM se určité množství kódu vždy opakuje. Jde o kód, který je nezávislý na aplikaci, souvisí pouze s implementací vzoru MVVM. Především kód vrstvy ViewModelu, například mechanismus notifikace o změně vlastnosti objektu (rozhraní INotifyPropertyChanged ), který je potřebný pro data binding. Dalším příkladem je implementace rozhraní ICommand nebo způsob komunikace mezi nezávislými ViewModely (řeší se často zasíláním zpráv podle vzoru Messenger ). Druhým důvodem pro značnou roztříštěnost a velký počet frameworků pro implementaci MVVM je to, že Microsoft dlouho žádný oficiální nástroj nevydal. Teprve až v poslední době se dostalo oficiální podpory v podobě WPF Application Framework (WAF)13 , WPF Model-View-ViewModel Toolkit 14 a MVVM Training 15 . V případové studii jsem k implementaci těchto základních funkcí MVVM vytvořil vlastní třídy: ObservableObject je abstraktní třída pro objekty poskytující automatické informace o změnách vlastností. Za tímto účelem implementuje rozhraní INotifyPropertyChanged. 12
Graphics Device Interface http://waf.codeplex.com/ 14 http://wpf.codeplex.com 15 Ke stažení na http://visualstudiogallery.msdn.microsoft.com 13
5.3
Implementační detaily View
43
SavableObject implementuje třídu ObservableObject. Rozšiřuje objekt o stav rozlišující, zda se od posledního uložení změnila nějaká data objektu. Vhodné jako rodičovská třída pro ViewModely, které reprezentují běžné business objekty. V případové studii je tato třída použita pro Klienta a Návštěvy. SelectableExpandableObject navíc přidává vlastnosti IsSelected a IsExpanded. Vhodné pro objekty v seznamech, napříkad položky zobrazené v komponentách ListBox nebo TreeView. RelayCommand implementuje rozhraní ICommand pro vykonávání příkazů pomocí delegátů. Messenger poskytuje prostředky pro komunikaci nezávislých objektů pomocí zasílání zpráv. Reference na objekty je realizována slabou vazbou, aby nedocházelo k zabránění uvolnění paměti Garbage Collectorem.
5.3
Implementační detaily View
Při spuštění aplikace se jako první zobrazí okno Klienti a Návštěvy. Uživatelské rozhraní je realizováno pomocí několika vnořených View. Na nejvyšší úrovni okna (MainWindow.xaml) je nastaven DataContext okna na ClientsAndCheckupsViewModel. Krom toho bsahuje okno pouze layout a další View pro horní menu. <Window x:Class="NP.MainWindow" ... <Window.DataContext> ... Hlavní komponentou pro zobrazení obsahu celého okna je ClientsAndCheckupsView implementovaný v souboru ClientsAndCheckupsView.xaml. Tato komponenta dědí nadřazený DataContext, což při její inicializaci (tedy při prvním zobrazení okna) automaticky vytvoří instanci třídy ClientsAndCheckupsViewModel. Krom toho obsahuje už jen mřížku pro layout a tři vnořené View. <UserControl ... DataContext="{Binding}"> ...
5.3
Implementační detaily View
44
Komponenty ClientsView a CheckUpsView jsou obě komponenty zobrazující seznam objektů. K tomu využívají běžného ListBoxu. Samotné komponenty obsahují pouze informaci o tom, odkud se má vzít seznam prvků a specikace vzhledu celého ListBoxu jako jsou rozměry, barevné schéma, kód pro podbarvení lichých řádků atd. Informace o tom jak mají vypadat jednotlivé položky seznamu jsou uloženy v DataTemplatu pro datový typ ClientViewModel a CheckupViewModel. Konkrétně v komponentě ClientsView je opět DataContext zděděn od nadřazeného elementu a ListBoxu je potom nastavena vlastnost ItemsSource na hodnotu Clients, což je název Property třídy ClientsAndCheckupsViewModel typu ObservableCollection a obsahuje objekty typu ClientViewModel. <UserControl x:Class="NP.Views.ClientsView" ... DataContext="{Binding}"> ...
5.4
Propojení View a ViewModelu
45
se vyvolá příkaz EditClientCommand definovaný ve třídě ClientsAndCheckupsViewModel. Protože příkaz implementuje také metodu CanExecute (jednoduše vrátí true, pokud je nějaký klient právě vybraný, jinak false), tak příslušná tlačítka a položky menu automaticky mění svoji klikatelnost. Data binding Ve WPF existují tři způsoby bindování: OneWay, TwoWay a OneWayToSource. Téměř v celé aplikaci je použito bindování TwoWay neboli obousměrné. To znamená, že pokud se hodnota změní v uživatelském rozhraní (uživatel napíše hodnotu do TextBoxu) nebo na ViewModelu (načtení nových dat z databáze), tak jsou změny automaticky ihned propagovány oběma směry. Bindování lze vidět u komponent, které zobrazují a umožňují editovat detaily Návštěvy (CheckUpDetailView.xaml) nebo Klienta (ClientDetailView.xaml). Shrnutí implementace View Uživatelské rozhraní je tvořeno systémem vnořených komponent (View ), definovaných v jazyce XAML, kterým je pomocí atributu DataContext nastaven příslušný ViewModel. Při první inicializaci grafické komponenty (okna) se vytvoří nová instance třídy ClientsAndCheckupsViewModel, na kterou je možné aplikovat data binding ze samotného okna a všech vnořených komponent. Komponenty zobrazující seznamy objektů (klientů, návštěv) jsou jednoduše nabindovány na kolekci typu ObservableCollection na tomto ViewModelu a způsob grafického zobrazení těchto elementů v GUI je definován v příslušných DataTemplatech.
5.4
Propojení View a ViewModelu
MVVM je velmi flexibilní a nabízí více možných způsobů implementace, aniž by některý z nich byl horší než jiný (to je také jeden z důvodů pro velké množství frameworků). Avšak v každém provedení MVVM jsou nevyhnutelné tři věci: 1. Vytvoření instance View. 2. Vytvoření instance ViewModelu. 3. Napojení View na ViewModel (View má referenci na ViewModel, ViewModel neví o View ). Paul Stovell vyjmenovává 8 možných způsobů, jak lze napojení uskutečnit. Ty nejčastější jsou vytvoření instance ViewModelu v konstruktoru View (v jeho code behind souboru), externí vytvoření a propojení třetí entitou a přiřazení v XAMLu (Stovell, 2010). Moje aplikace využívá poslední možnosti, tedy ViewModel je nastaven jako DataContext v XAML kódu View. Výhodou této volby je snadná možnost práce s testovacími daty v době návrhu aplikace.
5.5
5.5
Implementační detaily ViewModelu
46
Implementační detaily ViewModelu
Všechny ViewModely dědí od některé ze tříd ObservableObject, SavableObject nebo SelectableExpandableObject. Tyto poskytují již základní potřebnou funkcionalitu, zejména mechanismus automatického oznamování o změně hodnot nutný pro data binding. Pokud chce ViewModel oznámit změnu hodnoty nějaké Property, udělá to zavoláním metody RaisePropertyChanged s názvem dané Property v parametru. Takto má ViewModel úplnou kontrolu nad oznamováním změn hodnot, které jsou aktualizovány v uživatelském rozhraní. Například ve třídě CheckUpViewModel (CheckUpViewModel.xaml) je při změně hodnoty Weight oznámena změna nejen samotné Weight, ale také hodnoty BMI, která je na ní závislá. To znamená, že když uživatel změní jednu hodnotu, je ihned aktualizována i druhá a skrz data binding se tato změna zobrazí uživateli. Dílčí ViewModely potom obsahují především tyto části: 1. Jeden nebo více konstruktorů pro vytvoření. Obvykle konstruktor dostane jako parametr nějaká data (Model ), která mají být zprostředkována uživateli. 2. Soukromé atributy (Fields nebo Properties) pro uchování informací o stavu. 3. Observable Properties na které je možné bindovat. 4. Commands jsou veřejné Property typu ICommand. Ty jsou využity k vykonávání příkazů delegovaných z vrstvy uživatelského rozhraní. 5. Metody pro vlastní potřebu, například vykonání příkazů. Commands jsou implementovány jako property typu RelayCommand (třída implementující rozhraní ICommand, uložená v souboru RelayCommand.cs). Ta funguje jednoduše tak, že vykonání příkazu deleguje vybrané metodě. Práce s kolekcí objektů Zajímavým příkladem spolupráce View s ViewModelem v návrhovém vzoru MVVM je způsob, jakým fungují seznamy objektů. V okně Klienti a Návštěvy jsou dva seznamy objektů – seznam klientů a seznam návštěv právě vybraného klienta. Oba jsou zobrazeny v ListBoxu s vlastním DataTemplatem. ListBox je naplněn nastavením vlastnosti ItemsSource na hodnotu, která představuje seznam objektů. V případě klientů je DataContextem objekt typu ClientsAndCheckupsViewModel, na jehož atribut Clients typu ObservableCollection je ListBox nabindovaný. Kolekce Clients obsahuje jako jednotlivé prvky objekty typu ClientViewModel. Aktuálně vybraný klient. Protože třída ClientViewModel dědí od SelectableExpandableObject je k dispozici atribut IsSelected, který je v ListBoxu nabindován na vybranou položku. Tento binding je obousměrný, to znamená, že když uživatel vybere ze seznamu nového klienta, tak se tato změna projeví přímo ve ViewModelu a naopak pokud je programově na ViewModelu v kolekci klientů nějaký označený za vybraného, projeví se to automaticky v uživatelském rozhraní změnou vybrané
5.6
Implementační detaily Modelu
47
položky. ViewModel si v tomto případě udržuje samostatný atribut CurrentClient, který je důležitý pro další operace, například zobrazení návštěv právě vybraného klienta. Automatická synchronizace aktuálně vybrané položky mezi seznamem zobrazeným v uživatelském rozhraní a kolekcí datových objektů (které nevědí nic o uživatelském rozhraní) v paměti velmi usnadňuje a zpřehledňuje práci se seznamem objektů. K snadnému filtrování seznamů poskytuje WPF třídu CollectionViewSource. Ta rozšiřuje třídu ObservableCollection kromě filtrování také o možnost řadit a seskupovat objekty. Tyto změny se automaticky projeví v data bindingu bez toho, aniž by se změnila originální kolekce objektů. Tedy při zadání omezujícího filtru bude v původní kolekci stále stejný počet prvků, ale v uživatelském rozhraní se zobrazí pouze ty, které vyhovují filtru. Tento filtr je aplikován u kolekce klientů. Při změně textu v TextBoxu rychlého hledání se tato změna projeví díky data bindingu ve ViewModelu, který upraví filtr kolekce a ta je v uživatelském rozhraní aktualizována. Žádná z těchto tříd pro práci s kolekcemi neví nic o uživatelském rozhraní a není potřeba ručně přidávat, odebírat nebo znovu naplňovat ListBox nebo jiné komponenty. A naopak ListBox pouze potřebuje vědět název Property na kterou se má bindovat a to je vše. Použití je vidět v Property ClientsFilter třídy ClientsAndCheckupsViewModel.
5.6
Implementační detaily Modelu
Model představuje doménová data, která aplikace uživateli zprostředkovává. V případě nutriční aplikace jde o data týkající se klientů, jejich návštěv a jejich jídelníčků složených z potravin. Samotná data jsou uložena v lokální databázi Microsoft SQL Server Compact (SQL CE). Tato databáze nabízí možnosti relačních databází s tou výhodou, že vše je uloženo zcela lokálně v souborech. Samotné metody na práci s SQL CE jsou součástí .NET Frameworku, není tedy potřeba instalovat žádný databázový server. To ocení také uživatelé, protože například lokální instalace pokročilejších databází typu Microsoft SQL Server vyžaduje v instalačním procesu nějakou účast od uživatele. Nevýhodou této databáze je omezená funkcionalita oproti jiným databázovým systémům a výkon, tedy rychlost zpracování požadovaných operací. Nad samotnou databází, která zajišťuje perzistenci dat, je vytvořena další datová vrstva (Model ). To jsou data, která jsou v paměti v době běhu programu a jsou dále poskytnuta vrstvě ViewModelu nebo v některých částech aplikace (viz dále) jeho alternativě. Model se také stará o aktualizaci dat a o jejich opětovné uložení do databáze. V první iteraci implementace byl Model z velké části implementován pomocí LINQ to SQL, což je komponenta .NET Frameworku, která poskytuje runtime infrastrukturu pro práci s relačními objekty. LINQ to SQL patří mezi nástroje a techniky označované ORM (Object–relational mapping) i když LINQ to SQL nenabízí tolik možností jako třeba NHibernate, splňuje základní funkci. Na základě schématu databáze vytvoří objekty, se kterými lze pracovat při běhu programu a změny na
5.6
Implementační detaily Modelu
48
nich potom lze převést zpět do databázové formy. K tomuto byl použit nástroj SQL Metal, který ze souborové databáze SQL CE vytvoří datový typ nazvaný DataContext. Shoda názvu s DataContextem ve View, který složí k bindování na ViewModel je pouze náhodná, jde o zcela rozdílné věci. Tento DataContext obsahuje další třídy podle schématu databáze. Zjednodušeně lze říct, že každá tabulka v databázi zde má svůj typ. Například při vytváření instance ClientViewModel je tomuto jako parametr v konstruktoru předán objekt typu Client, což je třída vygenerová nástrojem SQL Metal. Tato implementace brzy odhalila jeden problém. DataContext má mít podle dokumentace16 krátký životní cyklus. Nepředpokládá se u něj, že by jeho instance existovala celou dobu spuštění programu, ale spíše, že bude při každé změně databáze vytvořen nový DataContext. Toto spolu s pomalejší odezvou integrované databáze SQL CE způsobilo v některých částech aplikace dlouhou odezvu na běžné operace. Šlo zejména o práci s potravinami. Tato tabulka má řádově tisíce záznamů. Při návrhu a práci s jídelníčky v okně Sestavy a Jídelníčky často odezva na reakci uživatele trvala déle než jednu sekundu, často i několik sekund. Tento problém je možné řešit více možnostmi: • akceptovat delší odezvu a vytvořit odpovídající změny v uživatelském rozhraní (informace o probíhající akci); • vytvořit cache vrstvu nad stávajícím DataContextem; • nahrazení DataContextu jiným Modelem. V programu je nakonec pro část zabývající se potravinami a jídelníčky použit jiný Model. Místo LINQ to SQL se na vygenerování těchto business objektů, odpovídajících entitám v databázi, používá ADO.NET. Výstupem je třída DataSet, která funguje podobně jako DataContext. Má tu nevýhodu, že nelze na operace s daty používat LINQ, ale je navržen pro delší životní cyklus (předpokládá se jedna instance po dobu spuštění aplikace) a dobře využívá vlastní cache. Protože DataSet má trochu jinou strukturu než DataContext a také protože při vytváření jídelníčků z potravin je potřeba s daty pracovat trochu jiným způsobem než při práci s klienty, je nakonec vrstva spojující View a Model v tomto případě implementována přímo v code behind souborech View. Všechny metody pro práci s databází a vytváření Modelů jsou ve třídě Data.cs, která obsahuje pouze statické metody.
16
http://msdn.microsoft.com/en-us/library/system.data.linq.datacontext.aspx
6
6
ZÁVĚR
49
Závěr
V první části práce jsem popsal architektonické návrhové vzory MVC (Model-ViewController ), MVP (Model-View-Presenter ) a MVVM (Model-View-ViewModel ) po teoretické stránce. Druhá kapitola přibližuje jejich historický a technologický kontext a porovnává je mezi sebou. Zjištěné rozdíly, které se týkají zejména způsobu zpracování uživatelského vstupu a komunikace mezi dílčími objekty, jsou shrnuty v závěru kapitoly. Toto shrnutí může sloužit jako pomůcka ulehčující rozhodnutí, který z těchto návrhových vzorů vybrat při implementaci konkrétní aplikace nebo jak poznat již implementovaný návrhový vzor z kódu. Použití vzorů v procesu návrhu aplikace je věnována třetí kapitola. Ta ilustruje jednotlivé kroky návrhu na jednoduchém příkladě a je použitelná jako samostatný návod. Ten je určen pro ty, kdo si přejí zlepšit své dovednosti a vytvářet aplikace s využitím systematického přístupu a dobrých praktik. Vzor MVP je ze všech tří návrhových vzorů nejuniverzálnější a lze ho realizovat ve velkém množství programovacích jazyků a technologií. Proto byl vybrán v implementační části návodu. Případová studie měla za úkol ověřit praktické nasazení vzoru MVVM na větší aplikaci. Jako případovou studii jsem vytvářel aplikaci pro nutriční poradenství ve spolupráci s MUDr. Petrem Ciklem, který je známým nutričním specialistou. Implementace prošla několika evolučními fázemi, které obměňovaly některé použité komponenty a technologie. První implementace využívala databáze MS SQL Express, kterou jsem později nahradil kompaktní databází MS SQL CE. V poslední verzi jsou také využity některé placené komponenty uživatelského rozhraní od firmy Telerik. Případová studie byla dostatečně komplexní, aby se na ní dalo aplikování vzoru MVVM posoudit. Na programu dále pracujeme s MUDr. Petrem Ciklem. Jednou z věcí, kterou je potřeba vylepšit je design uživatelského rozhraní. Protože díky vzoru MVVM je vytvořené dobré oddělení grafických komponent od aplikační logiky a dat, bylo možné tento aspekt aplikace nechat na pozdější spolupráci s grafikem. Prototyp programu byl představen na konferenci nutričních poradců, kde sklidil pozitivní ohlasy. Implementační detaily případové studie jsou popsány v páté kapitole a usnadní práci zájemcům o využití tohoto vzoru v prostředí .NET a jazyce C#. Pozornost je věnována tomu, jak vytvářet vnořené uživatelské komponenty v jazyce XAML, různým možnostem propojení s ViewModelem skrze DataContext, způsobům bindování, využití DataTemplatů a dalších podrobností. Detailů, se kterými se musí programátor seznámit při implementaci MVVM je poměrně mnoho. Nasadit tento návrhový vzor se tedy vyplatí až u větších aplikací. MVVM je relativně mladý návrhový vzor a existuje zde jistá roztříštěnost v oblasti nástrojů a dokumentace. V době psaní práce existovalo 14 frameworků k jeho implementaci. V práci nakonec využívám několik mnou navržených znovupoužitelných tříd, které pomáhají vzor MVVM realizovat. Aby mohla aplikace využít všech výhod návrhového vzoru MVVM, je potřeba, aby jej respektovaly všechny vrstvy. V ekosystému okolo frameworku .NET je běžné využití placených komponent. Ty rozšiřují nebo nahrazují základní kompo-
6
ZÁVĚR
50
nenty dodávané s .NET Frameworkem. Zejména u komponent uživatelského rozhraní technologie WPF (Windows Presentation Foundation) je to běžné. To, jak tyto komponenty podporují vzor MVVM, také ovlivní jeho celkovou použitelnost. Podobně je tomu s datovou vrstvou. Například při použití některých ORM (Object–relational mapping) nástrojů může v kombinaci s MVVM přístupem vzniknout v logické vrstvě zbytečná duplicita. Z toho důvodu jsem nevyužil MVVM přístup v celé aplikaci, ale jen v těch částech, kde je jako Model použit LINQ to SQL. Jedná se o tu část programu, která se zabývá klienty a návštěvami. Problematika tvorby aplikací je velmi širokou oblastí. Tato práce pojednává zejména o obecných aplikacích, které uživateli zprostředkovávají specifická data za využití třívrstvé architektury. Avšak s aktuálními trendy v oblasti IT (sociální sítě, služby využívající geolokaci, doplněná realita,. . . ) se otevírají zcela nové typy aplikací, které vyžadují specifický přístup. Příkladem jsou právě aplikace pro sociální média nebo aplikace pro chytrá mobilní zařízení, jejichž počet v posledních letech stále roste. Aby byly tyto aplikace úspěšné, je nutné nejen pečlivě zkoumat psychologické aspekty komunikace a chování, ale i využívat nové koncepty, které tyto platformy přináší (např. sociální graf). Podrobněji se tvorbou sociálních aplikací zabývají například Crumlish a Malone v knize Designing Social Interfaces (Crumlish a Malone, 2009). Existují také výzkumy, které detailněji zkoumají jednotlivé komponenty, například vyhledávací pole. Vyhledávání je dnes nedílnou součástí většiny aplikací a Morville a Callender jej popisují jako záležitost, které je potřeba se nadále věnovat, protože se nejedná o vyřešený problém (Morville a Callender, 2010). I v rámci klasických aplikací, kterým se tato práce věnuje, se objevují nové možnosti a technologie. V oblasti datové vrstvy se v posledních letech objevilo několik nových typů databází, souhrnně označovaných termínem NoSQL. Ty umí data uchovávat přímo v podobě objektů, grafů, dokumentů, a dalších. Ekosystém produkce softwaru také mění velké společnosti jako Amazon, které poskytují služby typu Cloud Computing a Cloud Storage. S tím souvisí nové možnosti jak provozovat aplikace (Software as a Service). Jak je vidět, problematikou popsanou v této práci proces tvorby aplikací zdaleka nekončí, ale spíše začíná.
7
7
LITERATURA
51
Literatura
Alexander, Ch. Notes on the Synthesis of Form. Harvard University Press, 1964. ISBN 0–674–62751–2. Alles, M., Crosby, D., Erickson, C., Harleton, B., Marsiglia M., Pattison, G., Stienstra, C. Presenter First: Organizing Complex GUI Applications for Test-Driven Development Proceedings of the conference on AGILE 2006. 2006, s. 276-288. ISBN 0-7695-2562-8. Boodhoo., J. Model View Presenter MSDN Magazine. 2006, vol. 21, no. 8, s. 43-51. ASIN B00006LKN3. Burbeck, S. Applications Programming in Smalltalk-80(TM): How to use Model–View–Controller (MVC) [online]. 1992. Dostupné na: http://stwww.cs.illinois.edu/users/smarch/st-docs/mvc.html [cit. 21. 2. 2011]. Crumlish, Ch., Malone, E. Designing Social Interfaces. 1. vyd. Sebastopol: O’Reilly Media, 2009. 520 s. ISBN 978–0–596–15492–9. Dvořák, M. Návrhové vzory (design patterns). Vysoká škola ekonomická v Praze, 2003. Diplomová práce. Dostupné na: http://objekty.vse.cz/Objekty/Vzory. Fowler, A. A Swing Architecture Overview [online]. Dostupné na: http://java.sun.com/products/jfc/tsc/articles/architecture/ [cit. 28. 2. 2011]. Fowler, M. GUI Architectures [online]. 2006. Dostupné http://www.martinfowler.com/eaaDev/uiArchs.html [cit. 28. 2. 2011].
na:
Fowler, M. Presentation Model [online]. 2004. Dostupné na: http://martinfowler.com/eaaDev/PresentationModel.html [cit. 11. 3. 2011]. Gamma, E., Helm, R., Johnson, R., Vlisside, J. Design Patterns: Elements of Reusable Object–Oriented Software. Addison Wesley, 1995. ISBN 0–201–63361– 2. Hansen, S., Fossum, T. Refactoring model-view-controller Journal of Computing Sciences in Colleges. 2005, vol. 21, no. 1, s. 120-129. ISSN 1937–4771. Morville, P., Callender, J. Search Patterns. 1. vyd. Sebastopol: O’Reilly Media, 2010. 180 s. ISBN 978–0–596–80227–1. Microsoft Introduction to WPF Windows Presentation Foundation [online]. Dostupné na: http://msdn.microsoft.com/en-us/library/aa970268.aspx [cit. 3. 5. 2011]. Microsoft Konceptuální přehled rozhraní .NET framework Knihovna MSDN [online]. Dostupné na: http://msdn.microsoft.com/library/zw4w595w.aspx [cit. 3. 5. 2011].
7
LITERATURA
52
Potel, M. MVP: Model-View-Presenter The Taligent Programming Model for C++ and Java [online]. 1996. Dostupné na: http://www.wildcrest.com/Potel/Portfolio/mvp.pdf [cit. 28. 2. 2011]. Procházka, D. Sestavujeme aplikaci. Mendelova univerzita v Brně, 2010. Doplňkové materiály k přednáškám kurzu Pokročilá uživatelská rozhraní. Smith, J. Advanced MVVM. Josh Smith, 2010. ASIN B003QF1RKI. Smith, J. WPF Apps With The Model-View-ViewModel Design Pattern MSDN Magazine. 2009, vol. 24, no. 2, s. 72-79. ASIN B00006LKN3. Tidwell, J. Designing Interfaces (Second Edition). 2. vyd. Sebastopol: O’Reilly Media, 2010. 576 s. ISBN 978–1–449–37970–4. Stovell, P. MVVM Instantiation Approaches [online]. 2010. Dostupné na: http://www.paulstovell.com/mvvm-instantiation-approaches [cit. 3. 5. 2011]. Summit, S. C Programming FAQs: Frequently Asked Questions. 2. vyd. Boston: Addison-Wesley Professional 1995. 432 s. ISBN 0–201–84519–9. Šimůnek, M. SQL : kompletní kapesní průvodce. 1. vyd. Praha: Grada, 1999. 247 s. ISBN 80–7169–692–7. Shirky, C. Ontology is Overrated: Categories, Links, and Tags Clay Shirky’s Writings About the Internet [online]. 2005. Dostupné na: http://www.shirky.com/writings/ontologyo verrated.html[cit.3. 5. 2011].