Komentáře k článku

Úvod do architektury MVC

MVC je zajímavý fenomén – jeho popis najdete v tisících článků, a přesto kolem něj stále panuje víc zmatení než pochopení. Cílem této třídílné série proto bude podat poctivý, snad v něčem i unikátní úvod do světa MVC a souvisejících prezentačních vzorů. Dnes začneme obecnými principy architektury MVC.

Zpět na článek

59 komentářů k článku Úvod do architektury MVC:

  1. danaketh

    RE: Úvod do architektury MVC
    Super. Tohle je přesně to co jsem potřeboval k ujasnění některých vazeb v MVC. Těším se na další díly.

  2. psonek

    Pravidla
    Z teoretické stránky se v MVC zas tak moc neorientuju, ale prakticky bych řekl, že umím napsat MVC aplikaci. Tohle jsou moje pravidla:

    • Dobrý model je základ. Používat silně typované kolekce, přístup k položkám modelu vždy přes properties.
    • Pro view je model read-only. Nikdy nemodifikovat model přímo v kódu view.
    • V GUI na každou uživatelskou akci jednořádková obsluha. Pokud má funkce button_Click víc než jeden řádek, je to špatně.
    • Definovat View jako interface. Ten interface pak musí být možné implementovat např. jako formulář, webovou stránku nebo v konzoli.

    Ze začátku je potřeba odolat pokušení měnit model přímo z view. A pak asi nejtěžší je navrhnout View interface. Buď je možnost si ho dobře promyslet předem nebo ho dělat stylem ad-hoc (postupně přidávat a měnit funkce).

    Typický příklad editace osoby:

    View::address_Validating() {
      controller.setAddress(addressTextBox.Text);
    }
    
    Controller::setAddress(Person p, string newAddress, IView view) {
      if(address == NULL) {
        view.OnEmptyAddress(newAddress);
        return;
      }
      p.Address = address;
      view.OnAddressChanged(p, newAddress);
    }
    
    View::OnEmptyAdress(Person p) {
      ShowMessageBox("Empty address!!");
    }
    
    View::OnAddressChanged(Person p, string newAddress) {
      addressTextBox.Text = newAddress;
    }
    
    1. Lojza

      Re: Pravidla
      Jo jo, moc se mi líbí, že ui event 'validace adres' je okoučováno v Controller::setAddress. :-))

    2. ava

      Re: Pravidla
      Hmm, prijde mi (i kdyz neznam kontext, pouzity jazyk ani framework :-), ze cely uvedeny priklad je tak komplikovany pouze proto, ze v sobe zahrnuje validaci – kontrolu toho, zda adresa neni prazdna, a pripadne osetreni. Kdyby mohla byt adresa libovolna, tak by mel priklad 0 radku, jestli to chapu spravne? (predpokladam ze samotne navazani view a controlleru na model tak, aby bylo mozne ve vstupnim policku editovat adresu, je v tomto priklade provedeno jinde, napr. v GUI builderu).

      Potom podle me doslo presne k te chybe, na kterou je upozorneno i v clanku – validacni logika neni v modelu, ale ve view/controller.

      Kdysi jsem psal mirne rozsahlou GUI aplikaci v pythonu (>100 oken), udelal jsem si vlastni MVC miniframework, ktery toto resil tak, ze kazdy model mel validacni metodu, ktera vracela kolekci aspektu ktere neprosly validaci, a popisu prislusnych chyb. Dialog potom pred acceptnutim volal funkci validate, ktera provedla validaci modelu, nasla k prislusnym nevalidnim aspektum prislusna views, ty vycervenila a prvni z nich focusla (aby uzivatel mohl pohodlne opravit chyby), a zobrazila errorbox se seznamem chyb v dialogu. Timto zpusobem byla oddelena prezentace chyb od samotne validace, veskera validace byla v modelu (bylo mozno zjistit zda je korektni i bez GUI), a do view/controlleru jsem nemusel nic cpat. Prislo mi to jako dobre reseni.

      Omlouvam se za priserne vmixovavani cechoanglismu do prispevku :)

      1. smilelover

        Re: Pravidla

        Potom podle me doslo presne k te chybe, na kterou je upozorneno i v clanku – validacni logika neni v modelu, ale ve view/controller.

        Pozor! V clanku se pise, ze validacni pravidla maji byt vylucne v modelu, ne logika. Snazit se do modelu cpat i veskerou validacni logiku je casto drbani se levou rukou za pravym uchem.

        U webovych aplikaci se regulerne a spravne resi validace na urovni C ci V, problem je, kdyz i ta pravidla jsou na techto vrstvach definovana a ony si je nezadaji od M (jako treba delky poli ci regexpy natvrdo zapsane primo v JavaScriptech pro validaci pred odeslanim formu).

        1. ava

          Re: Pravidla
          Hmm, neznam presnou definici 'validacni logiky' ani 'validacnich pravidel', tak se omlouvam za pripadne zmateni. Mel jsem na mysli 'programovy kod, ktery se vykona a overi, zda je model validni ci ne, a pokud neni, dokaze podat (nikoliv prezentovat) informaci o tom, co je spatne'.

          V klasicke newebove aplikaci neni problem toto mit pouze v modelu. Jestli to chapu spravne, ve webovych aplikacich to problem byt muze, protoze model a jeho logika jsou ulozeny na serveru a odezva (pripadne pruchodnost site) by byly neumerne vysoke (je tu jeste jiny principialni problem? O webovych aplikacich moc nevim)

          Asi nejcistsi reseni by bylo v takovem pripade bylo automaticky generovat javascriptovy client-side validacni kod ze zdrojaku validacniho kodu v modelu, aby se programator vyhnul duplicitam, ale nevim jestli to nekdo tak dela :) Pokud me nekdo pouci o tom, jak se toto dilema (duplikace kodu vs. odezva/propustnost) dnes resi, a jak by se spravne resit melo, budu jen rad..

          1. smilelover

            Re: Pravidla

            'programovy kod, ktery se vykona a overi, zda je model validni ci ne, a pokud neni, dokaze podat (nikoliv prezentovat) informaci o tom, co je spatne'.

            No, a ten kod k tomu overeni pouziva nejaka pravidla. Ta musi byt ulozena v Modelu, resp. presneji receno, Model o ne musime zadat. Ta logika muze byt IMHO kdekoliv a taky casto byva, protoze tlacit ji vzdy do modelu neni prakticke.

            V klasicke newebove aplikaci neni problem toto mit pouze v modelu. Jestli to chapu spravne, ve webovych aplikacich to problem byt muze, protoze model a jeho logika jsou ulozeny na serveru a odezva (pripadne pruchodnost site) by byly neumerne vysoke (je tu jeste jiny principialni problem? O webovych aplikacich moc nevim)

            Ne, na serveru to klidne muze byt, ale treba v Controlleru, ne nutne v Modelu. I kdyz, kdyz se to tak vezme — validacni logika bude mit vzdy nejaky opakujici se kus kodu, takze nebude primo v controlleru, ale v nejakem validacnim manazerovi, ktery budou jednotlive controllery volat. A to uz je v podstate v Modelu.
            Ale prikladem je treba validace pomoci anotaci na properties v controlleru (tam zas ovsem neni vzdy jednoduche rozumne ta pravidla dostat, alespon z pohledu Javy a jejiho chovani v pripade anotaci).

            Asi nejcistsi reseni by bylo v takovem pripade bylo automaticky generovat javascriptovy client-side validacni kod ze zdrojaku validacniho kodu v modelu, aby se programator vyhnul duplicitam, ale nevim jestli to nekdo tak dela :)

            Priznam se, ze taky ne vzdy, ale vidim to jako idealni reseni. Vykonovym problemum se da vyhnout tak, ze se to negeneruje on the fly, ale pri deployi nejakym skriptem (Maven, Ant, Phing… moznosti je plno).

            1. ava

              Re: Pravidla
              ad. 1)
              Nechapu vyznam pravidel, z meho pohledu kod = pravidla, o nic nezadam, proste spustim validacni metodu ktera je (a mela by) byt ulozena v modelu. U GUI aplikaci nevidim duvod, proc by to nemelo byt prakticke, krome spatne navrzeneho frameworku. Ponechme ted prosim stranou (opravdu, prosim, nebylo by to prinosem) napr. ulozene procedury v relacnich DB ktere kontroluji jeji konzistenci

              ad. 2)
              Proc by mela mit opakujici se kus kodu? Nevidim duvod, v mnou vyse zminene aplikaci se nic takoveho nestalo (pokud ano, bylo to mym opomenutim, nikoliv z principialniho donuceni)
              DialogController v mem pripade delal pouze to, ze kdyz se uzivatel pokusil acceptnout dialog, tak provedl neco nasledujiciho (jde o myslenku):

              validationResult = model.validate()
              if not validationResult.isValid:
              ….self.highlightAndFocusInvalidWidgetsFrom(validationResult)
              ….self.showError(validationResult.errorText())
              else:
              ….self.accept()

              od te doby jsem NIKDY nemusel psat validaci nikam jinam nez do prislusnych model.validate(), a zadarmo jsem mel upozornovani uzivatele na chybna policka atp..

              O validaci pomoci anotaci na properties v controlleru v Jave totalne nic nevim, ale nezni to moc lakave :-)

              ad 3)
              Problemem samozrejme neni vykon, ale
              a) obtiznost prekladu z jednoho jazyka do druheho (ten mensi, i kdyz dost velky problem)
              b) server muze napriklad validaci provadet oproti DB, coz javascriptovy klient nemusi mit umozneno. Pravidla na serveru a klientu by pak nebyla stejna, na klientu by zrejme byla jen nejaka oklestena verze serverovych. Toto rozliseni je snad jeste neprijemnejsi nez a)

              1. smilelover

                Re: Pravidla
                ad 1) Validace se temer vzdy da rozdelit na logiku a pravidla. Delky retezcu, hranice cisel, cisla vyhovujici rovnicim, regularni vyrazy. A jestli se tato pravidla pak pouziji v JS nebo treba v PHP, to uz je fuk.

                ad 2) opakovani kodu jsem myslel prave to, ze kdyz rozdelime validaci na pravidla a kod validujici data podle pravidel, bude ten kod pro velky pocet pripadu naprosto stejny.

                Validace pomoci anotaci v Jave je naopak velmi navykova :-) Jen je problem, ze hodnota property anotace nemuze byt treba vysledek volani staticke metody, ani kdyz ma RetentionPolicy.RUNTIME.

                ad 3) jo, tak pokud jde o pravidla slozitejsi nebo vazana na existujici data, tak je lepsi se na validaci na klientovi uplne vykaslat. Je to zbytecny luxus.

          2. Finta

            Re: Pravidla
            Z hladiska bezpecnosti je potrebne aby sa data validovali na strane servera. Validacia na strane klienta moze byt riesena cez Ajax. Tym sa da pekne vyhnut duplicite validacneho kodu a uzivatel dostane privetive prostredie. V pripade vypnuteho JS sa formular zvaliduje iba na strane servera.

    3. Sten

      Re: Pravidla

      V GUI na každou uživatelskou akci jednořádková obsluha. Pokud má funkce button_Click víc než jeden řádek, je to špatně.

      Ještě lepší je nedělat explicitní obsluhu vůbec, ale svěřit problém signálům a slotům (aka událostem a delegátům) a napojit je při tvorbě View.

      Definovat View jako interface. Ten interface pak musí být možné implementovat např. jako formulář, webovou stránku nebo v konzoli

      Nejenom View, ale i Model by měl být interface. Potom můžeme dávat data na různá místa se stále stejnými View a Controllerem.

    4. Borek BernardAutor příspěvku

      Re: Pravidla
      Přesně podobná pravidla jsou mnohdy užitečnější, než nějaké malůvky a obecné popisy :) Nicméně, ve vašem příkladu validace probíhá v Controlleru, což je komponenta s prezentační a aplikační logikou, zatímco validace správně patří do doménového modelu. Takže i obecné poučky mohou být někdy užitečné :)

      Také to, čemu říkáte Controller, je ve skutečnosti Presenter. Rozdíl mezi nimi bude vysvětlen v příštím díle.

      Díky za dlouhý a dobrý komentář.

  3. dc

    web app
    pretoze vecsina web app/jazykov/platforiem zo zaciatku neobsahovali ziaden framework tak sa znovu objavuje koleso a sme uneseny ze nieco take existuje.Nechcem tym nikoho zhadzovat alebo celu teoriu MVC odpisovat, len mi to pride trochu zvratene.Mam pocit ako keby velka cast web vyvojarov proste zacala rovno z webom a nikdy do incoho ineho ani nepichla a preto su z toho taky uneseny, pritom pri beznych desktopovych aplikaciach toto su v podstate bezne veci.Napriklad take MFC funguje vlastne ako MVC framework (da sa na to aj tak pozerat).

    1. danaketh

      Re: web app
      Ono to tak ale často skutečně je. Já sice začal na Basicu a Pascalu ale v té době by mi MVC jen komplikovalo život. Teď si od toho webového patlání odskakuji k Pythonu (a občas naťuknu Ruby) a tak MVC a další možnosti poznávám až takhle pozdě.

    2. Borek BernardAutor příspěvku

      Re: web app
      Na MFC se dá dívat jako na MVC framework tak maximálně, když to necháte vyslovit Němce :)

      Moje zkušenost je přesně opačná: udělat aplikaci s kvalitní MVC architekturou je na desktopu daleko náročnější než na webu. Je to patrně proto, že webový request-response model je jednoduchý a přímočarý – na začátku načtete data, ty nějak zpracujete, zkonvertujete do HTML nebo jiného výstupního formátu a tím máte hotovo. V aplikaci běžící na desktopu naopak pracujete se stavovým modelem, kde vám události od uživatele nebo od systému mohou přicházet z různých směrů a v různém pořadí, MVC triád existuje v každém okamžiku mnoho a podobně.

      Jistě, MVC zde již máme desítky let, ale to ještě neznamená, že ho umíme správně používat. Toto bohužel platí jak pro web, tak pro desktop.

      1. Anonym

        Re: web app
        Tiez mi pride, ze architektura dokument/pohlad v MFC je velmi podobna v clanku opisovanemu MVC. Nie som vsak ziadny odbornik, ale potesilo by ma keby ste mohli, hoci velmi strucne, ukazat v com su si odlisne.

        1. Borek BernardAutor příspěvku

          Re: web app
          D/V nerozlišuje View a Controller, čímž se od MVC dost liší. Někde jsem četl, že při vývoji MFC se vzor MVC zvažoval, ale technologicky prý bylo těžké ho realizovat, proto tým radši zvolil D/V. Ale není to úplně moje teritorium, takže po mně víc nechtějte :)

  4. Yenya

    Mezivrstvy jsou zlo
    Nejprve: diky za clanek, tesim se na dalsi pokracovani. Treba mi mnohe osvetli.

    Na druhe strane: je striktni rozdelovani na M, V a C vubec k necemu? Neni jednodussi proste podle potreby pouze refaktorizovat kod (ve stylu "kdyz uz neco delam podruhe/potreti, udelam si na to funkci/objekt/modul"?). Proc to striktne oddelovat? Chapu ze ma smysl oddelovat velkou cast View nekde bokem (uz proto, ze grafickou stranku veci casto navrhuje grafik/webdesigner, coz je nekdo jiny nez programator), ale duvod oddeleni M a C prilis nechapu, zvlast kdyz oboji pise ta stejna skupina lidi.

    Ja jsem zatim ziskal pocit, ze MVC jen vytvari taaakhle tluste mezivrstvy, ktere v podstate nic nedelaji.

    Videl jsem ne uplne maly (ale asi ne uplne velky) projekt v Ruby on Rails, kde se autor snazil dodrzovat MVC metodologii. Zhruba tretina az polovina kodu bylo zpristupnovani dat z SQL databaze do Ruby objektu (nepochybne znacna cast z toho mohla byt generovana), o neco mene bylo generovani HTML stranek, a uplne nejmene zrejme ten Controller. Akoratze vetsina toho kodu ve vsech trech vrstvach byly triviality typu "vezmu tento objekt/tento SELECT a toto z neho vypisu/vratim". Cili strasne moc textu ktery jen obaloval vrstvy do dalsich vrstev. Bylo tam zoufale malo mist, kde ten kod opravdu neco s daty delal. A kdyz clovek ukazal na stranku a chtel vedet proc je tam tato hodnota nebo co se stane kdyz stisknu toto tlacitko, bylo treba duvod hledat rozstrkany po nekolika oddelenych souborech zdrojoveho kodu.

    Neni lepsi napriklad zapouzdrovat SELECT do neceho vetsiho az v pripade, kdy opravdu tentyz SELECT potrebuju vickrat? Tyhlety pokusy o zapouzdreni databaze do objektu vedou pak k tomu, ze nevyuzivam moznosti databaze (abych slozitejsim SELECTem nechal databazi spocitat to co fakt v tomto konkretnim pripade potrebuju), ale pouzivam DB jen jako neinteligentni uloziste, a pak az ex post si z objektu vybiram, co potrebuju.

    Diky za pripadnou reakci na vyse uvedene treba v nekterem dalsim dile serialu.

    -Yenya, http://www.fi.muni.cz/~kas/blog/

    1. Sten

      Re: Mezivrstvy jsou zlo
      Důvod oddělení Modelu od Controlleru je kvůli tomu, že Model jsou opravdu jen nějak získaná data, která nemají sama nic dělat. Může to být třeba tenká vrstva nad databází, která bude vybírat data, jak o ně bude Controller (nebo View) žádat, nebo naopak úplně stejné View i Controller můžeme použít v embedded aplikaci, kde Model bude ukládat data do souboru a při startu je načte do paměti. Rozdíl je v tom, že nemusíme sahat do View ani Controlleru, tzn. nemusíme je ani znovu testovat. Stejně tak, pokud někdo přidá nové View a upraví Controller (nebo přidá nový; jeden Model může mít i více Controllerů), tak ho můžeme rovnou použít v obou verzích aplikace.

      V test-driven development se naopak běžně nahrazuje Model za pevně daná data a zkouší se, jestli Controller reaguje správně (mění správná data) či View vykresluje to, co požadujeme. Stejně tak můžeme nahradit Controller za něco pevně daného a zkoušet Model. Díky tomu se testují jednotlivé části samostatně, což zjednodušuje ladění i optimalizace a také umožňuje lépe rozdělit práci v týmu (můžete vyvíjet Controller, i když nemáte Model, stačí mít příslušné testy).

      Pokud Model jako obal databáze neumožňuje udělat složitější SELECT, který Controller nebo View potřebuje, bude nejspíš chyba v konkrétním Modelu.

      Samozřejmě MVC se nehodí na všechny případy, u jednodušších aplikací je to zbytečně složitý koncept.

      1. Borek BernardAutor příspěvku

        Re: Mezivrstvy jsou zlo
        Nejsem si jistý, jestli odpovídáte úplně na to, co se snažil říct Yenya, nicméně mám k vašemu příspěvků jeden komentář.

        Zdá se mi totiž, že mícháte Model a Servisní vrstvu. Pravda, máte nevýhodu, že je vám celý seriál servírován po kouskách a k popisu servisní vrstvy se dostaneme až ve třetím díle, nicméně na tomto místě bych rád podotknul, že dívat se na doménový model jako na (tenký) obal nad databází nebo jiným datovým úložištěm je nebezpečné. Model je naopak nosnou částí celé aplikace a je do značné míry na všem ostatním nezávislý – jak na prezentaci, tak na perzistenci.

        Jak jsem říkal, servisní vrstvě je věnována kapitola ve třetím díle, takže tam snad vše bude vysvětleno lépe a podrobněji.

        1. Sten

          Re: Mezivrstvy jsou zlo
          MVC docela běžně používám, takže o tomto vím. Ano, ve svém příspěvku jsem to dost zjednodušil, Model může být i hodně komplexní, může obalovat třeba nějaké košaté stromy nad kombinací databáze, souborů a RPC volání. Samozřejmě závisí to na tom, jestli berete Model jako abstraktní interface (potom je úplně nezávislý) nebo jako konkrétní implementaci (tak to beru já, nic o Servisní vrstvě nevím, protože o způsobu uložení dat MVC nic neříká).

          1. Sten

            Re: Mezivrstvy jsou zlo
            Model jako abstraktní interface není úplně přesně. Nemyslím tím interface ve stylu Javy (tzn. nulová funkčnost), ale interface ve stylu C++ CRTP, kdy interface obsahuje validaci (a další logiku, která je společná pro všechny implementace příslušného Modelu), ale vše ostatní nechává na konkrétní implementaci.

          2. Borek BernardAutor příspěvku

            Re: Mezivrstvy jsou zlo
            Model je v MVC doménový model nezávisle na tom, jak definujete "interface". Mluvit o databázi je zavádějící, protože tu má na starost persistenční vrstva. A tu, jak správně poznamenáváte, MVC vůbec neřeší.

      2. Yenya

        Re: Mezivrstvy jsou zlo
        Ještě jinak: striktním vyžadováním těchto vrstev se obíráte o značnou škálu prostředků. Kam byste v MVC zařadil třeba triggery, uložené procedury v databázi, anebo třeba databázové zprávy (Oracle: dbms_alert)?

        Nebo: lze pomocí MVC udělat aplikaci, ve které uživatel sám v podstatě skládá SELECT z nějakých dodaných prvků? Jako vývojář v zásadě víte nad jakými tabulkami tak ten SELECT může běžet, podle jakých sloupců se spojovat, podle jakých kritérií vybírat a třídit, a jak vypisovat data, ale to je tak všechno. Zbytek si určuje uživatel (příklad: různé statistické aplikace pro manažery – chtějí se na data dívat z fakt různých pohledů). Ne že by uživatel psal přímo SQL, ale v zásadě jeho podobu nějak určuje. Pokud toto není programovací nástroj převést na jeden velký SELECT, nevyužívá možností databáze a nemůže být optimální.

        Nevím jestli tohle běžné MVC systémy umožňují (ale určitě je to layering violation, čemuž se snaží zabránit). A přitom je to v mnoha případech dost užitečné. Ne že by takto měl být psaný celý velký systém, ale je potřeba aby se ty mezivrstvy necpaly tam kde je explicitně nepotřebuju.

        -Yenya, http://www.fi.muni.cz/~kas/blog/

        1. Sten

          Re: Mezivrstvy jsou zlo
          Triggery patří do Modelu, stejně jako uložené procedury. Databázové zprávy by asi také patřily do Modelu (a Controller by si je vyzvedával), ale tam si nejsem jistý.

          Pokud by se vhodně navrhl Model, tak by to šlo, ten SELECT by ale samozřejmě musel sestavit (a optimalizovat) on. Ale v tomhle případě by MVC asi bylo spíš na obtíž.

          1. Borek BernardAutor příspěvku

            Re: Mezivrstvy jsou zlo
            Přečtěte si, prosím, v článku ještě jednou, co je to Model. Triggery ani uložené procedury do něj rozhodně nepatří.

        2. Borek BernardAutor příspěvku

          Re: Mezivrstvy jsou zlo
          Triggery, uložené procedury a podobně nemají s MVC nic společného, jsou detailem persistenční vrstvy (v aplikaci zpřístupněné pomocí service layer).

          Pro "uživatelské sestavení SELECT příkazu" lze použít například Specification pattern (najdete ji i pod mnoha jinými názvy).

          1. Víko

            Re: Mezivrstvy jsou zlo
            Záleží na tom, co je v uložených procedurách implementováno. Rozhodně se nedá paušálně řící, že nemají s MVC nic společného.

        3. YF

          Re: Mezivrstvy jsou zlo
          MVC je architektonicky vzor primarne urceny pro systemy implementovane pomoci OOP – dal si nemyslim ze by vrstvy byly zlo :) obecne jsou vrstvy jenom jednou z mnoha forem dekompozice … MVC je rekl bych surovy zaklad vhodny pro systemy kde je jiz zapotrebi premyslet o napriklad rozsiritelnosti a nebo napriklad pokud mate tym lidi a projekt na kterem potrebujete resit rozdeleni prace – neni to dogma a jako vse se i toto da zneuzit nebo nespravne pouzit

    2. Anonym

      Re: Mezivrstvy jsou zlo
      Kontroler je uzitecny na hookovani kodu, oddeleni kontroleru a modelu se velmi hodi pro snadne testovani, ale i pro CLI utility pracujici s aplikaci. Rozhodne si nemyslim ze by ten pattern byl zbytecny :)

    3. Borek BernardAutor příspěvku

      Re: Mezivrstvy jsou zlo
      Díky za komentář, pokusím se reagovat.

      > Je striktni rozdelovani na M, V a C vubec k necemu? (…) Chapu ze ma smysl oddelovat velkou cast View nekde bokem (uz proto, ze grafickou stranku veci casto navrhuje grafik/webdesigner, coz je nekdo jiny nez programator), ale duvod oddeleni M a C prilis nechapu, zvlast kdyz oboji pise ta stejna skupina lidi.

      Oddělení zodpovědností do různých objektů je jedním ze základních principů dobrého objektového návrhu (tzv. Single Responsibility Principle). V případě MVC mají M a C dvě úplně jiné zodpovědnosti: Model obsahuje pouze data a doménovou logiku (tj. nemá s konkrétní prezentací nic společného), zatímco Controller je komponenta úzce spojená s prezentační a aplikační logikou.

      Když jejich zodpovědnosti namícháte, stane se vám například, že Controller bude obsahovat doménovou logiku a tu budete muset duplikovat, když bude Controllerů víc. Zde mi asi namítnete, že v tu chvíli můžete doménovou logiku extrahovat do nějakého jiného objektu a že tím duplikaci zabráníte, ale víte co? V tu chvíli vytváříte doménový model, respektive jeho část! Jak vidíte, při kvalitním návrhu aplikace dodržujícím základní principy OOP se stejně k aplikaci s oddělenými vrstvami dopracujete, i když tomu třeba MVC říkat nebudete.

      > A kdyz clovek ukazal na stranku a chtel vedet proc je tam tato hodnota nebo co se stane kdyz stisknu toto tlacitko, bylo treba duvod hledat rozstrkany po nekolika oddelenych souborech zdrojoveho kodu.

      Tohle je typický problém mnoha architektur a vzorů. Nové vrstvy zvyšují úroveň abstrakce, což může být dobře i špatně. U komplikovanějších aplikací se většinou má za to, že se přidaná abstrakce vyplatí, ale neplatí to u všech aplikací.

      > Tyhlety pokusy o zapouzdreni databaze do objektu vedou pak k tomu, ze nevyuzivam moznosti databaze (…), ale pouzivam DB jen jako neinteligentni uloziste, a pak az ex post si z objektu vybiram, co potrebuju.

      To je otázka implementace, ne architektury MVC.

      Díky,
      B.

      1. Yenya

        Re: Mezivrstvy jsou zlo

        Když jejich zodpovědnosti namícháte, stane se vám například, že Controller bude obsahovat doménovou logiku a tu budete muset duplikovat, když bude Controllerů víc. Zde mi asi namítnete, že v tu chvíli můžete doménovou logiku extrahovat do nějakého jiného objektu a že tím duplikaci zabráníte, ale víte co? V tu chvíli vytváříte doménový model, respektive jeho část!

        Samozřejmě, ale opravdu vytvářím jen část, a to přesně tu část, kterou tam mít musím (jinak bych duplikoval kód), a přesně v té chvíli, kdy ji začnu potřebovat. Ne dřív. Já netvrdím, že MVC-like architektura je obecně zlo, jen tvrdím, že mezivrstvy (raději ale volitelně použité helpery) by se neměly psát předčasně.

        -Yenya

  5. v6ak

    Validace nejen do Modelu
    Řekněme, že mám nějaké políčko na sumu peněz. Bude to tedy desetinné číslo (třeba BigDecimal). Podmínky budou následující:
    1) z definice vyplývá, že musí jít o číslo
    2) z nějakého dalšího důvodu to musí být 200 – 500
    Pravidlo č. 2 patří jednoznačně do modelu. Pravidlo č. 1 tam ale jednoznačně nepatří: model to dostává jako BigDecimal => ani se to k němu nemá jak dostat.

    1. ava

      Re: Validace nejen do Modelu
      Souhlas, 1) jsem povazoval za samozrejmost (patri s nejvyssi pravdepodobnosti do controlleru), mluvil jsem o validaci business logiky :)

    2. Borek BernardAutor příspěvku

      Re: Validace nejen do Modelu
      Když v Modelu napíšete něco jako

      [Range(200, 500)]
      var sum : BigDecimal;

      máte v něm explicitně pravidlo, že proměnná je typu BigDecimal. Pokud model realizujete jako sadu netypových proměnných, rovněž v něm budete chtít nějak vyjádřit, že 'sum' je číslo.

      Netvrdil bych proto, že pravidlo 1) do modelu "jednoznačně nepatří" – ono v něm naopak téměř vždy nějak zachyceno bude, i když ve většině technologií příslušnou "validaci" zajistí už kompilátor, případně interpret.

      Jiná věc je potom vrstva View. Zřejmě vycházíte z předpokladu, že widget zachytávající vstup podporuje pouze String a tedy třeba v HTML můžu do políčka "suma peněz" klidně zadat "abc" (což je nevalidní). V tom případě ano, nějak potřebuji v prezentačních komponentách (V, C) zajistit, aby byl vstup v pořádku, nicméně taky si lze představit technologii, kde mám ovládací prvky typu TextInput, DecimalInput, DateInput atd., takže v obecné rovině nelze tvrdit, že validace ve View musí nutně existovat.

      1. v6ak

        Re: Validace nejen do Modelu
        Na tom, jestli jde o validaci v modelu, se shodneme, jen to říkáme jinak.
        Samozřejmě, mohou tu být i omezené inputy, ale na nich to neukážu. A netvrdím, že to tam musí být, jen že za určitých podmínek můžu narazit na validaci mimo model. Prostě doufám, že se nenajde nikdo, kdo bude chtít třeba setMoney(String) /* první, co mě napadlo */ s validací čísla s tím, že veškeré validace mají být přece v Modelu.

    3. dave

      Re: Validace nejen do Modelu
      Tak jak to chápu já, tak v modelu musí být vždy všechna validační pravidla. To je jestli je implementuje i view je pak v podstatě jedno. Model je musí mít vždy.
      Jak jinak by pak šlo snadno nahradit jeden view druhým? Např. webové rozhraní, klasickým UI nějakého lokálního klienta.

      Takže v tomto případě, model si zkontroluje zda dostal bigdecimal a pak si zkontroluje jestli je mezi 200 a 500.

  6. David Grudl

    RE: Úvod do architektury MVC
    Výborně napsané a hlavně jsem rád, že tenhle seriál vůbec vznikl.

    1. Borek BernardAutor příspěvku

      RE: Úvod do architektury MVC
      V podstatě jsi stál u jeho zrodu :) Jsem rád, že se líbí.

  7. jos

    RE: Úvod do architektury MVC
    Někomu se asi při četbě následujícího nebude zdát výskyt slova Struts. Jenže MVC je pořád stejná m*dka bez ohledu na jazyk, sebelepší implementace to nezmění.

    Allen Holub: Holub on Patterns:

    Returning to Struts, this library isn't a model of OO architecture and was never inteded to be. The MVC architecture embodied in Struts pretty much forces you to use get/set methods. You can reasonably argue, that given the generic nature of Struts, it can't be fully OO, but other UI architectures manage to hide encapsulation better than MVC. Perhaps the real solution is to avoid an MVC based framework altogether. MVC was develpoed almost 30 years ago, and we've learned a lot since then.

      1. jos

        RE: Úvod do architektury MVC
        to není extrámní názor, to je oprávněná kritika ;) nikoliv však článku (i o špatnejch věcech se může psát, že), ale architektury MVC

  8. T

    Par poznamok
    V prvom rade vdaka za clanok. Vdaka bubline okolo ASP.NET MVC sa dostava do popredia problematika MVC aj v (ASP).NET komunite. Casto chyba ale background, ktory tento clanok poskytuje

    K uvodnej casti clanku nemam vyhrady, zial, ten zaver(posledny odsek) mi pride ako trosku zmotany, bud prilis vela nedotiahnutych myslienok na kope, alebo nedoslednost.

    1. "Toto jsou také komponenty, které se v jednotlivých variacích liší, zatímco Model je stále stejný, a proto k němu můžu uvést pár poznámek už tady"

    bohuzial, aj model moze byt ponaty rozne – aktivny(povedzme povodny koncept v duchu ktoreho su aj schemy v uvode clanku) a pasivny model, co ma potom zasadny dopad na riesenie controllera a view.

    2. "Model ve smyslu MVC je však daleko víc, je to tzv. doménový model"

    Model v zmysle MVC moze byt aj anemicky model(nechapat nutne ako urazku)(=transaction script pristup), active record, rozvinuty DDD model (ano, s domain modelom na vrchu), mozu to byt hoci vec services…od tohoto MVC ako pattern abstrahuje(vid. napr. GoF), nie je to vobec podstatne. (je tu vsak samozrejme otazka, ako riesit v kontexte konkretnej zvolenej architektury aktivny model, ak chceme ist touto cestou ;-)

    "doménový model, který modeluje vztahy reálného světa"

    bohuzial, toto je dost zavadzajuce zjednodusenie pointy DDD.

    3. "např. validátory v ASP.NET nebo ve Flexu), v architektuře MVC však správně patří do Modelu."

    Tu uz naozaj zachadzame do DDD. Nesuhlasim, zase nieco, co navrhovy vzor MVC neriesi.(vid. GoF)

    Navyse, okolo tohoto je neuzavreta diskusia aj v ramci DDD sceny. Business rules ok, v idealnom pripade maju byt v domain vrstve, okolo toho je zhoda. Ale co so zakladnymi validaciami inputov (ktore maju mimochodom ambiciu riesit asp.net validatory?). Aby som mohol validovat v business vrstve, musim mat aspon vstupy v nejakej podobe, ktore jej dokazem posunut.

    4. "V klasickém třívrstvém modelu, kde máme datovou, aplikační a prezentační vrstvu, Model v prezentační vrstvě v principu odpovídá modelu v aplikační vrstvě. Bohužel není zcela obvyklé, aby nástroje uměly tyto modely synchronizovat – tento úkol je tak většinou na bedrech programátora."

    Prax ukazala, ze Views musia riesit aj otazku stavu GUI / document modelu / modelu prezentacnej vrstvy.(pocnuc SmallTalkom) a ze je z hladiska praxe rozumne uvazovat o dvoch veciach(co v pripade predhistorickych uvah o GUI bolo bezpredmetne). Z tohto faktu sa vyprofiloval Fowlerovsky MVP, ktory ponuka pekne riesenie/vychodisko.

    Vid. materialy napr. na Fowlerovej stranke ku tejto problematike.

    1. Borek BernardAutor příspěvku

      Re: Par poznamok
      Hned na začátku díky za vynikající komentář. Pár poznámek:

      – Pojem doménový model jsem použil, protože model reprezentuje problémovou doménu. Nemyslel jsem tím nutně model ve smyslu DDD, i když k této interpretaci tíhnu.

      – V článku píšu, že model může být pouhou sadou datových objektů, ale že je to netypické. Netypické je to proto, že někam potřebujete dát validaci: ať už používáte doménový model ve smyslu DDD nebo třeba Active Record, validační pravidla vám kvůli principu DRY vždycky skončí v modelu. Pokud vaše aplikace validaci nepotřebuje, můžete si osekaný model dovolit, ale u drtivé většiny aplikací bude anemický model problémem. Proto jej taky Fowler řadí mezi ANTIvzory.

      – "Modeluje vztahy reálného světa" je zjednodušením, ano. Pro úvodní článek o MVC snad postačuje.

      – To, že GoF něco neřeší, ještě neznamená, že by se to řešit nemělo :) Řada jiných zdrojů naopak Model popisuje poměrně detailně, viz např. Fowler.

      – Jednotlivé variace MVP jsou předmětem druhého dílu

      – Mohl byste, prosím, rozvést pojem "pasivní model"?

      Díky,
      B.

      1. T

        Re: Par poznamok
        Dakujem aj ja za reakciu. Myslim, ze nazorovo mame blizko(co ma tesi) a v podstate ide +- o hru so slovickami, netreba preto v mojich nasledujucich poznamkach hladat nutne oponovanie ;-)

        – Fowler napr. v PoEAA popisuje rozne (enterprise) modely. DDD pristup sa hodi len na rozsiahle projekty s velmi zlozitym modelom, to zdoraznuje Fowler aj Evans(aj ked mnohe principy je mozne aplikovavat samozrejme na mensich). Netreba tento rozmer zbytocne vnasat do problematiky MVC, to je len nazor. Aj ked tomu oznaceniu dava Fowler v clanku, ktory sme citali asi obaja negativny nadych, v kontexte konktretneho projektu a jeho specifik(maly, CRUD oriented) by som to tak nevidel.
        Pod anemickym ma na mysli predovsetkym odnatie behavior z domenovych objektov.
        Ludia stavajuci napr. nad active record domenovy model v podstate nemaju, spliva s datovym modelom, alebo ho maju nad active recordom ako transaction scripty.

        – Validacne pravidla / business rules, to sa zhodneme, patria do modelu, netreba to rozpitvavat.(ako z modelu passnut vysledky validacii a sprostredkovat ich pouzivatelovi, je temou na dlhe zimne vecery :-)
        Otazne je, kam patria zakladne validacie user inputu(napr. datovy typ – date, int), aby bolo mozne vobec posunut input do domain modelu, upozornoval som na toto(a tusim aj iny citatelia vyssie)
        Dalej je otazne ako riesit zobrazenie mandatory flagu pri inpute, ak povinnost vyplnit pole je zavisla od nejakeho business pravidla a pod.
        ASP.NET validatory je mozne pouzit len na takuto zakladnu validaciu, hoci sa bezne pouziva aj na komplexne validacie ktore spadaju uz pod business.
        (Dovolim si povedat, ze prave MVP dava na pekne odpovede na tieto problemy ovela viac priestoru)

        – Modelovanie vztahov realneho sveta – ano, rozumiem, ta veta vo mne evokovala taku stratenu vetvu OOD, len som mal potrebu sa uistit – rozmyslam, ako to formulovat lepsie… ?? Domain model z hladiska DDD = vyber takej abstrakcie (takeho modelu), ktora najlepsie popisuje zakaznikov pohlad na svet(problemovu domenu), ktora je teda mysleniu zakaznika najblizsia. Je to podriadenie sa videniu sveta zakaznikom(resp. teami zakaznikovych domain expertov).

        – MVC ma/nema riesit. MVC je pattern. Pattern je (overenou) odpovedou na urcity problem, ktory ma ambiciu riesit. To ako (konkretne) designovat model je predmetom inych patternov.(ktore rozobera ako bolo spomenute komplexne napr. Fowler). Uz takto je MVC v pozicii super patternu (niecoho co stavia na inych patternoch)

        ———-
        – Aktivny model – vytvara notifikacie o zmenach, ktore sa v nom udiali. Views na tie, ktore su pre ne zaujimave pocuvaju, reaguju na ne tak, ze oslovia priamo model, ziskaju potrebne data a zobrazia ich/premietnu zmeny v modely na screen.

        – Pasivny model napr. pri ASP.NET MVC. Model nevytvara notifikacie o tom, ze sa v nom nieco zmenilo. View sa musi o tom, ze sa ma prerenderovat dozvediet inak. Typicky tak, ze controller posle message(view potom priamo accessuje model) alebo(a to je menej stastne podla mna) ako je to v ASP.NET MVC, ze controller natlaci data(projekciu dat z modelu) do view a forcene jeho prerenderovanie a pod.

        popisane namatkovo tu
        http://www.phpwact.org/pattern/model_view_controller

  9. YF

    nic moc :(
    neuveritelny jak se da z jednoduche myslenky vyrobit neco tak radoby sofistikovaneho – clanek mi spis pripada jako navod jak si postavit raketoplan nez popis vzoru – a to jeste autor slibuje pokracovani (ceho? :)) zda se mi ze se tu porad nekdo snazi prevykladat tu samou vec originalnim zpusobem ale uplne se zapomina na vlastni ucel toho co by vzor mel plnit …
    spojovat jednotlive vrstvy pseudosemantikou v podobe car a rikat jim "(ne)prime vazby" atd. to mi prijde uz silna kava :) ale tak chybama se clovek uci … tak preju at to nejak de aspon kdyz uz nic :)

    1. Borek BernardAutor příspěvku

      Re: nic moc :(
      Tento článek popisuje architekturu MVC (pokud to není z nadpisu a z textu dostatečně jasné), vzory budou příště.

      1. YF

        Re: nic moc :(
        "architektura MVC" je proste blabol – MVC je vzor – relativne jednoducha myslenka (kterou architektura nejakym zpusobem zahrnuje) pojmenovavat architekturu podle vzoru a popisovat ji timto zpusobem zvlast je redundantni – pak to vypada jako raketoplan :) na architekturu je kladeno daleko vic pozadavku a MVC adresuje jen nektere z nich

        1. Borek BernardAutor příspěvku

          Re: nic moc :(
          Těším se na vaše komentáře ke třetímu dílu, kde se otázce, co to vlastně MVC je, krátce věnuji :)

            1. Borek BernardAutor příspěvku

              Re: nic moc :(
              Nejsem příznivcem dlouhých teoretických úvodů, proto je kapitola o terminologii tam, kde je. Většina čtenářů to snad ocenila / ocení.

  10. Marián Košťál

    Typy frameworkov
    Prilis nesuhlasim s nazormi v odstavci "Motivace aneb problémy drag & drop vývoje". Myslim, ze je dolezite uvedomit si, cim sa odlisuju komponentove frameworky (ASP.NET WebForms) a poziadavkami riadene frameworky (ASP.NET MVC). Moj nazor je tu http://nmarian.blogspot.com/2009/01/porovnanie-aspnet-webforms-aspnet-mvc.html. Samotny vzor MVC je velmi stary (1979) v sucastnosti vsak jeho popularita rastie. Kazdy z typov webovych frameworkov v roznej miere naplna atributy kvality (udrziavatelnost, testovatelnost, znovupouzitelnost, ….) je to iba otazka volby pre co sa rozhodneme a ktore atributy kvality su pre nas dolezite. Prax myslim ukazala, ze takisto ako sa daju implementovat aplikacie pomocou komponentovych frameworkov, tak sa to da aj pomocou poziadavkami riadenych frameworkov.

    1. Borek BernardAutor příspěvku

      Re: Typy frameworkov
      Bude se vám líbit příští díl, který se přesně zabývá rozlišením komponentových a request/response modelů a tím, jaký dopad to má na použitelnou variaci MVC.

      Díky za komentář!

  11. ee

    CHYBA
    ja nevim co programujete, ale ten diagram je totalne spatne!!!! model logicky musi ovlivnit view tedy vazba mezi modelem a view je nezbytna!!!!!

    1. Martin Hassman

      Re: CHYBA čtenáře
      Já nevím, co komentujete, ale ten komentář je totálně špatně!!! Čtenář si musí napřed přečíst celý článek, aby ho správně pochopil a nedělal pak ze sebe v komentářích vola. Tato vazba dost důležitá. I v životě 8-)

Napsat komentář

Tato diskuse je již příliš stará, pravděpodobně již vám nikdo neodpoví. Pokud se chcete na něco zeptat, použijte diskusní server Devel.cz

Zdroj: https://www.zdrojak.cz/?p=3004