Objektově orientované programování a evoluce vývoje softwaru

Návrhové vzory Objektově orientované programování a evoluce vývoje softwaru

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 filosofie, 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. Nejdříve se podíváme do historie, jak se programovalo dříve a které konkrétní problémy OOP řeší. Je to totiž důležité k tomu, abychom pochopili, proč OOP vzniklo.

Tento článek se zaměřuje přímo na metody psaní kódu a objektově orientované programování, ne na metodiky vývoje softwaru obecně.

Evoluce metodik

Mezi tím, jak se programovalo před 40ti 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. 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 metod, které si zde popíšeme.

1. Imperativní metoda

Tato metoda má blízko strojovému kódu a jediná možnost, jak udělat něco vícekrát, je příkaz GOTO. Ten "skáče" na uvedené místo v programu (náznak cyklu). Této metodě se přezdívá "spaghetti code" pro její nepřehlednost a brzy přestala postačovat pro vývoj složitějších programů.

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 psát 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.

2. Modulární programování

Myšlenka této metody spočívá v rozdělování velkých problémů na více menších. K tomu se používají tzv. subrutiny (podprogramy), které si pamatují, odkud byly zavolány a vrátí se zpátky.

Strukturované programování

Strukturované programování je první metodika, která se udržela delší dobu a opravdu chvíli postačovala pro vývoj nových programů. Program zde postupuje odshora dolů a je využita tzv. funkcionální dekompozice. 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. 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.

Jak již jsem se zmínil na začátku článku, někdy se uvádí, že se jednoduché programy mají psát neobjektově, tedy strukturovaně. Není to však pravda, když opomineme fakt, že porušujeme filozofii OOP jako takovou, nikdy nemůžeme vědět, zda se tento program neuchytí a z malé utilitky se nestane něco vážnějšího. Potom opět nutně dospějeme do stavu, kdy program nebude možné dál rozšiřovat a budeme ho buď muset zahodit nebo celý přepsat s pomocí OOP.

Objektově orientovaný přístup

Jedná se o filozofii a způsob myšlení, designu a implementace, kde klademe důraz na znovupoužitel­nost. Metodika nalézá inspiraci v průmyslové revoluci - vynález základních komponent, které budeme dále využívat (např. 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ě :) ).

Jak OOP funguje

Snažíme se nasimulovat realitu tak, jak ji jsme zvyklí vnímat. Můžeme tedy říci, že se odpoutáváme od toho, jak program vidí počítač (stroj) a píšeme program spíše z pohledu programátora (člověka). Jde tedy o určitou úroveň abstrakce nad programem. To má značné výhody už jen v tom, že je to pro nás přirozenější a přehlednější.

Základní jednotkou je objekt, který odpovídá nějakému objektu z reálného světa (např. objekt člověk). Objekt má své atributy, čímž jsou myšleny vlastnosti neboli data, které uchovává (např. u člověka jméno a věk). Dále má metody, které jsou schopnostmi, které umí vykonávat (u člověka např. jdi_do_prace, pozdrav, mrkni).
Už tedy víme, že:

objekt = náhrada objektu z reality
atribut = vlastnost
metoda = schopnost

Třída

Třída je vzor, podle kterého se objekty vytváří. Definuje jejich vlastnosti a schopnosti.

Objekt, který se vytvoří podle třídy, se nazývá instance. Instance mají stejné rozhraní jako třída, podle které se vytváří, ale navzájem se liší svými daty (atributy). Mějme například třídu člověk a od ní si vytvořme instance Karel a Josef. Obě instance mají jistě ty samé metody a atributy, jako třída (např. jméno a věk) a metody (jdi_do_prace, pozdrav), ale hodnoty v nich se liší (první instance má atribut jméno Karel a věk 22, druhá Josef a 45).

Komunikace mezi objekty probíhá pomocí předávání zpráv, díky čemuž je syntaxe přehledná. Zpráva obvykle vypadá takto: příjemce.jméno_me­tody(parametry). Např. karel.pozdrav(sou­sedka) by mohl způsobit, že instance karel pozdraví instanci sousedka.

OOP stojí na základních třech pilířích:

1. Zapouzdření

Zapouzdření umožňuje skrýt některé metody funkce, aby zůstaly použitelné jen pro třídu zevnitř. Objekt si můžeme představit jako černou skřínku, která má určité rozhraní (interface), přes které jí předáváme instrukce/data a ona je vykonává.

Nevíme, jak to uvnitř funguje, ale víme, co to dělá. Nemůžeme tedy způsobit nějakou chybu, protože využíváme a vidíme jen to, co je zpřístupněno. Například když budeme potřebovat zjistit, zda je objekt auto schopný jízdy, nebudeme např. kontrolovat stav benzínu v nádrži, protože se může stát, že auto bude elektromobil a nádrž mít nebude - došlo by k chybě. Zavoláme metodu je_pojizdne(), která nám vrátí stav auta a nezajímá nás jak to udělá, protože víme, že to udělá dobře. Je totiž napsaná samotným tvůrcem třídy Auto a ten nejlíp ví, jak kontrolu pojízdnosti provést.

Zapouzdření tedy donutí programátory používat modul jen tím správným způsobem. Rozhraní (interface) rozdělí na veřejně přístupné (public) a vnitřní strukturu (private).

2. Dědičnost

Dědičnost je jedna ze základních vlastností OOP a slouží k tvoření nových datových struktur na základě starých. Pokusím se to vysvětlit na jednoduchém příkladu:

Budeme chtít vytvořit objekty programátor a grafik, kde grafik bude umět kreslit a programátor programovat. Bylo by jistě zbytečné a nepřehledné, kdybychom si museli definovat obě třídy úplně celé, protože mnoho vlastností těchto 2 objektů je společných. Programátor i grafik budou mít jistě jméno a věk a budou umět jít do práce a jít spát. Vytvořím tedy třídu člověk, kde definuji atributy vek a jmeno a metody jdi_do_prace a jdi_spat.

Nyní vytvořím třídu programátor, která bude dědit z třídy člověk. Bude mít tedy automaticky ty samé metody a atributy, jako člověk + k ní dopíši metodu programuj. Obdobně to bude s grafikem, který opět dědí z člověka, ale má navíc metodu kresli.

Takto nemusíme opisovat oběma třídám ty samé atributy, ale stačí dopsat to, v čem se liší, a zbytek zdědit. Přínos je obrovský, můžeme rozšiřovat komponenty o nové metody a tím je znovu využívat. Nemusíme psát spousty redundantního (duplikovaného) kódu. A hlavně - když změníme jediný atribut v mateřské třídě, automaticky se tato změna všude podědí. Nedojde tedy k tomu, že bychom to museli měnit ručně u 20ti tříd a někde na to zapomněli a způsobili chybu. Jsme lidé a chybovat budeme vždy, musíme tedy používat takové programátorské postupy, abychom měli možností chybovat co nejméně.

O mateřské třídě se někdy hovoří jako o nadtřídě a o třídě, která z ní dědí, jako o podtřídě. Podtřída může přidávat nové metody nebo si uzpůsobovat metody z mateřské třídy (viz dále).

Někdy se dokonce stává, že si některou třídu vytvoříme jen za účelem, aby z ní dědily ostatní třídy (např. třídu člověk si vytvoříme jen za účelem dědění do tříd grafik a programátor, ale samotný člověk v programu nemá žádnou instanci). Takovýmto třídám se říká abstraktní.

Jazyky, které dědičnost podporují, buď umí dědičnost jednoduchou (třída dědí jen z jedné třídy) nebo vícenásobnou (třída dědí hned z několika tříd najednou, tu podporují jen některé jazyky)

3. Polymorfismus

Polymorfismus umožňuje používat jednotné rozhraní pro práci s různými typy objektů. Mějme například mnoho objektů, které reprezentují nějaké geometrické útvary (kruh, čtverec, trojúhelník). Bylo by jistě přínosné a přehledné, kdybychom s nimi mohli komunikovat jednotně, ačkoli se liší. Kdybychom mohli mít třídu GeometrickyUtvar, která by obsahovala atribut barva a metodu vykresli. Všechny geometrické tvary by potom dědily z této třídy její interface (rozhraní). Ale objekty kruh a čtverec se jistě kreslí jinak. Polymorfismus nám umožňuje přepsat si metody vykresli u každé instance tak, aby dělali, co chceme, ale rozhraní zůstalo zachováno a my nemuseli přemýšlet, jak se to u onoho objektu volá.

Polymorfismus bývá často vysvětlován na obrázku se zvířaty, která mají všechna v rozhraní metodu speak, ale každé si ji vykonává po svém.

Polymorfismus

Na závěr si ukažme, jak může vypadat definice třídy v prog. jazyce (Zde C++)

Dědičnost

class Person {
  String first, mi, last;
  String getName() {
     return first + mi + last;
  }
}

class Doctor: Person {

String getName () {
    return "Dr." + Person::getName();
  }
}

 

  Aktivity (1)

Článek pro vás napsal David Čápka
Avatar
Autor pracuje jako softwarový architekt a pedagog na projektu ITnetwork.cz (a jeho zahraničních verzích). Velmi si váží svobody podnikání v naší zemi a věří, že když se člověk neštítí práce, tak dokáže úplně cokoli.
Unicorn College Autor se informační technologie naučil na Unicorn College - prestižní soukromé vysoké škole IT a ekonomie.

Jak se ti líbí článek?
Celkem (18 hlasů) :
55555


 


Miniatura
Předchozí článek
UML
Miniatura
Všechny články v sekci
Návrhové vzory
Miniatura
Následující článek
MVC architektura

 

 

Komentáře
Zobrazit starší komentáře (8)

Avatar
Kit
Redaktor
Avatar
Kit:

Práce s komplexními čísly je v C# poněkud nepohodlná, totéž platí i pro práci s polem. Pro vědecké výpočty se prostě nehodí.

Odpovědět 21.10.2012 14:35
Vlastnosti objektů by neměly být veřejné. A to ani prostřednictvím getterů/setterů.
Avatar
David Čápka
Tým ITnetwork
Avatar
Odpovídá na Kit
David Čápka:

To ti neberu, už z hlediska návrhu se k tomu nehodí.

Odpovědět  ±0 21.10.2012 14:37
Miluji svou práci a zdejší komunitu, baví mě se rozvíjet, děkuji každému členovi za to, že zde působí.
Avatar
Kit
Redaktor
Avatar
Odpovídá na David Čápka
Kit:

Nerozumím. Co mi nebereš a s čím souhlasíš?

Odpovědět  -1 21.10.2012 14:39
Vlastnosti objektů by neměly být veřejné. A to ani prostřednictvím getterů/setterů.
Avatar
David Čápka
Tým ITnetwork
Avatar
Odpovídá na Kit
David Čápka:

Neberu ti, že se C# na vědecké výpočty nehodí, konec konců je to VM. Pro tyto účely existují lepší nástroje. Jen říkám, že je to univerzální jazyk, jsou tam mraky knihoven a pokud se na matematické výpočty zrovna nespecializuji, určitě bych to občas zkousl (i nějakou tu optimalizaci by jistě VM udělal). Kdybych se na ně specializoval, vyberu jazyk co se k tomu hodí. Je to poměr mezi tím, jak se mi vyplatí učit něco jiného a tím, jak často to budu potřebovat.

Odpovědět  +1 21.10.2012 14:44
Miluji svou práci a zdejší komunitu, baví mě se rozvíjet, děkuji každému členovi za to, že zde působí.
Avatar
Kit
Redaktor
Avatar
Odpovídá na David Čápka
Kit:

Když jsem zrovna hledal, jak se v C# násobí matice, byla to hrůza. Možná na jednoduché věci by se to dalo použít, ale třeba složitější neuronovou síť bych tomu nesvěřil, protože by to bylo děsně pomalé.

Odpovědět  ±0 21.10.2012 14:56
Vlastnosti objektů by neměly být veřejné. A to ani prostřednictvím getterů/setterů.
Avatar

Neregistrovaný
Avatar
:

**

 
Odpovědět 1.8.2013 18:11
Avatar
mkropik
Člen
Avatar
mkropik:

Děkuji za tento článek a jím podobné. Dali mi v pár odstavcích více než některé docela drahé knihy ve kterých je daná problematika na mnohem více stránkách, ale přijde mi, že kolikrát po přečtení pár stránek již nevím co vlastně čtu. Jsem začátečník (věčný :-) ) a někdy to prostě potřebuji vysvětlit "méně vědecky". Konkrétně ABSTRAKCE, pořád jsem si to nějak nemohl představit a autor napsal jednu větu a bylo to tam :-D

 
Odpovědět 2.4.2015 14:41
Avatar
hanpari
Redaktor
Avatar
Odpovídá na mkropik
hanpari:

Abstrakce je neco jineho nez abstraktni trida. Abstrakce je proste zjednoduseni problemu

 
Odpovědět 2.4.2015 14:54
Avatar
Zoltan Lukac
Člen
Avatar
Zoltan Lukac:

David, velmi dobry clanok, kratke, jednoduche, vystizne. Pre mna ako pre uuuuuplne novacika a brutal absolutne zaciatocnika je to velmi prinosne, bez zbytocnych omacok :)

 
Odpovědět 21. března 22:37
Avatar
paja
Člen
Avatar
paja:

Ahoj , pekny clanek , pekne a prehledne popsano... Diky moc

 
Odpovědět 25. března 21:14
Děláme co je v našich silách, aby byly zdejší diskuze co nejkvalitnější. Proto do nich také mohou přispívat pouze registrovaní členové. Pro zapojení do diskuze se přihlas. Pokud ještě nemáš účet, zaregistruj se, je to zdarma.

Zobrazeno 10 zpráv z 18. Zobrazit vše