Videotutoriál Doctrine 2 a NotORM

Školení, která pořádám

Č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

Screencast

Zdrojové kódy

Co se mi na Doctrine 2 nelíbí?

  1. Zhýčkán jednosouborovými minimalizovanými verzemi (jQuery, Nette Framework, Adminer, …) se mi moc nelíbí knihovna čítající 333 souborů.
  2. Čá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.
  3. Je potřeba specifikovat adresář a jmenný prostor pro jakési proxy, i když se k ničemu nepoužijí.
  4. Při zadávání informací pomocí anotací je velmi snadné udělat překlep, o kterém se nijak nedozvíme.
  5. 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í.
  6. Pokud chceme s vazbami mezi entitami pracovat obousměrně, tak je také musíme na obou stranách ručně definovat.
  7. 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.
  8. 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.
  9. Pro metodu EntityRepository::find existuje šikovná zkratka, pro velmi podobnou metodu EntityRepository::findAll ale tato zkratka neexistuje.
  10. 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.
  11. 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.
  12. 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.
  13. 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.

Screencast

Zdrojové kódy

Na NotORM vidím oproti Doctrine 2 tyto zásadní rozdíly:

  1. 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.
  2. 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ě.
  3. 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.
  4. 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.

Jakub Vrána, Seznámení s oblastí, 6.1.2011, diskuse: 1 (nové: 0)

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 :)

Vložit komentář

Používejte diakritiku. Vstup se chápe jako čistý text, ale URL budou převedeny na odkazy a PHP kód uzavřený do <?php ?> bude zvýrazněn. Pokud máte dotaz, který nesouvisí s článkem, zkuste raději diskusi o PHP, zde se odpovědi pravděpodobně nedočkáte.

Jméno: URL:

avatar © 2005-2018 Jakub Vrána. Publikované texty můžete přetiskovat pouze se svolením autora. Ukázky kódu smíte používat s uvedením autora a URL tohoto webu bez dalších omezení Creative Commons. Můžeme si tykat. Skripty předpokládají nastavení: magic_quotes_gpc=Off, magic_quotes_runtime=Off, error_reporting=E_ALL & ~E_NOTICE a očekávají předchozí zavolání mysql_set_charset. Skripty by měly být funkční v PHP >= 4.3 a PHP >= 5.0.