Функциональное программирование (FP) строится на обработке данных с помощью функций как основных строительных блоков программы. В контексте Hyperapp это проявляется в построении приложения через чистые функции, управление состоянием и декларативное описание пользовательского интерфейса.
Чистая функция — это функция, которая:
Пример чистой функции:
const add = (a, b) => a + b;
В Hyperapp состояние приложения изменяется через функции, которые принимают текущее состояние и возвращают новое. Это позволяет гарантировать предсказуемость и тестируемость кода.
const increment = state => ({ ...state, count: state.count + 1 });
Иммутабельность означает, что данные не изменяются напрямую. Вместо изменения объекта создается новый объект с обновленными свойствами. Это ключевой принцип при работе с Hyperapp:
const state = { count: 0 };
const newState = { ...state, count: state.count + 1 };
Иммутабельность позволяет отслеживать изменения состояния, делать откаты и оптимизировать рендеринг, так как Hyperapp может эффективно сравнивать старое и новое состояние.
Hyperapp использует декларативный подход: UI
описывается через функции, которые возвращают виртуальные узлы
(h). Такой подход позволяет сосредоточиться на том, что
должно быть отображено, а не на том, как именно это сделать.
import { h } from "hyperapp";
const view = state =>
h("div", {}, [
h("h1", {}, `Счётчик: ${state.count}`),
h("button", { onclick: state.increment }, "Увеличить")
]);
Каждый рендер основывается на текущем состоянии. Изменения состояния
вызывают повторный вызов функции view, создавая новый
виртуальный DOM и минимально обновляя реальный DOM.
State — это единственный источник правды в
приложении. Hyperapp использует actions для изменения
состояния. Action — это чистая функция, которая принимает текущее
состояние и возвращает новый объект состояния:
const actions = {
increment: state => ({ count: state.count + 1 }),
decrement: state => ({ count: state.count - 1 })
};
Actions могут быть составными, то есть вызывать другие actions и возвращать функции:
const actions = {
increment: state => ({ count: state.count + 1 }),
doubleIncrement: (state, actions) => actions.increment(actions.increment(state))
};
Такой подход обеспечивает композицию и повторное использование логики, что является фундаментальной практикой функционального программирования.
Функции высшего порядка (HOF) — функции, которые принимают другие функции как аргументы или возвращают их. В Hyperapp HOF используются для создания обёрток над actions или генерации view-компонентов.
Пример HOF для логирования:
const withLogging = action => (state, actions) => {
console.log("Before:", state);
const newState = action(state, actions);
console.log("After:", newState);
return newState;
};
const actions = {
increment: withLogging(state => ({ count: state.count + 1 }))
};
Композиция функций позволяет строить сложные преобразования данных через последовательное применение простых функций. В FP широко используется оператор композиции, который можно реализовать в Jav * aScript:
const compose = (f, g) => x => f(g(x));
const double = x => x * 2;
const increment = x => x + 1;
const incrementThenDouble = compose(double, increment);
incrementThenDouble(3); // 8
В Hyperapp композиция помогает объединять несколько actions или вычислений состояния без потери чистоты функций.
Хотя чистое FP избегает побочных эффектов, приложения не могут полностью их исключить. Hyperapp использует effects — функции, которые описывают взаимодействие с внешним миром (HTTP-запросы, таймеры, localStorage). Эффекты выполняются отдельно от чистых функций состояния, что позволяет сохранять предсказуемость основной логики приложения.
const fetchData = () => (state, actions) => {
fetch("/api/data")
.then(response => response.json())
.then(data => actions.setData(data));
};
Эффекты отделены от чистых функций состояния и обрабатываются Hyperapp после того, как action вернул новое состояние.
Hyperapp реализует основные идеи функционального программирования:
Эти принципы обеспечивают легкую тестируемость, масштабируемость и предсказуемость приложений, построенных на Hyperapp, и позволяют создавать высококачественные интерфейсы с минимальной сложностью.