funkcionálně.cz

Přední český blog o funkcionálním programování, kde se o funkcionálním programování nepíše
««« »»»

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

6. 9. 2013

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:

@kaja47, kaja47@k47.cz, deadbeef.k47.cz, starší články