Prezentační vzory z rodiny MVC

Obecné vztahy v architektuře MVC byly obsahem prvního dílu, v dnešním pokračování se podíváme na několik konkrétních vzorů z rodiny MVC. Velkého vstupu na scénu se dočká především vzor MVP, u kterého si ukážeme, v čem se liší od klasického MVC. Podíváme se rovněž na některá specifika webového MVC.

Seriál: MVC a další prezentační vzory (3 díly)

  1. Úvod do architektury MVC 7.5.2009
  2. Prezentační vzory z rodiny MVC 11.5.2009
  3. Alternativy k MVC a závěrečné poznámky 15.5.2009

Po přečtení prvního dílu máte dobrou představu o obecné architektuře MVC, ale jak už jsem zmínil, vedle obecných principů jsou pro reálný vývoj užitečné především jednotlivé variace MVC. Těm je věnováno dnešní pokračování.

Dva velcí kamarádi: MVC a MVP

Ačkoliv vás rozhodně nechci nudit historickými daty a přepisovat něco, co si můžete najít na webu, z praktického hlediska je užitečné podívat se na historický vývoj MVC, protože má zajímavou návaznost na současnost.

První návrh MVC pochází ze 70. let minulého století, kdy sálové počítače ještě uměly uvařit kávu (údajně přiblížením hrnku drženého v azbestové rukavici na vzdálenost 10 cm od výkonné jednotky). V oněch archaických dobách byly vstup a výstup na sobě do značné míry nezávislé – pro jednoduchost si můžete představit, že jeden blok kódu se staral o vykreslení obdélníčků na obrazovku, zatímco jiný zpracovával vstup z klávesnice, horké to novinky tehdejšího světa hardwaru (slovo „myš“ tehdy v počítačových sálech vyvolávalo spíše paniku než cokoliv jiného). Za dané situace není divu, že vznikl vzor MVC, protože v podstatě odrážel stav hardwaru své doby – View vykreslovalo uživatelské rozhraní a Controller zpracovával vstup.

Jak se ale operační systémy a programovací jazyky vyvíjely, input a output se postupně spojily do jednoho (například Button dnes zvládá jak své vykreslení na obrazovku, tak ošetřování událostí myši, klávesnice a dalších zařízení). Tím v podstatě zanikla původní potřeba pro MVC, protože „C“ už nemusel ošetřovat vstup. Také zde se ale postupně přišlo na to, že oddělení aplikačního kódu od definice uživatelského rozhraní je žádoucí, ačkoliv už komponenty teoreticky mohou vstup ošetřovat samy. Právě zde vzniká velký bratr MVC: architektonický vzor MVP (Model-View-Presenter). Od MVC se na obrázku liší jen málo, ale principiálně dost podstatně, jak uvidíme za chvíli.

Tím ale historie nekončí. V devadesátých letech na scénu vstupuje web, a světe div se, opět tu máme platformu, která neumí pořádně sloučit vstup a výstup (výstup je HTML, vstup je URL). Asi vás nyní nepřekvapím, když řeknu, že schéma fungování dnešních webových MVC frameworků je v zásadě stejné jako původní MVC ve Smalltalku.

Myslíte, že tady už končíme? Nikoliv… Kolem přelomu tisíciletí se objevuje technologie ASP.NET, která, ač webová, přišla s konceptem ovládacích prvků, které si napříč HTTP requesty udržují stav a umí reagovat na události podobně jako desktopové platformy. Zde opět MVC ztrácí smysl, protože vstup je ošetřen rovnou ve View, ale zcela podle očekávání lze pro ASP.NET Web Forms použít vzor MVP.

Vidíte tu zákonitost?

  • platforma s odděleným vstupem a výstupem: aplikovatelný je vzor MVC, kde „C“ zpracovává vstup
  • platforma s konceptem ovládacích prvků: aplikovatelný je vzor MVP, kde vstup zpracovává View a úloha Presenteru se mění

Protože je dnes jedinou široce rozšířenou „platformou s odděleným vstupem a výstupem“ web, MVC najdete především tam. Naopak vzhledem k tomu, že dnešní klientské technologie jsou prakticky všechny „widgetové“, nemá v nich klasické MVC příliš uplatnění a typicky se použije MVP.

Aby nebylo zmatení málo, s Controllerem se můžete setkat i v aplikacích widgetového typu. Tam však nemá na starost zpracování uživatelského vstupu, ale typicky se zabývá instrukcemi vyšší úrovně. Controller například může zachytávat události, které k němu „probublají“, a může je mapovat na nějakou funkcionalitu (ta může být zapouzdřena například do objektů implementujících vzor Command). Controlleru v tomto pojetí se někdy říká Application Controller a jeho přítomnost se nevylučuje s přítomností Presenterů.

Pojďme se nyní na jednotlivé vzory podívat.

Vzor MVC

Schéma vzoru MVC

Schéma je v podstatě grafickým shrnutím všeho, co byste už nyní měli vědět. Tok událostí v aplikaci vypadá následovně:

  1. Uživatel vykoná nějakou akci na uživatelském rozhraní
  2. Ta je zachycena Controllerem
  3. Controller rozhodne, jak na akci zareagovat, a typicky změní nějaké hodnoty v Modelu nebo přímo ovlivní View
  4. View zobrazí změny uživateli

Tento koloběh se potom opakuje. Na schématu ještě vidíte, že Controller obsahuje vazbu na View, což je v MVC frameworcích docela typické, ale tato vazba je méně důležitá než schopnost Controlleru upravit Model. Vztah Controlleru a View je obvykle takový, že Controller rozhoduje, které View zobrazit, nic moc navíc.

(Poznámka: pokud čirou náhodou budete studovat i úplně první implementaci MVC ve Smalltalku, možná vás zarazí, že View tehdy mělo přímou vazbu na Controller. Tehdy to byl ale implementační detail, ne způsob, jakým by View posílalo Controlleru jakékoliv zprávy.)

MVC v prostředí webu

Jak bylo řečeno, s MVC se dnes nejčastěji setkáte ve webových technologiích. Protože ale téměř všechny prezentační vzory původně vzešly z desktopových technologií, je u webového MVC potřeba některé drobnosti dovysvětlit, případně upravit.

Úplně na začátku musím upozornit na to, že klasická webová aplikace se z pohledu třívrstvého modelu výrazně liší od plně AJAXové aplikace typu GMail. Zatímco klasická aplikace bere prohlížeč pouze jako tupé zobrazovací zařízení a veškeré uživatelské rozhraní (HTML) generuje na serveru, plně AJAXová aplikace naopak spoléhá na přítomnost JavaScriptu a podstatná část prezentační logiky se přesouvá na klienta. Jak asi sami cítíte, mezi prezentační vrstvou realizovanou na serveru a na klientovi je dramatický rozdíl – serverové MVC proto bude potřebovat technologii jako např. Zend Framework nebo ASP.NET MVC, klientské MVC naproti tomu bude realizováno v JavaScriptu. V dnešní době se navíc často potkáte se třetí skupinou aplikací, která AJAX drobně používá, ale pouze jím doplňuje jinak klasický model. Zde je prezentační vrstva realizována jak na serveru, tak částečně na klientovi a MVC by tedy teoreticky šlo použít na obou stranách.

Slušný zmatek, že? V praxi naštěstí narazíte s drtivou většinou na aplikace, kterým stačí serverové MVC. Plně AJAXových aplikací je minimum a částečně AJAXové aplikace zase neobsahují v JavaScriptu tak komplikovanou logiku, aby se MVC vyplatilo použít. Na následujících řádcích proto „webovým MVC“ budu myslet serverovou implementaci.

Jak tedy v prostředí webu vypadají komponenty M, V a C?

Model je v tomto případě nejjednodušší část, protože je identický s Modelem v desktopových technologiích. (Obsahuje data a business logiku, s konkrétní prezentací nemá nic společného.)

View se někdy říká, že u webové aplikace je to HTML, ale to je jako říci, že u desktopové aplikace se View rovná pixelům na obrazovce, respektive nízkoúrovňovým vykreslovacím instrukcím. View je ve skutečnosti serverový kód, který se o generování HTML stará, tj. PHP, C#, Java, Ruby a podobně. Navíc ani u webové aplikace není nutné, aby bylo výstupem HTML – klidně to mohou být formáty jako XML nebo JSON.

Controller se v prostředí webu nejčastěji skládá ze dvou hlavních částí. První je tzv. Front Controller, který zachytává všechny HTTP požadavky, ty následně zpracuje a přepošle konkrétním Controllerům, což je ona druhá část. Konkrétní Controller potom typicky přijme data původně pocházející z HTTP požadavku, uloží je do Modelu a ten prováže s konkrétním View, které už se umí o vyrenderování HTML nebo jiného formátu postarat.

Všimněte si, že ačkoliv slovní popis ukazuje některá specifika webového MVC, schéma uvedené výše pořád platí. Principiální podobnost s původním MVC je prostě velká.

Vzor MVP a jeho variace

Nyní se dostáváme do světa widgetových systémů, ale to nutně neznamená, že opouštíme prostředí webu. Jak ASP.NET Web Forms, tak řada nových RIA technologií (Flex, Silverlight, JavaFX) mají společné to, že jsou jako stvořené pro MVP (Model-View-Presenter).

Začněme schématem:

Schéma vzoru MVP

Oproti MVC se toho změnilo poměrně hodně:

  • Uživatelský vstup i výstup nyní plně kontroluje View (skrze ovládací prvky uživatelského rozhraní jako Button nebo TextInput).
  • Primární motivací pro oddělení View a Presenteru už není nutnost ošetření vstupu, důvody jsou čistě architektonické (prezentační vrstva s MVP se udržuje lépe než monolitické View).
  • View má typicky přímou vazbu na Presenter. Většinou to není technicky nutné, ale řada lidí tuto realizaci preferuje a i většina literatury o MVP s přímou vazbou View na Presenter počítá.
  • Presenter v mnoha případech přímo pracuje s View, takže i tato vazba je silnější než v případě vzoru MVC.

Vidíte, že změn je celkem dost (nenechte si namluvit, že MVC a MVP se liší jen posledním písmenkem), proto znovu popíšu zodpovědnosti jednotlivých komponent:

  • Model je to samé, co dřív, tedy data plus business logika.
  • View navíc oproti MVC zpracovává uživatelský vstup. Typicky dělá pouze to, že např. v reakci na kliknutí myši zavolá nějakou metodu na Presenteru – pouze deleguje uživatelské akce. Jakákoliv aplikační logika ve View je chybou.
  • Presenter obsahuje aplikační a prezentační logiku. Manipuluje s Modelem, což pomocí systému notifikací zajistí aktualizaci View, nebo ovlivňuje View přímo.

Podle toho, jak velkou zodpovědnost View má, rozdělil Martin Fowler vzor MVP dále na dvě hlavní variace: Supervising Controller a Passive View.

Vzor Supervising Controller

Supervising Controller v podstatě přesně odpovídá původnímu MVP vzoru tak, jak byl popsán výše a jak vypadala původní implementace tzv. Dolphin Smalltalk MVP vzoru.

Neptejte se mě, proč Fowler v názvu použil slovo Controller, ačkoliv se zcela jasně jedná o Presenter a sám ve své eseji Supervising Controller řadí pod MVP vzory. Podle této webové stránky na Fowlerově webu (všimněte si názvu HTML souboru!) to vypadá, že Fowler zpočátku nebyl o vhodném označení rozhodnut, a tak si vybral, co mu zrovna přišlo lepší. Kniha, kde měl být tento vzor vydán, nakonec nebyla dokončena a název Supervising Controller se tak bohužel uchytil. (Poučení pro vás: až budete slavní, nepublikujte koncepty svých prací veřejně…)

Nyní ale zpět ke vzoru samotnému. Vrstvě View je svěřena zodpovědnost za zobrazení dat z modelu, nejčastěji pomocí vzoru Observer nebo v modernějších technologiích pomocí data bindingu. Jakákoliv složitější prezentační logika je potom přesunuta do Presenteru, který má dovoleno s View libovolně manipulovat.

Vzor Passive View

Motivací pro vzor Passive View je udělat View co „nejhloupější“, tj. ani jednoduché zobrazení dat z modelu není považováno za něco, co by mohlo být View svěřeno. Struktura aplikace vypadá takto:

Schéma vzoru Passive View

Jediným, zato však podstatným rozdílem je, že zmizela vazba View na Model. Presenter má nyní daleko větší zodpovědnost, protože kromě prezentační logiky musí i správě synchronizovat View s Modelem.

Primární motivací pro tento vzor jsou automatické testy, které se pro View píší velmi těžko. Veškerá logika se proto přesouvá do Presenteru, který lze pokrýt testy výrazně snadněji.

Pokračování příště

Jak jste měli možnost vidět, vzory z rodiny MVC/MVP se často liší ve zdánlivých detailech, ale každý se hodí do jiné situace. Příště se podíváme na některé alternativní vzory a celou problematiku uzavřeme.

Používáte MVP?

Věděli jste, že nám můžete zasílat zprávičky? (Jen pro přihlášené.)

Komentáře: 26

Přehled komentářů

smilelover RE: Prezentační vzory z rodiny MVC
Borek Bernard RE: Prezentační vzory z rodiny MVC
Srigi pochvala a navrh
Borek Bernard Re: pochvala a navrh
babca Re: pochvala a navrh
Petr Re: pochvala a navrh
ZuseX4 Re: pochvala a navrh
v6ak Nevýhoda pasivního view
Borek Bernard Re: Nevýhoda pasivního view
v6ak Re: Nevýhoda pasivního view
Milan Čermák MVC a widgety
Borek Bernard Re: MVC a widgety
David Grudl Re: MVC a widgety
Borek Bernard Re: MVC a widgety
YF Borek stavitel aneb ...
jiravanet Re: Borek stavitel aneb ...
YF Re: Borek stavitel aneb ...
Aleš Roubíček Re: Borek stavitel aneb ...
YF Re: Borek stavitel aneb ...
jechtom Re: Borek stavitel aneb ...
YF Re: Borek stavitel aneb ...
Martin Hassman Re: Borek stavitel aneb ...
Jaroslav Tulach Takle pěkně mi to ještě nikdo nevysvětlil
Martin Malý Re: Takle pěkně mi to ještě nikdo nevysvětlil
Jaroslav Tulach Re: Takle pěkně mi to ještě nikdo nevysvětlil
Borek Bernard Re: Takle pěkně mi to ještě nikdo nevysvětlil
Zdroj: https://www.zdrojak.cz/?p=3005