Unikátní vlastnosti Nette
Školení, která pořádám
Framework Nette se v Česku začíná poměrně rozmáhat a já si myslím, že to je jedině dobře, protože dovoluje relativně snadno vytvářet dobré webové aplikace. To jde samozřejmě i bez frameworku a nemusí to ani být výrazně pracnější, ale člověk může udělat mnohem víc chyb.
Na frameworky nejsem žádný expert a neplatí to ani o Nette, nicméně zkusím ho popsat z pohledu programátora, který ho pár měsíců používá. Zaměřím se na věci, které mi přijdou unikátní, takové ty killer features. Netvrdím, že nikde jinde nejsou, ale chtěl bych je vyzdvihnout. Nebudu psát třeba o kvalitním objektovém návrhu nebo MVC resp. MVP, protože to mají frameworky více či méně skoro všechny.
Ladění
Laděnka je dobrá společnice, chyby zobrazuje velmi přehledně a to dokonce (díky mému přičinění) i ty fatální. Šikovné jsou i odkazy na spuštění editoru na řádku s chybou (také mým přičiněním). Výborná je automatická detekce vývojového a produkčního prostředí a spolupráce s FirePHP, za nejzásadnější ale považuji možnost nechat si posílat chyby e-mailem.
Já na školeních říkám, že by se v produkčním prostředí měly chyby logovat a tento log by měl zůstávat pokud možno prázdný, ale kontrolovat ho vlastními silami dá přeci jen dost práce (když si člověk vytvoří pravidelně spouštěnou úlohu, která mu obsah logu pošle, tak se o chybě dozví až s nějakým zpožděním). V Nette se prostě jen e-mailová adresa předá funkci Debug::enable
a je hotovo.
Jednosouborová verze
Pro vývoj lze použít přehledné zdrojové kódy, pro nasazení minimalizovanou verzi. Kromě toho, že je rychlejší, tak se také velmi pohodlně aktualizuje.
RobotLoader
V Nette je možné si nechat automaticky nahrávat soubory nezávisle na adresářové struktuře. Např. PEAR používá pevnou adresářovou strukturu, takže je dané, že např. třída PHPUnit_Util_Filter
bude v souboru PHPUnit/Util/Filter.php
. Nette takhle pevnou strukturu nemá (i když samo RobotLoader nepoužívá) a nevyžaduje to ani od programátora.
Zpočátku jsem měl tendence RobotLoader nepoužívat (závislostí mezi soubory mám totiž málo, což je ale spíš chyba), pak jsem ale přestal vzdorovat.
Obousměrný přepis URL
Přepis URL na akce je základem většiny webových frameworků. Za nesmírně užitečné považuji, že v Nette je přepis obousměrný – tedy že se odkazujete na akci, kterou chcete provést, a URL se vytvoří samo. To dovoluje strukturu URL navrhovat nezávisle na zbytku aplikace.
Šablony
O kontextově citlivém ošetřování výstupu už jsem psal. Za zásadní považuji i to, že jednoduchý zápis proměnné v šabloně je zároveň ten bezpečný. A že pro neošetřený výpis proměnné je oddělený zápis. Většina šablonovacích systémů má možnost automatického ošetřování také (není ale závislá na kontextu), nicméně pro neošetřený výpis dat se používají filtry jako safe
nebo unescape
, což je krkolomné.
Vynikající jsou i n:
atributy, které zjednodušují práci a zpřehledňují kód.
Práce s formuláři
Při zpracování formulářů se dá pokazit strašně moc věcí. Nette na všechny z nich myslí a formuláře dovoluje vytvářet a zpracovávat velmi elegantně. Také jde s dobou a naplno využívá možností HTML 5.
Posílání částí stránky AJAXem
Přiznám se, že AJAX v Nette jsem ještě nezkoušel, ale už se na nějaké rozumné využití těším. Pro přenos dat z AJAXových událostí totiž není potřeba psát vlastní obsluhu a místo toho se jen invaliduje část stránky, která se pak automaticky pošle. Za drobnou slabinu považuji to, že se kromě dat znovu přenáší i HTML kód, který už na stránce může být, ale ono toho kódu obvykle až tak moc nebývá.
Databáze
Práce s databází je odvozena z mé knihovny NotORM, takže mi nezbývá nic jiného, než ji také vychválit.
Co se mi naopak nelíbí
- Nette velmi úzkostlivě dbá na to, aby neovlivnilo okolní prostředí. To vede k tomu, že např. k parametrům z adresního řádku se místo jednoduchého
$_GET
přistupuje z prezenteru přes $this->getHttpRequest()->getQuery()
. A je nutné přistoupit takto, protože jinak data nebudou odošetřená. Možná bych v tom bych radikálnější a odošetření prováděl na globálních datech, ale je to jen jeden z důvodů tohoto přístupu. Druhým je třeba lepší testovatelnost. Řešením je pro přístup k datům z URL používat parametry metod (to je ještě pohodlnější než $_GET
) a pro POST používat Nette formuláře.
- Některé věcí se dělají jinak, než je člověk zvyklý, i když slouží k tomu samému. Např. místo exit je lepší v prezenteru zavolat
$this->terminate()
. Ono by se toho tolik nestalo, když by člověk zavolal přímo exit, ale zase by to zhoršilo testovatelnost. Nakonec to tak často ani není potřeba.
- Vadí mi dlouhý zápis přiřazování dat z prezenteru do šablony pomocí
$this->template->variable
. Některé frameworky používají jenom $this->variable
, což ale v Nette nejde, protože v prezenteru jsou např. persistentní parametry. V Nette se dá na konci každé metody zavolat $this->template->setParams(get_defined_vars())
, což šabloně přiřadí všechny lokální proměnné, za elegantní to ale také nepovažuji.
Všechno to jsou věci, které mi nějakým způsobem vadí, ale přitom je chápu. Kdybych věděl, co s nimi, tak už to commitnu.
Závěr
Za zásadní přednost webových frameworků včetně Nette považuji vedení k vytváření kvalitnějších webových aplikací. Nette je ale podle mě v řadě oblastí o krok napřed.
Diskuse
já:
Problém s Nette alespoň z pohledu lenosti je mizerná "spolupráce" s databází. Scaffolding je mu zcela neznámý - jednoduchý CRUD ač je základem prakticky všech webových aplikací se musí psát kompletně ručně.
Jinak obousměrné routování a lepší laděnku umí symfony -
http://jobeet.reikan.com.br/frontend_dev.php/job (vpravo nahoře).
Tipoval bych, že časem vznikne nějaká databáze nadstaveb (modulů) nad Nette, kde by byly právě takové věci jako CRUD. Další věc, co by se do takové databáze doplňků hodila, je generická administrace (třeba jako v Djangu).
Drobnosti, které mi vadí:
1) Presenter má podle mě příliš širokou zodpovědnost/funkčnost. Např. funkce run by klidně mohla být součástí jiné třídy (View, Dispatcher, apod.), což by odlehčilo uživatelské presentery, které z presenteru dědí.
2) Kompilování šablon mi přijde dost složité a nepřehledné. Nebylo by lepší použít rekurzivní sestup?
Matej:
trochu sa to asi pozdilo:)
Tomik:
To není laděnka, tedy něco co se vypíše při chybě a tu chybu popíše, to je profiler... (Ten má Nette taky.)
Ozzy:
Laděnka je lepší :)
já:
ok ok, to vypadá docela stejně jen v jiných barvách... co profiler vs. debug toolbar? dá se někde nette profiler veřejně najít?
Štěpán Kocourek:
Jakube, k problému s $this->getHttpRequest()->getQuery() v presenteru bych měl připomínku.
Víš o existenci metody $this->getParam($name, $default) v PresenterComponent?
A celé query se dá získat přes $this->params ($params je protected v PresenterComponent)...
Jakub Vrána :
To jsem nevěděl. Hlavně jsem taky nevěděl, že pokud má metoda v presenteru stejnojmenný parametr, tak se rovnou naplní. To se ještě budu muset podívat, jak je udělané.
Jarda:
Jako nechci rýpat, ale toto je přeci v rámci Nette dost zásadní neznalost :-)
Tomik:
Jakub píše: "Na frameworky nejsem žádný expert a neplatí to ani o Nette." Což se sice dá brát tak, že na frameworky není expert, a že toto tvrzení neplatí o Nette, ale jsem přesvědčen, že to tak nemyslel. Tudíž v článku to je napsané, takže rýpání se mi zdá opravdu bezpředmětné.
Jakub Vrána :
Souhlasím, otázka je, jak je to možné, když jsem o Nette přečetl celý tutorial, seriál na Zdrojáku a byl jsem na školení. Asi jsem abnormálně nepozorný…
Znát $this->getParam() podle mě není tak důležité jako vědět, že parametry URL se převedou na stejnojmenné parametry metod. A to jsem si zjistil ještě před vydáním článku :-).
visitor:
+1
Taky mi vadí, že objevuji pořád nové vlastnosti a zejména jen díky tomu, že někdo to náhodou na fóru řeší. Nějak mi chybí ucelené návody, tutoriály stylu "jak na to".
Lamicz:
Nette neni spatny, ale IMHO dela z PHP to, co neni. Je to stale jednoduchy scriptovaci jazyk pro dynamicke webove stranky a tak by to melo zustat. Prijde mi to zbytecne slozite (mozna je to zatim rozpracovanou dokumentaci) a dost velky velikostni overhead (nejen Nette ale vsechny PHP frameworky). Dela to z PHP nejakou "aplikaci". Podotykam, ze proti nemu nic nemam, sam sleduji deni a verim, ze priznivce si najde ;)
dRaGen:
Nesouhlasím, dle profileru na rozsáhlé stránce:
# Elapsed time: 73.0 ms | Allocated memory: 1 766.0 kB
A myslím že je to mnohem lepší než bastlil procedurálně popřípadě objektově v nějakym svém frameworku ;)
alex:
Nette rozhodně doporučuji všem, kteří píší v PHP třeba s nějakým vlastním frameworkem nebo pořád ještě nepřešli k objektům. Nette a Dibi představuje obrovskou pomoc, ulehčení práce a způsob jak se vyhnout chybám a dělat věci pořádně.
Jediné, co podle mého názoru tvoří překážku na cestě začátečníka je nedokonalá dokumentace (příklady, návody, ...). Často se mi stává, že jsem o něčem nevěděl (to je vidět i v této diskusi) nebo že je něco jinak, než je napsáno někde jinde. Začátky jsou tím pádem docela těžké.
tatramat:
mohu se zeptat, jakou uroven slozitosti webove aplikace, s jakym mnozstvim lidi (tym) a s jakou casovou dispozici (deadline) jste resil a jakymi prostredky? nechci flame, jen me zajima, co vede ruzne lidi k tvrzeni, ze PHP je 'jednoduchy skriptovaci jazyk pro webove stranky'...
v6ak:
Jak bylo prezentovno, i na kontaktní formulář se to hodí. Konkrétně Nette se dobře přizpůsobí.
David Grudl:
Díky za článek!
Jen pár poznámek k tomu, co se ti nelíbí, abys to probůh nepřekomitovával ;))
1) ad "k parametrům z adresního řádku se přistupuje z prezenteru přes $this->getHttpRequest()->getQuery()" V podstatě si odpovídáš sám výše zmíněnou feature: "...dovoluje strukturu URL navrhovat nezávisle na zbytku aplikace". Pokud tuhle důležitou nezávislost chceš porušit, neočekávej, že ti to framework ulehčí ;)
2) "místo exit je lepší v prezenteru zavolat $this->terminate() kvůli testovatelnosti" nemělo by to být spíš v části "Co mi líbí?" ;)
3) Nette by šlo naučit přiřazovat proměnné do šablony přes $this->variable, ale je to protimluv. Čti pomalu: "přiřazovat ... proměnné ... do ... šablony" přičemž $this není šablona - jak by potom mohlo být $this->variable = 123 přiřazení do šablony? Nicméně je legální přiřazovat proměnné do presenteru a ty potom v šabloně používat. V případě komponent je to dokonce běžná praxe.
4) "Za drobnou slabinu považuji to, že se kromě dat znovu přenáší i HTML kód, který už na stránce může být" - lze přenášet jen data, lze přenášet jen HTML kód, lze přenášet obojí. Přenos HTML kódu má výhodu v tom, že není potřeba budovat šablonovací systém na straně JavaScriptu.
ještě ad Dundee, "Kompilování šablon mi přijde dost složité a nepřehledné": kompilování probíhá na pozadí, programátor o něm v podstatě neví. Nebo máš na mysli něco jiného?
Dundee:
ad David: Já vím, že hrabat se v takovýchto střevech není potřeba, ale holt rád rozumím každému řádku kódu :)
A co si myslíš o té šířce zodpovědnosti Presenteru?
David Grudl:
Primárním úkolem presenteru je převést aplikační požadavek na odpověď, tedy vlastně metoda run() je to jediné, co se po presenteru požaduje (viz interface IPresenter). Samozřejmě o refactoringu se dá uvažovat, je to asi nejdelší třída, ale to je spíš téma na Nette forum.
Jiří Knesl:
K tomu exitu. Ten má několik základních nevýhod:
1) exit není ztížení, ale naprosté odstranění testovatelnosti. Kód, který obsahuje exity se a) nedá otestovat, b) ve výsledku ani použít. Když jsem třeba integroval do Nette Ruckusing Migrations, tak jsem (aby se to vůbec dalo použít, natožpak testovat) bez pardonu převedl všechny exity na vyjímky. Do té doby jsem stál na místě a nedalo se s tím prakticky nic udělat.
2) logika bodu, kdy chci zavolat exit je skutečně pouze ve funkci terminate() a nikde jinde. Funkce buďto dostane parametry ve svém definičním oboru a pak by měla být schopná něco vrátit, nebo má vyhodit vyjímku (+ pokud dojde za běhu, tak také vyjímku).
3) architektura frameworků je taková, že controller, případně presenter ani zdaleka není posledním bodem, kterým kód prochází. Useknout běh v takovou chvíli je stejně riskantní jako vytáhnout ze sítě počítač ve chvíli, kdy vypaluje CDčko.
Robert Vlach:
"Na frameworky nejsem žádný expert a neplatí to ani o Nette" — že by logický hlavolam? ;-)
Jinak pěkný článek, díky za něj!
chuj:
přiřazovat data do šablony přes $this->variable místo $this->template->variable je chyba přímo kardinální, první důvod píše David a pak hlavně nerozlišíš jestli $this->variable je proměná, kterou jsi definovat v presenteru, nebo je to nějaká šablonová proměnná. U složitějších presenterů Ti vznikne naprostý chaos a neudržovatelný kód, tím pádem tak i mixuješ aplikační záležitosti v presenteru s věcmi patřícími šabloně. Pokud jsi psal nějakou rozsáhlejší framework based aplikaci tak bys byl naopak velmi tvrdě za potírání hrůzy $this->variable pro přiřazení proměnné do šablony.
Jakub Vrána :
O to se nikdo nepře, že by to v Nette takhle nedávalo smysl, byť by se to uživatelským kódem dalo triviálně zařídit. S jiným rozdělením kompetencí (v jiném frameworku) bych si to představit ale dokázal.
Jde o to, že zápis $this->template->variable je prostě příliš dlouhý a přemýšlím o způsobu, jak se ho zbavit. Jednou možností by bylo pro šablonu použít všechny lokální proměnné (v článku je uveden krkolomný uživatelský způsob), to je ale zase moc velký FUD - všechny proměnné do šablony často ani nechci, takže bych je musel odnastavit.
Nabízelo by se také použití jiného prostoru identifikátorů, třeba $this["variable"], to už je ale v Nette zabrané pro komponenty, kde to má lepší smysl.
Abych to shrnul jednou větou: navržené to je dobře, ale používá se mi to méně dobře.
David Grudl:
Jako $template = $this->template najdes ve spouste mych presenterů...
Jakub Vrána :
Jasně, taky se dá pracovat s lokálními proměnnými, které se pak do šablony přiřadí. To je ale balastní kód, který se musí opakovat v každé metodě, a nemá žádný smysl kromě toho, že zkrátí identifikátory. Raději bych to řešil nějak systémově.
tatramat:
jiny framework pouziva pro predavani promennych z C do V napr metodu $this->set('variable', $value), pricemz je mozne pouzit napr. $this->set( compact( 'var1', 'var2', 'var3',...) ) - seznam promennych posilanych do view je pak v dostupny (krome samotne $variable) take skrze $this->viewVars[]. prijde mi to pomerne elegantni ;-)
chuj:
ale jo tohle je ok, i když zase tak velký rozdíl oproti $this->template to není. Osobně se mi to líbí ještě více než $this->template, obecně nemám moc rád ty zmagičtělé setry a getry.
v6ak:
Tady by se mi líbily anotace:
@TemplateVariable
$foo = ...;
Chtělo by to ale vymyslet i dobrou integraci s IDE, protože to by jinak pochopitelně brblalo.
mildabre:
Také mě se nelíbilo zdlouhavé a balastní předávání dat do šablony z presenteru, které se opakuje pořád dokola $this->template->variable. Je to daň frameworku. Na jedné straně je mnoho věcí hotových a stačí je jenom použít, na druhé straně se člověk musí přizpůsobit.
Podobně jako se místo exit píše $this->terminate() tak i ve spoustě jiných případů, kde už člověk ví jak to v PHP udělat ve frameworku nezbývá než hledat v dokumentaci a v případě Nette to v dokumentaci často není a musí člověk na fórum.
Nette obdivuji, je to můj první pokus používat framework, ale stále přemýšlím, zda by nebylo rychlejší si aplikaci napsat v PHP.
v6ak:
Bylo by zajímavé mít pro PHP něco jako Project Lombok ( http://projectlombok.org/ ), jehož obecným posláním je ulehčovat programátorům generováním takového balastního kódu, který se těžko recykluje knihovnou.
v6ak:
Jiných řešení by tu bylo spousta. Třeba $this['$variable'], $this->_variable místo $this->template->variable. Zvlášť ten první způsob by byl IMHO dost matoucí.
Další možností by bylo něco jako renderFoo(ITemplate $tpl[, params]), což by asi i mohlo být zpětně kompatibilní. Ale není to hezký trik.
tatramat:
Na frameworky nejsem žádný expert ...
...
Nette je ale podle mě v řadě oblastí o krok napřed.
- vzhledem ke kteremu jinemu frameworku? (napr.) ;-)
Jakub Vrána :
Vzhledem k mému povědomí :-). Praktickou zkušenost mám už jen s Djangem (Python).
já:
No, jenze Nette je vedle Djanga jako chudy pribuzny. Pokud bychom ciste pragmaticky merili "kroky napred" casem programatora stravenym nad prumernou aplikaci vyjde nam neco uplne jineho. Spousta neNettistu by mohla tvrdit, ze v hodne oblastech silne zaostava a jedine co je opravdu napred jsou kontextove vystupy...
Jakub Vrána :
Rád si přečtu, kdo je v čem jak napřed.
Já jsem v Djangu docela dlouho dělal a moje produktivita byla ve srovnání s Nette mizivá. Samozřejmě to bude způsobeno i mou nedostatečnou znalostí Pythonu, ale nebude to jediný důvod. Nette je prostě kompatibilní s mým způsobem myšlením.
Ondrej:
Povedeny clanek, diky!
"Nette je prostě kompatibilní s mým způsobem myšlením."
Stejne jako je iPhone a MacBook Pro kompatibilni s mym. Proste kazdy dela s tim kladivem, ktere mu sedne vic do ruky.
Jak zpiva Ivo Jahelka: "Svou pravdu máš, já mám zase jinou, možná se sejdou a možná se minou. Já vím, tenhle svět snad jednu vadu má, že každý z nás jen tu svou pravdu má."
Pitrsonek:
Ahoj chlapi,
jako zásadní chybu pro Nette vidím to, že vznikl v tak malé kotlině. Kdyby znikl v USA nebo zahraničí a primárně se propagoval v ANG, tak by se automaticky pro něj vytvořila větší komunita. Jasný v ČR je hodně PHP dežů, ale jen řádka z těch chnopnějších investuje svůj čas do toho aby budoval něco navíc pro Nette. Nette, je to nařáchlý framework a všechnu čest Davidovi co dokázal udělat skoro celé sám, ale na vidíte to na fóru či Wiki pro Nette, většina lidí se jen ptá jak co udělat a není moc lidí kteří by dokázali poradit, ve fóru se míchají rady pro starou verzi a novou Nette a ve WiKi je tomu stejně tak. Bohužel je to prevážně práce jedné chytré hlavy která to vymyslela a teď nemá čas a tak rozsáhlou základnu lidí kteří by vše dostatečně a kvalitně zdokumentovali.
Z dokumentace se člověk doví základní věci, které jsou naprosto většinou stejné ve včech MVC nebo MVP frameworkách, ale jádro Nette a fičuryny musí horko težko dolovat ve fóru nebo v dokumentaci.
Například pro celkem důležitou tématiku AJAX je pár informací ze kterých člověk není zrovna moc moudrý viz.: http://doc.nette.org/cs/ajax-snippety.
Prostě dokumentace atd. je vytvořena horkou jehlou a nyní se na ní neklade už tak velký důraz, člověk stráví hodně času tím aby dohledával co se změnilo jak co použít a nalezne to ve fóru kde hodně lidí řeší jestli je to dobře navržené řešení nebo ne ale není na tom postavený žádný rozsáhlejší příklad praktického použití.
Toto je můj postřech začínajícího Nettisty, který do teď dělal a dělá v CakePHP.
Nette fandím a budu jen rád, když se mu bude dařit. Ale nějaký scaffolding nebo generátor základní kostry (CRUD) aplikace z databáze mi opravdu chybí. Člověk musí všechny modely, prezentery a view bastlit od základu znovu pro nový projekt.
Peter Lištiak:
Na dokumentáciu sa kladie dôraz. Žiaľ, nevyšlo niekoľko pokusov komunity a tak momentálne David "uťal" vývoj a venuje sa dokumentácii. Hotová by mala byť v krátkej dobe.
Diskuse je zrušena z důvodu spamu.