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.

  1. Router vybere controller Podle URL a HTTP metody najde konkrétní vstupní bod. Routing je frameworková infrastruktura, nikoli čtvrtá povinná část MVC.
  2. 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.
  3. 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.
  4. 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.
  5. 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.

Zavolejte mi

Zavolám vám následující pracovní den mezi 9:00 a 17:00.

Můžete mi také zavolat rovnou.

+420 605 181 728

Nechte mi telefonní číslo a pošlete žádost o zpětné zavolání.

Odesláním souhlasíte se zpracováním údajů pro vyřízení žádosti.