Devel.cz Lupa Měšec Podnikatel Root Zdroják.cz DigiZone Slunečnice Vitalia TopDrive KupDnes Navrcholu NovýTarif Dobrý web Weblogy Woko Jagg Computer.cz SK: MojeLinky

Hlavní navigace

Vlákno názorů k článku
Nette Framework: Refactoring

ja
ja (neregistrovaný) ---.zla.cz
31. 3. 2009 6:08

...

1. Nemuzu si pomoct, ale "drzet" stav mincovniku a jednotlive akce resit pomoci GETu i pres tvoje argumenty mi prijde jako zhuverilost. Chapu ze je to pro priklad, ale...
2. Proc upravovat zobrazeni dat v controleru? Jednak pripadna lokalizace se bude hledat po celym kodu a jednak to nejde koncepcne moc dohromady pro vic moznych verzi zobrazeni(html, xml, json...). Jestli v tomhle spociva "presenter" tak uprimne fuj :P
3. K cemu htmlSpecialChars($display) - v te osekane sablone to snad probuh nedela automaticky ze ne?
v6ak aura:72
31. 3. 2009 9:41

Re: ...

2. Celkem souhlasím - proč by se měl controler o to zajímat? View to může zobrazit obrázkem, poslat id přes JSON, ...
3. Cože? Jak to chceš udělat? Něco ala magic_quotes_gpc? Pokud k 2. říkáš "fuj?", pak k tomto říkám "dvakrát fuj!".
mat
mat (neregistrovaný) ---.helemik.cz
31. 3. 2009 10:12

Re: ...

ad 3) viz http://nettephp.com/cs/quick-start-6
{$variable} => <?php echo htmlspecialchars($variable) ?>
{!$variable} => <?php echo $variable ?>
atd.
uživatel si přál zůstat v anonymitě ---.kn.vutbr.cz
31. 3. 2009 12:30

Re: ...

Add 2. Metoda renderXYZ(...) patří do pohledu (MVC neříká že kontroler musí být samostatná třída, ale že by se tyto činnosti měli oddělit. Jak to uděláš (a to záleží na konkrétním programátorovi) záleží na tobě.
David Grudl aura:74
31. 3. 2009 16:40

Re: ...

ad 2: Moc otázce nerozumím. Co myslíš tím upravováním zobrazení dat? Předpokládám že controller měl být presenter.

ad 3: pokud myslíš v tom posledním příkladu, tak ano, tam se to (probuh) děla automaticky. Velmi užitečná feature.
v6ak aura:72
31. 3. 2009 16:49

Re: ...

Myslím, že 2. odpovídá tomu, co jsem k tomu připsal - View si může zobrazit stav jakkoli, třeba obrázkem. Je tedy blbost, aby mu to Presenter diktoval. Nebo ne? Pokud se mýlím, rád bych z toho omylu byl vyveden.
U 3. jsem pochopil "osekané šablony" jako to bez projetí metodou CurlyBracketFilter::invoke. Právě proto jsem se proti tomu bouřil.
Naopak, pokud myslí "ořezanými šablonami" prostě tu kratší formu, pak můžu jen souhlasit, že se to dělá "samo".
David Grudl aura:74
31. 3. 2009 17:00

Re: ...

Nechci se domýšlet, na co konkrétně vedla otázka, proto se ptám. Co se konkrétně stalo v článku v presenteru takového, že to "nejde moc dohromady pro vic verzi zobrazeni(html, xml, json...)"?

Navíc v dalším pokračováním dokonce dojde k záměně HTML za JSON.
v6ak aura:72
31. 3. 2009 17:08

Re: ...

"Co se konkrétně stalo v článku v presenteru takového, že to "nejde moc dohromady pro vic verzi zobrazeni(html, xml, json...)"?"
Odpovím za sebe:
Například:
$this->template->display = 'Málo peněz';
V HTML může být výstup třeba Málo peněz, ale taky třeba JS, obrázek (no dobře, proti tomu lze něco namítnout...), může být potřeba měnit html třídu a další věci. Tato logika by se musela přesunout do Presenteru, kde mi nevoní - je to logika Viewu.
V XML by to mohlo být třeba <error id="not-enough-money"> a podobně v JSON.

"Navíc v dalším pokračováním dokonce dojde k záměně HTML za JSON."
Vyžaduje to manipulaci s Controllerem?
OT: "v dalším pokračováním" není správně - má být "v dalším pokračování". SRY za OT, ale uhodilo mě to do očí.
David Grudl aura:74
31. 3. 2009 17:28

Re: ...

Tady je jasně definované rozhraní mezi presenterem a šablonou, do nějž patří string $display. Zdůrazňuji, že nijak neupravený pro "předpokládané" potřeby výstupu. Prostě čistý řetězec.

Je pak věcí šablony, jestli jej zobrazí v <p id="display">{$display}</p>, v JavaScriptovém alert($display) nebo třeba XML <error id="not-enough-money">$display</error> (pro tento případ by bylo vhodné rozšířit API o příznak chyby nebo chybový kód).

Řekl bych, že si děláš ve věci zmatek žonglováním s termíny controller, presenter, view a šablona. Controller není presenter, view není šablona. Píšeš "tohle mi nevoní, tohle je logika view" ale hovoříš o šabloně - ptám se, je také to "logika šablony"? Neplatí, že hranice mezi částmi Model-View-Controller kopíruje hranici tříd (nebylo tomu tak ani v tzv. klasickém MVC, kde view a controller implementovala jedna třída).
v6ak aura:72
31. 3. 2009 17:39

Re: ...

"Řekl bych, že si děláš ve věci zmatek žonglováním s termíny controller, presenter, view a šablona."
Na tom asi něco bude.

"Neplatí, že hranice mezi částmi Model-View-Controller kopíruje hranici tříd" + "pro tento případ by bylo vhodné rozšířit API o příznak chyby nebo chybový kód"
Někdy je to IMHO vhodnější. Nevoní mi přidávání nějakého stavového kódu v Presenteru nebo Controlleru (tady je to jedno, ne?) jen kvůli tomu, že to chce View?
Pokud to chápu, tak tady se přesouvá část View do Presenteru, aby místo celého View byla šablona.

"nebylo tomu tak ani v tzv. klasickém MVC"
Proti této argumentaci lze použít citaci z http://zdrojak.root.cz/clanky/nette-framework-mvc--mvp/ : "Historický exkurz měl ukázat, jak různorodé bylo pojetí MVC už v okamžiku vzniku. Byla to holt doba pionýrská. Nechápejte proto MVC dogmaticky!"
Pokud jde jen o nějaké "mimochodem", pak budiž.
David Grudl aura:74
31. 3. 2009 18:02

Re: ...

> Pokud to chápu, tak tady se přesouvá část View do Presenteru, aby místo celého View byla šablona.

Dalo by se říct, že metoda renderDefault() je součástí vrstvy View, společně se šablonou. Takže přesouvání kódu mezi renderDefault a šablonu se děje spíš v zájmu toho, co je vhodné mít v šablonovací logice a co už nikoliv. Ale ať už je to tam nebo tam, vždy je to součást View.

Rovnou odpovím i na otázku, proč tedy presenter nerozdělit na svě samostatné třídy: v Nette to lze poměrně snadno provést, ale nejpozději ve chvíli, kdy se začnou používat komponenty, se to ukáže jako velmi nepraktické. Proto místo dělení na dvě třídy se používá dělení na životní fáze.

> různorodé bylo pojetí MVC už v okamžiku vzniku

Tím "klasickým MVC" se obvykle myslí jeho první implementace. Která původní návrh moc přesně nedodržovala.
v6ak aura:72
31. 3. 2009 21:09

Re: ...

No já si teď neumím přesně představit ty problémy, i když možná tuším - počkám, až ukážeš komponenty a pak to rozeberu.
Přiznám se, že Nette se mi původně zdálo divné, ale vypadá to, že všechny ty divnosti mají svůj účel a logické opodstatnění.
A na klasické MVC bych se neodkazoval, když mluvíme o současnosti...
ja
ja (neregistrovaný) ---.zla.cz
31. 3. 2009 20:11

Re: ...

2. Myslel jsem přesně to co psal v6ak. Přeci i tak pracuješ v šabloně s logikou (isset($coffee)), proč tedy mít logiku na dvou místech? ...to není problém frameworku, jen mé pragmatické smýšlení nechápe proč to dělat takhle, když to víc věcí komplikuje...
3. Pokud existuje i varianta {!...} tak samozřejmě ok, jen se chytám toho, že ze spousty "automatických" featur zvětšiny pro začínající "programátory" při pokročilejším programování smrděly problémy.
David Grudl aura:74
31. 3. 2009 20:15

Re: ...

Tak zkus schválně navrhnout jiné a lepší řešení tohoto konkrétního úkolu. Jaké proměnné dávat do šablony a jakou logiku mít v šabloně.
yeah
yeah (neregistrovaný) ---.zla.cz
31. 3. 2009 22:14

Re: ...

Spíš než návrh ti napíšu jak to funguje v Symfony. Má taky svoje nevýhody, ale řekněme že funkční kód od šablony odděluje imho velice dobře.

1. Má sloty, což vypadá asi takhle:
layout:
<meta name="robots"><?php if(!include_slot('robots')): ?>index,archive<?php endif; ?>" />
a v html šabloně erroru:
<?php slot('robots', 'noindex,noarchive') ?>

2. Má komponenty a helpery. Šablona komponenty Display (sf_user je v šablone obal okolo session, v akci je pod $this->getUser()) includovaná do layoutu:
<?php echo $sf_user->hasMoney() ? format_currency($sf_user->getMoney()) : __("Insert coins") ?>

3. A z akce v controleru ti zbyde např. jenom
executeBuy() {
if(!$this->getUser()->buyCoffie()) return sfView::ERROR;
}

Ve finále máme čistej controler, logika html šablon je čistě v šablonách, můžu si navymýšlet šablony pro xml i json aniž bych musel šáhnout do "funkčního" kódu.
David Grudl aura:74
2. 4. 2009 14:06

Re: ...

Díky, takto je to mnohem názornější.

Ve své podstatě se snažíš veškerou zobrazovací logiku přenést do šablony. V případě chyby se použije jiná (error) šablona, o obsahu displeje rozhoduje šablona na základě surových dat z modelu.

Po technické stránce lze totéž udělat i v Nette (jen místo "slotu" je "block", helper zůstává helperem a "return sfView::ERROR" se nahradí za "$this->setView('error')"). Rozdíl zůstává v rovině řekněme filosofické.

Namítl bych, že jsi do šablon umístil nikoliv "logika html šablon", ale "logiku celého view", ačkoliv šablony jsou jen podmnožinou view. Tohle se mi nelíbí. V tomto konkrétním případě mi také vadí duplicita šablon, existence cca stejných šablon automatu lišících se jen hláškou na displeji.

O "čistej controller" tady nejde - v Nette je kontroler víceméně součástí frameworku a controller != presenter. Presenter na sebe bere břemeno udržet čisté šablony a udržet také čistého sám sebe.

V praxi je jednodušší zadat kodérovi výrobu šablony s tím, že "v této proměnné je obsah displeje, v této indikátor chyby, atd.", než "tady najdeš cenu nápoje, tady obsah mincovníku a v tomto dokumentu je popsána logika, kterou musíš respektovat". Nebo ne?
yeah
yeah (neregistrovaný) ---.zla.cz
2. 4. 2009 16:23

Re: ...

No, můj způsob práce je co nejvíc oddělit formu zobrazení a kód, který manipuluje s objektama před zobrazením(ať už tomu říkáme jakkoliv) abych si mohl se šablonama dělat co chci a v kontroleru mi zase nerušily řetězce. Ty budeš takhle asi vždycky vázán na presenter, který s jinou formou prezentace budeš muset měnit. Já si v routování akorát nastavím "koncovky" šablon - a mám z výstupu instantní rss, json atd. Jestli správně hádám tak ty vytvoříš buď další presenter(opakující se nebo nadbytečný kód) nebo budeš nastavovat šablonu podle nějaké proměnné(budeš směšovat kód pro různé šablony)...

Nicméně máš pravdu, s kodérem to budeš mít mírně jednoduší ty, já bych teda z nich nedělal přímo cvičené opičky...s lehčí nápovědou taky lecos pochopí :)
Václav Šír
2. 4. 2009 23:26

Re: ...

To, co se v Symfony nazývá akce, je v Nette rozdělené na akci a view. Metoda renderDefault patří k view a plní obvykle podobnou funkci jako Code Behind v ASP.NET (prostě věci, které se člověku nechce dávat do šablony, ale přitom je to pouhá prezentační logika).

Pokud by k akci chtěl přidat další view, tak by přidal pouze další renderNěco metody, ve kterých by si data upravil pro jiné šablony (při použití push šablon), kód samotné akce by se neopakoval. Akorát by teda do akce musel přidat nějakou logiku pro výběr view, třeba na základě parametru z routy, např:
public function actionDefault($view = "default")
{
    // Logika akce, tj. controlleru
    // ...

    if (in_array($view, array("default", "rss"))
    {
        $this->view = $view;
    }
}
Viz http://nettephp.com/cs/action-vs-view
Zasílat nově přidané příspěvky e-mailem