S objekty do světa

Musím se přiznat, že jsem na prvním ročníku konference WebExpo postrádal přednášku o pravém objektovém programování webové aplikace. Smutnil jsem, že se žádná významná osoba touto problematikou nezajímala. Postupem času jsem si začal uvědomovat zatemnění především začínajících vývojářů při neúplném pochopení architektury MVC a především zanedbávání modelu, který byl často nahrazován databázovými dotazy přímo v controllerech. Pořekadla jako Model je funkční základ aplikace.“ nebo Na model lze napasovat několik různých UI.“ se řadili pouze mezi teoretické poučky.

Podobný problém zaznamenal i Tomáš Jukin a tak jsme se rozhodli vyrazit s objekty mezi lidi. Na letošním WebExpu si v rámci našeho workshopu Vývoj objektových webových aplikací v PHP metodikou USDP pomocí UML povíme, že vývoj webových aplikací na základě bezhlavého psaní kódu už dnes neletí. Vysvětlíme si, jak efektivně modelovat webové aplikace pomocí objektové metodiky Unified Software Development Process a jako jednotný dorozumívací jazyk v rámci vývojového týmu (popř. přímo s klienty) používat UML. Nad obyčejný podřadný kód posadíme abstraktní rovinu, která nám pomůže udělat si obrázek o systému mnohem rychleji než marné orientování v kódu. Značnou výhodou hotové aplikace bude její velmi dobrá upravitelnost a rozšiřitelnost.

Náš 3,5 hodinový workshop se koná v sobotu 17.10.2009 časně zrána. Workshop bude rozdělen do dvou částí. Nejprve si povíme něco málo nezábavného o teorii modelování informačních systémů, metodice Unified Software Development Process a notačním jazyku UML. V druhé části vás provedeme řízením reálného projektu na základě metodiky USDP. Budeme si hrát na vývojový tým a společnými silami vyvineme použitelnou objektovou webovou aplikaci. Účastníci si v rámci workshopu vyzkouší CASE nástroj Enterprise Architect, získají teoretické základy metodiky USDP a jazyka UML a pochopí jak správně nakládat s modelem z architektury MVC na reálném příkladu založeném na technologiích Nette Framework a Doctrine. Pište správné objektové webové aplikace a bude se vám lépe usínat!

Pravé objektově orientované programování v PHP

Kdo by neznal čím dál více se rozšiřující serverový skriptovací jazyk s nedomyšlenou rekurzivní zkratkou PHP, který je známý nejen jako výukový trenažér pro amatérské webmastery. Statistiky ukazují, že dnešní hostingový program bez podpory PHP je buď ten nejlevnější nebo s chybou v metrixu. S příchodem páté verze se v PHP objevuje objektová syntaxe a PHP se mění z výukového trenažéru na kvalitní objektový serverový skriptovací nástroj, se kterým lze dělat velké věci. Protože PHP projekty z našeho světa jen tak nezmizí, rozhodl jsem se sepsat článek, který kategorizuje a odděluje od sebe jednotlivé přístupy tvorby PHP projektů.

A: Strukturální přístup

Každý, kdo zná PHP, se ve svém životě setkal s koncepcí PHP projektíku založeného na statických stránkách, jejichž obsah se přepíná pomocí jediného GET parametru a jazykového konstruktu include. V lepších případech je využita databáze nebo zápis do souborů. Takovýto projekt využívá pouze strukturálních funkcí, nejčastěji implementovaných přímo v PHP.

PHP projekt založený na strukturálním přístupu obvykle postrádá logiku a je nejčastěji založen na práci s textem. Vůbec nechci tento přístup odsuzovat, naopak, takový přístup disponuje největší perzistencí v porovnání s dalšími přístupy, ale hodí se jen na malé, velmi jednoduché projekty.

B: Objektově strukturální přístup

Ne nadarmo se řadí PHP mezi multiparadigmatické programovací jazyky. Hlavně několik posledních let se začíná rozrůstat síla PHP frameworků, které programátorům uzpůsobují a mnohdy ulehčují jejich programátorský styl. Z těch nejznámějších zmíním Zend Framework, CakePHP nebo český Nette Framework. PHP frameworky jsou nejčastěji psané v objektovém kódu a založené na MVC architektuře.

Při tvorbě PHP projektu, který využívá některý z objektově psaných frameworků, je kód projektu psaný samozřejmě také objektově. Důležité je, uvědomit si, že pokud je objektový kód, nemusí být objektová i logika. V objektově strukturálním přístupu aplikace logiku postrádá a z pohledu architektury je stále strukturální. Aplikace pouze plní za sebou seřazené a do tříd obalené metody. Takovýmto přístupem jsou koncipovány středně složité projekty, které vyžadují složitější komponenty (například z knihovny frameworku) a usnadňují práci programátorovi, mnohdy bohužel na úkor perzistence.

C: Pravý objektový přístup

Pokud chceme programovat náš PHP projekt opravdu objektově, musíme naučit systém přemýšlet. Proto v pravém objektovém přístupu využíváme nejen objektové syntaxe, ale i objektové logiky, na které je postavena systémová architektura. Nejen že systém využívá objektového kódu některého frameworku, ale pracuje i s našimi doménovými objekty, které tvoří problémovou doménu projektu. Tyto objekty tvoří model MVC architektury a jsou nejčastěji mapovány do databází pomocí některého ORM nástroje, který může být integrován přímo do frameworku.

Takový přístup bychom měli zvolit, pokud se jedná o složitější PHP projekt. Vzniklý systém nevyniká perzistencí, proto je nutno ho co možná nejlépe optimalizovat (databázové dotazy – kvalitní ORM, dobře navrhnutá architektura, cache…), ale vyniká správností objektového konceptu.

Musím ještě podotknout, že žádný z přístupů není nejhorší a žádný nejlepší, protože vždy záleží na konkrétním PHP projektu. I když osobně preferuji pravý objektový přístup, tak se mi zamlouvá i strukturální přístup pro jednoduché projekty. Nejmíň se mi ale zarývá pod nehty objektově strukturální přístup, protože nejsem schopný kloubit správný objektový koncept a logicky strukturální přístup. Je to jako duševní bariéra. Ale každému vyhovuje něco jiného.

Asociace typu M:N

Rozhodl jsem se publikovat první technicky založený článek. Mapování objektů do relační databáze je pro dnešní objektové jazyky občas oříškem. Největší neplechu páchá asociace typu M:N. Ta není dnešními objektovými jazyky přímo podporována. V tomto článku přiblížím, jak úspěšně vysvětlit objektovým jazykům, že hvězdičky můžou svítit na obou stranách.

Cože to vlastně ta asociace typu M:N je? Každý se s ní už určitě setkal. Na diagramu 1 je zobrazen jednoduchý příklad. Učitel může vyučovat několik žáků z různých tříd a zároveň každý žák může být vyučován několika různými učiteli. Dokážu si představit, že obě analytické třídy budou nahrazeny návrhovými třídami a že hodnoty atributů budou uloženy ve dvou tabulkách relační databáze. Ve fázi analýzy je na tento diagram radost pohledět, jenže ve fázi návrhu už tak růžově nevypadá.

Diagram 1: Asociace typu M:N ve fázi analýzy

Diagram 1: Asociace typu M:N ve fázi analýzy

Podívejme se nyní do pozdější fáze analýzy, co se s naší školskou delegací stalo. Na diagramu 2 jsou vidět doplněné atributy a operace. Jen objasním, že operace zjistiSeznamZaku() vrací asociativní pole všech objektů typu Žák, které daný objekt typu Učitel vyučuje. Na opačné straně vrací operace zjistiSeznamUcitelu() asociativní pole všech objektů typu Učitel, které vyučují daný objekt typu Žák. Některé jazyky místo pole používají kolekce objektů, tím už se ale náš článek nezabývá. Ostatní atributy a operace popisovat nemusím, protože jsem zvolil opravdu jednoduchý příklad.

Diagram 2: Asociace typu M:N s atributy a operacemi tříd

Diagram 2: Asociace typu M:N s atributy a operacemi tříd

Přenesme se nyní mezi řádky nějakého skriptu, který vypisuje ke každému učiteli všechny vyučované žáky. Pokud by se databáze sestávala pouze ze dvou tabulek, jako je vidět v diagramu 3, budou nám stále chybět reference mezi jednotlivými objekty typů Učitel a Žák a náš skript, ať už bude sepsán jakkoli, náš cílený problém nevyřeší a nedokáže ke každému učiteli vypsat všechny jím vyučované žáky. Příklad tabulek je v MySQL.

Diagram 3: Pohled na zamýšlené databázové tabulky

Diagram 3: Pohled na zamýšlené databázové tabulky

Takže nám něco chybí. Pojďme se zbavit té ohyzdné asociace typu M:N a rozbijme ji na dvě asociace typu 1:M. Vložme mezi asociaci typu M:N jednu třídu navíc, kterou můžeme pojmenovat speciálním názvem například Výuka nebo jednoduše spojením názvů obou spojovaných tříd, tzn. UčitelŽák. Tato geniální třída bude sloužit jako pojítko mezi našimi třídami. Každá instance bude ukazovat právě na jeden objekt typu Učitel a právě na jeden objekt typu Žák. Jako celek jsem určil třídu Učitel z toho důvodu, že budeme vypisovat žáky, které učitel vyučuje. Objekty typu Učitel jsou tedy odpovědné za životní cyklusy objektů typu Výuka. Stejně tak bychom mohli třídu Výuka přiřadit třídě Žák. Výsledek je zobrazen na diagramu 4.

Diagram 4: Využití propojující třídy Výuka

Diagram 4: Využití propojující třídy Výuka

Na diagramu 5 jsou zobrazeny tabulky relační databáze, které jsou nyní propojené přes cicí klíče (foreign keys) tabulky Výuka.

Diagram 5: Pohled na konečné tabulky databáze

Diagram 5: Pohled na konečné tabulky databáze

(pozn. děkuji maartymu za upozornění komentářem, že EA umí modelovat databáze…)

Metoda zjistiSeznamZaku() nyní vybere z tabulky Výuka veškeré řádky, u kterých je idUcitele rovno id hledaného učitele. Metoda vytvoří pole objektů typu Žák, jejichž id se nachází v nalezených řádcích v tabulce Výuka. Toto pole nakonec vrátí. Již zmiňovaný skript nyní může pole projít a vypsat jméno a příjmení.

Tak jsme si osvětlili, jak se manuálně vypořádat s asociací typu M:N. Nad relačními databázemi dnes ale existují ORM nástroje, které se s asociací typu M:N vypořádají automaticky a programátor ani nepocítí, že se v databázi nachází ještě nějaká propojovací tabulka. Takový ORM nástroj pro PHP je například Doctrine, který je inspirován Hibernate pro Javu.

štítky: , ,