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
Screencast
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.
Na autorově blogu si můžete přečíst odpovědi Lead Developera Doctrine na uvedené připomínky.
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.
Screencast
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.
Disclaimer: Autor textu je zároveň autorem popisované knihovny NotORM.
Přehled komentářů