Videotutoriál Doctrine 2 a NotORM
Článek vyšel na serveru Zdroják.
Se zájmem jsem sledoval seriál o Doctrine 2 na serveru Zdroják, ale některým informacím se mi nechtělo uvěřit. Ne snad, že by byl seriál špatný, naopak ho považuji za celkem zdařilý, ale nezdál se mi samotný návrh některých věcí v Doctrine. A protože je seriál na příklady poměrně chudý, tak jsem se rozhodl vyzkoušet Doctrine 2 na příkladu vlastním a tím se s knihovnou lépe seznámit. Svoje pokusy a omyly jsem zaznamenal a vzniklé video vám teď nabízím ke shlédnutí.
Doctrine 2 – získávání dat
Co se mi na Doctrine 2 nelíbí?
- Zhýčkán jednosouborovými minimalizovanými verzemi (jQuery, Nette Framework, Adminer, …) se mi moc nelíbí knihovna čítající 333 souborů.
- Část Doctrine závisí na části Symfony, která je obsažena i v distribuci. Vlastně by se tomu nedalo nic vytknout až do okamžiku, když bych chtěl v projektu použít jinou verzi Symfony, než kterou používá Doctrine.
- Je potřeba specifikovat adresář a jmenný prostor pro jakési proxy, i když se k ničemu nepoužijí.
- Při zadávání informací pomocí anotací je velmi snadné udělat překlep, o kterém se nijak nedozvíme.
- Vazební tabulky entit vytvořených v globálním jmenném prostoru postrádají první znaky. Podezíral jsem z toho betaverzi (tutoriál jsem vytvořil před vydáním ostré verze), ale dostalo se to i do finálního vydání.
- Pokud chceme s vazbami mezi entitami pracovat obousměrně, tak je také musíme na obou stranách ručně definovat.
- Prakticky nikde nás nemusí zajímat skutečné názvy sloupců, které Doctrine 2 generuje, ale v definici indexu je použít musíme.
- Sloupec přidaný do entity se při aktualizaci schématu nezařadí na správné místo, ale umístí se až na konec tabulky.
- Pro metodu
EntityRepository::find
existuje šikovná zkratka, pro velmi podobnou metoduEntityRepository::findAll
ale tato zkratka neexistuje. - Zcela zásadně mi vadí, že Doctrine 2 pokládá dotaz při každém průchodu cyklem, to je zabiják výkonnosti.
- Pokud chceme udělat něco jen maličko složitějšího (třeba setřídit záznamy), tak musíme použít jazyk DQL. Takže pokud si napíšeme kód třeba ve tvaru
$em->getRepository('Article')->findBy(array('category' => $category))
a následně se dozvíme, že bychom články měli ještě podle něčeho setřídit, tak musíme tento kód smazat a celý ho přepsat do jazyka DQL. - Při spojení tabulek, které DQL elegantně podporuje, se stejná data přenáší opakovaně. To není tak velký problém jako opakované kladení dotazů v cyklu, ale výkonnosti to také může škodit.
- Z mého pohledu se ten úplně největší problém projeví v případě, kdy se rozhodneme do vazební tabulky přidat sloupec s nějakou informací. V Doctrine 2 to znamená zahodit velkou část kódu a ještě více kódu napsat úplně od začátku. Přitom z pohledu zadavatele jde o úplnou maličkost („je to bezva, jen ještě prosím k těm nálepkám u článků přidej váhu“).
Můj celkový dojem z Doctrine 2 je bohužel takový, že i když se knihovna tváří jako vysokoúrovňová a tudíž by měla být robustní, tak skutečné chování je přesně opačné. Kvůli každé maličkosti se musíme uchylovat k jazyku DQL (který je velmi podobný SQL), což sice nemusí být pro řadu programátorů problém, ale rozhodně to má hodně daleko k vysokoúrovňovému objektovému přístupu, který bych od Doctrine očekával. Za ještě horší ale považuji to, že vytvořený kód není robustní a i drobná změna v zadání znamená jeho významné přepsání.
Na Doctrine 2 se mi líbí jedna věc – z definice entit se dá vygenerovat schéma. A i když tento proces není dokonalý a nepokrývá všechny možnosti databází, tak v tom spatřuji velkou výhodu hlavně při nasazování aplikace. Nicméně třeba fakt, že seriál o této funkci prakticky mlčí, ve mně prohlubuje podezření, že v praxi se tento postup spíše nepoužívá a schéma se definuje ručně, což je ta nejhorší možná varianta, protože stejnou práci je potřeba udělat dvakrát a změny se musí ručně udržovat na dvou místech.
NotORM – získávání dat
Protože jsem sám autorem knihovny pro práci s daty v databázi, tak jsem z cvičných důvodů vyřešil stejnou úlohu i v knihovně NotORM.
Na NotORM vidím oproti Doctrine 2 tyto zásadní rozdíly:
- NotORM se nestará o schéma databáze, což nás nutí definovat strukturu databáze externě, ale zároveň nám dovoluje využít všech možností databázového systému.
- NotORM pokládá konstantní počet dotazů, což je z pohledu výkonnosti často ten nejlepší přístup, protože se v každém průchodu cyklem nepokládá nový dotaz ani se nepřenáší stejná data opakovaně.
- Kód je velmi snadno modifikovatelný – pokud chceme např. setřídit záznamy, tak jednoduše za
$category->article()
doplníme->order("published")
. Stejně tak jsou triviální i změny v návrhu – když se rozhodneme k nálepkám článků přidat váhu, tak nemusíme smazat ani jeden znak stávajícího kódu. - Pokud z tabulky nepotřebujeme získat všechny sloupce, tak to v Doctrine 2 můžeme zajistit pomocí DQL. NotORM nabízí podobný mechanismus, kromě toho se ale použité sloupce mohou vybrat také automaticky, což zajistí výkonnostně optimální řešení s využitím minimálního úsilí.
Kromě toho je kód využívající NotORM také podstatně kratší a přehlednější – velmi jednoduchým způsobem zkrátka vyjadřujeme myšlenku toho, co chceme s daty provést. Rozhodně se nedá říct, že by bylo zadání ušito na míru NotORM – jde o klasický demonstrační příklad využívající vazby 1:N a M:N. U složitějšího příkladu by rozdíl v pohodlnosti práce s knihovnami vynikl ještě lépe.
Další část
První část videotutoriálu Doctrine 2 se zabývala získáváním dat. Druhá část bude o jejich ukládání, ve třetí se podíváme na návrh modelu.
Přijďte si o tomto tématu popovídat na školení Jak vytvářím webové aplikace.
Diskuse
finc:
Osobně mi přijde tento přístup dost neštastný. Myslím si, že nemá cenu znažit se do PHP docpat něco, co tam evidentně nepasuje.
Je vidět, že celé Doctrine se inspirovalo u Hibernate. Spoustu věcí, je zde více než podobných.
Rozdíl je ovšem to, že Java není PHP. Anotace jsou v Jave na úrovní syntaxe jazyka. EntityManager a samotné Entity se namapují při "deploy" aplikace. To už se ani nebavím o možnostech, které má Doctrine vůči Hibernate.
Mě osobně nejvíc v PHP vyhovuje Dibi. Entity a EntityManager (nebo-li Hibernate Session) si nechám pro Javu :)
Diskuse je zrušena z důvodu spamu.

