Декларативный код в JavaScript

Императивный стиль программирования описывает набор шагов, которые нужно выполнить для достижения желаемого результата. Что касается декларативного стиля, то он описывает не конкретные инструкции, а желаемый результат. Примеры часто применяемых декларативных языков — HTML, SQL и даже JSX в React.

Допустим, базе данных не сообщают точные шаги получения данных. Вместо этого применяют SQL для описания того, что надо получить из базы.

SELECT * FROM Users WHERE Country='USA';

Примерно то же самое можно представить и в императивном JavaScript:

let user = null;

for (const u of users) {
  if (u.country === 'USA') {
    user = u;
    break;
  }
}

А вот, как это выглядит в декларативном JavaScript, если применять экспериментальный оператор конвейера:

import { filter, first } from 'lodash/fp';

const filterByCountry =
  country => filter( user => user.country === country );

const user =
  users
  |> filterByCountry('USA')
  |> first;

Предпочтение выражений над операторами

Если наша цель — декларативный код, то выражения должны быть предпочтительнее, чем операторы. Выражения возвращают значение всегда, а операторы применяются для выполнения действий, не возвращая никаких результатов. Это ещё называют побочными эффектами функционального программирования.

Как известно, чаще всего мы используем следующие операторы: for, switch, if, return, while.

Посмотрим на простой пример:

const calculateStuff = input => {
  if (input.x) {
    return superCalculator(input.x); 
  }

  return dumbCalculator(input.y);
};

Этот же код мы можем переписать в виде тройного выражения, которое является декларативным:

const calculateStuff = input => {
  return input.x
          ? superCalculator(input.x)
          : dumbCalculator(input.y);
};

Если же return — это единственный оператор в лямбда-функции, то язык программирования JavaScript даёт возможность также и полностью избавиться от лямбда-выражения:

const calculateStuff = input =>
  input.x ? superCalculator(input.x) : dumbCalculator(input.y);

При этом тело функции мы можем сократить с 5 строк кода до 2-х.

Есть и другие недостатки применения операторов. К примеру, они вызывают побочные эффекты и изменения, свойственные недетерминизму, в результате чего код делается менее надёжным и читаемым. Также операторы небезопасны и для переупорядочивания, т. к. они полагаются на порядок, в котором были использованы. Кроме того, операторы (в том числе и циклы) трудно распараллелить, т. к. они меняют состояние за пределами своей области видимости. В итоге, при работе с операторами следует понимать, что потребуются дополнительные умственные затраты, что связано с повышенной сложностью.

Что касается выражений, то их можно безопасно переупорядочивать и не вызывать побочных эффектов, также их можно без труда распараллелить.

Декларативное программирование потребует усилий

Декларативное программирование нельзя изучить за одну ночь. Особенно, если учесть, что многие обучались императивному программированию. Декларативное программирование — это, прежде всего, дисциплина и умение мыслить совершенно по-новому. Неплохой первый шаг в декларативном программировании — научиться создавать код без изменяемого состояния, а также не используя ключевое слово let.

Но факт остаётся фактом: если вы сами попробуете декларативное программирование, вы удивитесь тому, насколько элегантным станет код.

Осталось посмотреть на предлагаемую конфигурация ESLint:

rules:
  fp/no-let: warn
  fp/no-loops: warn
  fp/no-mutating-assign: warn
  fp/no-mutating-methods: warn
  fp/no-mutation: warn
  fp/no-delete: warn

Источник