IT rekvalifikácia. Seniorní programátori zarábajú až 6 000 €/mesiac a rekvalifikácia je prvým krokom. Zisti, ako na to!

1. diel - Úvod do objektovo orientovaného programovania v Pythone

Vitajte pri prvom tutoriále kurzu objektovo orientovaného programovania v Pythone. Kurz Základná konštrukcia jazyka Python už máme za sebou, minule sme ho dokončili dielom Matematické funkcie v Pythone a knižnica math. V tomto kurze sa naučíme objektovo programovať a hlavne objektovo myslieť. Je to niečo trochu iné, než sme robili doteraz a samotný program už nebudeme chápať ako niekoľko riadkov príkazov, ktoré interpret vykonáva zhora nadol.

Objektovo orientované programovanie (ďalej len OOP) nevzniklo náhodou, ale je dôsledkom vývoja, ktorý k nemu smeroval. Ide o modernú metodiku vývoja softvéru, ktorú podporuje väčšina programovacích jazykov. Častou chybou je, že sa ľudia domnievajú, že OOP sa využíva iba pri písaní určitého druhu programov a inak je na škodu. Opak je pravdou - OOP je filozofia, je to nový pohľad na funkciu programu a komunikáciu medzi jeho jednotlivými časťami. Malo by sa používať vždy, či už robíme malú utilitku alebo zložitý databázový systém. OOP nie je len technika alebo nejaká odporúčaná štruktúra programu, je to hlavne nový spôsob myslenia, nový náhľad na problémy a nová éra vo vývoji softvéru.

Najprv sa pozrieme do histórie, ako sa programovalo skôr a aké konkrétne problémy OOP riešia. Je to totiž dôležité na pochopenie, prečo OOP vzniklo.

Evolúcia metodík

Je veľký rozdiel medzi tým, ako sa programovalo pred 40 rokmi a ako sa programuje dnes. Prvé počítače neoplývali veľkým výkonom a aj ich softvér nebol nijako zložitý. Vývoj hardvéru je však natoľko rýchly, že sa počet tranzistorov v mikroprocesoroch každý rok zdvojnásobí (Moorov zákon). Bohužiaľ sa ľudia nedokážu rozvíjať tak rýchlo ako hardvér. Stále rýchlejšie počítače vyžadujú stále zložitejší a zložitejší softvér (resp. ľudia toho chcú po počítačoch stále viac a viac). Keď sa v jednej chvíli zistilo, že okolo 90 % softvéru je vytvorených s oneskorením, s dodatočnými nákladmi alebo zlyhalo úplne, hľadali sa nové cesty, ako programy písať. Vystriedalo sa tak niekoľko prístupov, presnejšie sa im hovorí paradigmy (chápajme ako smery myslenia). Poďme si ich popísať.

1. Strojový kód

Program v strojovom kóde bol len súborom inštrukcií, kde sme nemali žiadnu možnosť pomenovávať premenné alebo zadávať matematické výrazy. Zdrojový kód bol samozrejme špecifický pre daný hardvér (procesor). Táto paradigma bola čoskoro nahradená.

2. Neštruktúrovaná paradigma

Neštruktúrovaný prístup je podobný assemblerom, jedná sa o súbor inštrukcií, ktorý sa vykonáva zhora nadol. Zdrojový kód už nebol závislý od hardvéru a bol lepšie čitateľný pre človeka, prístup na nejaký čas umožnil vytvárať komplexnejšie programy. Bolo tu však stále veľa úskalí: Jediná možnosť, ako urobiť niečo viackrát alebo ako sa v kóde vetviť, bol príkaz GOTO. Príkaz GOTO nám umožňoval "skákať" na jednotlivé miesta v programe. Miesta boli predtým špecifikované číslom riadku zdrojového kódu, čo je samozrejme nepraktické. Keď do kódu vložíme nový riadok, čísla prestanú súhlasiť a celý kód je rozbitý. Neskôr vznikla možnosť definovať tzv. „návestia“. Takto sa obchádzala napr. absencia cyklov. Takýto spôsob písania programov je samozrejme veľmi neprehľadný a čoskoro prestal postačovať na vývoj zložitejších programov.

Obrovské rozšírenie počítačov za posledných niekoľko dekád má na svedomí rast dopytu po softvéri a logicky aj rast dopytu po programátoroch. Iste existujú ľudia, ktorí dokážu bez chyby písať programy v ASM alebo iných nízkych jazykoch, ale koľko ich je? A koľko si asi za takú nadľudskú prácu účtujú? Je potrebné písať programy tak, aby aj menej skúsení programátori dokázali písať kvalitné programy a nepotrebovali na tvorbu jednoduchej utilitky päť rokov praxe.

3. Štruktúrované programovanie

Štruktúrované programovanie je prvou paradigmou, ktorá sa udržala dlhšiu dobu a naozaj chvíľu postačovala na vývoj nových programov. Programujeme v ňom pomocou cyklov a vetvenia. To je v podstate to, kam sme sa doteraz dostali.

Program je možné rozložiť do funkcií, ako sme si už ukázali v lekcii Funkcie a výnimky v Pythone. Pri štruktúrovanom programovaní hovoríme o tzv. funkcionálnej dekompozícii. Problém sa rozloží na niekoľko problémov a každý problém potom rieši určitá funkcia s parametrami. Nevýhodou je, že funkcia vie len jednu činnosť. Keď chceme niečo iné, musíme napísať novú. Neexistuje totiž spôsob, ako zobrať starý kód a len trochu ho modifikovať. Musíme písať znova a znova a tým vznikajú zbytočné náklady a chyby. Túto nevýhodu je možné čiastočne obísť pomocou parametrizácie funkcií (počet parametrov potom ale rýchlo narastá) alebo použitím globálnych premenných. S globálnymi dátami však vzniká nové nebezpečenstvo – funkcie majú prístup k dátam ostatných. To je začiatok konca. Nikdy totiž neustrážime, aby niekde nedošlo k prepísaniu globálnych dát medzi funkciami. Tým začne dochádzať k nekontrolovateľným problémom. Celý program sa potom skladá z nezapuzdrených blokov kódu a zle sa udržuje. Každá úprava programu zvyšuje zložitosť a program potom nutne dôjde do stavu, keď náklady na pridávanie nových funkcií vzrastú na toľko, že sa ho už neoplatí rozširovať. Zástupcovia tohto prístupu sú napríklad jazyky C a Pascal.

Medzi štruktúrovaným programovaním a objektovo orientovaným programovaním existoval ešte medzičlánok, tzv. modulárne programovanie, ktoré nám umožňuje zapuzdriť určitú funkcionalitu do modulov. Stále však neexistuje spôsob, ako už napísaný kód modifikovať a znova využiť.

Niekedy sa uvádza, že sa jednoduché programy majú písať neobjektovo, teda štruktúrovane. Nie je to však pravda. Keď zabudneme na fakt, že porušujeme filozofiu OOP ako takú, nikdy nemôžeme vedieť, či sa tento program neuchytí az malej utilitky sa nestane niečo vážnejšie. Potom opäť nutne dospejeme do stavu, kedy program nebude možné ďalej rozširovať. Budeme ho buď musieť zahodiť alebo celý prepísať s pomocou OOP.

Neobjektovým metódam písania kódu sa pre ich neprehľadnosť prezýva spaghetti code (pretože špagety sú zamotané).

Objektovo orientovaný prístup

Jedná sa o filozofiu a spôsob myslenia, dizajnu a implementácie, kde kladieme dôraz na znovupoužiteľnos­ť. Prístup nachádza inšpiráciu v priemyselnej revolúcii. Konkrétne vo vynáleze základných komponentov, ktoré je možné ďalej využívať (napr. keď staviame dom, nebudeme si páliť tehly a sústružiť skrutky, jednoducho ich už máme hotové).

Poskladanie programu z komponentov je výhodnejšie a lacnejšie. Môžeme mu veriť, je otestovaný (o komponentoch sa vie, že fungujú, sú otestované a udržiavané). Ak je niekde chyba, stačí ju opraviť na jednom mieste. Sme motivovaní k písaniu kódu prehľadne a dobre, pretože ho po nás používajú druhí alebo my sami v ďalších projektoch. Priznajme si, že človek je od prírody lenivý a keby nevedel, že sa jeho kód bude znovu využívať, nesnažil by sa ho písať kvalitne:)

Znalosti, ktoré sme sa doteraz naučili, samozrejme budeme používať ďalej. Náš kód budeme iba inak štruktúrovať a to do komunikujúcich objektov.

Ako OOP funguje

V tejto paradigme sa snažíme nasimulovať realitu tak, ako ju sme zvyknutí vnímať. Môžeme teda povedať, že sa odpútavame od toho, ako program vidí počítač (stroj) a píšeme program skôr z pohľadu programátora (človeka). Ako sme kedysi nahradili assembler ľudsky čitateľnými matematickými zápismi, teraz ideme ešte ďalej a nahradíme aj tie. Ide teda o určitú úroveň abstrakcie nad programom. To má značné výhody už iba v tom, že je to pre nás prirodzenejšie a prehľadnejšie.

Základnou jednotkou je objekt, ktorý zodpovedá nejakému objektu z reálneho sveta (napr. objekt človek alebo databáza).

Objekty v objektovo orientovanom programovaní - Objektovo orientované programovanie v Pythone - Objektovo orientované programovanie v Pythone

Každý objekt má svoje atribúty a metódy.

Atribúty

Atribúty objektu sú vlastnosti alebo dáta, ktoré uchováva (napr. u človeka meno a vek, u databázy heslo). Ide o jednoduché premenné, s ktorými sme už stokrát pracovali. Niekedy o nich hovoríme ako o vnútornom stave objektu.

Metódy

Metódy sú schopnosťami, ktoré vedia objekt vykonávať. U človeka by to mohli byť metódy: jdi_do_prace(), pozdrav() alebo mrkni(). Pri databáze potom treba pridej_zaznam() alebo vyhledej(). Metódy môžu mať parametre a môžu tiež vracať nejakú hodnotu. Veľmi dobre ich poznáme, používali sme napr. metódu upper() na objekte str (reťazec). Reťazec je vlastne objekt, ktorý reprezentuje v realite nejaký text. Môžeme si teda jednoducho predstaviť, že rokujeme s reťazcom textu, niečo mu prikazujeme alebo na ňom niečo nastavujeme. Objekt reťazec potom teda obsahuje metódy, ktoré s ním vedia pracovať (nahradzovať jeho časti, prevádzať na veľké písmená a pod.) a má tiež nejaké atribúty, napr. length, ktorý značí jeho dĺžku.

Objekty v objektovo orientovanom programovaní - Objektovo orientované programovanie v Pythone - Objektovo orientované programovanie v Pythone

V starších jazykoch metódy nepatrili objektom, ale voľne sa nachádzali v moduloch. Namiesto text.upper() by sme teda postarom písali upper(text). Nevýhodou bolo samozrejme najmä to, že metóda upper() vtedy nikam nepatrila. Nebol spôsob, akým si vyvolať zoznam toho, čo sa s reťazcom dá robiť av kóde je neporiadok. Navyše sme nemohli mať dve metódy s rovnakým názvom. V OOP ale môžeme mať uzivatel.vymaz() a clanek.vymaz(). To je veľmi prehľadné a jednoduché, zatiaľ čo v štruktúrovanom programe by sme museli písať: vymaz_uzivatele(uzivatel) a vymaz_clanek(clanek). Takýchto hlúpych metód by sme museli mať niekde rozhádzaných tisíce. Ak vám to pripomína jazyk PHP, bohužiaľ máte pravdu. PHP je v tomto naozaj hrozné a to z toho dôvodu, že jeho návrh je starý. Síce sa časom plne preorientovalo na objekty, ale jeho základy sa už nezmenia. Python je našťastie jazyk moderný a plne podporuje objektovo orientovanú paradigmu.

V tomto článku si vysvetlíme len úplné základy, teda ako objekty vytvárať a ako zapuzdriť ich vnútornú logiku. Ďalším funkciám OOP (hovoríme tu najmä o dedičnosti) budú venované až ďalšie lekcie, aby toho nebolo zrazu veľa :)

Trieda

S pojmom trieda sme sa už tiež stretli. Chápali sme ju ako súbor príkazov. Trieda však umožňuje oveľa viac. Trieda je vzor, podľa ktorého sa objekty vytvárajú. Definuje ich vlastnosti a schopnosti.

Objekt, ktorý sa vytvorí podľa triedy, sa nazýva inštancia. Inštancie majú rovnaké rozhranie ako trieda, podľa ktorej sa vytvára, ale navzájom sa líšia svojimi dátami (atribútmi). Majme napríklad triedu Clovek a od nej si vytvorme inštancie karel a josef. Obe inštancie majú určite tie isté metódy a atribúty ako trieda (napr. jmeno a vek) a metódy (jdi_do_prace() a pozdrav()), ale hodnoty v nich sa líšia (prvá inštancia má v atribúte jmeno hodnotu Karel a vo vek 22, druhá Josef a 45).

Objekty v objektovo orientovanom programovaní - Objektovo orientované programovanie v Pythone - Objektovo orientované programovanie v Pythone

Komunikácia medzi objektmi prebieha pomocou odovzdávania správ, vďaka čomu je syntax prehľadná. Správa zvyčajne vyzerá takto: prijemce.nazev_metody(parametry). Napr. karel.pozdrav(sousedka) by mohol spôsobiť, že inštancia karel pozdraví inštanciu sousedka.

OOP stojí na základných troch pilieroch:

  • Zapúzdrenie
  • Dedičnosť
  • Polymorfizmus
Vysvetlime si prvú z nich.

Zapuzdrenie

Zapúzdrenie umožňuje skryť niektoré metódy a atribúty tak, aby zostali použiteľné len pre triedu zvnútra. Objekt si môžeme predstaviť ako čiernu skrinku (anglicky blackbox), ktorá má určité rozhranie (interface), cez ktoré jej odovzdávame inštrukcie/dáta a ona ich spracováva.

Nevieme, ako to vo vnútri funguje, ale vieme, ako sa navonok chová a používa. Nemôžeme teda spôsobiť nejakú chybu, pretože využívame a vidíme len to, čo tvorca triedy sprístupnil.

Príkladom môže byť trieda Clovek, ktorá bude mať atribút datum_narozeni a na jeho základe ďalšie atribúty: plnolety a vek. Keby niekto zvonku zmenil datum_narozeni, prestali by platiť premenné plnolety a vek. Hovoríme, že vnútorný stav objektu by bol nekonzistentný. Toto sa nám v štruktúrovanom programovaní môže pokojne stať. V OOP však objekt zapuzdrime. Atribút datum_narozeni označíme ako privátny a ten tým pádom nebude zvonku viditeľný. Naopak von vystavíme metódu zmen_datum_narozeni(), ktorá dosadí nový dátum narodenia do premennej datum_narozeni a zároveň vykoná potrebný prepočet veku a prehodnotenie plnoletosti. Použitie objektu je bezpečné a aplikácia stabilná.

Zapúzdrenie teda donúti programátorov používať objekt len tým správnym spôsobom. Rozhranie (interface) triedy rozdelí na verejne prístupné (public) a jej vnútornú štruktúru (private).

V nasledujúcej lekcii, Prvá objektová aplikácia v Pythone - Hello object world , si vytvoríme svoj prvý objektový program.


 

Všetky články v sekcii
Objektovo orientované programovanie v Pythone
Preskočiť článok
(neodporúčame)
Prvá objektová aplikácia v Pythone - Hello object world
Článok pre vás napísal gcx11
Avatar
Užívateľské hodnotenie:
7 hlasov
(^_^)
Aktivity