[2009–11–14] Anotace: eAccelerator by již neměl být překážkou

Upozornění: Tohle vlákno je hodně staré a informace nemusí být platné pro současné Nette.
David Grudl
Nette Core | 8218
+
0
-

Třída Nette\Annotations by již neměla mít problém s eAcceleratorem.

O co jde: eAccelerator může znemožnit správnou funkčnost metod getDocComment() z rozšíření Reflection. Na těchto metodách je založeno používání anotací. Problém řeší eAccelerator ve verzi 0.9.5 či vyšší se zapnutou direktivou --with-eaccelerator-doc-comment-inclusion. Protože toto některé hostingy nemají, nebylo na nich možné anotace používat. Proto bylo např. anotování persistentních proměnných umožněno přes statické metody.

Nyní třída Nette\Annotations umí konflikt s eAcceleratorem řešit – PHP soubory si parsuje sama.

Poprosil bych uživatele o důkladné otestování.

Honza Marek
Člen | 1664
+
0
-

To je dobré. Hlavně by to mohlo otevřít diskuzi o větším využití anotací. Osobně bych si uměl představit třeba:

class NecoPresenter extends BasePresenter
{
	/**
	 * @dumyslneOchranitProtiCSRF
	 */
	public function handleSmazat($id)
	{
		...
	}
}
Ondřej Mirtes
Člen | 1536
+
0
-

Já bych byl zase za přístup, kdy anotace jsou jen alternativa k nějakému čistému PHP řešení (jako je getPersistentParams()). Protože komentáře, ať už obsahují cokoli, považuji za něco, co by v žádném případě nemělo ovlivňovat chod aplikace, tzn. po jejich odstranění by se aplikace měla chovat naprosto stejně.

Jan Tvrdík
Nette guru | 2595
+
0
-

Proto se na ně nesmíš dívat jako na komentáře, ale jako na součást zdrojového kódu.

EDIT: Dobrý editor by dokonce imho měl umět zobrazit phpDoc jinou barvou, než běžný komentář. (Škoda, že PhpEd to neumí).

Editoval Jan Tvrdík (15. 11. 2009 13:22)

redhead
Člen | 1313
+
0
-

Určitě. V javě se to normálně používá, u nějakého frameworku dokonce pro validace formulářů, což nette má vymakané lépe.

Patrik Votoček
Člen | 2221
+
0
-

Jan Tvrdík napsal(a):

EDIT: Dobrý editor by dokonce imho měl umět zobrazit phpDoc jinou barvou, než běžný komentář. (Škoda, že PhpEd to neumí).

PhpED ze to neumi? Jaktoze me to teda ukazuje? http://twitpic.com/pmg0y

Panda
Člen | 569
+
0
-

Tipuji, že měl na mysli barvu celého bloku s phpdoc, tzn. /** ... */, ne jen samotné phpdoc tagy.

v6ak
Člen | 206
+
0
-

Přiznám se, že kdysi jsem uvažoval o nějakém preprocesoru pro PHP, který by řešil mimo jiné anotace a anonymní třídy včetně viditelnosti. U anotací mi šlo spíše o generování kódu, tedy něco ve stylu anotací http://projectlombok.org/ . Běhové anotace by tímto samozřejmě šly dostat pryč z komentářů.

Jenže, poslední dobou v PHP tolik nedělám, takže se mi do toho nechce investovat čas. Pokud by někdo měl zájem o podrobnější popis, jsem ochoten to někde sepsat a případně i poradit (e-mail, Jabber, Brebentítko (anonymní webová brána pro Jabber), Google Wave). Mám i nějaké implementační nápady, není to pouhé snění.

Zatím jsem příliš nepřemýšlel o integraci s IDE.

Snad to není příliš OT.

Jan Tvrdík
Nette guru | 2595
+
0
-

Panda napsal(a):

Tipuji, že měl na mysli barvu celého bloku s phpdoc, tzn. /** ... */, ne jen samotné phpdoc tagy.

Přesně tak.

David Grudl
Nette Core | 8218
+
0
-

Anotace jsou stále kontroverzní téma ;)

(Nicméně v Nette jich je mnohem víc: třída Object, magické properties, používání RobotLoaderu, nezahazování E_NOTICE – anotace to všechno nesou na kříži)

V anotacích se skrývá ohromná zbraň na rozšíření jazyka. Něco jako naznačil Honza Marek. Rád bych se tímto směrem vydal, ale je potřeba zvládnou dva kroky:

  1. anotace musí přestat být kontroverzní – chtělo by se říct, že lidé si zvyknou na všechno, stačí je prostě začít ve frameworku hojně používat ;) Ale neřeknu to ;) Alternativní cesta by tedy mohla existovat, jen musí být na univerzální bázi, tj. místo statických metod getPersistentParams mít třeba  getAnnotations nebo prostě pod třídou zapsat anotace deklarativně deklarativně, např. Annotations::add(__CLASS__, '$var', ...).
  2. musí být striktní – neboli odolné vůči chybám a překlepům. Pokud se překlepnu v anotaci, musí vyskočit výjimka namísto toho, aby akce tiše přestala být např. chráněná proti CSRF.
v6ak
Člen | 206
+
0
-

No, Annotations::add mi přijde spíše imperativní než deklarativní…
Asi by se mělo někde důrazně uvést, že Annotations::add(…) může být voláno jen těsně po definici třídy, tedy, přesně řečeno, mělo by se zabránit použití třídy před uvedením anotací.
Ale víc by se mi líbilo to getAnnotations(), tady se už asi málokdo bude snažit vecpat další anotaci za běhu. Už by to nešlo tak přirozeně.
Striktní anotace? Naprosto souhlasím. Myslím, že inspirace Javou zde může být otevřeně patrná. Jen je menší problém, že se musí oddělit dokumentační komentáře.
Btw ty compile-time anotace (např. @Getter, @Setter a @Data) by šly v omezené míře dělat přes nějaký autoloader s použitím cache. (Hlavní koncepční rozdíl od Nette šablon je v použití autoloaderu.)

v6ak
Člen | 206
+
0
-

Oprava: getAnnotations má ten problém, že se tam člověk může splést v názvu celé metody a pak bez varování budou všechny anotace ignorovány. Php nemá @Override ani pro instanční metody, natož pro statické.

Takže asi bude nejlepší to add v nějaké podobě. Asi bych to povolil volat pouze přímo ze souboru, kde je třída definována. Tím ‚přímo‘ myslím, že bych zakázal i volání přes funkci. Vím, že je to takové divné řešení. IMHO je ale nejméně divné ze všech divných.

Petr Motejlek
Člen | 293
+
0
-

Dřív jsem si myslel, že jsou anotace v komentářích špatné, ale když se nad tím člověk zamyslí, tak to zase takové zlo není. Komentáře jsou od toho, aby dokumentovaly určitou funkcionalitu, když si ale představím anotaci, která mi určuje, že anotovaná metoda bude vždy spuštěna v nové transakci, tak to je určitě věc, kterou je dobré dokumentovat taky. PHP zatím (nevím, jestli někdy bude) neumí Java-like anotace, takže ty komentářové jsou jediná možnost a jestli už David dokáže obejít limitace dané různými cachujícími akcelerátory, beru to jako správnou možnost.

Asi jediný problém vidím v tom, že teď se situace má tak, že můžu anotaci napsat prakticky jak chci a nic mě nekontroluje, jestli jsem neudělal překlep v názvu anotace, nebo parametrech. Anotace by měl něakým způsobem tedy zpracovávat už NetteLoader, když si na soubory šahá při prvním načtení. Měl by si vzít všechny anotace, co najde (teď nevím, bereme PHPDoc @author jako anotaci, nebo ne? ;)), a nějakým způsobem je prověřit – napadá mě třeba systém, kde každá anotace musí být definována jako třída a když NetteLoader na takovou anotaci narazí, předal by té třídě do nějaké statické metody jako parametr jméno třídy (metody) kde nalezl tu anotaci a parametry, co u ní jsou napsané. Ta třída by potom prověřila, jestli ty parametry jsou správně a mohla by se nějakým způsobem zachovat.

Např. třída/anotace RequiredSecurityLevel by si poznamenala všechny metody (třídy) u kterých je jako anotace uvedena (parametr by mohla být třeba minimální role uživatele), a kdykoliv by někdo přistoupil k takové anotované třídě/metodě, vyzkoušela by, jestli má k tomu oprávnění, nebo ne.

Dává to smysl, nebo to jsou jen bláboly? ;)

v6ak
Člen | 206
+
0
-

Vpodstatě něco jako jsem psal já, ne?

Petr Motejlek
Člen | 293
+
0
-

Ne úplně, ty píšeš něco, co by musel někdo řešit na úrovni běžného kódu. Jestli jsem to pochopil dobře, tak si představuješ, že na začátku souboru, kde bude třída, budu volat něco, co anotace řeší.

Já navrhuji tuhle starost nechat na NetteLoaderu a vytvářet pro anotace speciální třídy, jejichž nějakou statickou metodu, třeba addClass, addMethod a addAttribute by volal NetteLoader, když by objevil anotaci. Pak by se krásně řešilo, jestli je anotace dobře, nebo ne, protože by ta třída okamžitě mohla vyhodit výjimku. Pokud bude v anotaci překlep, zjistí to NetteLoader, protože nenajde tu třídu, které by předal informace.

Honza Kuchař
Člen | 1662
+
0
-

Jo, pokud budou anotace vyhazovat výjimky, tak to bude opravdu jiné kafe. :)

David Grudl
Nette Core | 8218
+
0
-

Přesně nad tím jsem uvažoval, že pokud požádám o anotaci @security, vytvoří se objekt SecurityAnnotation (neexistující třída je fatální chyba) a v konstruktoru se mu předají parametry načtené z anotace – třída už si je bude umět sama zkontrolovat a v případě špatných datových typů nebo chybějících povinných položek vyhodí výjimku. Stále však zůstává možnost, že se seknu a místo @security napíšu třeba @secure a ono to bude vypadat tak, že uvedený člen jen anotaci nemá.

Opačný postup, kdy pro každé @xyz musí existovat třída XyzAnnotation, by byl asi docela opruzoidní, ačkoliv… Možná by se dal udělat seznam výjimek (Nette obsahuje 17 případů).

Jakub Šulák
Člen | 222
+
0
-

určitě bych volil ten druhý postup. Pokud se programátor přepíše a nevyhodí to ani Parse error (což nejde) a jen jednodušše „to nebude fungovat“, tak je to špatný.

Ale spíš přemýšlím, jak by to chodilo s extended třídami?

Například, kdyby anotace „param“ volala třídu ParamAnnotation a já bych chtěl v části aplikace volat ParamAnnotationEx, která by třeba dělala něco navíc.

v6ak
Člen | 206
+
0
-

Taky jsem pro druhý postup.

Ale co o řešení /* místo /**? To taky může být problém.

Extended třídy? Tak měl bych třeba ParamAnnotation a ExcellentParamAnotation (blbější název jsem si už nemohl vymyslet), případně bych mohl mít i abstraktní třídy.

Spíš nevím jak to bude s namespace.

Honza Marek
Člen | 1664
+
0
-

David Grudl napsal(a):

Opačný postup, kdy pro každé @xyz musí existovat třída XyzAnnotation, by byl asi docela opruzoidní, ačkoliv… Možná by se dal udělat seznam výjimek (Nette obsahuje 17 případů).

Seznam výjimek by musel být přístupný přes nějakou veřejnou proměnnou. Pokud někdo bude chtít použít nějakou dokumentační anotaci, která není známa vývojářům Nette, tak by měl mít šanci ji tam napsat.

Petr Motejlek
Člen | 293
+
0
-

Honza Marek napsal(a):

David Grudl napsal(a):

Opačný postup, kdy pro každé @xyz musí existovat třída XyzAnnotation, by byl asi docela opruzoidní, ačkoliv… Možná by se dal udělat seznam výjimek (Nette obsahuje 17 případů).

Seznam výjimek by musel být přístupný přes nějakou veřejnou proměnnou. Pokud někdo bude chtít použít nějakou dokumentační anotaci, která není známa vývojářům Nette, tak by měl mít šanci ji tam napsat.

To by se teoreticky dalo řešit už v config.ini.

Petr Motejlek
Člen | 293
+
0
-

Ještě k těm rozšířením, podle mě by prostě nedávalo smysl, aby v aplikaci existoval objekt třeba MyAnnotation, který by se aktivoval při anotaci @my, ale já bych chtěl, aby se při té anotaci volal nějaký můj objekt MyOtherAnnotation – to je přeci divné, ne? Když budu chtít něco dávat mojí třídě, prostě použiju @myOther ;).

Jinak bych to (díky, že PHP není silně typované ;)) řešil přes něco stylu Annotation::getHandler($annotationName), který by vrátil jméno třídy/instanci třídy, která řeší danou anotaci, ale pořád mi to přijde jako trochu overkill … Pokud se bavíme o tom, že potřebuju rozšířit funkcionalitu například SecureAnnotation, tak prostě udělám SecureAnnotationEx a přepíšu si anotaci v kódu – přijde mi to čistší.

David Grudl
Nette Core | 8218
+
0
-

Kontrolovat /* */ místo /** */ by se dalo externím skriptem. Nakonec něco takového chci už delší dobu stejně přidat do frameworku, zkontroloval by BOM, přítomnost závěrečného ?> a mohl by kontrolovat i zápis komentářů.

Smysl extended tříd nevidím, viz Petr

Petr Motejlek
Člen | 293
+
0
-

Napadla mě ještě jedna věc v souvislosti s tím rozšiřováním. Vím, že jsem kdesi v dokumentaci viděl anotaci @secure, zatím jsem ji nemusel použít, tak ani nevím, jestli to byla jen idea, nebo jestli Nette interně hlídaní práv pro spuštění metod řeší.

Jak by se Netto mělo chovat, kdybych se rozhodl poupravit chování @secure a vytvořil si na to tedy MySecureAnnotation třídu, která by to řešila nějak po svém, ale místo toho, abych u metod, kde chci tohle jiné hlídání použít, přepsal @secure na @mySecure, to @mySecure jen dopsal?

Mělo by něco zkontrolovat, že existují dvě anotace, jejichž obslužné třídy se navzájem rozšiřují, a vyhodit výjimku, nebo by to mělo projít? ;)

David Grudl
Nette Core | 8218
+
0
-

Třídy XyzAnnotation by byly pouhé nosiče informace, místo současné stdClass. Hlídaly by jen typy a povinné hodnoty parametrů.

Jakub Šulák
Člen | 222
+
0
-

extended třídy:
Jedná se mi o to, jak se bude například řešit, když budu mít v celé aplikaci @param anotaci a v určité části aplikace budu chtít (například z důvodu zpětné kompatibility) kontrolovat typ a v jiné ne. Stejně tak potom třeba nějaká anotace @secure – k metodě se dostane jen ten kdo má oprávnění…atd.

ale možná je jiné řešení…

Petr Motejlek
Člen | 293
+
0
-

To já jsem právě myslel, že by i samy řešily, co se má stát. Třeba ta SecureAnnotation by se měla nahookovat na volání metody, u které je anotace @secure, a testovat, jestli ji uživatel s daným oprávněním může spustit.

Určitě ale bude i jen validace parametrů a správnosti názvu anotace krok správným směrem.

Patrik Votoček
Člen | 2221
+
0
-

Jak se tahle novinka projevuje na rychlosti? (prece jenom kdyz je vlastni parser tak to asi bude pomalejsi)

Panda
Člen | 569
+
0
-

Je tam cache, která by se měla aplikovat i v případě, že Reflection k dispozici je, takže první požadavek bude o kousek pomalejší a pak už by to mělo být stejně rychlé.