11. diel - Statika v PHP do tretice
V minulej lekcii, Triedny prvky v PHP druhýkrát - konštanty , sme pokračovali v popise triednych prvkov a uviedli sme si konštanty. Dnešným PHP tutorialom tému statiky uzavrieme, vysvetlíme si statický register, databázový wrapper a nakoniec budeme polemizovať o tom kedy statiku použiť.
Statický register
Statický register je trieda, v ktorej sú len statické premenné, obsahujúce nejaké hodnoty. Typicky sa takáto trieda používa pre uchovanie nastavenia aplikácie. Je potom zdieľaná v celej aplikácii a obsahuje napr. Heslo k db, url webu, predvolený jazyk a podobne. V neobjektových aplikáciách sa namiesto statického registra používali globálne premenné. Trieda by mohla vyzerať napr. Nasledovne:
class Nastaveni { public static $udajeDB = array( 'jmeno' => 'root', 'heslo' => '' ); public static $url = 'localhost'; public static $jazyk = 'cz'; }
V celej aplikácii sa potom môžeme napr. Pýtať na nastavený jazyk alebo zmeniť toto nastavenie:
if (Nastaveni::$jazyk != 'cz') $pozadi = "pozadi_anglicke.png";
Použitie statického registra je opäť veľmi kontroverzný. Na uloženie konfigurácia aplikácie nie je zlý, býva však veľmi často používaný na uloženie rôznych inštancií objektov, s ktorými sa v aplikácii ďalej pracuje. Všetky objekty sú potom prístupné odvšadiaľ cez register a to je jednoducho zle. Je otázka, či sa dá o takejto aplikácii potom vôbec hovoriť ako o objektové.
Databázový wrapper
Pomerne časté a aj zmysluplné použitie statiky je pre databázový wrapper. Asi ste doteraz pracovali so zastaranými neobjektovými databázovými ovládači (napr. Funkcia mysql_query () a podobne). V PHP sa s databázou pracuje objektovo pomocou ovládača PDO (ako PHP Database Objects). Tento ovládač funguje tak, že sa vytvorí inštancia triedy PDO a tá sa pripojí k databáze. Aby sme sa k databáze nemuseli pripájať stále znovu a znovu, zdieľame túto jednu pripojenú inštanciu v celej aplikácii. Práve k tomu použijeme statiku. Pretože sme dlho nerobili nič praktického a práca s databázou je veľmi dôležitá, skúsime si to hneď budúci lekciu, kde si tvorbu Wrapper aj lepšie popíšeme.
Kontroverzia
Ako som sa už zmienil na začiatku tohto trojčlánku o statike, statika je jedno z najkontroverznejších tém objektovo orientovaného programovania. Keď sa nad tým zamyslíte, tak v podstate narušuje jeho koncept, pretože statické prvky sú prístupné odkiaľkoľvek a bez inštancie. Keď máte v aplikácii pár statických tried (napríklad 4) a zvyšok normálnych, je všetko v poriadku. Akonáhle ale máte každú druhú triedu statickú, je niekde problém.
Vždy platí, že každú aplikáciu možno napísať čisto objektovo bez použitia statiky. Niektorí programátori dokonca zastávajú názor, že statiku by jazyky vôbec nemali obsahovať. Samozrejme to nie je tak horúce, avšak statika je veľmi často zle používaná a preto zvyšok článku venujem rozobratie správnych a zlých využitie tejto techniky.
Správne použitie statiky
Keď sa zamyslíte, urobili sme si tu niekoľko príkladov a všetky mali spoločné určité črty. Jednalo sa o pomocné metódy alebo pomocné triedy, ktoré sa často používajú na viacerých miestach v aplikácii. Z triedy často nemá zmysel vytvárať inštanciu a keby to šlo, chceli by sme vždy len jednu (jednu Matematiku, jednu konzolu, jednu databázu ...). V objektových redakčných systémoch sa staticky často píšu tiež tzv. Helper, čo sú krátke pomocné metódy pre formátovanie výstupu. Na ITnetwork.cz máme napr. Taký helper, čo vypíše vybraný dátum slovami:
echo('Dnes je :' . DatumHelper::slovy($datum));
Ďalším príkladom bola ona matematická knižnica, tá dokonca nemá žiadny vnútorný stav a jedná sa len o skupinu pomocných metód.
Do statické premenné nejaké triedy môžeme tiež uložiť inštanciu aktuálne prihláseného užívateľa, aktuálne zobrazeného článku a podobne. To sú opäť veci, ktoré je potrebné zdieľať v mnohých triedach.
Statika v uznávaných projektoch
Statiku nájdeme v základných objektových knižniciach uznávaných programovacích jazykov, ako sú napr. Java alebo C# .NET. Statika je tu použitá presne pre pomocné metódy, ako zobrazenie jednoduché správy alebo napríklad vypísanie textu do konzoly:
Console::writeLine("Text"); MessageBox::show("Špatné heslo"); $vysledek = Databaze::dotaz("SELECT * FROM `clovek`");
Konzolu máme len jednu a pracujeme s ňou vo veľkom počte tried, preto dáva zmysel mať jej triedu ako statickú. Podobne je to s databázou, aplikácia takmer vždy používa práve jednu databázu a to z mnohých miest.
Zlé použitie statiky
Keď sa budete rozmýšľať, či máte statiku použiť, tak ju radšej nepoužívajte Na 90% je totiž zbytočná. Statiku by ste nemali používať v iných prípadoch ako vo vyššie zmienených. Ak nevytvárate nejakú systémovú triedu, ktorá sa bude používať všade, určite by nemala byť statická.
Aj napr. Trieda, ktorá slúži na správu ľudí a obsahuje metódy ako registruj (), vymaz () a podobne by nemala byť statická a je lepšie, keď si vždy, kedy potrebujete s ľuďmi pracovať, vytvoríte jej inštanciu. Trieda by sa mohla volať treba SpravceLidi. Nemalo by vás napadnúť urobiť ani statickú galériu, statické ľudí a podobne. Celé tieto 3 články som písal hlavne preto, aby ste statický kód vedeli čítať. Neznamená to, že ho máte písať a určite budete často narážať v cudzom kódu na statické prvky, ktoré by statické byť nemali.
Odovzdávanie závislostí a dependency injection
Statika sa používa väčšinou k odovzdávanie závislostí, teda tried, ktoré potrebujú ostatné triedy na to, aby fungovali. Jedná sa napr. O už spomínanú databázovú triedu alebo o nastavení aplikácie. O riešenie závislostí medzi objektmi v aplikáciách sú napísané celé knihy a existuje milión prístupov. Je to jedno z nejřešenějších tém v objektovo orientovanom programovaní. Ťažko povedať, či je pre začiatočníkov vhodnejšie statika alebo riešiť závislosti pomocou návrhových vzorov, mne pripadá statika jednoduchá a pri rozumnom použití aj prehľadná.
Väčšinou platí, že v systéme do veľkosti pár desiatok tried vám stačí občas použiť statiku a aplikáciu to nejako vážne neuškodí. Robia to tak uznávané frameworky, robím to tak aj ja. S väčšími projekty sa zvyšuje počet závislosťou (najmä keď používate knižnice tretej strany, čo sa snažím robiť minimálne) a tým aj počet statických tried. Akonáhle v aplikácii staticky zdieľate viac než pár prvkov, je lepšie od statiky upustiť a odovzdávať každej triede napr. V konstruktoru to, čo potrebuje. Len tak sa aplikácii podarí ustrážiť a nestane sa spleťou vzájomne previazaných statických tried, kde človek už nevie čo je na čom závislé. Práve z toho dôvodu niektorí programátori odporúčajú statiku vôbec nepoužívať.
Technike odovzdávanie závislostí automaticky a bez statiky sa hovorí Dependency Injection (skrátene DI), viac si o nej môžete prečítať napr. V článku Dependency injection. Ďalším riešením, ktoré som si obľúbil najmä pri tvorbe hier, je vytvoriť si zdieľané inštancie v nejakom kontajneri a objektom potom v konstruktoru odovzdávať túto nádobu (vzoru sa hovorí service locator). Vyhneme sa statike a napr. V hre sa jednoducho z triedy Hrdina dostaneme na inštanciu triedy Kontajner a cez neho na mapu, ostatné objekty, nastavenie hry, databázovú triedu a podobne.
Ako riešiť závislosti v reálnom systéme je ukázané okrem iného aj ďalej, v nadväzujúcom kurze. Téma statiky sme teda prebrali. V budúcej lekcii, Riešené úlohy k 9.-11. lekciu OOP v PHP , si ukážeme základy práce s databázou pomocou ovládača PDO.
V nasledujúcom cvičení, Riešené úlohy k 9.-11. lekciu OOP v PHP, si precvičíme nadobudnuté skúsenosti z predchádzajúcich lekcií.