MVC architektura
MVC je velmi oblíbený architektonický vzor, který se uchytil zejména na webu, ačkoli původně vznikl na desktopech. Je součástí populárních webových frameworků, jakými jsou např. Zend nebo Nette pro PHP, Ruby On Rail pro Ruby nebo MVC pro ASP .NET. Osobně si bez něj (nebo nějakého podobného principu) nedokáži představit složitější web.
Motivace
Základní myšlenkou MVC architektury je oddělení logiky od výstupu. Řeší tedy problém tzv. "špagetového kódu", kdy máme v jednom souboru (třídě) logické operace a zároveň renderování výstupu. Soubor tedy obsahuje databázové dotazy, logiku (např. PHP operace) a různě poházené HTML tagy. Vše je zamotané do sebe jako špagety.
Kód se samozřejmě špatně udržuje, natož rozšiřuje. Je špatně highlightovaný, protože si s ním IDE neví rady, HTML není správně naformátováno, ztrácíme se v jeho stromové struktuře. Naším cílem je, aby zdrojový kód s logikou vypadal jako zdrojový kód (např. PHP) a výstup vypadal jako HTML stránka s co nejmenší příměsí dalšího kódu.
Komponenty
Celá aplikace je rozdělena na komponenty 3 typů, hovoříme o Modelech, View (pohledech) a Controllerech (kontrolerech), od toho MVC. Označení pohled se budu snažit vyhýbat, protože mi přijde matoucí, že takto přeložené nekoresponduje s označením V. Neexistuje žádná striktní definice architektury a tak se můžete setkat s více výklady. Zaměřil jsem se na ten nejrozšířenější.
Komponenty jsou samozřejmě třídy, odděděné z abstraktních tříd Model, View a Controller. Pojďme si jednotlivé komponenty nejprve popsat.
Model
Model obsahuje logiku a vše, co do ní
spadá. Mohou to být výpočty, databázové dotazy, validace a podobně. Model
vůbec neví o výstupu. Jeho funkce spočívá v přijetí
parametrů zvenku a vydání dat ven. Zdůrazním, že parametry nemyslím URL
adresu ani žádné jiné parametry od uživatele. Model neví, odkud
data v parametrech přišla a ani jak budou výstupní data
zformátována a vypsána.
Pokud používáme ORM (Objektově-Relační Mapování), korespondují modely přímo s databázovými tabulkami. Máme tedy model Uzivatel, Komentar nebo Clanek. Instance modelů obsahují samozřejmě atributy z databáze. Instance modelu Uzivatel má atribut jméno. Třídě můžeme definovat instanční metody, např. takovou, která vypočítá věk uživatele podle jeho data narození. Metody týkající se obecně uživatelů (tedy třídní) často vkládáme do modelu jako statické, např. oveření správné délky a znaků hesla (tedy jeho validaci, protože heslo ověřujeme ještě předtím, než je instance uživatele vytvořena a zároveň s uživatelem logicky souvisí).
Pro programování bez ORM můžeme využít principu manažerů. Modely máme např. UzivatelManazer, KomentarManazer nebo ClanekManazer. Obsahují metody k výběru potřebných údajů z databáze, např. metodu k výběru přezdívky a informací o uživateli při vypsání jeho profilu. Jinou metodou bychom vybírali otisk hesla z databáze, abychom ověřili přihlášení, další by nám vrátila třeba články uživatele. V manažeru zároveň najdeme pomocné metody k práci s uživateli, např. ono ověření správné délky a znaků hesla.
Nyní máme představu, co model vykonává, pojďme se podívat na pohled.
View
Pohled (View) se stárá o zobrazení výstupu
uživateli. Nejčastěji se jedná o phtml šablonu,
obsahující HTML stránku a tagy nějakého značkovacího
jazyka, který umožňuje do šablony vkládat proměnné, případně
provádět iterace (cykly) a podmínky. Pro PHP nemá příliš velký smysl
používat značkovací jazyk, jelikož je samo značkovacím jazykem a
umožňuje takový styl zápisu kódu, aby struktura HTML stránky zůstala
zachována. Pohled uzivatel tedy vypíše detaily o uživateli, pohled
clanek vypíše obsah článku.
Pohledů máme mnoho, např. pro funkcionalitu s entitou uživatele: uzivatel_registrace, uzivatel_prihlaseni, uzivatel_profil a podobně. Pohled uzivatel_profil je ale již společný všem uživatelům a jsou do něj posílána různá data, vždy podle toho, koho zrovna zobrazujeme. Tato data jsou poté dosazena do HTML elementů šablony.
Šablony lze samozřejmě vkládat do sebe, abychom se neopakovali (šablona s layoutem stránky, šablona s menu a šablona článkem).
View není jen šablona, ale zobrazovač výstupu. Obsahuje tedy minimální množství logiky, která je pro výpis nutná (např. kontrola, zda si uživatel vyplnil prezdívku před jejím vypsáním nebo cyklus s komentáři, které se vypisují).
View podobně jako Model vůbec neví, odkud mu data přišla, stará se jen o jejich zobrazení uživateli.
Controller
Controller je nyní onen chybějící prvek, který osvětlí
funkčnost celého vzoru. Jedná se o jakéhosi prostředníka,
se kterým komunikuje uživatel, model i view. Drží tedy celý systém
pohromadě a komponenty propojuje. Jeho funkci pochopíme z
ukázky životního cyklu stránky. Opět existuje mnoho různých přístupů,
nejčastěji má každá entita jeden controller, máme tedy UzivatelController,
ClanekController a tak podobně.
Životní cyklus stránky
Životní cyklus zahajuje uživatel, který zadá do prohlížeče adresu webu a parametry, kterými nám sdělí, kterou podstránku si přeje zobrazit. Budeme chtít zobrazit detail uzivatele s id 15. Udělejme si ukázku URL adresy:
http://www.domena.cz/uzivatel/detail/15
Požadavek jako první zachytí tzv. router. Ten podle parametrů pozná, který controller voláme. Jistě bychom vymysleli mnoho způsobů, jak jméno controlleru poznat, nejjednodušší se zdá být uvést ho jako 1. parametr. Zde je tedy zavolán controller UzivatelController., kterému jsou předány parametry detail a 15.
Daný controller podle parametrů pozná, co se po něm chce, tedy že má zobrazit detail uživatele. Zavolá model, který uživatele vyhledá v databázi a vrátí jeho údaje. Dále zavolá další metodu modelu, která např. vypočítá věk uživatele. Tyto údaje si controller ukládá do proměnných. Nakonec vyrenderuje view (pohled). Název pohledu poznáme podle akce, kterou provádíme. View jsou předány proměnné s příslušnými daty. Controller tedy poslechl uživatele, obstaral podle parametrů dotazu data od modelu a předal je view.
View přijme data od controlleru a vloží je do
připravené šablony. Hotová stránka je zobrazena uživateli, který často o
celé této kráse ani netuší
Celou situaci můžeme znázornit diagramem:

Získali jsme tedy oddělení logiky od výstupu, view jsou jako HTML, modely zas v našem skriptovacím jazyce (např. v PHP). Dosáhli jsme přehlednosti kódu, který je logicky rozčleněný.
MVC architektura nám usnadňuje i myšlení při vývoji projektu. Když píši logiku, patří do modelu, formátování a stylování výstupu řeším v šabloně, to co uživatel chce z parametrů zjišťuji v controlleru. 3 různé problémy na 3 různých místech, oddělené tak, aby do sebe nezasahovaly a nedělaly nám vývoj složitější.