Co je vůbec objektové a funckionální programování?

Dlouhou dobu jsem nechápal objektové programování. Věděl jsem, co to je a jak ho používat, ale nechápal jsem ho na základní úrovni, chyběl mi hluboký vhled do hlavních myšlenek, tedy to, o co se vždycky snažím: neklouzat po povrchu, ale proniknout přímo do epicentra a odtud se propracovávat směrem ven.

Zásadní myšlenky jsou to nejdůležitější, a musíme je znát, abychom skutečně pochopili, co nám to které paradigma přináší. Bohužel tyhle základy často vnímáme pokroucené skrz optiku jazyka, které se k danému paradigmatu hlásí. Ideu nahrazujeme artefaktem. Interface implementací.

Java je populární objektově orientovaný jazyk, takže když známe Javu známe OOP, žejo?

Ani v nejmenším. Javě jako jazyku a kultuře, která kolem něj vyrostla, se podařilo zdeformovat pojem OOP. Zavedla vlastní termíny a pojmy a abstrakce a artefakty a vzory, které se OOP týkají jenom okrajově, ale většinové publikum je přijalo jako podstatu OOP. Já jsem nebyl výjimkou.

Jaké jsou tedy ty hlavní myšlenky OOP a FP?

Jsou to ty, kterým se daný styl programování odlišuje od všech ostatních.


Nejdůležitější ideou objektového programování je polymorfismus (a s ním spojený late bindind).

Někdo uvádí, že gró OOP leží v pojmech identita, zapouzdření a kompozice, ale myslím si, že to není tak úplně pravda.

Zapouzdření je fakt, že objekt má svůj protokol, který specifikuje množinu zpráv na které umí odpovět a není jiný způsob jak se podívat přímo do útrob objektu. Ale aby to mělo smysl, potřebuje polymorfismus – tedy možnost, že na jednu zprávu může každý objekt odpovědět po svém. Kdybychom ho něměli, pak by zapouzdření nedávalo smysl, protože by šlo jenom o jiný fixní pohled na interní data. Každý polymorfní objekt může být interně reprezentován zcela odlišně, ale s ostaními částmi systému komunikuje stejným protokolem.

Kompozice je způsob jak organizovat části programu a je to zase polymorfismus, který umožňuje, aby jeden objekt odpovídal přímo a jiný akci delegovat na jiný objekt.

Identita je zákeřná mrcha, která nejenom, že není zásadní, ale je dokonce na škodu. Jde o problematický koncept, protože nás nutí přemýšlet v rámci objektů, které existují jako konkrétní místa v paměti a ne v rámci univerzálně platných dat a faktů. Také přímo navádí k programování s měnitelným stavem (a pozorovatelný měnitelný stav je špatný, protože do programů vnáší zbytečnou složitost, často způsobenou tím, že spolu nějaké části programu komunikují změnami sdíleného stavu a komunikaci by v OOP měla probíhat jedině prostřednictvím zpráv). Identita se dá simulovat v systémech, které ji nemají (id sloupce v relačních databázích) a naopak se dá zapomenout v systémech, které ji mají (definuji vlastní protokol, který se k objektům chová jako k hodnotám). Zajímavě se k tomuto problému staví Concept-oriented programming, které zcela odděluje pojmy objekt a identita.

Typy pak v OOP světě slouží jako (staticky ověřitelná) klasifikace objektů. Když objekt má daný typ, znamená to, že umí odpovídat na danou množinu zpráv.

Mimochodem všimněte si, že jsem k popisu OOP nepoužil slova jako třída, interface, metoda nebo dědičnost. Nejsou zásadní a dokážeme se bez nich obejít.


Naproti tomu hlavní ideou funkcionálního programování je referenční transparentnost. Nejsou to funkce vyšších řádů, monády, lamba kalkul, ani žádné pokročilé matematické koncepty. Je to jenom tenhle jeden pojem.

Funkce je referenčně transparentní, když její výsledek je daný jedině jejími argumenty a ničím jiným. To má spoustu implikací: volání funkce můžeme nahradit jejím tělem nebo rovnou výsledkem a na chování programu se nic nezmění, o programu pak můžeme začít uvažovat jako o soustavě rovnic, funkce jsou funkcemi v matematickém slova smyslu a nemůžou mít žádné vedlejší účinky a všechny hodnoty jsou neměnné. To všechno vyplývá z hlavní myšlenky FP.

Díky tomu jsou funkcionální programy přímočaré a jednodušší na pochopení. Stačí sledovat vstupy a výstupy, nemusím si pamatovat, jaké vedlejší účinky má daná funkce a jak to ovlivní chování celého systému. Spousta starostí jednoduše zmizí. Neměnné typy zcela odstraní mutnost defenzivního programování, protože neměnnou věc nikdo nezmění. Všichni můžou mít kopii a programátoři můžou v klidu spát. To je požehnání pro paralelní kód, ale má svoje místo i v klasickém nudném jednovláknovém kódu.

Kvůli těmto pravidlům FP jazyky můžou být líné, snadno paralelizovatelné a užitečné pro paralelní programování. Když je hodnota neměnná, nemusím hlídat, kdo ji kde a jak změní, ale můžu ji zcela volně sdílet mezi libovolným počtem vláken (což je také dobré pro CPU cache, které si mezi sebou nemusí přehazovat horkou cache-line pro zápis). Tohle je hlavní z důvodů, proč funkcionální programování v posledních letech získává na popularitě.

Pokud si teď říkáte: „to všechno je pěkné, ale mě se to netýká, protože programuji v PHP/Javě/C“, tak vězte, že funkcionálně se dá programovat v každém jazyce. V některých je to snažší, ale jde to ve všech. Stačí psát kód, který se opírá o tu jednu stěžejní myšlenku referenční transparentnosti.


Takže co dál? Objektově nebe funcionálně? Odpověď zní překvapivě: obojí. V následujících letech se masově rozšíří objektově funkcionální paradigma, které spojuje to nejlepší z obou světů: OOP pro organizaci a modularizaci programů a FP kvůli referenční transparentnosti, neměnným typům a snazšímu paralelnímu programování.

Dále k tématu:

Flattr this!

This entry was posted in Funkcionální programování, OOP. Bookmark the permalink.

7 Responses to Co je vůbec objektové a funckionální programování?

  1. paranoiq says:

    a na principu identity je postaven hrůzný anti-pattern identity map :/

  2. Co s tyka OOP kvuli organizaci a modularizaci programu, to pro me bylo tak trochu WTF uz kdyz jsem to slysel v prednasce Martina Oderskeho (viz. napr tento slide http://parleys.com/…pter32/about). Fakt, ze v nejakem jazyce chybi slusny system modularizace kodu prece neznamena, ze je treba to resit objektovym programovanim. Napr. Racket ma spickovy system modulu a nepotrebuje k tomu vubec OOP (i kdyz ho umi). Ano, muzes trochu poodstoupit a tvrdit, ze kvalitni system modularizace je v zasade „high-level“ OOP. To mi ale prijde jako „argument kvuli argumentu“ ;) Respektuju OOP a jeho pouziti tam, kde to ma smysl. Ale zrovna tenhle argument organizace a modularizace mi prijde celkem prustrelny.

    Jinak ocenuju duraz na ref. transparentnost. Prijde mi, ze se to trochu v te hegemonii kolem FP ztraci a tak je dobre to pripominat :)

  3. KarelI says:

    Mam pocit, ze jste se dopustil ponekud rozsireneho omylu ze OOP je hlavne o polymorfismu. Ono to na tech uvodnich lekcich vypada hezky – kdyz se zacne s temi klasickymi geometrickymi objekty, vypadaji ruzne, ale chovaji se podobne. A pak student uvazuje objektove a vsude cpe polymorfismus a dedi hlava nehlava. A pak skonci v situaci kdy uz ani neumi nic jineho nez podedit pet objektu dohromady aby dostal co potrebuje.

    Ovsem v realnem svete velkych programu to tak samozrejme neni a treba takove zapouzdreni dava velmi dobry smysl samo o sobe uz jen proto, aby bylo mozno udrzet objekt v rozumnem stavu napric aplikaci. Stejne tak kompozice – dostaneme snadne testovani jednotlivych casti a zaroven rozumnou funkcnost celku (kdyz se udela spravne). Oboji je na dlouhe vypraveni a pestuje se dlouholetymi zkusenostmi a pritom se o polymorfismus nemusi ani zavadit. Ja sam uz jsem nekolikrat zazil situaci, kdy se program docela zjednodusil kdyz jsem prestal lpet na nekterych spolecnych vlastnostech i kdyz to zprvu vypadalo ze se to uplne nabizi.

    • v6ak says:

      Ano, viděl jsem už různé pseudoobjektové zrůdnosti. Například někdo podědil ByteArrayOutput­Stream jen proto, že implementoval nějaký OutputStream, který obsahoval v impementaci nějaký buffer. Jeden z mnoha příkladů, kdy měla být použita kompozice.

  4. PP says:

    Já za hlavní myšlenku OOP považuji fakt, že objekt zaštiťuje data i metody nějaké domény a nejde jen o nějakou skořápku na funkce, kterým posílám data k zpracování.

    A polymorfismus je fajn, ale je to podle mne jen taková vedlejší vlastnost :-D

  5. v6ak says:

    „Ale aby to [zapouzdření] mělo smysl, potřebuje polymorfismus“

    Je to IMHO přesně naopak. Zapouzdření bez polymorfismu může existovat a dávat smysl. Mám někde jednu implementaci, jejíž detaily nechci vystavovat ven, abych mohl tu implementaci kdykoli změnit. Tady mám zapouzdření, ale ne nutně polymorfismus.

    Na druhou stranu polymorfismus bez aspoň částečného zapouzdření dost dobře nejde. Pokud nemám dostatečně zapouzdřeno a kód se tedy bude spoléhat na některé vnitřní detaily nějaké implementace, musí z principu mít tyto vnitřní detaily všechny implementace shodné. Což dost omezuje možnosti využití polymorfismu.

Leave a Reply

Your email address will not be published. Required fields are marked *