Hledat
Přihlásit se
  • Věda a technika
  • Herní doupě
  • Tipy pro PC
  • IT Byznys
  • Mobily
  • Počítače
  • Počítače
  • Témata
  • Poradna
  • Diskuzní fórum
  • Video
  • Bazar
  • Blogy
  • MĚŘENÍ RYCHLOSTI
  • RSS
  • Facebook Twitter Google+ YouTube
  • Hardware
  • Software
  • Počítače
  • Notebooky
  • Služby na webu
  • Apple
  • Google
  • Microsoft
  • Seznam
  • Tiskové zprávy
Další témata
  • Týden Živě
  • Zprávy Živě
  • Testy
  • Pitvy
Všechna videa
X

Doporučit článek

Vaše jméno:

Váš e-mail:

E-mail adresáta:

Komentář:

kontrolní kód

Odeslat

Blogy Živě » Principy programování

Principy programování

O tom, jak dobří programátoři uvažují
 

Interface a implementace

14. 9. 2009, ricmat

V následujícím článku se dozvíte, co vyjadřují slova rozhraní (interface) a implementace, tedy dva mezi programátory běžně používané termíny.

 

Interface

Rozhraní (interface) je vlastně něco jako palubní deska v autě. Je to něco, co zajišťuje správné dorozumívání se (ovládání, komunikaci) s autem. Bez volantu bychom nemohli měnit směr jízdy, bez pedálů zase zrychlovat či zpomalovat.
Samozřejmě také další zařízení nám známá z běžného života mají svůj interface. Interfacem k počítači je klávesnice a myš, interfacem k televizi je v dnešní době dálkový ovladač a těch několik tlačítek na televizoru samotném. Rozhraním k elektřině je pak buď zásuvka, nebo dva póly baterie.
Nemusí ale vůbec jít jen o technická zařízení. Interfacem k domu jsou vlastně dveře. Ke skříni nebo k ledničce přistupujeme skrz jejich dveře, k radiátoru nebo zdroji vody pomocí kohoutku. Až donedávna nám byly interfacem ke kosmu pouze pozemské dalekohledy. A konečně interfacem k člověku je samotná řeč.

Jednu vlastnost ale mají všechny zmíněné věci společnou. A sice tu, že nám musejí alespoň k něčemu být užitečné (musejí “nabízet” něco, čeho se dá využít; například skříň, radiátor, televize) nebo alespoň poskytovat nějakou informaci o sobě (být alespoň pasivně “sledovatelné”; například vesmír). Jedině pak má takové komunikační rozhraní smysl.
Pokud nějaká věc nic z vyjmenovaného “neumí”, nelze ničeho využít ani nic sledovat, nemůže pak logicky existovat v rozhraní takové věci žádný způsob (tlačítko, páčka, oko), jak s danou věcí “nakládat”. Taková věc se pak jeví, jako by žádné rozhraní neměla, není to ale pravda. Říkáme, že má takzvaně prázdné rozhraní. V běžném životě to navíc může být pouze dočasný stav - člověk si například rozumně použitelnou schopnost řeči vybuduje až v prvních letech.

Mohli jsme si také všimnout, že interface umožňuje komunikaci jedním (od nás k věci nebo od věci k nám) nebo oběma směry. Když pozorujeme vesmír nebo film, je směr komunikace výhradně od nich k nám (vesmír i film nám ukazují svůj stav). Pokud ale řídíme auto, je zde komunikace obousměrná - pomocí volantu a pedálů komunikujeme my s autem, pomocí všemožných kontrolek na palubní desce zase auto s námi.

Pro princip rozhraní také platí, že na to, abychom mohli nějakou schopnost nějaké věci využít, musí ona věc možnost ovládání této schopnosti v rozhraní “nabízet”, “zveřejnit”. Pokud tomu tak není, nemůžeme danou schopnost využít, i když ji ona věc “umí”.
Jako příklad může sloužit lidské oko. To je rozhraním pro vnímání světa pomocí světla. Nicméně oko neumí vnímat všechny “barvy”, a tak nám zůstává část světa skryta, i když ji svět ukázat umí. Oko ale mozku nenabízí možnost ukázat všechny barvy.

Může se také stát, že jedna věc podporuje hned několik rozhraní a potom může být každá schopnost přístupná z libovolné kombinace takových rozhraní. Dnešní běžné auto například umožňuje programově nastavit naklopení škrticí klapky, to ale není možné udělat pomocí palubní desky, nastavení musí provést odborný technik pomocí přístroje k tomu určeného. Auto tedy podporuje přinejmenším dvě rozhraní, která se v tomto případě liší svým účelem - jedno pro běžného řidiče, jedno pro odborný servis.

Interface v širším slova smyslu ale nejsou pouze ovládací prvky. Jsou to také pravidla, která jsou sice zpravidla někde popsaná, ale nejsou přímo součástí interfacu. Přesto jsou pro správnou funkci nezbytná.
Palubní deska, volant ani pedály samy o sobě nic nenaznačují o tom, že není přípustné startovat nebo řadit s nesešlápnutou spojkou nebo zastavit se zařazenou rychlostí. Na to, abychom tato pravidla znali, musíme se někde jinde (v autoškole) naučit, jak s takovým interfacem vlastně zacházet. Pokud bychom tak neudělali, zničíme startér, převodovku či alespoň nám chcípne motor.

Implementace

Pokud je interface to, čím s něčím komunikujeme nebo to ovládáme, implementace jsou právě ta “střeva”, která tu schopnost zajišťují.
Když řídíme auto pomocí volantu a pedálů, je jeho implementací motor, systém os, kola a vlastně všechno, co dělá auto autem. Implementací elektřiny (tak, jak ji používáme) je elektrárna, případně baterie, implementací skříně je systém desek a poliček a jejich kování. Je to tedy to “maso”, které vykonává, co potřebujeme.

Aby byla nějaká schopnost využitelná, musí ji podporovat jak interface, tak implementace. Těžko bychom mohli ovládat nějakou funkci bez příslušné “páčky” a těžko by nám páčka něco udělala, kdyby nevedla nikam.

Polymorfismus

Všimněme si jednoho dalšího rozdílu mezi interfacem a implementací. Interface je to, co musí znát obě strany komunikace - ten, kdo interface používá, i ten, kdo ho implementuje (tedy ten, kdo zajišťuje ono provádění schopností).
Na druhou stranu implementaci (vnitřnosti, to, jak se schopnosti provádějí) zná už jen objekt, který interface implementuje.

To má nejen ten důsledek, že člověk nemusí znát princip fungování spalovacích motorů, aby byl schopen řídit, ale především to, že ovládání auta a jeho fungování se stávají oddělenými záležitostmi, které se mohou měnit nezávisle na sobě.
A právě možnost vyměnit implementaci stejného interfacu se nazývá polymorfismus. Člověk se tedy nemusí učit řízení každého modelu auta zvlášť, protože všechna běžná auta dodržují stejný princip řízení (volant, pedály, řadicí páka) - aneb implementují stejný interface. Každý samozřejmě po svém - jedno auto má motor spalovací, jiný vznětový, jedno má kubaturu 1.4 a jiné 2 litry. Vždy ale můžeme vyměnit Hyundai Elantru za Nissan Almeru a budeme je přitom oba umět řídit.

Interface a implementace v programování

Principu rozhraní a implementace se při programování využívá dnes a denně. V počítači vlastně všechno komunikuje se vším, proto je dodržování tohoto principu velmi důležité.

Zvláštní význam má pak princip oddělení interface od implementace. Ten, kdo nějakou funkčnost využívá, by k ní zásadně měl přistupovat přes její interface, protože implementace se mění mnohem častěji než interface. Zbytečná vazba na implementaci potom vede k nutnosti měnit i každého, kdo funkčnost využívá.

V programech má svůj interface a implementaci vlastně každá složitější struktura.
Interfacem k datové struktuře je její jméno (název typu struktury) a veřejně přístupná data. Interfacem ke konkrétním proměnným jsou jejich jména vzniklá při jejich deklaraci spolu s typem, který představují (u tzv. silnětypových jazyků). Rozhraním funkce je její název, počet a typy parametrů a návratová hodnota (tzv. signatura funkce). U objektových jazyků je interfacem k objektu název třídy a seznam veřejných funkcí a dat.

Implementace funkce je pak vlastní kód, který se vevnitř funkce odehrává, implementací objektu je vlastně kód všech jeho metod (funkcí) spolu s jejich logickým propojením uvnitř objektu.

Také funkce operačního systému tvoří interface (např. win32api), jehož implementací je operační systém samotný (např. Windows).
Jindy je tento princip použit na binární úrovni. Nehledě na to, že u souborů obecně je jejich interfacem jejich jméno a implementací jejich obsah, mají také například DLL soubory uvnitř sebe přístupný interface (seznam funkcí, které umějí udělat) i s jejich implementací.

Explicitní interface objektů

Budeme nyní chvíli přemýšlet objektově orientovaným přístupem. Jak jsem již uvedl, je u objektů jejich interfacem seznam všech jejich veřejně přístupných prvků (dat, funkcí).
Objektové jazyky ale obvykle umějí také definovat seznam funkcí (a někdy i dat), tento seznam pojmenovat unikátním identifikátorem a považovat ho za interface. O každém typu objektu lze pak říct, zda daný interface podporuje nebo ne - o splnění jeho podpory se potom postará sám kompilátor. Jde tedy vlastně o oddělení interface a implementace na vyšší úrovni.
Můžeme poté mít více typů objektů, které takový interface implementují. Kdokoliv, kdo takové objekty používá, má v objektovém jazyce možnost deklarovat příslušnou proměnnou toho objektu typem společného interfacu (v objektových jazycích totiž vytváří explicitní interface nový typ). V takovém případě je jednoduše možné vyměnit implementaci onoho interfacu z jednoho objektu za jiný, samozřejmě za předpokladu, že oba objekty společný interface implementují. Jde jednak o naplnění principu polymorfismu (výměny implementace při zachování interfacu), jednak jde o logicky čistší programování, protože mimo schopnosti deklarované v interfacu není možné použít žádných jiných.

Jedno z praktických využití polymorfismu v programování je také testování kódu, kdy lze testovanému objektu “podhodit” testovací implementace různých dalších objektů (tzv. mock objekty), se kterými testovaný objekt v rámci své funkčnosti jinak přichází do styku. U podstrčených implementací lze potom obvykle simulovat různé podmínky, ve kterých se testovaný objekt může nacházet, a hodnotit správnost chování testovaného objektu. Už kvůli tomuto aspektu by tedy obecně měla být takřka veškerá funkčnost všech objektů v programu “schovaná” za explicitními interfacy.

Samozřejmě absence explicitních interfaců neznamená hned vazbu na implementaci, i konkrétní objekt je stále skrytý za interfacem v obecném slova smyslu - a jeho implementaci je stále možné měnit bez postihu klienta, byť již jen na úrovni konkrétního typu.

Nechtěná vazba na implementaci

Vazbou klienta (toho, kdo nějakou funkčnost používá) na implementaci (té funkčnosti) se rozumí logické spojení logiky klienta s logikou implementace a souvisí s porušením principu skrývání informací (information hiding) a principu oddělení interface od implementace. Obecně jsou vazby na implementaci nežádoucí a měli bychom se jim vyhýbat - to proto, že v opačném případě musíme v případě změny implementace měnit i všechny klienty, kteří původní implementaci používají, což je postup značně náchylný na chyby.
Představme si dvě funkce, A a B (jedna druhou nemusí vůbec volat). Nejde samozřejmě o to, že by funkce A byla přímo navázána na implementaci funkce B - to není možné, protože funkce musejí být svým interfacem (tzn. signaturou a názvem funkce) nutně odděleny.
Jde o stav, kdy funkce A něco “předpokládá” o chování funkce B, aniž by se B k takovému chování “přiznávala”. Takové chování bývá totiž jen (vedlejším) projevem implementace funkce B, a ta když se změní, přestane najednou kvůli chybnému předpokladu fungovat i funkce A.
Předpokládejme například, že máme program pro evidenci nějakých objednávek. Každou objednávku je potřeba umět uložit, o což se stará funkce UlozObjednavku, která ji ukládá do souboru, který (otevřený) dostane jako parametr. To, že soubor musí být před zavoláním funkce otevřený a že si ho případně uzavře opět klient, může být někde zdokumentováno jako pravidlo používání této funkce, a tedy součástí interfacu v širším slova smyslu.
Pak ale máme v programu obecnou funkci Vypis, která má za cíl vypsat všechny objednávky podle zvoleného řazení. Tato funkce nicméně předpokládá, že funkce UlozObjednavku uloží novou objednávku na konec souboru. Proto pokud funkce Vypis bude chtít řadit od nejdříve do nejpozději uložené objednávky, stačí jí zobrazit pořadí objednávek stejné jako pořadí dat v souboru.
Tento předpoklad je ale pouze předpokladem, který vznikl na základě znalosti implementace funkce UlozObjednavku v době původní tvorby programu. Takové chování této funkce přitom nebylo nikdy dokumentováno. Tím vzniká nechtěná logická vazba na implementaci nesouvisející funkce.
Když budeme později chtít optimalizovat ukládání objednávek (nebo třeba změnit úložiště ze souboru na databázi), najednou se onen předpoklad ukáže mylným, protože UlozObjednavku najednou začne ukládat na náhodná místa a poslední záznam (např. v databázi) vůbec nebude muset být posledně uloženým. Kvůli změně v jedné funkci programu (ukládání objednávek) najednou přestane fungovat úplně jiná, zdánlivě nesouvisející funkce programu (řazení objednávek při výpisu podle času změn).

Proto je při programování absolutně nezbytné buď veškeré chování interfaců pečlivě dokumentovat (a potom je možné měnit implementaci jen tak, že ta nová bude dodržovat i původní chování), nebo nedělat žádné předpoklady o takovém nedokumentovaném chování.
V našem případě by se tedy buď musela funkce UlozObjednavku “přihlásit” (zdokumentováním) k tomu, že záznam bude vždy ukládat na konec (ať to pro různé zdroje dat znamená cokoliv), nebo funkce Vypis nesmí předpokládat nic o řazení dat v datovém zdroji a musí se pokusit data seřadit i podle času poslední změny - i za cenu toho, že při původní implementaci by to nebylo nutné.

Pokud je program plný takových logických nedokumentovaných vazeb, je jen těžko udržovatelný a jakékoliv další úpravy, ať už v rámci oprav nebo dalšího vývoje, vedou obvykle k dalším chybám.

 

Závěrem

Interface, implementace a principy s tím související (oddělení interface od implementace, polymorfismus, vyvarování se vazeb na implementaci) hrají v programování velmi důležitou roli. Bez dodržování těchto principů není možné složit jednoduše spravovatelný a logicky poskládaný program.

Autor je technickým ředitelem společnosti RM Software.


Publikováno v rubrice Principy programování. Reakce v diskuzi lze sledovat prostřednictvím RSS 2.0. Můžete přidat komentář, nebo se na článek odkázat ze svého webu.

« Způsoby komunikace v programování
Princip zobecnění a abstrakce »
 

Komentáře v diskuzi

1.  ricmat(ověřeno)   14. 9. 2009, 15:27

Zde se hned na zacatku omlouvam za nepresnost:
“Jako příklad může sloužit lidské oko. To je rozhraním pro vnímání světa pomocí světla. Nicméně oko neumí vnímat všechny “barvy”, a tak nám zůstává část světa skryta, i když ji svět ukázat umí. Oko ale mozku nenabízí možnost ukázat všechny barvy.”

Zdroj nezverejnenych informaci (svet) je totiz jiny objekt nez implementace interfacu nedovolujiciho nam videt vsechny barvy (oko). Ale na lepsi priklad jsem proste neprisel a na priblizeni beznemu ctenari by to melo stacit :-)

2.  Martin(193.200.150.xxx)   14. 9. 2009, 17:32

Opět a znova produkt “Konzultant Java MBA”, který pravděpodobně dosud netuší, že interface tady není jako svatý grál OOP jak se to často prezentuje, ale jedná se pouze o reakci na logický problém nemožnosti sdílet objekty do/z DLL. Dá se to samozřejmě vyjádřit mnohem jednodušeji:

1) Interface je způsob, kterak předávat objekty mezi dvěma stranami bez nutnosti znát vlastní definici objektu druhé strany.

2) Zatímco většina jazyků nepovoluje vícenásobnou dědičnost pro objekty, pro interface ano.

3.  ricmat(ověřeno)   14. 9. 2009, 19:07

[2]
Bez urazky, ale pokud si myslite, ze interfacy (ty explicitne definovane) jsou zde proto, ze nektere jazyky nepodporuji vicenasobnou implementacni dedicnost, pak si jako zamestnance vyberu vsemi deseti radeji Konzultanta Java MBA nez Vas.
Nektere jazyky vicenasobnou dedicnost nepodporuji samozrejme kvuli moznym nespravnym pouzitim takoveho pristupu, v kazdem pripade ale plati, ze principy, o kterych pisu, jsou nadjazykove. A jazyky se prizpusobuji principum, ne principy jazykum, jak se snazite mylne uvadet.

Za dalsi si nejsem uplne jisty, zda jste clanek vubec cetl. O OOP je v nem jedina cast, a to “Explicitní interface objektů”. Vsude jinde se v clanku hovori o interfacu obecne, coz by prumernemu ctenari melo byt po prvnich vetach jasne.
Prave vase definice podstatu interfacu vubec nevystihuji, protoze mluvi v objektove orientovane terminologii (predavani objektu, dedicnost). Interface je ale daleko obecnejsi pojem a byl tu davno pred objektovym paradigmatem. I u ryze strukturalniho programovani ma funkce svuj interface - jak jste si jiste precetl, je jim jeji nazev a signatura.

4.  peto(85.216.181.xxx)   15. 9. 2009, 10:45

>Také funkce operačního systému tvoří interface (např. win32api), jehož >implementací je operační systém samotný (např. Windows).

Podla mna mala ta veta zniet inak a o:

Také funkce operačního systému tvoří interface (např. win32abi), jehož implementací je operační systém samotný (např. Windows).

api je len nejake mapovanie abi a pri win32 je nepresne…

5.  cheap lv bags(211.206.124.xxx)   20. 12. 2010, 04:43

Compared with people not to do, cheap lv bags but to surpass themselves, cry cry out tears of emotion, to laugh to laugh growth character.

6.  Air Jordan 16(222.122.78.xxx)   20. 12. 2010, 08:16

Air Jordan 16 tall me why

Přidat komentář

*
Opište prosím text z obrázku.
Anti-Spam Image


Aktuální články a bleskovky

Lenovo uvádí nové ThinkPady s čipy Ivy Bridge
Lenovo uvádí nové ThinkPady s čipy Ivy Bridge
Brýle Google Glass jsou patentované
Brýle Google Glass jsou patentované
Ifttt.com: Propojte a automatizujte svůj internet
Ifttt.com: Propojte a automatizujte svůj internet
Nejlepší programy pro práci s Wi-Fi
Nejlepší programy pro práci s Wi-Fi



Principy programování využívá WordPress MU a běží na Blog.zive.cz. Vytvořte si svůj vlastní blog
Sledování přes RSS: články a komentáře


  • Stránky

    • O programu
  • Archivy

    • Listopad 2009
    • Říjen 2009
    • Září 2009
  • Rubriky

    • Principy programování (12)
  • Administrace

    • Přihlásit se

1210_Computer.png

Časopis Computer

  • Nakupujte v zahraničí
  • Test 7 čteček elektronických knih
  • Technologie: nové standardy digitálního vysílání
  • Přehled cloudových uložišť
  • Poradíme s výběrem kamery na dovolenou

Partnerská sekce pro IT profesionály:
Microsoft TechNet/MSDN


Video Živě

Bluetooth stojánky pro Android: Philips AS111, AS141 a AS351
Ifttt.com -- založení úkolu
Zprávy Živě - 12. května 2012
iPad docky Logitech AV Stand a Logitech Speaker Stand

další videa »






Mladá Fronta a.s. Mladá Fronta a.s.
Tiráž | Autoři | Připomínky | Odběr novinek | RSS | Textová verze
Copyright 2000–2012 Mladá fronta a.s. | Inzerce: onlinesales@mf.cz | Kontakt na redakci | Návštěvnost měří NetMonitor