Ujasnění pojmů a základní logická stavba miniCMS
- na1k
- Člen | 288
Už se nějakou dobu opakovaně snažím ponořit do Nette a konečně odhalit, jeho hlavní myšlenku – tedy MVP©. A i po pročtení snad všech materiálů od quick startu, přes fórum až (částečně) k dokumentaci jsem sice pochopil jak používat například formuláře nebo jiné přidružené vychytávky Nette, ale ta základní stavba aplikace se ne a ne vsáknout. Rád bych tu proto napsal můj pohled, jak to zatím chápu a byl bych rád kdyby mi to někdo aspoň trochu lidským způsobem vysvětlil, jestli teda nežádám moc :-p Věřím že to mnohým začínajícím může pomoct. Takže…
Řekněme že vymýšlím kostru CMS, tedy v základu budu chtít oddělený frontend a backend, které budou navíc rozšířené o moduly (zde asi moduly != Nette moduly) jednou pro výpis a podruhé pro správu dat.
Začnu tedy od bootstrapu, routy mi nasměrují požadavek do nějakého modulu, presenteru a view. V tomto případě by byly moduly frontend a backend, správně? Presenter mi pak zajistí seskládání výsledné stránky (view) a chápu ho tak, že tvoří prostředníka mezi něčím, co dodává data (někde to bylo popsáno jako černá skříňka co zpracovává signály a vrací data) a šablonou, která data nějakou formou vypisuje. Presenter tedy sám o sobě požadavky nezpracovává a k datům (db) nepřistupuje. Nebo by snad měl?
A teď k té černé skříňce. Představuji si ji jako třídu, která řekněme spouští dotazy do databáze a vrací pole, které pak presenter předá šabloně a ta je vykreslí. Co ale (z pohledu zdejších tutoriálů a článků) takováto třída je? Tipoval bych nevykreslitelnou komponentu, tedy Nette\Component. Nebo to snad souvisí se službami? Ty jsem teda zatím moc nepochopil, ale beru to podobně jako dibi – zajišťují mi nějaké funkce a volám je staticky. Provázanost s vykreslovaným obsahem ale moc nechápu, třeba ale žádná není. Každopádně můžu je brát jako něco navíc a při tomhle základu je prostě vynechat? :-T
Tím bych teda dovedl nějak pospojovat presentery a nějaká základní stránka by z toho byla. Ale co na tom mění použití modulů? Jde jenom o to, že je všechno lépe organizované, v oddělený složkách a s možností routovat podle modulů? A jaké prvky z pohledu Nette potom budou součásti backendu (kterým bych neodborně říkal moduly), které by zajišťovaly správu různých částí webu (články,…)? Asi bych použil zase presentery – pro každý jeden a byl by pokoj. Mate mě ale controller – vykreslitelná komponenta. Podle slovníku bych ale chápal, že controller využiju spíš na vykreslení například menu. Potom mi ale uniká proč se tomu říká controller, určitě v tom bude ještě něco :) A ještě pro doplnění – fakt, že pro získání a práci s daty používám „černé skříňky“ platí i pro controllery?
Možná by mě ještě zajímalo co, jak a kdy se automaticky volá a includuje, ale o tom snad až jindy :-p Teď bych byl převelice rád, kdyby mi někdo vyvrátil (nebo lépe potvrdil) mé myšlenkové postupy co se architektury týče :) Předem díky, jenom doufám, že ten sloh nebude odrazující už od prvního pohledu :)
- _Martin_
- Generous Backer | 679
Začnu tedy od bootstrapu, routy mi nasměrují požadavek do nějakého modulu, presenteru a view. V tomto případě by byly moduly frontend a backend, správně? Presenter mi pak zajistí seskládání výsledné stránky (view) a chápu ho tak, že tvoří prostředníka mezi něčím, co dodává data (někde to bylo popsáno jako černá skříňka co zpracovává signály a vrací data) a šablonou, která data nějakou formou vypisuje. Presenter tedy sám o sobě požadavky nezpracovává a k datům (db) nepřistupuje. Nebo by snad měl?
Správně. Ona černá skříňka (neplést s Internetem :) IT Crowd fanoušci vědí) je model a presenter by k databázi přistupovat NEměl.
A teď k té černé skříňce. Představuji si ji jako třídu, která řekněme spouští dotazy do databáze a vrací pole, které pak presenter předá šabloně a ta je vykreslí. Co ale (z pohledu zdejších tutoriálů a článků) takováto třída je? Tipoval bych nevykreslitelnou komponentu, tedy Nette\Component. Nebo to snad souvisí se službami? Ty jsem teda zatím moc nepochopil, ale beru to podobně jako dibi – zajišťují mi nějaké funkce a volám je staticky. Provázanost s vykreslovaným obsahem ale moc nechápu, třeba ale žádná není. Každopádně můžu je brát jako něco navíc a při tomhle základu je prostě vynechat? :-T
Ke skřínce viz. odkaz výše. Model může být jakákoliv třída, která má své pevně dané rozhraní. Může být třeba třída s rodičem DibiTable, vylepšená o vlastní metody. Tyto třídy jsou ukládány do složky app/models. Se službami to nesouvisí, s Nette\Component také ne.
Tím bych teda dovedl nějak pospojovat presentery a nějaká základní stránka by z toho byla. Ale co na tom mění použití modulů? Jde jenom o to, že je všechno lépe organizované, v oddělený složkách a s možností routovat podle modulů?
Myslím, že ano.
A jaké prvky z pohledu Nette potom budou součásti backendu (kterým bych neodborně říkal moduly), které by zajišťovaly správu různých částí webu (články,…)? Asi bych použil zase presentery – pro každý jeden a byl by pokoj.
Ano, od toho jsou presentery.
Mate mě ale controller – vykreslitelná komponenta. Podle slovníku bych ale chápal, že controller využiju spíš na vykreslení například menu. Potom mi ale uniká proč se tomu říká controller, určitě v tom bude ještě něco :) A ještě pro doplnění – fakt, že pro získání a práci s daty používám „černé skříňky“ platí i pro controllery?
Třeba na menu, ale i samotný presenter vychází z controlleru (neplést s controllerem z MVC). Černá skříňka zůstává, je jedno, zda k ní přistupuješ z presenteru či jakékoliv jiné vykreslitelné komponenty.
- Villem
- Člen | 19
na1k napsal(a):
Začnu tedy od bootstrapu, routy mi nasměrují požadavek do nějakého modulu, presenteru a view. V tomto případě by byly moduly frontend a backend, správně? Presenter mi pak zajistí seskládání výsledné stránky (view) a chápu ho tak, že tvoří prostředníka mezi něčím, co dodává data (někde to bylo popsáno jako černá skříňka co zpracovává signály a vrací data) a šablonou, která data nějakou formou vypisuje. Presenter tedy sám o sobě požadavky nezpracovává a k datům (db) nepřistupuje. Nebo by snad měl?
Ona černá skříňka (model) by toho měla umět ještě o něco víc. Kromě dodávky dat by se měla postarat ještě o ukládání a hlavně o tzv. integritu dat (tedy zajistit aby si data vzájemně neodporovala).
Odpověď na tvou otázku, jestli by měl presenter přitupovat k DB je proto složitější. U zobrazení dat je to dle mého celkem jedno. Jestli presenter přímo zavolá SELECT do DB, nebo funkci, která to udělá za něj je celkem jedno (nad jedině pokud by se struktura DB měnila, ale vždy si je možné si vytvořit pohled). Při vkládání/změně potom záleží, na tom kde zajišťuješ integritu. Pokud ti ji zajišťuje DB tak podle mne je zase jedno jestli presenter přímo tvoří SQL dotaz, nebo k tomu účelu volá funkci.
Tak doufám, že jsem tě moc nezmátl.
Editoval Villem (16. 1. 2009 14:38)
- Ondřej Brejla
- Člen | 746
Villem napsal(a):
U zobrazení dat je to dle mého celkem jedno. Jestli presenter přímo zavolá SELECT do DB, nebo funkci, která to udělá za něj je celkem jedno (nad jedině pokud by se struktura DB měnila, ale vždy si je možné si vytvořit pohled). Při vkládání/změně potom záleží, na tom kde zajišťuješ integritu. Pokud ti ji zajišťuje DB tak podle mne je zase jedno jestli presenter přímo provádí SQL dotaz, nebo k tomu účelu volá funkci.
…
To právě jedno není. Protože to pak popírá celou architekturu. Pokud se o přístup k datům a o manipulaci s nimi stará model, jsem schopen ho použít ve více Presenterech a případnou úpravu výběru edituji pouze v něm. Pokud budu přistupovat k DB přímo v Presenteru a to třeba v 10ti Presenterech, které na sobě nebudou nijak závislé (čti žádné dědění), budu nucen úpravy provádět ve všech Presenterech. Vzniká redundantní kód což je cesta do pekel. Navíc kontrolovat integritu dat pouze v DB je čirý nesmysl. Pokud potřebuji rozumně manipulovat s případnými chybovými hláškami, které vzniknou neintegritou dat, je rozumné provádět kontrolu právě na vrstvě modelu.
Takže ANO – model používat :)
Editoval Warden (16. 1. 2009 14:46)
- kravčo
- Člen | 721
na1k napsal(a):
A teď k té černé skříňce. Představuji si ji jako třídu, která řekněme spouští dotazy do databáze a vrací pole, které pak presenter předá šabloně a ta je vykreslí. Co ale (z pohledu zdejších tutoriálů a článků) takováto třída je? Tipoval bych nevykreslitelnou komponentu, tedy Nette\Component. Nebo to snad souvisí se službami? Ty jsem teda zatím moc nepochopil, ale beru to podobně jako dibi – zajišťují mi nějaké funkce a volám je staticky. Provázanost s vykreslovaným obsahem ale moc nechápu, třeba ale žádná není. Každopádně můžu je brát jako něco navíc a při tomhle základu je prostě vynechat? :-T
S Nette\Component to priamo nesúvisí, samozrejme ak je to vhodné, môže
z neho dediť. Podstatné je práve to, čo si písal – je prostredníkom,
ktorý sa (okrem iného) stará o ťahanie dát z databázy. Toto oddelenie
má okrem iných (veľa) výhod aj tú, že v prezenteri nepíšeš zložité
sql dopyty, ale len volania modelu, napr
$data = $model->getData();
. Nette (zatiaľ) neobsahuje žiadne
podporné triedy pre modely, dá sa ale využit DibiTable z dibi, tá je však
abstrakcia nad jednou db tabuľkou a nie základ modelu…
Tím bych teda dovedl nějak pospojovat presentery a nějaká základní stránka by z toho byla. Ale co na tom mění použití modulů? Jde jenom o to, že je všechno lépe organizované, v oddělený složkách a s možností routovat podle modulů? A jaké prvky z pohledu Nette potom budou součásti backendu (kterým bych neodborně říkal moduly), které by zajišťovaly správu různých částí webu (články,…)? Asi bych použil zase presentery – pro každý jeden a byl by pokoj. Mate mě ale controller – vykreslitelná komponenta. Podle slovníku bych ale chápal, že controller využiju spíš na vykreslení například menu. Potom mi ale uniká proč se tomu říká controller, určitě v tom bude ještě něco :) A ještě pro doplnění – fakt, že pro získání a práci s daty používám „černé skříňky“ platí i pro controllery?
Na úvod objasnenie pojmu. V Nette nepoznáme controller, vykresliteľný komponent je Control a s controllerom z iných fw nemá veľa spoločného. Pomôcť, ako rozdeliť rôzne funkčné celky stránky (články atď.) na moduly, prezentery a view môže článok na phpfashion: Návrh struktury presenters/views.
Možná by mě ještě zajímalo co, jak a kdy se automaticky volá a includuje, ale o tom snad až jindy :-p Teď bych byl převelice rád, kdyby mi někdo vyvrátil (nebo lépe potvrdil) mé myšlenkové postupy co se architektury týče :) Předem díky, jenom doufám, že ten sloh nebude odrazující už od prvního pohledu :)
Nette sa štandardne includuje cez
require_once LIBS_DIR . '/Nette/loader.php';
čo zaregistruje auloloader, ktorý includuje len triedy Nette na požiadanie (samozrejme pri compact verzii sa includnu všetky naraz)
require_once LIBS_DIR . '/Nette/loader.php'; // tu sa zaregistruje autoloading
Debug::enable(); // tu sa includne trieda Debug on-demand
Lepšou (fikanejšou) možnosťou je použiť RobotLoader, ktorý vie autoloadovať všetko v adresároch, ktoré mu zadáš:
// príklad akrabat.forms
$loader = new /*Nette\Loaders\*/RobotLoader();
$loader->addDirectory(APP_DIR);
$loader->addDirectory(LIBS_DIR);
$loader->register();
Automaticky includuje všetky triedy, ktoré sú definované niekde v
APP_DIR
& LIBS_DIR
. To znamená žiadne písanie
dlhých výčtov include 'blablabla.php';
v každom súbore…
- Villem
- Člen | 19
Warden napsal(a):
Villem napsal(a):
U zobrazení dat je to dle mého celkem jedno. Jestli presenter přímo zavolá SELECT do DB, nebo funkci, která to udělá za něj je celkem jedno (nad jedině pokud by se struktura DB měnila, ale vždy si je možné si vytvořit pohled). Při vkládání/změně potom záleží, na tom kde zajišťuješ integritu. Pokud ti ji zajišťuje DB tak podle mne je zase jedno jestli presenter přímo provádí SQL dotaz, nebo k tomu účelu volá funkci.
…
To právě jedno není. Protože to pak popírá celou architekturu. Pokud se o přístup k datům a o manipulaci s nimi stará model, jsem schopen ho použít ve více Presenterech a případnou úpravu výběru edituji pouze v něm. Pokud budu přistupovat k DB přímo v Presenteru a to třeba v 10ti Presenterech, které na sobě nebudou nijak závislé (čti žádné dědění), budu nucen úpravy provádět ve všech Presenterech. Vzniká redundantní kód což je cesta do pekel. Navíc kontrolovat integritu dat pouze v DB je čirý nesmysl. Pokud potřebuji rozumně manipulovat s případnými chybovými hláškami, které vzniknou neintegritou dat, je rozumné provádět kontrolu právě na vrstvě modelu.
Takže ANO – model používat :)
Takže za prvé já jsem nikde nenapsal, že se model nemá používat. Já jsem jenom napsal, že je možné aby celý model byl naimplementován v databázi. Použiju tvůj příklad pokud budu kromě webového zobrazení dělat ještě desktopového klienta musel bych tu část modelu, která není v DB naimplementovat tam. Redundantní kód což je cesta do pekel :). Ale nepředpokládám, že to je častý případ. Já sem jenom proti dogmatickému odmítání přístupu do DB v presenteru.
Za druhé práce s chybovými hláškami je, dle mého, práce presenteru. Mohl bys rozvést proč je kontrola integrity dat pouze v DB nesmysl.
Takže ANO – model používat, ať už je naimplementován kdekoliv.
- _Martin_
- Generous Backer | 679
Villem napsal(a):
Já sem jenom proti dogmatickému odmítání přístupu do DB v presenteru.
To přeci není dogma, ale koncepce návrhového vzoru, který jasně říká, že model a presenter mají být dvě oddělené nezávislé části aplikace. Jistě, zda se budeš tím konceptem řídit je jen na tobě, ale na1k se tu snaží pochopit koncept MVP a osobně si myslím, že když už se někdo pro nějaký koncept rozhodne, tak se jím bude řídit – alespoň v jeho základní myšlence, kam oddělení modelu a presentu rozhodně patří.
- Ondřej Brejla
- Člen | 746
Villem napsal(a):
Takže za prvé já jsem nikde nenapsal, že se model nemá používat. Já jsem jenom napsal, že je možné aby celý model byl naimplementován v databázi. Použiju tvůj příklad pokud budu kromě webového zobrazení dělat ještě desktopového klienta musel bych tu část modelu, která není v DB naimplementovat tam. Redundantní kód což je cesta do pekel :). Ale nepředpokládám, že to je častý případ. Já sem jenom proti dogmatickému odmítání přístupu do DB v presenteru.
Za druhé práce s chybovými hláškami je, dle mého, práce presenteru. Mohl bys rozvést proč je kontrola integrity dat pouze v DB nesmysl.
Takže ANO – model používat, ať už je naimplementován kdekoliv.
Nikde jsem nenapsal, že jsi model odmítal, jen jsem nakonec vyjádřil můj názor, aby nevznikaly zbytečné dohady. Neměla to být záminka k chytání za slovo :)
To „dogma“ má nějaké opodstatnění, ale samozřejmě tě nikdo nenutí ho dodržovat :)
Desktopová aplikace může data požadovat v jiné formě, potřebuju jiný model na stejnou DB. Programování modelu tu není redundancí, protože se jedná v podstatě o další aplikaci. Mluvil jsem o redundanci kódu v jednom typu aplikace. Snad mi rozumíš.
Pokud budu kontrolovat integritu pouze v DB, tak pro každou kontrolu musím do db. Tzn mám form, každé pole po změně focusu chci kontrolovat třeba ajaxem na správný formát, pokaždé se budu připojovat k DB, to je imho zbytečný nesmysl.
Samozřejmě, že kontrola integrity na DB vrstvě je super, ale sama je dost nepružná.
Takže ano, integrita v DB jistě, ale ne pouze
Snad jsem to rozumně vysvětlil a nezačne tu nějaký zbytečný flame…
Editoval Warden (16. 1. 2009 15:45)
- Villem
- Člen | 19
A jéje. To sem tomu dal. Ale jediné vysvětlení, které mě napadá je, že máme prostě odlišnou představu o tom co všechno by mělo model zajišťovat. Taky tomu říkám říkám MVC/P. Ale máte pravdu zbytečně tady matu lidi.
Jedná se jenom o to jak já dělám aplikace, kde co nejvíce aplikační logiky dám do databáze (jako uložené procedury a pohledy) a beru DB jako model. K tomu příkladu s kontrolou formátu: To dle méno je právě záležitost presentru – reakce na uživatele a validace dat. Nechápu, proč by měl model řešit, jestli uživatel zadal správné hodnoty.
A tím končím. Takto tady můžem diskutovat do nekonečna. Není důležité jak je model naimplementován, ale aby se jeho rozhraní vůči zbytku aplikace nemuselo měnit při úpravách.
- Ondřej Brejla
- Člen | 746
Uložené procedury, pohledy, jasně, určitě, proč ne.
Kontrola formátu právě musí být v modelu, když budu kontrolovat v Presenteru, tak mi do modelu může teoreticky vložit kdo chce co chce.
Rozhraní modelu by se dokonce nejen nemuselo, ale vůbec nemělo měnit…jediné, co by se mohlo měnit jsou zapouzdřené implementační detaily.
Souhlas, končíme.
- gawan
- Člen | 110
Villem napsal(a):
K tomu příkladu s kontrolou formátu: To dle méno je právě záležitost presentru – reakce na uživatele a validace dat. Nechápu, proč by měl model řešit, jestli uživatel zadal správné hodnoty.
Tiež som to najskôr nechápal, ale potom som v praxi musel riešiť nasledovný problém.
V aplikácii som mal nejaký veľmi zložitý formulár, cez ktorý používatelia zadávali produkty. Ako aplikácia rástla a rástol aj počet užívateľov, prišla požiadavka na doprogramovať dávkový import dát cez XML súbor. Najprv som robil druhú validáciu na XML súbore. Potom sa, ale začali meniť požiadavky na vstupné dáta a musel som meniť dve rôzne validácie na dvoch rôznych miestach. A to bola cesta do pekla. Nakoniec som sa rozhodol presunúť validáciu do modelu a v presentery/controllery formulára po POSTe volám:
<?php if ($model->validate()) $model->save(); ?>
a to isté volám v cykle pri hromadnom importe dát z XML súboru a celú validáciu riešim v modely na jednom mieste.
Ak je vo vašej aplikácii, čo i len malá šanca na to, že v budúcnosti budú dáta prichádzať aj inak ako cez jeden formulár, potom vrele odporúčam validáciu presunúť do modelu. A najlepšie riešenie je z validácie v modely automaticky generovať javascriptovú validáciu vo formulári.
- Villem
- Člen | 19
gawan napsal(a):
<?php if ($model->validate()) $model->save(); ?>
Volání if ($model->validate())
by mělo být součástí
metody save()
. Pokud model umožňuje uložit nevalidní data je,
dle mého, špatně napsaný. Pokud jsi bral jako automatické tak se
omlouvám.
Pokud dobře chápu co se mi snažíš naznačit je to, že by model měl poskytovat veřejné rozhraní pro validaci dat. Tak tady se neshodneme. Já to považuji za zbytečné, protože pak může toto rozhraní může velice rychle narůst do obřích rozměrů. Jediné co od modelu v tomto případě požaduji je, aby v případě selhání vrátil chybu ze které lze zjistit co se stalo. Pokud chci validovat formulář ještě před odesláním, tak si tu validaci prostě naprogramuji. Navíc u komplexních formulářů stejně není možné provádět tuto celou validaci před odesláním (přesně řečeno je, ale je to velice drahé).
A poslední poznámka: Pokud mi stejná/podobná data chodí z více zdrojů tak buď přes jeden presenter, a nebo je sdílený kód v předcích (OOP).