Lekce 1 - Úvod do objektově orientovaného programování v JavaScriptu
Vítejte u první lekce kurzu o objektově orientovaném programování v JavaScriptu. Kurz Základní konstrukce jazyka JavaScript již máme za sebou. V tomto kurzu se naučíme objektově programovat a hlavně objektově myslet. Je to něco trochu jiného, než jsme dělali doteď. Samotný skript už nebudeme chápat jako sekvenci příkazů, které interpret vykonává odshora dolů, ale jako soubor objektů s vlastními vlastnostmi a metodami, které mezi sebou interagují a společně tvoří funkční celek.
V kurzu se naučíme základní filozofii OOP. Řekneme si, co jsou vlastnosti a konstruktory, jaké jsou rozdíly mezi referenčními a hodnotovými datovými typy. Ukážeme si populární formát dat JSON, práci s AJAXem a API. Vysvětlíme si dědičnost, polymorfismus, zapouzdření a statiku. Naučíme se používat arrow funkce, promisy, reflexi, proxy, iterátory, generátory a mnoho dalšího. Vše si vyzkoušíme na praktických projektech:
Minimální požadavky
Pro úspěšné absolvování jsou zapotřebí znalosti z předcházejícího kurzu Základní konstrukce jazyka JavaScript.
Proč programovat objektově
Znalost objektově orientovaného programování v JavaScriptu je
naprosto klíčová, a to již jen proto, že kromě několika
primitivních datových typů je v tomto jazyce úplně vše
objektem. I když objekty můžeme do nějaké míry používat jen
intuitivně, frameworky třetích stran jako Angular nebo React
po nás budou vyžadovat hlubší porozumění této
problematice. A ovládání těchto frameworků zas budou vyžadovat
vaši zaměstnavatelé nebo složitost vašich vlastních projektů Vyvíjet vážnější projekt bez
objektů je pracnější, náročnější a výsledek bude vždy
nekvalitní.
Objektově orientované programování (dále jen OOP) nevzniklo náhodou, ale je důsledkem vývoje, který k němu směřoval. Jedná se o moderní metodiku vývoje softwaru, kterou podporuje většina programovacích jazyků. Častou chybou je, že se lidé domnívají, že OOP se využívá pouze při psaní určitého druhu programů a jinak je na škodu. Opak je pravdou - OOP je filozofie, je to nový pohled na funkci programu a komunikaci mezi jeho jednotlivými částmi. Mělo by se používat vždy, ať už děláme malou utilitku nebo složitý databázový systém. OOP není jen technika nebo nějaká doporučená struktura programu, je to hlavně nový způsob myšlení, nový náhled na problémy a nová éra ve vývoji softwaru.
Abychom porozuměli výhodám, které nám OOP přináší, podíváme se krátce do historie na to, jak se programovalo dříve.
Evoluce metodik
Mezi tím, jak se programovalo před 40 lety a jak se programuje dnes, je velký rozdíl. První počítače neoplývaly velkým výkonem a i jejich software nebyl nijak složitý. Vývoj hardwaru je však natolik rychlý, že se počet tranzistorů v mikroprocesorech každý rok zdvojnásobí (Moorův zákon). Bohužel, lidé se nedokáží rozvíjet tak rychle, jako se rozvíjí hardware. Stále rychlejší počítače vyžadují stále složitější a složitější software (respektive lidé toho chtějí po počítačích stále více a více). Když se v jedné chvíli zjistilo, že okolo 90 % softwaru je vytvořeno se zpožděním, s dodatečnými náklady nebo selhalo úplně, hledaly se nové cesty, jak programy psát. Vystřídalo se tak několik přístupů, přesněji se jim říká paradigma (chápejme jako směr myšlení). My si je zde popíšeme.
Strojový kód
Program byl jen souborem instrukcí, kde jsme neměli žádnou možnost pojmenovávat proměnné nebo zadávat matematické výrazy. Zdrojový kód byl samozřejmě specifický pro daný hardware (procesor). Toto paradigma bylo brzy nahrazeno.
Program sčítající dvě čísla (83 a -2) by vypadal například takto:
2104 1105 3106 7001 0053 FFFE 0000
Jak vidíme, programovat ve strojovém kódu určitě není to pravé a i taková banalita má mnoho řádků.
Nestrukturované paradigma
Nestrukturovaný přístup je podobný assemblerům (ASM), jedná se o soubor
instrukcí, který se vykonává odshora dolů. Zdrojový kód již nebyl
závislý na hardwaru a byl lépe čitelný pro člověka. Tento přístup na
nějakou dobu umožnil vytvářet komplexnější programy. Bylo tu však stále
mnoho úskalí. Jediná možnost, jak udělat něco vícekrát nebo jak se v
kódu větvit, byl příkaz GOTO
. GOTO
nám
umožňovalo "skákat" na jednotlivá místa v programu. Místa byla dříve
specifikována číslem řádku zdrojového kódu, což je samozřejmě
nepraktické. Když do kódu vložíme nový řádek, čísla přestanou
souhlasit a celý kód je rozbitý. Později vznikla možnost definovat
takzvané "návěstí". Takto se obcházela například absence cyklů.
Takovýto způsob psaní programů je samozřejmě velice nepřehledný a brzy
přestal postačovat pro vývoj složitějších programů.
Náš příklad by vypadal v ASM takto:
ORG 100 LDA A ADD B STA C HLT DEC 83 DEC –2 DEC 0 END
Uvědomme si, že obrovské rozšíření počítačů za posledních několik dekád má na svědomí růst poptávky po softwaru a logicky také růst poptávky po programátorech. Jistě existují lidé, kteří dokáží bez chyby psát programy v ASM nebo jiných nízkých jazycích, ale kolik jich je? A kolik si asi za takovou nadlidskou práci účtují? Je potřeba tvořit programy tak, aby i méně zkušení programátoři dokázali psát kvalitní programy a nepotřebovali k tvorbě jednoduché utilitky 5 let praxe.
Strukturované programování
Strukturované programování je první paradigma, které se udrželo delší dobu a opravdu chvíli postačovalo pro vývoj nových programů. Programujeme pomocí cyklů a větvení. To je v podstatě to, kam jsme se doteď dostali.
Skript lze rozložit do samostatných funkcí, to jsme se naučili a dostatečně procvičili na mnoha příkladech. U strukturovaného programování hovoříme o takzvané funkcionální dekompozici. Problém se rozloží na několik podproblémů a každý podproblém potom řeší určitá funkce s parametry.
Nevýhodou je, že funkce umí jen jednu činnost, když chceme něco jiného, musíme napsat novou. Neexistuje totiž způsob, jak vzít starý kód a jen trochu ho modifikovat, musíme psát znovu a znovu - vznikají zbytečné náklady a chyby. Tuto nevýhodu lze částečně obejít pomocí parametrizace funkcí (počet parametrů poté ale rychle narůstá) nebo použitím globálních proměnných. S globálními daty vzniká však nové nebezpečí - funkce mají přístup k datům ostatních. To je začátek konce, nikdy totiž neuhlídáme, aby někde nedošlo k přepsání globálních dat mezi funkcemi a začne docházet k nekontrolovatelným problémům. Celý program se potom skládá z nezapouzdřených bloků kódu a špatně se udržuje. Každá úprava programu zvyšuje složitost, program potom nutně dojde do stavu, kdy náklady na přidávání nových funkcí vzrostou na tolik, že se program již nevyplatí rozšiřovat. Zástupci tohoto přístupu jsou například jazyky C a Pascal.
Náš příklad by vypadal takto:
function secti(a, b) { return a + b; } let c = secti(83, -2); document.write(c);
U JavaScriptu nám sice občas projde napsat krátký skript neobjektově, pokud se ovšem začne rozšiřovat nebo dokonce rovnou plánujeme vytvořit něco většího, bez objektů bychom nutně dospěli do stavu, kdy program nebude možné dál rozšiřovat a budeme ho buď muset zahodit nebo celý přepsat pomocí OOP.
Neobjektovým metodám psaní kódu se přezdívá "spaghetti code" pro jejich nepřehlednost (protože špagety jsou zamotané).
Objektově orientovaný přístup
Jedná se o filozofii a způsob myšlení, designu a implementace, kde klademe důraz na znovupoužitelnost. Přístup nalézá inspiraci v průmyslové revoluci - vynález základních komponent, které budeme dále využívat (například, když stavíme dům, nebudeme si pálit cihly a soustružit šroubky, prostě je již máme hotové).
Poskládání programu z komponent je výhodnější a levnější. Můžeme
mu věřit, je otestovaný (o komponentách se ví, že fungují, jsou
otestovány a udržovány). Pokud je někde chyba, stačí ji opravit na
jednom místě. Jsme motivováni k psaní kódu přehledně a dobře,
protože ho po nás používají druzí nebo my sami v dalších projektech
(přiznejme si, že člověk je od přírody líný a kdyby nevěděl, že se
jeho kód bude znovu využívat, nesnažil by se ho psát kvalitně ).
Znalosti, které jsme se doteď naučili, samozřejmě budeme používat dál. Náš kód budeme pouze jinak strukturovat a to do komunikujících objektů.
Ještě si jen pro ilustraci ukažme opět náš příklad, tentokrát v
objektech. Funkce secti()
již nebude někde volně poletovat, ale
bude patřit objektu Scitacka
, který je jednou z komponent naší
aplikace:
'use strict'; class Scitacka { secti(a, b) { return a + b; } } const scitacka = new Scitacka(); let c = scitacka.secti(83, -2); document.write(c);
Kód nám zatím asi nic moc neříká, což vůbec nevadí
V příští lekci, První objektová aplikace v JavaScriptu, si vytvoříme první objektovou aplikaci