IT rekvalifikace s garancí práce. Seniorní programátoři vydělávají až 160 000 Kč/měsíc a rekvalifikace je prvním krokem. Zjisti, jak na to!
Hledáme nové posily do ITnetwork týmu. Podívej se na volné pozice a přidej se do nejagilnější firmy na trhu - Více informací.

Lekce 11 - Statika v PHP do třetice

V minulé lekci, Třídní prvky v PHP podruhé - konstanty, jsme popisovali třídní prvky a uvedli jsme si konstanty.

V dnešním díle si vysvětlíme statický registr, databázový wrapper a nakonec budeme polemizovat o tom, kdy použít statiku.

Statický registr

Statický registr je třída, ve které jsou jen statické proměnné, obsahující nějaké hodnoty. Typicky se taková třída používá pro uchování nastavení aplikace. Je potom sdílená v celé aplikaci a obsahuje např. heslo k DB, URL webu, výchozí jazyk a podobně. V neobjektových aplikacích se místo statického registru používaly globální proměnné. Třída by mohla vypadat například takto:

class Nastaveni
{
    public static $udajeDB = array(
        'jmeno' => 'root',
        'heslo' => ''
    );

    public static $url = 'localhost';

    public static $jazyk = 'cz';

}

V celé aplikaci se potom můžeme například ptát na nastavený jazyk nebo toto nastavení změnit:

if (Nastaveni::$jazyk != 'cz')
    $pozadi = "pozadi_anglicke.png";

Použití statického registru je opět velmi kontroverzní. K uložení konfigurace aplikace není špatný, bývá však velmi často používán k uložení různých instancí objektů, se kterými se v aplikaci dále pracuje. Všechny objekty jsou potom přístupné odevšuď přes registr a to je prostě špatně. Je otázka, jestli se dá o takové aplikaci potom vůbec mluvit jako o objektové.

Databázový wrapper

Poměrně časté a i smysluplné použití statiky je pro databázový wrapper. Asi jste doteď pracovali se zastaralými neobjektovými databázovými ovladači (např. funkce mysql_query() a podobně). V PHP se s databází pracuje objektově pomocí ovladače PDO (jako PHP Database Objects). Tento ovladač funguje tak, že se vytvoří instance třídy PDO a ta se připojí k databázi. Abychom se k databázi nemuseli připojovat stále znovu a znovu, sdílíme tuto jednu připojenou instanci v celé aplikaci. Právě k tomu použijeme statiku. Protože jsme dlouho nedělali nic praktického a práce s databází je velmi důležitá, zkusíme si to hned příští lekci, kde si tvorbu wrapperu i lépe popíšeme.

Kontroverze

Jak jsem se již zmínil na začátku tohoto trojčlánku o statice, statika je jedno z nejkontroverzněj­ších témat objektově orientovaného programování. Když se nad tím zamyslíte, tak v podstatě narušuje jeho koncept, jelikož statické prvky jsou přístupné odkudkoli a bez instance. Když máte v aplikaci pár statických tříd (třeba 4) a zbytek normálních, je vše v pořádku. Jakmile ale máte každou druhou třídu statickou, je někde problém.

Vždy platí, že každou aplikaci lze napsat čistě objektově bez použití statiky. Někteří programátoři dokonce zastávají názor, že statiku by jazyky vůbec neměly obsahovat. Samozřejmě to není tak horké, nicméně statika je velmi často špatně užívána a proto zbytek článku věnuji rozebrání správných a špatných využití této techniky.

Správné použití statiky

Když se zamyslíte, udělali jsme si tu několik příkladů a všechny měly společné určité rysy. Jednalo se o pomocné metody nebo pomocné třídy, které se často používají na více místech v aplikaci. Ze třídy často nemá smysl vytvářet instanci a kdyby to šlo, chtěli bychom vždy jen jednu (jednu Matematiku, jednu konzoli, jednu databázi...). V objektových redakčních systémech se staticky často píší také tzv. helpery, což jsou krátké pomocné metody pro formátování výstupu. Na ITnetwork.cz máme např. takový helper, co vypíše vybrané datum slovy:

echo('Dnes je: ' . DatumHelper::slovy($datum));

Dalším příkladem byla ona matematická knihovna, ta dokonce nemá žádný vnitřní stav a jedná se pouze o skupinu pomocných metod.

Do statické proměnné nějaké třídy můžeme také uložit instanci aktuálně přihlášeného uživatele, aktuálně zobrazeného článku a podobně. To jsou opět věci, které je potřeba sdílet v mnoha třídách.

Statika v uznávaných projektech

Statiku nalezneme v základních objektových knihovnách uznávaných programovacích jazyků, jako jsou např. Java nebo C# .NET. Statika je zde použita přesně pro pomocné metody, jako zobrazení jednoduché zprávy nebo třeba vypsání textu do konzole:

Console::writeLine("Ema má mámu.");
MessageBox::show("Špatné heslo");
$vysledek = Databaze::dotaz("SELECT * FROM `clovek`");

Konzoli máme jen jednu a pracujeme s ní ve velkém počtu tříd, proto dává smysl mít její třídu jako statickou. Podobně je to s databází, aplikace téměř vždy používá právě jednu databázi a to z mnoha míst.

Špatné použití statiky

Když se budete rozmýšlet, zda máte statiku použít, tak ji raději nepoužívejte :) Na 90 % je totiž zbytečná. Statiku byste neměli používat v jiných případech než ve výše zmíněných. Pokud nevytváříte nějakou systémovou třídu, která se bude používat všude, určitě by neměla být statická.

I například třída, která slouží ke správě lidí a obsahuje metody jako registruj(), vymaz() a podobně by neměla být statická a je lepší, když si vždy, kdy potřebujete s lidmi pracovat, vytvoříte její instanci. Třída by se mohla jmenovat třeba SpravceLidi. Nemělo by vás napadnout udělat ani statickou galerii, statické lidi a podobně. Celé tyto 3 články jsem psal hlavně proto, abyste statický kód uměli číst. Neznamená to, že ho máte psát a určitě budete často narážet v cizím kódu na statické prvky, které by statické být neměly.

Předávání závislostí a dependency injection

Statika se používá většinou k předávání závislostí, tedy tříd, které potřebují ostatní třídy k tomu, aby fungovaly. Jedná se např. o již zmíněnou databázovou třídu nebo o nastavení aplikace. O řešení závislostí mezi objekty v aplikacích jsou napsané celé knihy a existuje milion přístupů. Je to jedno z nejřešenějších témat v objektově orientovaném programování. Těžko říci, jestli je pro začátečníky vhodnější statika nebo řešit závislosti pomocí návrhových vzorů, mně připadá statika jednoduchá a při rozumném použití i přehledná.

Většinou platí, že v systému do velikosti pár desítek tříd vám stačí občas použít statiku a aplikaci to nějak vážně neuškodí. Dělají to tak uznávané frameworky, dělám to tak i já. S většími projekty se zvyšuje počet závislostí (zejména když používáte knihovny třetí strany, což se snažím dělat minimálně) a tím i počet statických tříd. Jakmile v aplikaci staticky sdílíte více než pár prvků, je lepší od statiky upustit a předávat každé třídě např. v konstruktoru to, co potřebuje. Jen tak se aplikaci podaří uhlídat a nestane se spletí vzájemně provázaných statických tříd, kde člověk už neví co je na čem závislé. Právě z toho důvodu někteří programátoři doporučují statiku vůbec nepoužívat.

Technice předávání závislostí automaticky a bez statiky se říká Dependency Injection (zkráceně DI), více si o ní můžete přečíst např. v článku Dependency injection. Dalším řešením, které jsem si oblíbil zejména při tvorbě her, je vytvořit si sdílené instance v nějakém kontejneru a objektům poté v konstruktoru předávat tento kontejner (vzoru se říká service locator). Vyhneme se statice a např. ve hře se jednoduše ze třídy Hrdina dostaneme na instanci třídy Kontejner a přes něj na mapu, ostatní objekty, nastavení hry, databázovou třídu a podobně.

Jak řešit závislosti v reálném systému si ukážeme jindy. Téma statiky jsme tedy probrali.

V následujícím cvičení, Řešené úlohy k 9.-11. lekci OOP v PHP, si procvičíme nabyté zkušenosti z předchozích lekcí.


 

Předchozí článek
Třídní prvky v PHP podruhé - konstanty
Všechny články v sekci
Objektově orientované programování (OOP) v PHP
Přeskočit článek
(nedoporučujeme)
Řešené úlohy k 9.-11. lekci OOP v PHP
Článek pro vás napsal David Hartinger
Avatar
Uživatelské hodnocení:
148 hlasů
David je zakladatelem ITnetwork a programování se profesionálně věnuje 15 let. Má rád Nirvanu, nemovitosti a svobodu podnikání.
Unicorn university David se informační technologie naučil na Unicorn University - prestižní soukromé vysoké škole IT a ekonomie.
Aktivity