Po letech opomíjení se funkcionální programování stává mainstreamem. Proč zrovna teď?

Funkcionální programování lze jen stěží označit za novinku. Už počátkem 90. let jsem na univerzitě napsal spoustu kódu v LISPu. Před 25 lety. A už v té době byl zmíněný jazyk o něco starší než moje tehdejší študácké já.

V anglickém originále zveřejněno na blog.salsitasoft.com.

Výhody funkcionálního programování jsou již dlouho známé. Úspěšný vývoj softwaru je z velké části o udržení složitosti pod kontrolou, zatímco se aplikace musí vyrovnat s náporem podmínek reálného světa. Je o boji s nerealistickými deadliny, zatímco my vývojáři kupíme jednu funkci na druhou. Toto vše je mnohem jednodušší, když se vaše aplikace skládá z dobře testovatelných čistých funkcí bez prapodivných vedlejších efektů a proměnlivého globálního stavu.

A přesto žádný funkcionální jazyk zatím nedosáhl masového užívání. Tím myslím ten typ intergalaktické nadvlády, kterou si užívalo C v sedmdesátých letech, než předalo žezlo C++, Javě a v následujících dekádách pak JavaScriptu. Ani žádný z hlavních uchazečů z nižší váhy (Python, PHP, Perl, Ruby, C#) není úplně funkcionální.

Teď se ale v tomto směru děje něco magického. Samozřejmě tu mluvím o Clojure.

Dělám si srandu! Žádný nový funkcionální jazyk světem programování v základech neotřásá, spíš se pomalu dostává do popředí funkcionální potenciál úřadujícího šampióna. Aktuálně vypomáhám s jednou mobilní aplikaci. Je založená na React/Redux a přistihl jsem se, jak píšu kód ve stylu:

aliasesList.reduce((allMatching, matching, index) => {  
  if (matching.count() > 0) {
    const expanded = allAliases.take(index)
      .concat(List.of(matching))
      .concat(allAliases.skip(index + 1))
      .filter(aliases => aliases.count())
      .reduce((current, aliases) =>
        current ? current.flatMap(
          i1 => aliases.map(i2 => i1.concat(i2))
        ) :
        aliases.map(alias => List.of(alias)),
      null);
    return allMatching.concat(expanded);
  } else {
    return allMatching;
  }
}, new List());

Hej, máš svůj LISP v mém JavaScriptu!

Proč tedy bylo FP programátorským lidem tak dlouho opomíjeno? A čím to, že je nakonec masově přijímáno?

Pryč s podstatnými jmény

Odpověď na první otázku souvisí s celkovým trendem ve vývoji softwaru. Po absolvování univerzity jsem byl smeten objektově orientovanou tsunami a dalších 20 let jsem nenapsal ani řádek LISPu. Komunita vývojářů softwaru se tenkrát rozhodla, že OOP je Jediná Správná Cesta. A tato móda ještě zesílila, když se o pár let později objevila Java. Komunita tehdy zkrátka neměla dostatek kolektivní pozornosti, kterou by mohla nebo byla ochotna věnovat funkcionálnímu programování.

Za vlády triumvirátu Zapouzdření, Dědičnosti a Polymorfismu OOP slibovalo lék na bujení softwarové složitosti. Nicméně v posledních letech se slabiny OOP stávají čím dál patrnější. Rigidní objektové hierarchie s křehkými základními třídami přispívají k bolestivé evoluci schémat. Roztahání stavových proměnných všude možně napříč kódem vede k problémům v souběžnosti a k nepředvídatelným vedlejším efektům. S tím, jak se ztrácí zalíbení v objektových „podstatných jménech“, odpovídajícím způsobem roste uznání funkcionálním „slovesům“.

V dobráckém žertu jsem si rýpnul do Clojure, ale na tomto místě by mu měla být na funkcionální renesanci probíhající v posledních letech po právu připsána zásluha. Tím, že řeší mnoho praktických problémů, které zamořily dřívější LISPy, Clojure představilo FP úplně nové generaci vývojářů. Clojure také v neposlední řadě pobídlo k vytvoření Om, což mělo obrovský vliv na evoluci dnešního JS ekosystému (viz dále).

Javascript dospěl

Krom deziluze ohledně OOP jsou spolu ony dvě výše položené otázky svázány i prostřednictvím dalších dvou trendů: Jednak v nástupu JavaScriptu jakožto plnohodnotného všestranně použitelného programovacího jazyka, jednak v tom, že si FP našlo své místo v širším JavaScriptovém ekosystému.

Na přelomu desetiletí se většina webového vývoje soustředila na server a skripty na straně klienta hrály jen vedlejší roli. Přesto několik Ajaxových průkopníků (například Gmail) už v té době demonstrovalo přitažlivost single-page aplikací běžících kompletně v prohlížeči, které chápou server hlavně jako centralizovanou úschovnu dat. Webové aplikace s rychlou odezvou tvářící se jako desktopové byly už tehdy očividně lepší než ty staré rachotiny poháněné pomocí CGI z dob webového pravěku.

Dalším posílením tohoto trendu bylo v roce 2008 vydání prohlížeče Google Chrome, který mimo jiné přinesl oproti konkurenci skokový nárůst výkonu při interpretaci JavaScriptu díky enginu V8. Bleskurychlý JavaScript byl podmínkou pro vznik „all-in-one“ frameworků pro „jednostránkové appky“, opět v čele s Googlem a jeho AngularJS. V8 se následně také stalo srdcem pro Node.js, což je samostatné běhové prostředí pro JavaScript, užívané především pro vývoj serverové části.

Najednou už JS není jen pro skriptující děcka. Angular a jeho bratři spolu s Nodem v posledních několika letech zažehli doslova explozi používání JavaScriptu.

Funkce a forma

Jak to vše souvisí s funkcionálním programováním? Brendan Eich (tvůrce JS) byl, jak sám tvrdí, najat do Netscapu v roce 1995, aby do stejnojmenného prohlížeče implementoval podporu funkcionálního jazyka Scheme. Přestože nakonec podlehl tlaku managementu, aby výsledný jazyk „vypadal jako Java“, dokázal v jazyce zachovat některé zásadní funkcionální aspekty (např. first-class funkce). Díky tomu někdy JavaScript bývá v nadsázce popisován jako „LISP s C syntaxí“.

Nakonec tak vznikl jazyk, který je velmi univerzální. Dnešní web nabízí miliony řádků kódu jako důkaz toho, že v JS můžete psát jak imperativní kód, tak kód objektově-orientovaný, nebo klidně i příšerně nechutný špagetový. Ale na rozdíl od ostatních jazyků s C syntaxí má základní vybavení, aby posloužil i jako základ pro opravdový funkcionální jazyk.

Funkcionální stálice map a reduce byly do JS (přesněji do ECMAScriptu) přidány v roce 2011. Jeho nástupce ECMAScript 2015 (původně ECMAScript 6) pak přidal několik dalších funkcionálně laděných konstruktů jako const a milovanou „fat arrow“ => s konzistentní syntaxí a konečně rozumným vázáním this. Většina funkcí ES2015 si ale na svou širší podporu v prohlížečích bohužel bude muset ještě počkat. S řešením tohoto problému nedávno přišel Babel transpiler, který umožňuje použití konstruktů z ES2015 (a dokonce i ES2016) již dnes, protože je kompiluje do pro prohlížeče univerzálně srozumitelného ES5.

Stejná reak(t)ce

AngularJS byl důležitým činitelem v boomu JavaScriptu, ale s kořeny v JavěOOP je cokoli, jen ne funkcionální. V posledních několika letech se pozoruhodnou rychlostí rozběhl React ze stáje Facebooku a stal se jedním z nejoblíbenějších JavaScriptových client-side frameworků. React je doplňován Flux architekturou a knihovnou Immutable.js, obojí též z dílny Facebooku. (Je pozoruhodné, jak se vzestup funkcionálního JS děje ve stejnou dobu, kdy můžeme pozorovat Facebook, jak odsouvá Google stranou ve snaze stát se alfa samcem JS frameworků.)

React se zdá být velmi funkcionálním přístupem k namapování stavu aplikace na webový pohled (view). Opravdu, poslední verze dokonce představila zjednodušenou syntaxi pro psaní čistých komponent bez vedlejších efektů.

React však řeší pouze problém zobrazování dat, což je také důvod, proč Facebook doporučuje pro širší architekturu aplikace využít také Flux. Díky tomu, že Flux je jen sada základních principů (stores, akce, centralizovaný dispatcher, jednosměrný proud dat), o nadvládu soupeří mnoho konkurenčních konkrétních implementací. Žádná z nich se dlouhou dobu nezdála být jasným vítězem, dokud se nedávno neobjevil Redux.

Redux je založen na třech přikázáních: jediný data store používati budeš, změna stavu pouze jako reakce na vyslanou akci se provede a změny stavu jen čistými funkcemi (tzv. reducery) prováděny jsou.

Když ještě přidáme Immutable.js, Redux začne setsakramentsky připomínat clojurovský Om. Teoreticky bylo možné JavaScriptový kód funkcionálně psát vždy, ale React, ReduxImmutable.js konečně nabízejí JS vývojářům praktické ingredience pro vytváření rozsáhlých funkcionálních aplikací: vývoj čistých reducerů bez vedlejších efektů k manipulaci s neměnitelným stavem, a to ve vypulírované ES6 syntaxi. Popularita tohoto přístupu (a tím pádem i funkcionálního programování) strmě vzrůstá: Když jsem si poprvé před několika měsíci všiml Reduxu, měl na GitHubu něco kolem 500 hvězdiček. Dnes jich tam má přes 16 tisíc!

Funkcionální budoucnost

Je trochu předčasné říci, zda nově vzniklá náklonnost k funkcionálnímu JavaScriptu přetrvá. JS krajina byla v posledních letech tak nestabilní, že se ze střelhbité kadence vzniku stále nových „Frameworků, Co Zabijí Všechny Ostatní Frameworky“ stal tak trochu vtip. Ale dlouhý rodokmen funkcionálního programování a atraktivita jeho hlubších principů naznačuje, že je nepravděpodobné jeho vyhynutí. I když budou zmíněné konkrétní implementace nahrazeny, zdá se, že roste pravděpodobnost toho, že budoucnost moderního vývoje softwaru – konečně! – bude funkcionální.

Salsita Software

Salsita Software je softwarová společnost, která se specializuje na vývoj komplexních moderních webových a mobilních aplikací. Sponzorujeme JavaScripting.com, komunitní portál, který pomáhá vývojářům hledat knihovny a frameworky pro JavaScript.

Překlad: Tomáš Křen, Luboš Turek a Adam Eda Zemek

CEO v Salsita Software, kde vyvíjíme prvotřídní webové a mobilní applikace pro naše mezinárodní klienty.

Věděli jste, že nám můžete zasílat zprávičky? (Jen pro přihlášené.)

Komentáře: 20

Přehled komentářů

Pavel Francírek
Hmmm Re:
Daniel Steigerwald Re:
Míra Re:
Martin Hassman Re:
Dor Re:
Oldis
Ivan Nový Protože už chaos způsobený HTML a CSS nestačí :-)
Olah Re: Protože už chaos způsobený HTML a CSS nestačí :-)
Taco Re: Protože už chaos způsobený HTML a CSS nestačí :-)
Dor Re: Protože už chaos způsobený HTML a CSS nestačí :-)
Taco Re: Protože už chaos způsobený HTML a CSS nestačí :-)
Palo Re: Protože už chaos způsobený HTML a CSS nestačí :-)
no
pavel Re:
noname Re:
nod Re:
tisonet Ukázka kódu
clpx Re: Ukázka kódu
Martin Hassman Re: Ukázka kódu
Zdroj: https://www.zdrojak.cz/?p=18071