Přejít k navigační liště

Zdroják » Různé » Alternativy k MVC a závěrečné poznámky

Alternativy k MVC a závěrečné poznámky

Články Různé

Zatímco předchozí dva díly byly zaměřené na architekturu a vzory z rodiny MVC, dnes se budeme věnovat „věcem okolo“. Především to budou alternativní prezentační vzory, podíváme se na úlohu servisní vrstvy a několika poznámkami celou minisérii uzavřeme.

Nálepky:

Alternativy k MVC

K architektuře MVC dnes existují dvě rozšířené alternativy:

  1. Autonomous View
  2. Presentation Model (jinak zvaný Model-View-ViewModel)

Autonomous View

Komponenta chovající se jako Autonomous View v sobě kombinuje uživatelské rozhraní a další logiku, ať už prezentační, aplikační, doménovou, nebo jejich mix. V PHP budiž příkladem skript, který na začátku načte data z MySQL databáze a pak je pomocí různých podmínek a cyklů vypíše do HTML. Ve widgetových systémech zase aplikace s Autonomous View často vznikají při „drag&drop vývoji“.

Samozřejmě, pokud jste sérii o MVC dočetli až sem, nemáte patrně o „vzor“ Autonomous View zájem nebo se od něj naopak snažíte oprostit, ale přesto za zmínku stojí, protože:

  • Je zdaleka nejrozšířenějším modelem vývoje aplikací (podle Programátorovy statistické ročenky)
  • Je výchozím modelem většiny technologií
  • U malých aplikací nebo v jiných specifických případech může být praktičtější než MVC

Věnujte prosím pozornost poslednímu bodu: opravdu nemá cenu snažit se MVC aplikovat vždy a všude, příkladem budiž drobná prezentační logika na klientovi v lehkých AJAX aplikacích. Ale nebojte se, poslední větou, kterou si o Autonomous View přečtete, bude samozřejmě doporučení se mu pokud možno vyvarovat u jakékoliv netriviální aplikace – vyhnete se mnoha jeho problémům, mezi které patří obtížná až nemožná testovatelnost aplikace a téměř žádná dělba zodpovědností vedoucí k horší udržovatelnosti, menší flexibilitě a dalším nepěkným věcem.

Presentation Model (Model-View-ViewModel)

Vzor Presentation Model (PM), někdy nazývaný Model-View-ViewModel (M-V-VM), se obvykle zařazuje mimo MVC/MVP, nicméně i on patří mezi „dobré“ prezentační vzory, které se řídí podobnými principy jako MVC.

Vzor PM se většinou zobrazuje následovně:

Vzor MVVM

Hlavní rozdíl je, že View již nepřistupuje k Modelu přímo, nýbrž přes mezivrstvu, kterou je prezentační model. Tato mezivrstva je dále zajímavá tím, že je jakousi kombinací Modelu a Presenteru.

Asi právě kvůli tomu se PM často popisuje jako vzor odlišný od MVP, nicméně zkusme se na diagram podívat jinak. V reálné aplikaci je úplně klidně možné, že komponenta prezentačního modelu bude realizována ne jedním, ale několika objekty, když např. budeme chtít oddělit chování a stav. Ve chvíli, kdy to uděláme, se diagram velmi přiblíží modelu MVP – chování bude uloženo v Presenteru a stav v Prezentačním Modelu. Protože zde PM implementuje návrhový vzor Adapter, někdy se mu říká Model Adapter, což je koncept z některých MVP implementací známý. Jak tedy vidíte, rozdíl mezi PM a MVP není tak velký, jak se může na první pohled zdát.

Servisní vrstva

Jestliže je MVC architekturou prezentační vrstvy aplikace, možná se ptáte, jak aplikace komunikuje s okolním světem. Musí přece nějak data do modelu načíst, ať už z lokálního disku nebo třeba z databáze. Často přece potřebuje komunikovat s nějakou webovou službou nebo něco na ten způsob. Kde tedy žije tato funkcionalita?

Umístit ji do modelu je možné, ale nešikovné. Například třída, která implementuje zákazníka a současně dokáže jeho data uložit na disk, porušuje Single Responsibility Principle. Odpovědí je tedy oddělení čtvrté části aplikace, které se říká servisní vrstva (Service Layer).

Servisní vrstva má s Modelem společné to, že nijak nesouvisí s konkrétní prezentací a byla by tedy chyba, kdyby se přímo odkazovala na objekty View nebo Controlleru. Pokud do diagramu MVC přidáme servisní vrstvu, bude vypadat následovně:

Servisní vrstva

Tento model, někdy nazývaný „MVCS“, zachycuje kompletní architekturu aplikace, která dělá vše, co se od prezentační vrstvy očekává: umí data načíst, zobrazit, upravit a uložit.

U servisní vrstvy si všimněte pár věcí:

  • Servisní vrstva může, ale nemusí mít přímou referenci na Model. Obvykle se taková reference považuje za přijatelnou, i když obecně platí, že čím volnější vazba mezi komponentami, tím lépe.
  • Objekty servisní vrstvy jsou typicky schované za rozhraním, aby šel Controller testovat a nemusely se přitom používat reálné externí systémy, které mohou být pomalé nebo způsobovat jiné problémy. Pokud mám tedy např. v aplikaci službu EmailService, schovám ji za rozhraní IEmailService (nebo ještě lépe IMessagingService) a controlleru během testování předám FakeEmailService, která text jen uloží do souboru nebo třeba neudělá vůbec nic. Testování tohoto typu dále usnadňují tzv. mock frameworky, které se dají nalézt pro většinu dnešních technologií.

Poslední velká složitost MVC

Pokud jste pochopili základní principy MVC i rozdíly mezi jednotlivými variacemi, gratuluji, pravděpodobně nyní o MVC víte více než 95 % vašich vývojářských kolegů po celém světě (opět převzato z Programátorovy statistické ročenky; zmatení kolem MVC bohužel stále drtivě poráží jeho pochopení).

Přesto je ještě jedna věc, která stojí mezi vámi a dokonale napsanou aplikací: konkrétní technologie. Ono na diagramu se třemi obdélníčky a pár šipkami vypadá vše jednoduše, ale v reálu existuje v aplikaci „MVC triád“ hodně a zařídit, aby mezi sebou komunikovaly bez vytváření pevných závislostí, není vůbec jednoduché. Každá technologie má svůj vlastní „nejlepší způsob“, který bude záviset na věcech jako:

  • jakým způsobem se načítá aplikace a instanciují objekty
  • zda má technologie podporu pro data binding
  • jestli jsou metody pro přístup k datům synchronní nebo asynchronní

a podobně. Co bude krásně fungovat v technologii A, nemusí být v technologii B vůbec použitelné nebo minimálně může existovat daleko lepší způsob. Klišé na tomto místě je, že kdo zná principy, snadno si poradí, ale toho jsem si v praxi bohužel nevšiml. Znovu se vrátím k tomu, co jsem psal už v prvním díle: znalost obecných architektonických principů je užitečná, ale ne vždy dá konkrétní odpovědi na otázky, které potřebuje vývojář znát. Chápat MVC v jeho principu a umět vytvořit kvalitní aplikaci v konkrétní technologii je asi podobné jako chápat, že na kytaru se hraje mačkáním strun a brnkáním, a pak umět zahrát Bacha.

MVC: vzor, architektura nebo princip?

Série o MVC by nebyla kompletní, kdybych se aspoň na chvíli nezastavil u toho, co to vlastně MVC je. Možná vám připadá zvláštní, že tato kapitolka je zařazena na úplný konec místo na začátek, ale pro praxi není zase tolik důležitá a její umístění tomu odpovídá.

S jakými názvy se tedy v souvislosti s MVC setkáte?

  • Když někdo o MVC mluví jako návrhovém vzoru, tak buďto dělá chybu, nebo pojmem „návrh“ myslí něco jiného, než je zvykem (patrně myslí architekturu). Vztah návrhových vzorů a MVC je takový, že MVC je realizováno pomocí návrhových vzorů – např. notifikace změn v modelu může implementovat vzor Observer, Presenter může být pro View Strategií a podobně. Někdy se proto MVC označuje za „vzor (složený ze) vzorů“.
  • Označit MVC za architektonický vzor je nejvhodnější, pokud je řeč o konkrétní variaci. S tímto označením se setkáte velmi často.
  • MVC jako architektura se zase používá, když o MVC mluvíme zhruba na úrovni prvního článku této série, kdy rozdíly mezi MVC a MVP ještě nejsou tolik podstatné.
  • Někdy se pak v souvislosti s MVC slyší pojem princip nebo přístup. Druhý zmíněný je asi lepší, protože slovo „princip“ má ve světě objektového návrhu konkrétní význam – patří sem principy jako Single Responsibility Principle, Open/Closed Principle a podobně.
  • Ve světě konkrétních technologií dále často narazíte na pojem MVC framework, což je označení pro konkrétní implementaci nějaké variace MVC/MVP. Zde si dejte pozor na to, že za MVC se často označují i variace vzoru MVP, což je buď z neznalosti autorů (a pak se frameworku radši vyhněte), nebo z marketingových důvodů („C“ má větší marketingový potenciál než „P“).
  • Poslední pojem, který se v souvislosti s MVC používá, je triáda. Často se tím myslí konkrétní trojice objektů realizujících třídy v modelu MVC. Toto označení je užitečné, když se o triádách mluví v množném čísle (triád je v aplikaci typicky mnoho).

Závěr

Pokud jste se prokousali až sem, gratuluji, nechybělo moc a byli jste lepší než autor. :) Přemýšlím, co by měla být hlavní věc, kterou si z této série odnesete, a je to asi toto:

Problematika MVC a souvisejících prezentačních vzorů je velmi složitá, ale určitě stojí za to se jí věnovat. Znalost architektonických vzorů vede k tvorbě kvalitnějších aplikací a dělá z běžných programátorů skutečné vývojáře.


Zdroje

Zdrojů o problematice MVC/MVP najdete mnoho, jejich kvalita však značně kolísá (například Wikipedia je v této oblasti bohužel plná polopravd, zavádějících tvrzení i vyložených omylů). Zde jsou některé materiály, které přímo nebo nepřímo souvisí s problematikou MVC a považuji je za přínosné:

Komentáře

Subscribe
Upozornit na
guest
43 Komentářů
Nejstarší
Nejnovější Most Voted
Inline Feedbacks
View all comments
ava

Chybi mi odkaz na programatorovu statistickou rocenku :)
btw: Prvni! (poprve :-)

Mirek.Charvat

Pořád si nejsem jistý jednou věcí. Jak použít archtitektonický vzor MVC například v případě počítačového modelu auta.

Když si například zjednoduším auto tak, že jede stále po stejnorodé silnici (bere se v úvahu pouze sklon), mohou z něj ale nastupovat a vystupovat cestující (mění se hmotnost a poměr výkon motoru / hmotnost), ubývá a doplňuje se palivo (může úplně dojít), řidič ovládá spojku a převodovku (přechodové funkce), plynový pedál (křížová závislost odezvy na otáčkách motoru a bohatosti směsi, zatížení motoru) a volant. Takových automobilů můžete mít na scéně několik. K tomu postavy řidičů a cestujících (různé hmotnosti, styly řízení). Vše je v interakci se vším – vždy způsobem, který je pro každou dvojici možný. Nad tím sedí pozorovatel – uživatel, který například ovláda semafory, jedno z aut a pod.

Co je tu Model, co Controler a co View (Presenter)?

Převodovka každého z aut na scéně má zařazený nějaký převodový stupeň, ale to nezajímá nikoho jiného, než nanejvýcš instanci tohoto auta a jejího řidiče. Ostatní objekty zajímá až projev (důsledek) zařazení právě tohoto převodového stupně. V aplikaci ale může být zařazený stupeň nějak graficky indikován pro vnějšího pozorovatele a on do nastevní může zasáhnout.

Chápu to dobře, když si mylím, že MVC se musí vždy uplatňovat pouze na úrovni své vrstvy. Tzn. že převodovka jako třída má vlastní vnitřní MVC, rozčlenění, poskytuje rozhraní (V, C) a nadžazené auto jako celek s ní prostřednictvím jejího V, C komunikuje podle potřeby ve svých částech M, V i C a poskytuje dále V C rozhraní řidiči (řadící páku – indikace zařazení stupně + možnost změny)? Je to pořád MVC?

Mirek.Charvat

Ještě doplním, že se jedná o aplikaci, která nečeká jen na odezvy uživatele u klávesnice. Pořád se v ní něco děje a zpracovávají se tedy i vnitřní události bez ohledu, jestli uživatel reaguje nebo ne.

Rene Stein

Záleží,co přesně chcete v systímu dělat-sledovat.
Tohle už ale určitě není vhodný scénář pro MVC. V Real Time vzorech se pro tyto typy apliakcí používá tzv. Data Bus.
Data Bus představuje variaci na vzor Observer, ale objekty, které se notifikují o událostech, jsou od sebe více odděleny, mohou poicházet z vícero vrstev a většinou se notifikují vzájemně (jsou "subject" změn i "observer" dalších změn – veškeré změny jsou ale distribuovány přes Data Bus, který může mít pull a push variantu.

Zde je alespoň letmý úvod – http://my.safaribooksonline.com/0201699567/ch08lev1sec5

Mirek.Charvat

Jasně, tak to i řešívám … každopádně díky za odkaz.

Jde mi o to, že by se mělo říci, pro jaký typ problémů se MVC dá použít. Jaké podmínky v charakteristikách modelovaného systému musí být splněny. Protože ani kávovar v jiném článku také není zrovna nejšťastnější příklad – je závadějící, protože skutečná mašina je real-time systém.

Rene Stein

Budeme-li precizní,tak každá aplikace je real-time, protože uživatel také potřebuje vidět výsledky v reálném čase. :)
Obecně – MVC je vhodné pro aplikace, v nichž je potřeba odělit odpovědnosti související s generováním uživatelského rohraní a zpracováním vstupů z uživatelského rozhraní.

Formálněji – aplikace, pro něž je uživatelský vstup předpokladem spuštění právě jedné business transakce, kdy MVC se zabývá získáním vstupu (View), distribucí vstupu přes controller do vstupní části modelu (mimo odpovědnost MVC je interní zpracování business trasakce v modelu – interní komunikace mezi objekty, synchronizace stavů, obalení business trasakce třídou Unit Of Work, normalizace business transakce na atomickou databázovou transakci) – MVC pokračuje renderováním nového view – view se seznamem chyb, pokud business trasakce selhala, jinak další "normální" view, redirect apod. A tady začíná svět různých variací na MVC vzor.

Slovo "právě jedna business transakce" u webových aplikaci je samozřejmě míněno v kontextu jednoho požadavku jednoho uživatele na webový server (business transakce specifická pro request). Takových (izolovaných) požadavků v jednom okamžiku na jeden webový server je samozřejmě libovolné množství.
Většinou se mluví o tzv. LOB (line of business), "Data centric" aplikace.

U real time aplikace většinou musíte řešit velké množství simultánnních a na sobě nezávislých transakcí reaktivních objektů.

Mirek.Charvat

No, pak je real-time úplně vše :o)

Měl jsem na mysli systémy, které nečekají na podnět, ale pracují samy neustále mění vnitřní stav.

I když on ten kávovar vlastně lze brát jako tiše čekající na podnět a pak sice provádějící sadu vnitřních procesů, ale tam se nejedná o nic jiného, než naplňování cíle: výdeje kávy.

Aleš Roubíček

MVC je prezentační vzor, tudíž je vhodný pouze pro uživatelské rozhranní automobilu. Krásným příkladem by byla přístrojová deska. Controller by v tomto případě byl jedním z účastníků ServiceBus komunikace o které psal René. View jsou kontrolky, displeje a ciferníky.

MVC rozhodně není architekturou aplikace samou o sobě, ale pouze části, která má na starosti uživatelské rozhranní.

Mirek.Charvat

Ano, a pokud bych potřeboval zahrnout i vzájemné iterakce přístrojů, rodělil bych to dál … je to tak?

Takže MVC lze použít u objektů, které se mohou z mého pohledu jako celek chovat jako černá skříňka a uvnitř nich není potřeba řešit události, prostě mění stav pouze na základě podnětu zvenčí.

Aleš Roubíček

Vyvozujte ukvapené závěry.

Měřič zobrazované veličiny (rychlosti, otáček, obsahu nádrže) přece není i budíkem na přístrojovce, ale je v tomoto pípadě součástí modelu. Měřič může vyvolávat událost SpeedChanged a controller tuto událost zpracuje a změní view.

Mirek.Charvat

No, to asi pořádně nečtete – nemluvím o měřiči, ale o jeho části: přístroji …

Takže znovu … pokud je budík součástí panelu a nepotřebuju po něm více, než view, pak můžu oddělit logiku zpracování signálů od přístrojovky jako celku. Pokud mne zajímá i interakce mezi budíky na palubce (což je praktický případ například simulace vzájemného ovlivňování vlivem změny teploty, nebo magnetického pole), pak musím palubku rozsekat na menší části. Každá z nich bude mít vlastní "MVC", a to už z principu. Je jedno jak to napíšu a v kódu zašmodrchám nebo uspořádám. Jedná-li se o černou skříňku, musí mít nějaké rozhraní (V s vstupními porty), systém pro zpracování podnětů (C) a vnitřní stav a definovaná pravidla pro jeho změny a generování zpětných odezev. Může to být libolně zamícháno, nebo rozčleněno.

Proto je možná kolem MVC tolik dohadů, protože není dost obecný. Myslím z hlediska reality a potřeby modelování.

Mirek.Charvat

Ne-e :o)

Neptám se, jak realizovat MVC. Ptám se, kde jsou hranice jednoho MVC svazku, jaké jsou podmínky pro rozčlenění kódu dle MVC. Obecné řešení nesmí být závislé na technologii. Paralelu MVC musím být schopen vystopovat stejně tak v železe (konstrukci reálného auta), jako v kódu programu, nebo i v biologickém organismu – pokud to není možné (myslím obecně, nezávisle na mé dovednosti cokoli rozpoznat), není MVC nic jiné než logicky vypadají, leč zavádějící myšlenková pastička, nebo jen zvláštní forma řešení nějaké obecné rovnice, závislosti, problému – podobně jako je Bernulliho rovnice jen speciální formou obecné Navier-Stokesovy rovnice prodění tekutin.

Domnívám se, že MVC je nanejvýš speciální formou řešení obecného kybernetického problému černé skříňky … dám to následně do samostatného vlákna …

smilelover

Nejak nerozumim vasemu pojeti servisy. V prvnim dile jste psal:

Model jsou tedy data plus business logika (někdy zvaná doménová logika) aplikace. Teoreticky může být model pouhou sadou datových objektů bez business logiky, ale to je poměrně netypické.

Pro me je ale servisni vrstva prave to, co obsahuje business logiku provadenou nad domenovymi objekty. Controller ma odkaz na servisu, ta obsahuje business logiku a pouziva DAO vrstvu pro persistovani objektu. Model jsem vzdy bral jako zapouzdreni vsech techto veci a proto mi vzdycky byla divna i vazba V na M, protoze si nemyslim, ze V by mel drzet odkaz na veci jako jsou servisy… Samozrejme by mel pracovat s domenovymi objekty — pak by se vazba V -> M dala chapat.

Takze nejen ze mi pripadne divna servisa mimo M, pripadne mi divne i to, ze vazba servisy na M je nepovinna (protoze i kdyz jde o webservisu, ktera nepracuje treba s lokalnimi domenovymi objekty dane aplikace, Controller to vubec nema co zajimat, on proste interaguje s Modelem – tedy jeho „vyslancem“ v podobe servisy — a odkud ten bere data neni vubec jeho vec).

Kdyz mam tedy aplikaci pracujici s informacemi o nejakych odobach, mam controller, ten drzi odkaz na PersonService a ta pracuje s objekty tridy Person a uklada je treba pres PersonDAO nebo neco takoveho…. co je tedy podle vas MODEL? Jen Person? A jak ma vypadat vazba V na M?

bh3

Business logika patri do modelu, service layer pak zajistuje akorat perzistenci domenovych objektu, a jak je v clanku napsano, nejlepsi je ho schovat za interface.

Vazba V -> M je pokud to dobre chapu read-only, view umi zobrazit data modelu, ale editaci zajistuje controller (presenter).

Co se tyce vazby controlleru na service, tak ta je potreba prave pri ukladani zmen, naplnovani ruznych seznamu atd.

ad aplikace o osobach: ano model je Person.

Docela casta chyba, s kterou ste se mozna potkal, je kdyz model obsahuje pouze data a zadne chovani, cela logika se nachazi jinde v systemu, napr. prave v servisni vrstve. To je spatne, mam pocit ze se tomu rika anemic models…

smilelover

Hmmmm, no ja anemic models nepovazoval za takove zlo…. :) Ale kdyz tak koukam na Wikipedii, tak ta uvadi SoC jako jedinou vyhodu, tak si to budu muset jeste prostudovat :)

Kazdopadne spatny je i druhy extrem. Kdy to ujede tak, ze v domenovych tridach je logika, kterou v realne problemove domene ta entita nevykonava.

Rene Stein

Čekal jsem, až bude série článků ukončena, abych poznal, jak Borek pojímá MVC.

Musím říci, že ale ani po přečtení celé série nejsem moudřejší.
Než se začít dohadovat nad "vysokoúrovňovými" věcmi, vždy se rád nejdříve shodnu na tzv. myšlenkových a implementačních trivialitách, protože na nich se pozná, jak člověk přemýšlí. Epochálním a letmo načrtnutým megalomanským "architektonickým" stavbám se těžko oponuje, protože žijí ve světě svých nezpochybnitelných a vždy při nárazu kritických připomínek rychle upravitelných předpokladů.:)

Citace:
"Komponenta chovající se jako Autonomous View v sobě kombinuje uživatelské rozhraní a další logiku, ať už prezentační, aplikační, doménovou, nebo jejich mix. V PHP budiž příkladem skript, který na začátku načte data z MySQL databáze a pak je pomocí různých podmínek a cyklů vypíše do HTML."

Zde se míchá několik věcí dohromady:

Nemělo by spíš zaznít.
Autonomous View v sobě kombinuje veškerou logiku, která se týká správy a udržování stavu uživatelského rozhraní. Tedy autonomous view přebírá role, které jsou při separaci různých odpovědností souvisejících s řízením uživatelského rozhraní rolemi samostatných tříd controller-presenter. To je téma tohoto článku.

Další (odstrašující, fakt jsm se lekl :) ) příklad už nesouvisí s probíraným vzorem (vzory). Můžete mít autonomní pohled, který jako podkladový model používá běžný business model, nebo anemický business model, anebo jen sadu transakčních skriptů, či rovnou přistupuje do SQL databáze. I M v MVC model může být označením pro transakční skript nebo jen sadu metod, které vracejí po předání SQL "resultset-recordset".

Příklad s PHP tedy představuje extrém a atypické použití autonomního view.

Přijde mi to ale jako hezký návod pro vývojáře, kteří píšou špagetový kód bez jakéhokoli rozvrstvení aplikace, aby mohli na pohovorech na otázku:"Jak píšete typicky webové aplikace", odpovědět jinak než "seberu data z databáte a pak už je pěkně v cyklu vypíšu, jaké komplikace woe". Nyní mohou rafinovaně říci : "Pro své jednoduché aplikace jsem namísto typického bastlení použil zjednodušenou a velmi efektivní variantu VZORU autonomní pohled. Mou domněnku potvrdil autoritativní zdroj, samotný velký Zdroják!" :)

Citace:
"Jestliže je MVC architekturou prezentační vrstvy aplikace, možná se ptáte, jak aplikace komunikuje s okolním světem. Musí přece nějak data do modelu načíst, ať už z lokálního disku nebo třeba z databáze. Často přece potřebuje komunikovat s nějakou webovou službou nebo něco na ten způsob. Kde tedy žije tato funkcionalita

Umístit ji do modelu je možné, ale nešikovné. Například třída, která implementuje zákazníka a současně dokáže jeho data uložit na disk, porušuje Single Responsibility Principle. Odpovědí je tedy oddělení čtvrté části aplikace, které se říká servisní vrstva (Service Layer)."

Tady už je to na mě příliš a univerzální zaklínadlo Single responsibility principle, kterým se tlučou po hlavě všichni předpokládaní heretici, k mé duševní pohodě nepřispívá.

Tedy servisní vrstva: Co přesně označuje?
Zkusme vyjít ze dvou příkladů v článku.
1) Zákazník a jeho uložení dat na disk.

Pokud vyjdeme z klasického vícevrstvého modelu, tak naším zájmem by mělo být, aby za ukládání zákazníka odpovídala perzistentní vrstva, kterou používají další (vyšší-např. business vrstva) vrstvy aplikace. Ano – ze zákazníka (business vrstva-tedy Model) určitě vydělíme odpovědnost za ukládání svých dat, vytvoříme nějaké společné rozhraní, které realizuje objekt v db vrstvě a v okamžiku, kdy má dojít k uložení dat, objekt zákazník po zavolání jeho metody UložSe může zavolat metodu z databázové vrsty Ulož, které předá svoje data. Samozřejmě nechceme-li mít delegující metodu UložSe přímo v objektu zákazník, nic nám nebrání vytvořit v Modelu další (podpůrné) objekty typu Data Mapper, které interně volají metody databázové vrstvy a objekt Objednávka nemá ve svém veřejném rozhraní žádné Kainovo znamení (metodu UlozSe)signalizující – jsem SW objekt a proto podporuji perzistenci, což by někteří dogmatici mohli považovat za porušení 11. přikázání (pardon, vlastně jen ončas užitečného SRP doporučení).
Důležité je, že Controller, tak jak je naznačeno v článku, NEPOUŽÍVÁ žádné servisní objekty pro uložení, ale pracuje s business modelem a poté, co potřebuje uložit data, zavolá příslušnou metodu business objektu, data mapperu apod, a poté je volání přeneseno na perzistenční vrstvu.

Servisní vrstva, o které je řeč v článku, připomíná spíš právě vrstvu složenou z repozitáře objektů a data mapperů, ale je popsána na zavádějících příkladech a podpírána (alespoň) nevyslovenými předpoklady – možná.:)

Citace:
"Controller testovat a nemusely se přitom používat reálné externí systémy, které mohou být pomalé nebo způsobovat jiné problémy. Pokud mám tedy např. v aplikaci službu EmailService, schovám ji za rozhraní IEmailService (nebo ještě lépe IMessagingService) a controlleru během testování předám FakeEmailService, která text jen uloží do souboru nebo třeba neudělá vůbec nic. Testování tohoto typu dále usnadňují tzv. mock frameworky, které se dají nalézt pro většinu dnešních technologií."

Základní otázka zní – k čemu controller, jehož odpovědností je ve všech možných inkarnacích zprostředkovávat komunikaci mezi View a modelem, jak nám bylo v článku několikrát naznačováno, najednou potřebuje emailové služby? Je to chlapík ten controller, všichni ostatní participanti jsou chudáčci, kterým musí odlehčovat v jejich odpovědnostech, ale tady si na svá tajemná, ale beze všech pochybností mohutná a altruistická záda naložil sadu dalších odpovědností.

Není to tak, že pravidla, kdy mají být odeslány emaily(emailové notifikace), je součást business pravidel? A je tedy odpovědností samotných objektů "modelu" (např. v objektu, který implementuje stavový automat pro objednávku), že poté, co uživatel dá příkaz ve View (kliknutí na tlačítko, submit) ke stornování objednávky, controller tento příkaz přenese do stavového automatu, ve stavovém automatu dojde k přechodu do stavu Storno a současně se spustí akce, která přes speciální servisní vrstvu pro odesílání emailu (IEmailService) odešle notifikaci.
Ano – controller může chtít odesílat také emaily (např. informaci o nějaké chybě/logovací informace) a pak může využít také služby objektu skrytého za rozhraním IMessagingService. Ale jak to souvisí s tímto vzorem a s vazbou controlleru na model a servisní vrstvy na business model?

Co by ale mělo platit:
Implementace rozhraní IMessagingService patří do nízkoúrovňových vrstev aplikace, rozhraní IMessagingService nemá žádné předpoklady, tedy nevidí v žádném případě jejich rozhraní, ani o objektech z business vrstvy, natož z controlleru. Je to služba s jasně vymezenou jednou odpovědností, voila, ani jsme se nemuseli opakovat magicou říkanku SRP.

IMessagingService
{
bool Config(Map configValues)
void SendMessage(string message, string subject, int priority …)
}

Nejlepší rozhodnutí jsou ne ta, která vás při návrhu baví, ale která vyplynou z požadavků. :)

Dovedu si představit služby využívané přímo controllerem, které mají přímo vazby na třídy v "Modelu". Například jde o fasády, které realizují uživatelské scénáře a ještě více izolují controller od modelu. Ale to je téma spíš na celý článek.

Už teď je můj komentář příliš dlouhý – snažil jsem se ukázat, v čem mi přijde článek spíše matoucí, než že by byl tím kýženým světlem, které nám, zneuživaným ovečkám, co podlehly krysařům vyluzujícím falešné MV*tóny, po desetiletích tápání ukáže tu pravou cestu, kde nebudeme hhlavně řešit tím, že si pleteme presenter a controller. Ta naznačená distinkce mezi controllerem a presenterem je totiž také zvláštní.

I v desktopové aplikaci se dá běžně použít (a já běžně používám) Front Controller a sada controllerů-presenterů v pozadí.

Např. (i v MDI) aplikaci tlačitka, položky v toolbaru a položky menu se po svém stisku pošlou do controlleru svůj "identifikátor-klíč", front controller podle klíče vyzvedné controller (realzovaný většinou vzorem Command) pro danou "akci", zavolá jeho metodu Execute a controller si uloží do seznamu provedených akcí, aby mohl např. akci odvolat. Pak je zajímavé řešit, jak může controller pomoci při realizaci undo-redo scénáře, jak si poradit ve webových a desktopových aplikacích s controllery, které udržují-neudržují vlastní stav. To je přímo na sérii článků.

Články mají za mě několik dobrých a kvalitních odstavců, ale z valné vštšiny jde spíše o kompiláty názorů z Domain Driven Designu, postupů v ASP.NET MVC, Silverlightu, něco předpokládaného z Dependency injection apod. Slovo kompilát není míněno nijak pejorativně, naopak dobrý kompilát by se v češtině určitě hodil, ale vadí mi Borku, že své vlastní termíny a předpoklady moc nevysvětluješ. Navíc, třeba Domain Driven Design má své vlastní problémy, na které člověk narazí při prvním pokusu o implementaci. Ale to je už opravdu zcela jiné téma.

Rene Stein

Díky za reakci, snad jen na vysvětlení.

Články mi "poněkud" ani zcela v žaludku neleží. :) Mrzí mě, pokud to tak vyznělo, snažil jsem se o vstřícné čtení a motivaci komentáře jsem popsal hned na jeho začátku. :) Navíc bych řekl, že některé další reakce mi dávají za pravdu.
Hnidopišské čtení by, věřte mi, vypadalo zcela jinak a mým cílem nebylo nijak sérii shodit. BTW: Na twitteru jsem posílal včera i DM, která podle mě také nevstřícná nebyla…

Jen na objasnění "sugestivních" obratů a ironie (hlavně kolem) SRP. Tyto části jsou jen a pouze pobavenou reakcí na jeden váš (pro mě) zvláštní a za hranicí vstřícného "čtení" článek, který ve formě školometského mentorování reagoval na kód a článek AD. Víc tady nemá smysl dodávat.

SRP nezpochybňuji, jen se bavím tím, když někdo princip-obušek vytáhne a pak většinou po vyřknutí všech OOP zaklínadel o "změnách z jednoho důvodu" skončíme na tom, co je to ta jedna odpovědnost (a jak se projeví v rozhraní třídy. V komentáři jsem poté u IMessagingService podotýkal, jak k SRP třídě dojdeme.

Takže jen pár postřehů:

Ad Autonomous View) Tady předvádíte nevstřícné čtení vy.
Nechápu, jak se na podstatě Autonomous View projevuje, fakt, jestli jsem přebíral nebo nepřebíral po někom zběsilý projekt. Jestliže Vy jste takový projekt přebíral, víte proto lépe, co je to Autonomous View? Neboli – když říkám, že váš příklad je atypický a extrémní, protože zamlžuje, jak je Autonomous view konvečně chápáno, tak vy mi podsouváte, že říkám zcela něco jiného: "Extrémní je výskyt takovýmto způsobem 'zběsile vytvořeného' projektu" v našem světě (nebo mě litujete, že se ke mně se takové zbastlené projekty nedostaly, jsem Tomáš, který nevěří ve všemocná programátorská prasata a nemůže tudíž ani uvěřit v těžký kříž chudáka vývojáře, co přebírá cizí projekty a jehož čas vyplňuje refaktorizace čuňačin skrytých pod rouškou autonomních view:) )? To snad je jen nedorozumění.

Konkrétněji – hledal jsem, kde můžete mít pro tato svá tvrzení oporu. A i u ve Flexu, který je Vám blízky

"The vision at the core of the Autonomous View pattern is one of smart reusable components glued together to form a hierarchy of composite views. In extreme cases, business logic and interactions with remote-services are also implemented directly in the views. ****But many Autonomous View architectures do attempt some extraction of this kind of logic into separate classes for use by multiple views."****
Zdroj: http://weblogs.macromedia.com/paulw/archives/2007/09/presentation_pa_1.html

Vzory se mohou nazývat vzory, když je jasné, jaký problém vzor řeší a jaké jsou jeho variace. Vymlouvat se na to, že Autonomou view není dobře popsán, no ehm – proč pak ale o něm mluvit jako o vzoru, jde o pouhý draft, který spíš mate než vysvětluje. Proč tedy nezavedete svůj pojem pro popsání toho, co máte na mysli a nepodáte jeho definici?
Zbaslený kód může být jedině antivzorem, anebo tedy mohu začít zbastlené projekty popisovat jako tradiční exempláře vzoru Autonomous View, který vznikl mírnou evolucí časem ověřeného programového idiomu "Spagheti Code". :)

Ad IMessagingService – uvedl jste dva příklady, já jsem se je snažil podrobně rozebrat a
dobrat se toho, co tedy servisní vrstva ve vašem pojetí v aplikaci představuje. Výhody Controlleru z prezentačního vzoru, který řídí odesílání emailů (kromě situace zmíněné v mém komentáři) mi unikají.

Poznámka k Front Controlleru – byl to jen závěrečný povzdech, že hranice mezi MVC a MVP jsou neostré. Rysy desktopových i webových aplikací se prolínají a kombinují. V desktopových aplikacích můžeme mít cosi, co je nazýváno application controller (jak jste v článku zmínil), ale mnohdy AC figuruje i v roli FC a hranice mezi MVC a MVP lze jen těžko nalézt. Navic, jak víte a částečně jste v článku zmínil, MVP u Fowlera je v *draftech* nakonec potlačen (Retirement note for Model View Presenter Pattern) a mluví hlavně o samostatných kandidátech na vzor Front Controller, Passive view (a Presentation model).

Školometská:) poznámka na závěr – článek jsem přečetl (kupodivu) rád a jsem rád, že vznikl, jen bych mu neříkal esej. :) Esej je podle mě subjektivně laděná odborná analyticko-syntetická úvaha, která předpokládá u čtenáře obeznámenost s tématem, neobtěžuje se většinou s citací zdrojů, ale stávající poznatky obléká do nového neotřelého hávu nebo vyvozuje zajímavé důsledky ze stavu stávajícho vědění. Syntetický rekapitulující text mi do formy eseje nepasuje.

Martin Hassman

Autonomou view … proč pak ale o něm mluvit jako o vzoru … jedině antivzorem

On je ten vzor v případě AV zcela záměrně uveden v uvozovkách. Použití termínu antivzor by bylo jen poněkud ostřejší variantou téhož. To už je jen o tom, jak moc důrazně chceme na tu čarodějnici před spálením ukázat, aby se všem zošklivila.

David Grudl

Nevím co je to DM, AD, AC, FC a když je řekne SRP, očekávám KLADIVO.

PŘML se za SRML KMTŘ!

ps.
PŘML = přimlouvám
SRML = srozumitelnější
KMTŘ = komentáře, vole

YF

… tak borek dostavel raketoplan (nebo house-of-pain?) :)) existuje takovej vybornej anglickej termin: "brainfuck" – taky mi to pripomina prdeni hlavou – tak sem si rikal jak dlouho clovek musi prdet nez s tim zacne neco delat :) myslim ze je zde taky docela jasne videt proc nema cenu na neco takovyho psat 'kontruktivni' kritiku protoze timhle stylem bysme u toho stravili mladi (v mem pripade stari) nezbysme k necemu dospeli :) myslim ze je na case zacit myslet (hlavou) … :) timto nechci autora urazit – prosim ber to s humorem – ja sem se bavil cele tri dily a doufam ze se jednou zasmejes i ty :) at se dari! :)

v6ak

Co si přesně mám představit pod servisní vrstvou a kdo je zodpovědný za vytvoření její instance? Mám si pod tím představit DB layer jako třeba Dibi? Anebo ten bude touto vrstvou obalen?
O vytvoření její instance se stará Presenter/Controller?

Luk83

V pojetí MVC je DB layer Model. To je v článku vysvětleno.

Logicky se dá odvodit, že při řešení určitých problémů je třeba zvolit oddělenou vrstvu která se může volat odkudkoli a bude velmi jednoduché udržovat a upravovat logiku zpracování.

Například generování a stahování XML feedu je dobré oddělit a napsat samostatnou třídu, která řeší tento feed jako individuální (používá určité značky) volá se cronem přes controller a využívá model pro spojení s databází. Pak je velmi jednoduché, například při změně nejakých značek nebo struktury feedu zasáhnout a neřešit logiku návrhu aplikace.

V pátek jsem řešil problém práv u obsáhlejší aplikace a dospěl jsem k oddělené vrstvě, která se volá z controlleru (kontroluje akce dostupné uživateli) a zároveň z view kdy kontroluje zda má uživatel právo vidět určité odkazy. Při tom používá model, který tato práva ověřuje v databázi. Do budoucna bude tato vrsva mnohem robustnější a nebojím se dál na tomto stavět, protože mám opět vyřešenou logiku aplikace, jen se postarám o pravidla ověřování.

v6ak

Db layer minimálně těžko bude mít business logiku => těžko může být modelem.
Pro RSS je tu prostě jiný view.

Aleš Roubíček

Zbytečně zacházíte do implementačních detailů.

muz.Payne

Chcel by som sa tymto spytat kde presne patri navrhovy vzor UI Delegate pouzivany v ramci Java Swing. Jedna sa len o iny nazov niektoreho zo spomimanych vzorov, alebo ide o uplne odlisny vzor???

uf

UI delegate je podle me strategie pro kresleni – vsechno ostatni je stejne, jen vlastni tvary a barvicky jsou jinac. Opravi me nekdo?

Mirek.Charvat

Vycházím z předpokladu, že aplikace se jako celek chová černá skříňka. Černá skříňka komunikuje s okolím pomocí signálů, vstupních a výstupních. Ke všem svým vnitřním částem má černá skříňka výhradní přístup, tzn. nesdílí je s jinou černou skříňkou jinak, než prostřednictvím rozhraní. Kombinace PHP+MySQL je tedy tvořena minimálně dvěma černými skříňkami PHP běžící instancí PHP scriptu a databází s databázovým strojem. Je to asi banální, ale podle mého je důležité si právě toto uvědomit.

Co je MVC z pohledu struktury černé skříňky PHP scriptu? "V" je druh výstupního signálu (výsledná HTML stránka). Generují se i jiné výstupní signály. Např. ukládání dat do cookies. "C" je systém pro zpracování pouze určité množiny vstupních signálů (URL dotaz, data s ním spojená). "M" je vše ostatní včetně výstupních a vstupních signálů směřujích k a od druhé černé skříňky s databází.

Popsal jsem to dobře?

Pokud ano. Je asi celkem jasné, v čem je MVC systém členění aplikace speciální a jak je tím vlastně zavádějící.

Mirek.Charvat

Jo-o i ne-e :o)

Ať se nazývá cokoli jakkoli, ať už máte jakýkoli model (abstrakci) reality, vždy je nejdůležitější jaká je technická podstata věci. Náhled na aplikaci pomocí struktury černých skříněk mohu porovnat s náhledem MVC a mně šlo o to, jestli jsem vzájemné porovnání udělal dobře. O tom v článku nic není.

Ať už se jedná o náhled na realitu pomocí členění do MVC, černých skříněk nebo čehokoli jiného, jedním z dosti podstatných důvodů, proč si jakékoli takové schéma zavádím je pochopit, co vlastně dělám, jak to funguje a má fungovat aby … a druhým, abych si následně zjednodušil práci a mohl se odpoutat od komplexnosti a zúžit svůj pohled na detail s jistotou, že to s čím v detailu (nebo obecně na aktuální úrovni) pracuji jsou skutčně celistvé stavební kamínky a ne jen se tak tvářící konce špaget.

Už mi rozumíte, co se snažím říci?

Když se pokusím MVC způsob pohledu použít v praxi, narazím na to, že je právě v tomto ohledu zavádějící. Ono je zdánlivě logické rozčlenění. Tváří se jako by vystihoval samu podstatu fungování aplikace, ale z výše uvedeného porovnání s jiným druhem abstrakce reality, černou skříňkou (která je podle mého realitě mnohem blíže, ale je otázka, jestli jsem to srovnání udělal opravdu dobře), prostě vyplývá, že v některých částech aplikace dělá z jedné odrůdy jablka jablko jako druh a na jiném místě míchá zbylé odrůdy jablek s hruškami.

Proto je ASI kolem praktického nasazení MVC tolik nejasností a je to tak náročné na detailní provedení. Protože člověk musí mít neustále na paměti, že v případě MVC není abstrakcí typu "podstata fungování", jakkoli se tak tváří, ale způsobem náhledu typu "paní radová, její knihkupec, jeho poznámkový blok a zbytek planety" :o)

Mirek.Charvat

… přesněji: "paní radová, její knihkupec, jeho knihkupectví a zbytek světa"

uf

Pekna serie. Ale pro mou prirozenou natvrdlost ji mam schovanou a nekdy se k ni vratim. Dik. MVC a MVP teoreticky znam, ale ostatni moc ne…

uf

Esce jsem zapomnel dodat, ze princip Jednoduche odpovednosti (trida/objekt ma za ukol jen jednu vec) mi stale dela problemy. Je to asi tim, ze vse vidim z nizkourovnoveho programatorskeho hlediska, uz premyslim, jak to napsat, a navrh z nadhledu ne a ne udelat. Treba tento tyden. Ale nikomu to nerikejte, kdyz se tim zivim :-).

Jaroslav Tulach

Dík za pěkné články. Myslím, že jsem si v těch třípísmenných
zkratkách udělal výrazně větší pořádek než jsem měl před jejich
přečtením.

Ještě mi však nedá nepřidat ještě jednu zkratku. Nedávno jsem četl
DCI a přišlo
mi to jako rozumná kritika MVC s pěkným návrhem jak z toho ven. Možná se
to někomu bude při navrhování hodit.

Steve

Přijde mi, že příčiny nepochopení jsou 2 hlavní.

  • Někteří si myslí, že model je přepravka dat z controlleru do view.
    V ASP.NET MVC tomu třeba nahrává i fakt, že hlavička generické třídy
    ViewPage vypadá: „ViewPage<TModel>“.
    1. Šipka od view k modelu. Přijde mi, že v ASP.NET MVC nebo i Zend
      Frameworku je spíš taková tendence, že controller předá view všechno, co
      je potřeba, a view už nic jiného nepoužívá. Viz třeba examply a
      dokumentace přímo od autorů obou frameworků.

Enum a statická analýza kódu

Mám jednu univerzální radu pro začínající programátorty. V učení sice neexistují rychlé zkratky, ovšem tuhle radu můžete snadno začít používat a zrychlit tak tempo učení. Tou tajemnou ingrediencí je statická analýza kódu. Ukážeme si to na příkladu enum.