MobX – javascript aplikace jako spreadsheet

MobX je jednoduchý, čitelný a přímočarý javascript state management umožňující kompletně oddělit aplikaci od jejího zobrazení. V článku najdete lehký úvod a pár osobních tipů. Nahlédňete mimo reduxový mainstream.

Po tom, co jsem objevil MobX, jsem naprosto propadl jeho kouzlu. Mnoho článků v češtině jsem ale nenašel, tak si říkám, že napíšu takové shrnutí, jak a proč ho používám já. Na MobXu se mi líbí, že je jednoduchý, čitelný, přímočarý, umožňuje kompletně (ano vím, redux to umí také, ale IMHO ne tak přímočaře a samozřejmé) oddělit aplikaci (stav, state) od jejího zobrazení (presentation).

Co je to MobX

Dnes se webové aplikace píší prakticky všechny jako Single Page Application (SPA). Ve zkratce: jedná se o jedinou HTML stránku s javascriptovým kódem, který vykresluje (renderuje) vše ostatní.

Existuje několik přístupů (a tím pádem frameworků a knihoven) jak psát SPA.
Od MVC (např. Ember.js, angular), až po kombinaci:

State management

Stav aplikace je soubor objektů, které vznikly při jejím používání. Jsou to např. načtená data z API, vyplněné formulářové prvky, chyby vzniklé validací těchto prvků, index zobrazeného obrázku v carouselu atd. Vedle stavu existují akce, které onen stav aplikace mění. Jedná se třeba o stisk tlačítka “načti data z API” nebo psaní do inputu nějakého formuláře, autovalidace tohoto formuláře nebo timeout na posouvání carouselu.

V současnosti state managementu dominuje redux, o kterém už zde psal Tomáš Randus.
Já mám rád čitelný, jednoduchý kod, který je jasně modularizován. U reduxu jsem měl problém s:

  • jeho “výřečností” (boilerplate code)
  • pro přidání jedné další funkcionality je třeba upravovat několik míst (action creatory i reducery, + extra konstanty)
  • vzájemnou kombinací reducerů (combineReducers) vznikne cosi, o čem nemám dobrou představu, co je :)

Proto preferuji a začal jsem používat MobX.

Reaktivní funkce

MobX operuje s observable daty, akcemi, které tato data mění, a reaktivními funkcemi. Reaktivní funkce je funkce, která je spuštěna znovu právě tehdy, když se změní observable data, která jsou v ní použita (“dotting into”). Jednoduchý příklad od Jiřího Špáce:

const {observable, autorun} = require('mobx')

// naše data
const state = {
  firstName: 'Michael',
  lastName: 'Westraste',
  nick: null
}
// obs je nyní observeble data
const obs = observable(state)

// funkce, která používá state
function vypisState() {
  console.log('firstName + lastName', state.firstName + ' ' + state.lastName)
}
// nyní je reaktivní a odteď se vypíše state pokaždé, když se změní
autorun(vypisState)

state.firstName = 'Gandalf'  // autorun spustí vypisState
state.lastName = 'TheWhite'   // autorun spustí vypisState

Jak jednoduché, přehledné a čitelné. Wow efekt nastane tehdy, když si za autorun představíte metodu render react komponenty.

Ano! Přesně tak, komponenta se překreslí právě a jen tehdy, když se změní data, která vykresluje. A to přesně dělá mobx-react.

Máme tedy observable data a akce, které data mění, idealně vše přehledně zabaleno do ES6 tříd.
Máme tedy vše, co potřebujeme, abychom napsali celou logiku aplikace bez zaobírání se její vizualizací. To, jak budeme aplikaci (state) vizualizovat, je naprosto oddělený příběh.

Spreadsheet analogie

Autor tento přístup připodobňuje k spreadsheetu. Spreadsheet je kombinací buněk (s daty nebo vzorci, které s těmito daty operují), tj. aplikace (stav). Pak jsou to grafy, kontingenční tabulky nebo jiné potvory, které to vše zobrazují/prezentují.

Oddělení aplikace od jejího zobrazení má několik výhod. Jednou z nich je možnost kompletně otestovat aplikaci bez nutnosti mít napsanou jedinou zobrazovací komponentu. Stačí jednoduché mocky pro mockování requestú a je hotovo, vyřízeno.

V zobrazovací části je možnost jednoduše vyměnit knihovnu pro zobrazovaní. Každou technologii je IMHO potřeba neustále zpochybňovat, jinak bychom šli s proudem jako ovce. Je tak možné zkusit místo Reactu třeba riot.js. Nebo, pakliže píšete ES6 stateless functional components, teoreticky celkem bezbolestně přejít na preact. Přestože alternativ je dost a mnohé nabízí zajímavé benefity, ja zatím jdu se stádem a píšu React komponenty.

Pattern “komín”

Zlí jazykové tvrdí, že pomocí MobX lze jen tězko psát rozsáhlé aplikace. Já tvrdím, že to není pravda a dalším důvodém tohoto miničlánku je popis způsobu, jak mobx aplikaci strukturuji já.
Možná tento způsob už někdo popsal a nazval, nicméně, jako spousta další programátorů, i já jsem liný a nevěnoval jsem martýrium času hledáním unikátnosti svého přístupu. A možná je to věc tak jasná, že nestojí za článek. Jestli platí aspoň jedna z těchto věcí, pak se omlouvám a vypískejte mne v komentářích.

Ale k věci: používám ES6 dědičnost a snažím se psát malé třídy, které dělají dobře definovaný úkol, který vystihuje název souboru, ve kterém třída bydlí. Každá třída má data (typicky MobX observables, buňky zmiňovaného spreadsheetu) + computed members (buňky se vzorci ve spreadsheetu). A akce (MobX actions – metody třídy, které nad těmito daty operují, mění stav aplikace, načítají data, atd., prostě MobX Klasika :)

Tyto třídy, funkční bloky (FB), pak dědím jednu od druhé a tvořím takový vysoký “komín” (chimney pattern :) hierarchie tříd. Někdo takové FB nazývá mixins. Objekt, který se pak zinstancuje, má pak přímo přístup ke všem datům a akcím, což mi příjde užitečné. FB mj. umožňují vykostit určitou část funkcionality do extra knihovny (řádně otestované, znovupoužitelné). Pořadí vzájemného dědění FB nehraje roli. Navíc, aby pořadí šlo podle potřeby určovat, FB mohou mít následující tvar:

export default (BaseClass) => class A extends BaseClass {
...
}

Což je modul vracející funkci, která bere jako param třídu, která má být předkem (základem “(pod)komína”). Vrací pak třídu, která od této třídy dědí (bude v (pod)komíně přímo nad ní).
Jinými slovy: vezmeme už hotový komín a přidáme na něj další kostku :)

Tento přístup zkouším třeba v fb-similar-discussions a nebo v react-mobx-admin. Budu rád, když se potká s nějakou kritikou. Uvidíme, jak s tímto přístupem zamíchá mobx-state-tree.

Závěr

I přesto, že sám autor nepočítá, že by MobX někdy nahradil redux, já osobně věřím, že si své uživatele najde. Minimálně já v něm vnímám velký potenciál a podle toho, že je druhou nejpoužívanější knihovnou pro state management, nejsem sám.

Pro kompletnost doplním odkaz na super článek od autora MobX 3 Reasons why I stopped using React.setState, který mne hodně inspiroval. Na jeho základě jsem pak kompletně přešel na MobX i jako router řesení, za použití page.js od TJe. A na tape pro testování, protože umožňuje komentovat i jednotlivé kroky a ne jen celé testcasy.

A to je konec (mého) příběhu. :)

Programátor webových aplikací, snílek a pirát v jedné osobě.

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

Komentáře: 1

Přehled komentářů

Martin Soch
Zdroj: https://www.zdrojak.cz/?p=19274