1. Obecně o programování Cíl látky V tomto bloku bude věnována pozornost základnímu pojmu co je to vlastně programování. Budou vysvětleny jaké činnosti jsou potřebné a jak by měly být řazeny, aby vznikl požadovaný software. K tomu aby pojem programování bylo možné lépe chápat, jsou v tomto bloku uvedeny programovací paridigmata tak, jak historicky vznikala. V závěru bloku je podrobněji řečeno jak se a kdo se hlavně podílel na vzniku objektové orientace.
1.1. Co je to programování Slovo „programování“ se používá různých významech. Programují se různé přístroje jako například rekodéry videa, topení, klimatizace apod. V my se budeme dále věnovat „programování aplikací pro samočinné počítače“. Při „programování“ bychom se neměli soustřeďovat pouze tvorbu zdrojových kódu v konkrétních programovacích jazycích ale vývoj by měl procházet postupně několika specializovanými činnostmi: 1. sběrem požadavků na systém 2. analýzou problému 3. návrhem řešení 4. implementací 5. ověřením Všech těchto pět základních činností vývoje softwaru je dobré několikrát zopakovat. Tedy vyvíjet software iterativně a v každé iteraci realizovat jen část požadovaných funkcí. Cílem tohoto postupu je co nejdříve testovat vykonavatelný kód, tak aby včas odhalily chyby nebo různá nedorozumění. Mluvíme zde o „programu“ a o „softwaru“. Pod pojmem „program“ můžeme opravdu myslet jenom vykonavatelný kód, který je výsledkem překladu a sestavení, a někdy možná i zdrojové kódy. Zatímco do pojmu „software“ zahrnujeme vše co tvoří program a dále veškerou další dokumentaci. Všechny tyto věci zahrnujeme pod společný pojem „artefakty“. Artefakty se, i při tvorbě softwaru, opravdu rozumí to, že se jedná produkty vytvořené člověkem. Tyto artefakty produkované v projektech s vývojem softwaru mohou mít různé podoby a formy: • textové dokumenty s požadavky, s popisy případů užití , s testovacími předpisy, ... • analytické a návrhové modely • vykonavatelné kódy aplikací a automatizovaných testů • dokumentace ke zdrojovým kódům • různé skripty na řízení překladu, sestavení nebo testů • uživatelské příručky 1
1.1.1. Sběr požadavků Prvotní věcí v projektu s vývojem softwaru je shromáždění požadavků na chování budoucí aplikace a na omezení, která se musí respektovat. Požadavky lze rozdělit do dvou základních kategorii Funkční požadavky
Specifikují to co se od systému očekává.
Nefunkční požadavky
Specifikují různá omezen, jako jsou například pro jaký operační systém bude aplikace určena, jaký typ databáze má využívat. Zatímco výkonnostní parametry mohou definovat například počet transakcí za určitou dobu, doby odezev, množství uschovaných dat.
Podcenění významu požadavků je podle statistik nejčastější příčinou neúspěchu projektů s vývojem softwaru. Velmi cenným zdrojem informací o funkcích budoucího softwarového systému jsou případy užití, které rozvíjejí funkční požadavky. Při jejich sestavování se řídíme pouze pohledem budoucích uživatelů co budou ze systémem dělat. Přitom se naprosto nepřihlíží tomu, jak ten software bude realizován. Případy užití a jejich specifikace slouží po celou dobu vývoje softwaru pro návrháře, kodéry a testery. Nesmí se též zapomenout, že tyto informace mohou posloužit velmi účinně při tvorbě uživatelských příruček. Pokud nejsou požadavky a případy užití v projektu s vývojem softwaru k dispozici, je takový projekt charakterizován velkou zmatečností, neustálým předěláváním, nedodržování termínů a mnohdy i překročení nákladů.
1.1.2. Analýza Cílem analýzy je pochopit na nejvyšší úrovni abstrakce co se od systému očekává a jak logicky by měl pracovat. Tedy jaké jsou hlavní funkce tohoto systému a jaké jsou vztahy mezi nalezenými „reálnými“ objekty. Analýza se sestavuje vždy v jazyku dané problémové oblasti. To znamená v pojmech, které používá zadavatel a budoucí uživatelé vyvíjeného systému. Je nutné se vyvarovat pojmům z oblasti programovacích jazyků, softwarových technologií apod. Důvodem je to, že se v této fázi je nutné se domluvit se zadavateli. Měl by zároveň vzniknout překladový slovník mezi „světem“ zadavatelů a vývojářů. Výsledky analýzy je dobré zpracovávat pomocí vhodného modelovacího jazyka v podobě modelu. Jako nejlepším modelovacím jazykem, který se již stal všeobecně známým standardem, je Unified Modeling Language (UML). I k analýze lze přistupovat objektově, kdy významným pomocníkem je právě UML. Po objektové analýze může následovat kromě přirozeného objektového návrhu i neobjektový návrh. To záleží na omezeních daného projektu, například tehdy, když se požaduje naprogramování v neobjektovém programovacím jazyku. 2
1.1.3. Návrh Při návrhu se návrháři zaměřují na základní architektonické principy jak bude daný software realizován. Zde se již používají pojmy z programátorského prostředí a použitých technologií. Zde dochází ke konvertování jedné analytické tříd i do několika návrhových tříd, které již mohou mít „technologické“ názvy tříd, metod i atributů. Návrhové třídy se vyznačují tedy daleko menší úrovní abstrakce než analytické třídy. I návrhové třídy je dobré modelovat pomocí UML a výsledek ukládat pomocí vhodného nástroje do modelu. Nástroje jsou známy většinou pod zkratkou CASE. CASE nástroje většinou jsou schopny pokrýt celý životní cyklus vývoje softwaru. Tj. od zachycení požadavků, případů užití, analytických a návrhových tříd.Dále dokáží převést model tříd do koster vzdrojových v různých programovacích jazycích nebo i obrácený postup tj., že zdrojových kódů vytvořit zpětně model tříd.
1.1.4. Implementace Implementací se rozumí samotné vytváření zdrojových kódů. Co se týče objemu prací je tato činnost nejrozsáhlejší. Z toho vyplývájí tyto závěry: 1. Každé nepochopení skutečných požadavků zadavatele může později znamenat značné přepracování zdrojových kódů. 2. Tím ovšem dojde ke ztrátě vynaložené práce, zvýšení nákladů a nevratnou ztrátu času.
1.1.5. Ověření Ověřováním se zjišťuje shoda mezi požadavky a výsledným produktem. Ověřování lze rozdělit na dvě části: • na přezkoumání • na testování
Přezkoumání Přezkoumání je metoda jak ověřit takové artefakty, které nelze automaticky zkontrolovat. Jsou to většinou textové dokumenty. Takové dokumenty musí vždy překontrolovat člověk.
Testování Testováním rozumíme dokumentované porovnání chování již hotových aplikací proti požadavkům. Testování se již může provádět pomocí různých nástrojů nebo člověkem, ale vždy musí být tento proces dokumentován. Dokumentováním v testování se rozumí, že je podle požadavků připraven testovací postup, který se provede s testovanou aplikací. Výsledek testování se zase musí dokumentovat v podobě zprávy nebo protokolu. 3
K podpoře testování je k dispozici řada různých nástrojů a informačních databází. Problematice testování je věnováno samostatné téma 3.
1.2. Programovací paradigmata Trocha historie nikoho nezabije Přehled programovacích paradigmat je zde uveden z důvodu ujasnění si, jak postupně se měnily názory jak programovat. Většina informací je ze
Důležitá pasáž Obecně paradigma je určitá množina vzorů, vztahů či vzorců myšlení. Programovací paradigma je • výchozí imaginární schematizace úloh, soubor náhledů na obor informační/výpočetní problematiky • soubor přístupů k řešení specifických úloh daného oboru • soustava pravidel, standardů a požadavků na programovací jazyky Jednotlivá paradigmata mohou zřetelně ulehčit práci v rámci svého určení a komplikovat nebo úplně odsunout "neohniskové" úlohy do zcela "nekompatibilních" dimenzí (například některé jazyky nelze použít k výpočtům nebo jiné zase k interakci s uživatelem). Zdroj: http://cs.wikipedia.org/wiki/Paradigma
1.2.1. Naivní paradigma Naivní paradigma bývá někdy chápáno jako samostatné paradigma a ještě častěji se mezi paradigmaty programování ani neuvádí. Naivní způsoby programování se vyznačují jakousi všudypřítomnou chaotičností, mají obvykle nesystematickou syntaxi i sémantiku. V některých rysech tento přístup mají podobné vlastnosti jako nestrukturované jazyky. Typickým zástupcem je například jazyk BASIC.
1.2.2. Sekvenční paradigma Sekvenční programovaní byl jeden z prvních stylů programování. Jeho základním principem bylo sekvenční (sériové) řazení příkazů. Přechod v sekvenci příkazů byl měněn pomocí příkazu GOTO, který umožňoval přejít na jakýkoliv příkaz, který byl opatřen tzv., návěštím nebo dokonce se dalo přejít na jakoukoliv adresu v operační paměti. Tento styl programování vyplynul z instrukcí strojového kódu, jako jsou instrukce nepodmíněných a podmíněných skoků. Sekvenční programování využívaly tyto programovací jazyky: • asemblery • BASIC
4
• FORTRAN Sekvenční styl se vyznačuje nepřehledným a nečitelným zápisem u rozsáhlých programů, protože volnost programátora není téměř ničím omezena a tyto programovací jazyky obsahují velmi často pouze primitivní konstrukce. V současné době se tyto jazyky používají minimálně. Assemblery nejčastěji k programování jednočipových mikroprocesorů. FORTRAN přežívá v programování matematických úloh. Klasický BASIC se výrazně proměnil ve Visual Basic s objektovou vestavbou. Zdroje: • Strojový kód [http://cs.wikipedia.org/wiki/Strojový_kód] • Jazyky symbolických adres tzv. assemblery [http://cs.wikipedia.org/wiki/ Jazyk_symbolických_adres] • BASIC [http://cs.wikipedia.org/wiki/BASIC] • FORTRAN [http://cs.wikipedia.org/wiki/FORTRAN]
1.2.3. Strukturované paradigma Strukturované programování nebo též procedurální programování vychází z předchozího sekvenčního stylu, kdy přebírá sekvenční řazení a odstraňuje nadměrné používání příkazů typu GOTO. Novým prvkem je, že sekvenci příkazů vkládá do nových jazykových konstrukcí tzv. struktur. Základní strukturu tvoří blok, který obsahuje sekvenci příkazů. Tyto bloky lze do sebe vnořovat, opakovat nebo volit. Kromě toho, že sekvence instrukcí lze různě strukturalizovat, lze strukturalizovat i data do různorodých tvarů (záznamů). Jakoukoliv strukturu lze graficky vyjádřit stromem. Tím se programy přibližují některým situacím v reálném životě. Ovšem ne všechny situace v reálném životě lze takto řešit pouze rozpadem do strukturálního rozkladu. Graficky lze programové struktury zobrazit pomocí struktogramů. Příkladem může být Nassi-Shneiderman-Diagramm [http://de.wikipedia.org/wiki/NassiShneiderman-Diagramm]. Existuje i česká varianta, tzv. KoPeNoGramy autorů Kofránek, Pecinovký, Novak, která vznikla v 80 letech. Příklady těchto kopenogramu lze nalézt například na stránkách věnovaných programovacímu jazyku Karel [http://pckarel.sweb.cz/pckarel.html] Zdrojové kódy v tomto stylu jsou daleko čitelnější, protože zavádějí abstraktní úrovně, což je velmi blízké k lidskému myšlení. Jazyky obsahují již složitější příkazy, takže programátor se nemusí zabývat detailními konstrukcemi tak, jak to bylo o jazyků se sekvenčním stylem. Samozřejmě z toho vyplývá, že programátor je již více omezen, ale ziskem je bezpečnější a srozumitelnější zdrojový kód. Typickými jazyky pro strukturalizované programování jsou • historicky jeden z prvních byl ALGOL [http://cs.wikipedia.org/wiki/ ALGOL] • Pascal Pascal [http://cs.wikipedia.org/wiki/Pascal_%28programovac %C3%AD_jazyk%29] 5
• jazyk C [http://cs.wikipedia.org/wiki/C_%28programovac %C3%AD_jazyk%29]
1.2.4. Objektové paradigma Objektové paradigma se nejvíce přibližuje k principům reálného světa, protože umožňuje vytvářet vztahy mezi libovolný objekty, které tvoří síť vzájemně komunikujících objektů. Vlastnosti: • • • •
základním stavebním prvkem je objekt každý objekt má stav a chování objekty mezi sebou komunikují prostřednictvím zpráv grafické vyjádření vztahů mezi objekty je síť
Přejímá vše ze strukturálního programování pro implementaci těla metod. Objektové paradigma je hlavním tématem předmětu IOOP, proto je v této kapitole uvedena pouze tato stručná charakteristika. Podrobnější informace o tomto paradigmatu budou uvedeny v dalších kapitolách. Čistě objektové programovací jazyky: • Smalltalk [http://cs.wikipedia.org/wiki/Smalltalk] • Ruby [http://cs.wikipedia.org/wiki/Ruby_%28programovac %C3%AD_jazyk%29] Hybridní jazyky Java C++ • Java [http://cs.wikipedia.org/wiki/Java_%28programovac %C3%AD_jazyk%29] • C++ [http://cs.wikipedia.org/wiki/Java_%28programovac %C3%AD_jazyk%29] • C Sharp [http://cs.wikipedia.org/wiki/C_Sharp]
1.2.5. Další programátorské styly nebo přístupy V této kapitole jsou uvedeny další programátorské
Imperativní programování Imperativní programování je jedno z programovacích paradigmat, neboli způsobů, jak jsou v programovacím jazyku formulována řešení problémů. Imperativní programování popisuje výpočet pomocí posloupnosti příkazů a určuje přesný postup (algoritmus), jak danou úlohu řešit. Program je sadou proměnných, jež v závislosti na vyhodnocení podmínek mění pomocí příkazů svůj stav. Základní metodou imperativního programování je procedurální programování, tyto termíny bývají proto často zaměňovány. 6
Zdroj: http://cs.wikipedia.org/wiki/Imperativní_programování
Deklarativní programování Deklarativní programování je založeno na myšlence programování aplikací pomocí definic co se má udělat a ne jak se to má udělat. Opakem tohoto principu je imperativní programování popisující jednotlivé úkony pomocí algoritmů. Zjednodušeně to lze popsat tak, že imperativní programy obsahují algoritmy, kterými se dosáhne chtěný cíl, zatímco deklarativní jazyky specifikují cíl a algoritmizace je ponechána programu (interpretu) daného jazyka. Zdroj: http://cs.wikipedia.org/wiki/Deklarativní_programování
Funkcionální programování Funkcionální programování patří mezi deklarativní programovací principy. Alonzo Church [http://cs.wikipedia.org/wiki/Alonzo_Church] vytvořil formální výpočtový model nazvaný Lambda kalkul [http://cs.wikipedia.org/wiki/Lambda_kalkul]. Church pak společně s Turingem ukázal, že lambda kalkul (a další výpočetní modely) má výpočetní sílu Turingova stroje, což otevřelo cestu k ChurchovaTuringova teze [http://cs.wikipedia.org/wiki/Churchova-Turingova_teze]. Výpočtem funkcionálního programu je posloupnost vzájemně ekvivalentních výrazů, které se postupně zjednodušují. Výsledkem výpočtu je výraz v normální formě, tedy dále nezjednodušitelný. Program je chápán jako jedna funkce obsahující vstupní parametry mající jediný výstup. Tato funkce pak může být dále rozložitelná na podfunkce. Programovací jazyk C Sharp již lamda kalkul obsahuje a pro programovací jazyk Java bude doplněn ve verzi 8.
Stavové programování Při stavovém programování je systém naprogramován tak, aby podle potřeb a vnějších požadavků přecházel mezí různými stavy. V každém stavu potom systém nabízí odpovídající funkce
Událostmi řízené programování Při událostmi řízeném programování je systém neustále v podstatě v témže stavu tj. v čekání na následující událost. Jakmile se systém dočká události, obslouží ji odpovídajícím způsobem, a opět čeká na další.
1.3. Jak vznikala objektová orientace Historie objektové orientovaného softwarového inženýrství rekapituluje historii tradičního softwarového inženýrství. Trvalo desítky let než se zformovaly procedurální a databázové konstrukce. U objektového programování se to podařilo v rámci několika let. Vývoj softwaru počal prostě programováním. Jak rostla velikost softwarových produktů, tak si začali lidé kolem vývoje softwaru uvědomovat, že nelze jen tak pouze zapisovat programový kód. 7
Kdo se hlavně podílel na vzniku objektově orientovaného programování? Byli to především: • Ole-Johan Dahl [http://en.wikipedia.org/wiki/Ole-Johan_Dahl] • Kristen Nygaard [http://en.wikipedia.org/wiki/Kristen_Nygaard] • Alan Kay [http://en.wikipedia.org/wiki/Alan_Kay] cs.wikipedia.org/wiki/Alan_Kay])
(CZ
[http://
• Adele Goldberg [http://en.wikipedia.org/wiki/Adele_Goldberg_ %28computer_scientist%29] • Barbara Liskov [http://en.wikipedia.org/wiki/Barbara_Liskov] Liskov Substitution Principle Liskov_substitution_principle]
(LSP)
[http://en.wikipedia.org/wiki/
• David Parnas [http://en.wikipedia.org/wiki/David_Parnas] I would advise students to pay more attention to the fundamental ideas rather than the latest technology. The technology will be outof-date before they graduate. Fundamental ideas never get out of date. However, what worries me about what I just said is that some people would think of Turing machines and Goedel's theorem as fundamentals. I think those things are fundamental but they are also nearly irrelevant. I think there are fundamental design principles, for example structured programming principles, the good ideas in "Object Oriented" programming, etc. (viz) [http://faculty.indwes.edu/ bcupp/lookback/SoftwareEngineering/DavidParnas.Poster.htm] • Jean Ichbiah [http://en.wikipedia.org/wiki/Jean_Ichbiah] • Bjarne Stroustrup [http://en.wikipedia.org/wiki/Bjarne_Stroustrup] C++ Další odkazy • Object-oriented programming oriented_programming]
[http://en.wikipedia.org/wiki/Object-
• Turingova_cena [http://cs.wikipedia.org/wiki/Turingova_cena] Historie objektové orientace převzato a zjednodušeno z knihy Základy objektově orientovaného návrhu v UML.
1.4. Vlastnosti objektů reálného světa Než bude popsána samotná objektová orientace, je vhodné si připomenout, že se pohybujeme ve světě reálných objektů, které • mají řadu nejrůznějších atributů, jejichž obsah a počet vzájemně objetky od sebe odlišují • mnohé atributy jsou pro mnoho objektů společné, jako například barva, hmotnost • některé atributy jsou pro daný objekt stálé (například hmotnost), jiné lze měnit (například jméno) 8
• mnoho atributů může být reprezentováno jinými objekty (dům má okna, okna mají rámy, rámy mají skla), jeden objekt je složen z mnoha dalších a dohromady tvoří jeden celek • existují takové atributy, které odkazují na jiné objekty, přičemž mezi nimi je rovnoprávný vztah • objekty lze rozdělit do skupin stejného druhu • mezi objekty existuje přirozená hierarchie • objekty nejsou pasivními nositeli atributů, ale dokáží i aktivně reagovat na akce okolního světa, který je reprezentován zase jenom objekty.
9