[2009–11–14] Anotace: eAccelerator by již neměl být překážkou
- David Grudl
- Nette Core | 8218
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
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
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
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)
- Patrik Votoček
- Člen | 2221
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
- v6ak
- Člen | 206
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
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
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:
- 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řebagetAnnotations
nebo prostě pod třídou zapsat anotacedeklarativnědeklarativně, např.Annotations::add(__CLASS__, '$var', ...)
. - 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
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
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
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? ;)
- Petr Motejlek
- Člen | 293
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
Jo, pokud budou anotace vyhazovat výjimky, tak to bude opravdu jiné kafe. :)
- David Grudl
- Nette Core | 8218
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
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
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
David Grudl napsal(a):
Opačný postup, kdy pro každé
@xyz
musí existovat třídaXyzAnnotation
, 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
Honza Marek napsal(a):
David Grudl napsal(a):
Opačný postup, kdy pro každé
@xyz
musí existovat třídaXyzAnnotation
, 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
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
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
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
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
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
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
Jak se tahle novinka projevuje na rychlosti? (prece jenom kdyz je vlastni parser tak to asi bude pomalejsi)