Slovník pojmů
MVC
Model, View a Controller rozdělují odpovědnosti uživatelského rozhraní. MVC ale neurčuje celou architekturu aplikace ani to, ve které složce musí být každá třída.
Stručná definice
Vstup, aplikační stav a výstup nemají splývat v jednom místě.
Model představuje data, stav a pravidla, se kterými rozhraní pracuje. View převádí výsledek do podoby pro uživatele nebo klienta a Controller reaguje na vstup, vyvolá potřebnou práci a koordinuje tvorbu odpovědi. Konkrétní webové frameworky mohou spolupráci částí interpretovat odlišně, základním cílem ale zůstává oddělení odpovědností.
V serverové webové aplikaci se MVC často potkává s routerem, aplikačními službami, doménovým modelem, databází a frameworkem. Tyto prvky nejsou automaticky dalšími částmi MVC. Vzor hlavně organizuje cestu mezi vstupem uživatele, modelem aplikace a výslednou prezentací.
Jaký problém řeší
Změna obrazovky nemá nutit přepsat pravidla objednávky.
Bez rozdělení odpovědností snadno vznikne jeden controller nebo skript, který současně čte request, skládá SQL, rozhoduje o pravidlech a generuje HTML. Takový kód se obtížně testuje i mění.
- oddělení zpracování HTTP vstupu od pravidel a stavu aplikace
- použití stejné aplikační operace pro HTML stránku, JSON API nebo konzolový příkaz
- samostatná úprava prezentace bez přesouvání businessových rozhodnutí do šablony
- menší controllery, které koordinují jeden use case místo řízení celé aplikace
- jasnější místo pro validaci vstupu, autorizaci, načtení dat a sestavení odpovědi
Praktický příklad
Detail objednávky v PHP aplikaci
Požadavek GET /orders/1042 nejdřív zpracuje router a vybere OrderDetailController. Controller převezme identifikátor 1042 a uživatelský kontext, ověří formát vstupu a zavolá aplikační službu pro zobrazení objednávky. Sám nemá obsahovat SQL dotaz, výpočet oprávnění, převod měn ani pravidla stavů objednávky.
Aplikační služba načte potřebný model, vynutí autorizaci a vrátí výstupní data. Pro serverově vykreslenou stránku je View může předat HTML šabloně. U JSON API může prezentační roli plnit responder nebo serializer, který sestaví stabilní JSON a správný HTTP status; View proto není nutně jen soubor s HTML.
Textový diagram toku a jeho alternativa
HTTP Request
→ Router
→ Controller
→ Application / Domain (Model)
→ View nebo JSON responder
→ HTTP Response
Jak funguje
Od HTTP požadavku k odpovědi
Tok je textovou alternativou diagramu. Přesné názvy tříd nejsou součástí vzoru a mohou se mezi Symfony, Laravel, Nette nebo vlastním řešením lišit.
- Router vybere controller Podle URL a HTTP metody najde konkrétní vstupní bod. Routing je frameworková infrastruktura, nikoli čtvrtá povinná část MVC.
- Controller převezme vstup Získá identifikátor objednávky a uživatelský kontext, převede technický request na vstup pro aplikaci a rozhodne, jak reagovat na výsledek.
- Application a Model vykonají práci Aplikační služba koordinuje use case a model chrání data a pravidla. Přístup k databázi může zajišťovat repository nebo jiný datový adaptér.
- Controller zvolí prezentaci Úspěšný výsledek může předat HTML šabloně, JSON responderu nebo jiné podobě View; chybu převede na odpovídající stav a výstup.
- View vytvoří odpověď Prezentační část formátuje data pro klienta. Nemá znovu rozhodovat, zda uživatel objednávku smí vidět nebo zda je její stav platný.
Hlavní části
Tři role, jejichž hranice se v praxi přizpůsobují rozhraní.
MVC neříká, že každou část představuje právě jedna třída. Model může zahrnovat více objektů a služeb, View může mít presenter i šablonu a controllerů bývá podle jednotlivých akcí více.
Model
Drží významná data, stav a pravidla aplikace. Může zahrnout doménové objekty, aplikační služby, dotazové modely či přístup k datům. Model není automaticky Doctrine Entity ani pouhá kopie databázové tabulky.
View
Prezentuje data v podobě vhodné pro klienta. Může jít o HTML šablonu, serverový komponent, JSON reprezentaci nebo jiný výstup; nemá být místem pro podstatná businessová rozhodnutí.
Controller
Reaguje na vstup, připraví argumenty pro aplikační operaci a zvolí výslednou odpověď. Controller může provést jednoduchou koordinaci, ale nahromadění business logiky vede k obtížně testovatelnému „tlustému controlleru“.
Oddělení odpovědností
Hranice umožní měnit formát výstupu, HTTP detaily nebo způsob načtení dat s menším dopadem. Nevhodně vytvořené abstrakce však mohou cestu requestu pouze prodloužit bez reálného oddělení.
HTML a API
API stále potřebuje vstupní řízení, aplikační model a reprezentaci výsledku, ale nemusí používat šablonu ani přesně stejnou interpretaci View jako klasický server-rendered web. Důležitější než nálepka je jasná odpovědnost.
Výhody a omezení
Oddělení pomáhá, jen pokud mezi částmi zůstávají pravdivé hranice.
Přínosy
- prezentační změna má menší dopad na aplikační pravidla
- controller lze testovat jako tenkou koordinaci a model samostatně podle scénářů
- stejnou operaci lze vystavit přes HTML i JSON bez kopírování business logiky
- odpovědnosti jsou pro tým čitelnější než v jednom univerzálním request handleru
Omezení a časté chyby
- zaměnit Model za jednu ORM entitu nebo celý persistence layer
- vložit autorizaci, SQL a všechna pravidla do controlleru
- načítat data a měnit jejich stav přímo z HTML šablony
- kopírovat frameworkovou adresářovou strukturu a považovat ji za důkaz MVC
- vytvářet presenter, mapper a DTO pro triviální výstup, aniž oddělují skutečný zdroj změny
Vztah k architektuře aplikace
MVC řeší uživatelské rozhraní, ne všechny hranice systému.
MVC není totéž co třívrstvá architektura. Třívrstvý návrh obvykle rozlišuje prezentační, aplikační a datovou vrstvu; MVC popisuje spolupráci Modelu, View a Controlleru kolem vstupu a prezentace. Pojmy se mohou v konkrétní aplikaci překrývat, nelze je ale mechanicky mapovat jedna ku jedné.
Clean Architecture a Domain-Driven Design odpovídají na jiné otázky. Clean Architecture řeší směr závislostí, DDD význam domény a hranice modelů, zatímco MVC organizuje rozhraní. Jedna PHP aplikace proto může používat MVC na HTTP okraji a současně uvnitř aplikační či doménové hranice.
Pro malou CRUD obrazovku může být přímý controller s jednou aplikační službou dostatečný. Složitější objednávkový proces potřebuje výraznější model a testovatelné use cases; další vrstvy ale mají vznikat kvůli konkrétní složitosti, ne jen kvůli názvu vzoru.
Na co myslet
Controller koordinuje, Model rozhoduje a View prezentuje.
Při kontrole změny pomáhá sledovat, zda odpovědnost neleží v části, která se mění z jiného důvodu.
- udržet HTTP request a response na vstupní a prezentační hranici
- pojmenovat aplikační operace podle záměru uživatele místo technických CRUD kroků, když to doména vyžaduje
- nepředávat celé ORM objekty do veřejného JSON výstupu bez vědomého kontraktu
- ověřit autorizaci na serveru před vydáním detailu objednávky
- testovat businessová pravidla mimo šablonu a controller
- volit počet tříd podle složitosti toku a pravděpodobných změn
Časté otázky
MVC bez zbytečných záměn
Je Model v MVC totéž co Doctrine Entity?
Ne. Doctrine Entity může být jedním objektem datového nebo doménového modelu, ale Model v MVC je širší odpovědnost za stav a pravidla aplikace. Může zahrnovat služby, dotazové modely i další objekty.
Patří business logika do Controlleru?
Controller může koordinovat vstup a reakci, ale podstatná pravidla mají zůstat v aplikační nebo doménové části. Jinak je nelze rozumně použít z jiného vstupu ani samostatně testovat.
Je View vždy HTML šablona?
Ne. U klasické stránky to často je šablona nebo presenter. U JSON API může prezentační odpovědnost plnit responder či serializer, který vytvoří reprezentaci a HTTP odpověď.
Je MVC totéž co třívrstvá nebo Clean Architecture?
Ne. MVC organizuje spolupráci kolem uživatelského vstupu a prezentace. Vrstvená nebo Clean Architecture řeší širší uspořádání aplikace a směr jejích závislostí.
Jak MVC používám v praxi
HTTP vrstvu držím u koordinace a pravidla v čitelné aplikační hranici.
V PHP aplikacích volím strukturu controllerů, služeb a modelu podle složitosti konkrétního toku. Cílem je bezpečná změna, ne mechanické naplnění tří složek.