Lekce 1.1

Deklarativní myšlení, čisté funkce a proč React působí "jinak"

Pokud se učíte React, téměř okamžitě uslyšíte frázi: React je deklarativní. Skvělé. Ale co to vlastně znamená?

Co se naučíte
  • Rozdíl mezi imperativním a deklarativním programováním
  • Proč deklarativní kód funguje: předvídatelnost
  • Pravidla předvídatelných funkcí
  • Jak deklarativní kód + čisté funkce = React
  • Praktické příklady imperativního vs deklarativního kódu

Pokud se pokusíte najít vysvětlení, dostanete definici jako:

Imperativní programování je, jak něco děláte. Deklarativní programování je, co děláte.

To zní hluboce… jakmile už rozdíl chápete.

Pro všechny ostatní je to jako říct "slepice přišla první", když ani nemáte rádi vejce.

Pojďme to napravit.

Tento článek spojuje dvě klíčové myšlenky:

  • Pochopení imperativního vs deklarativního programování
  • Pochopení předvídatelnosti, vedlejších účinků a čistých funkcí

Společně tvoří mentální základ, díky kterému React "klikne".

Imperativní vs Deklarativní: Skutečné vysvětlení

Začněme metaforami — protože metafora funguje.

Metafora #1: Red Lobster

Vstoupíte do Red Lobster, přijdete k recepci a řeknete:

Imperativní (JAK)

"Vidím volný stůl pod cedulí Gone Fishin'. Půjdeme tam a posadíme se."

Deklarativní (CO)

"Stůl pro dva, prosím."

Imperativní = popisujete kroky.

Deklarativní = popisujete cíl, důvěřujete systému někoho jiného, že provede kroky.

Metafora #2: Ptání se na cestu

Zavoláte kamarádovi a řeknete: "Jak se dostanu k vám domů z Walmartu?"

Imperativní

Dají vám dlouhý seznam odboček a výjezdů.

Deklarativní

"Moje adresa je 298 West Immutable Alley."

Deklarativní řešení předpokládají, že existuje abstrakce, která už zná "jak".

GPS. Zaměstnanec restaurace. Automatická převodovka ve vašem autě.

Deklarativní systémy vždy skrývají imperativní motor pod povrchem.

Skutečný deklarativní kód

Některé jazyky jsou inherentně deklarativní:

  • HTML — popisujete strukturu, ne jak kreslit pixely
html
<header>
  <h1>Declarative Programming</h1>
  <p>Sprinkle the word 'declarative' to sound smart</p>
</header>
  • SQL — popisujete, jaká data chcete, ne jak je najít
sql
SELECT * FROM Users WHERE Country="Mexico"

Přečtete si je a okamžitě víte, co se děje.

Imperativní JavaScript vs Deklarativní JavaScript

Podívejme se na tři klasické úlohy ve stylu pohovoru.

1. Zdvojnásobit každé číslo v poli

Imperativní

javascript
function double(arr) {
  let results = [];
  for (let i = 0; i < arr.length; i++) {
    results.push(arr[i] * 2);
  }
  return results;
}

Deklarativní

javascript
function double(arr) {
  return arr.map(item => item * 2);
}

2. Sečíst všechna čísla v poli

Imperativní

javascript
function add(arr) {
  let result = 0;
  for (let i = 0; i < arr.length; i++) {
    result += arr[i];
  }
  return result;
}

Deklarativní

javascript
function add(arr) {
  return arr.reduce((a, b) => a + b, 0);
}

3. Přepnout zvýraznění na tlačítku

Imperativní (jQuery/DOM)

javascript
$("#btn").click(function () {
  $(this).toggleClass("highlight");
  $(this).text() === "Add Highlight"
    ? $(this).text("Remove Highlight")
    : $(this).text("Add Highlight");
});

Deklarativní (React)

jsx
<Btn onToggleHighlight={handleToggle} highlight={highlight}>
  {buttonText}
</Btn>

V deklarativní verzi:

  • Popisujete, jak by UI mělo vypadat
  • React řeší, jak aktualizovat DOM
  • Stav řídí výsledek

React je deklarativní, protože vaše UI je funkce vašeho stavu, ne série manuálních DOM instrukcí.

Proč deklarativní kód funguje: Předvídatelnost

Přejděme k druhé myšlence — předvídatelnosti.

Jako vývojáři je naše práce jednoduchá:

Udělat programy předvídatelné.

Každá chyba, která kdy vznikla, přišla z nesouladu mezi:

  • co vývojář očekával
  • co program udělal

Předvídatelný kód = méně překvapení = méně chyb.

Co tedy dělá kód nepředvídatelným?

Dvě věci:

  • Vedlejší účinky
  • Nekonzistentní výstupy

1. Vedlejší účinky

Funkce by měla přijmout vstup → vytvořit výstup.

Cokoli jiného je vedlejší účinek.

Příklady funkcí s vedlejšími účinky:

Mutace externího stavu

javascript
function addTodo(todo) {
  todos.push(todo); // ❌ mutation
}

Závislost na externím stavu

javascript
function calculateFinalPrice(price, qty) {
  return price * qty * (1 + TAX_RATE); // ❌ depends on TAX_RATE
}

Změna globálního prostředí

javascript
function updateDocumentTitle(title) {
  document.title = title; // ❌ DOM mutation
}

Vedlejší účinky nejsou zlé — jsou jen nepředvídatelné.

Ale když je izolujeme, zbytek programu se stává snadnějším k uvažování.

2. Nekonzistentní výstupy

Pokud funkce při stejném vstupu vrací různé výstupy — je nepředvídatelná.

Příklady:

Math.random()
Date.now()
array.splice()

I toto:

getGithubProfile("user")

Každé volání vrací jiný promise.

Dvě pravidla předvídatelných funkcí

Pravidlo #1: Žádné vedlejší účinky

Funkce by neměla záviset na nebo měnit cokoli mimo svůj rozsah.

Pravidlo #2: Konzistentní výstupy

Stejný vstup by měl vždy vrátit stejný výstup.

Tato dvě pravidla popisují to, co funkcionální programování nazývá čisté funkce.

Čisté funkce jsou:

  • Skládatelné
  • Znovupoužitelné
  • Cacheovatelné
  • Testovatelné
  • Snadné k uvažování
  • Snadné ke čtení

Jsou také základem toho, jak funguje React render cyklus.

Pragmatická předvídatelnost

V reálném světě nemůžete zcela vyhnout vedlejším účinkům — síťové požadavky, DOM aktualizace, localStorage atd.

Ale můžete je omezit.

Příklad: pragmatická, ale stále předvídatelná funkce isPrime s cacheováním:

javascript
let primeCache = { 1: false };

const isPrime = (n) => {
  if (primeCache[n] !== undefined) return primeCache[n];

  for (let i = 2; i <= Math.sqrt(n); i++) {
    if (n % i === 0) {
      return (primeCache[n] = false);
    }
  }

  return (primeCache[n] = true);
};

Nečistota je izolována.

Nic jiného nezávisí na primeCache.

Takto funguje dobrá abstrakce.

Velké spojení: Deklarativní kód + Čisté funkce = React

Mentální model Reactu je postaven na:

  • Popisování, jak by UI mělo vypadat
  • Používání čistých funkcí (komponent)
  • Spoléhání na neměnný stav
  • Vyhýbání se vedlejším účinkům uvnitř renderu
  • Nechání Reactu řešit jak

React komponenta je v podstatě:

javascript
UI = f(state)

Ne:

text
do this, then change this, then update this…

Deklarativní myšlení + předvídatelné funkce =

  • proč React působí snadněji, jak aplikace rostou

Shrnutí

Deklarativní programování není magie.

Čisté funkce nejsou akademická teorie.

Oba jsou nástroje pro jednu věc:

Maximalizace předvídatelnosti.

Když je váš kód předvídatelný:

  • Je snadnější ho testovat
  • Je snadnější ho znovu použít
  • Je snadnější ho změnit
  • Obsahuje méně chyb
  • A vaše UI vrstva (React) se stává osvěžujícím způsobem intuitivní

Toto je posun v myšlení, díky kterému React "klikne".