Основы функционального кодинга и его применение в JavaScript

В последнее время React и Redux продвинули в массы использование функционального кодинга, но не все освоили его. Давайте разбираться.

Прежде чем мы рассмотрим, что такое функциональное программирование, полезно будет узнать, когда оно чаще всего используется. Например, при преобразовании данных «один в один»:

В приведенном выше фрагменте кода представлены типы хранилища, компонента и функционального слоя между ними.

Код типа convertUserMapToArray, преобразует данные из хранилища, в формат, подходящий для пользовательского интерфейса.

ФП – это процесс создания ПО при помощи «чистых» функций. Чистая функция – это функция без сайд-эффектов, имеющая одно входное и одно выходное значение.

Основы функционального кодинга и его применение в JavaScript

Например, мы можем быть уверены, что 2 + 2 = 4, а 3 x 3 = 9.

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

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

Рассмотрим несколько примеров побочных эффектов.

Мутация

Изменение переданного аргумента.

В приведенном выше примере изменяется значение arr по ссылке. В результате, мы не можем предугадать, что вернет эта функция.

Разделяемое состояние

Использование какой-либо формы глобального состояния функционального кодинга.

В этом примере мы не можем предсказать, что вернут эти функции, поскольку все зависит от некоторого внешнего значения. Важен порядок вызовов функций.

Асинхронный код

Код, который не выполнится немедленно.

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

Декларативный код описывает, что он делает:

Императивный код описывает, как он это делает:

Верхний блок написан на React с использованием декларативной библиотеки. Он сообщает: «Мы хотим счетчик на странице».

Нижний блок использует vanilla JS. Он явно находит ноду DOM и обновляет ее. Для маленького примера – это нормально, но в крупном проекте могут возникнуть проблемы с масштабированием. Код на React выглядит проще и компактнее, а с vanilla JS все обстоит иначе.

Императивный код

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

Две данные функции выполняют одно действие – берут список файлов и возвращают словарь, где ключом является file.id.

Императивный код более неряшлив (8 строк кода, вместо 3), а из-за этого больше мест для появления ошибок.

Разделение

При разработке логики и функциональной части есть риск создать скрытые побочные эффекты, вызывающие ошибки в логике. Следите за тем, чтобы функции были небольшими и выполняли одну задачу.

Композиция

Основы функционального кодинга и его применение в JavaScript

Все описанные функции выполняют преобразование аргумента. Первая – сортирует список файлов, вторая – возвращает массив файлов с расширением PDF, а последняя функция реализует преобразование списка 1:1 в его новую “версию”, просматривая список файлов и возвращая ключ каждого из них.

Неизменность

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

Memoization

Memoization – это метод оптимизации, используемый в основном для ускорения работы ПО путем сохранения результатов функций и возврата кэшированного результата при повторном вводе тех же данных.

В математике и информатике функцией высокого порядка называется функция, выполняющая по крайней мере одно из следующих действий:

  • принимает одну или несколько функций в качестве аргументов (т. е. процедурных параметров);
  • возвращает функцию в качестве результата.

Кажется сложным, но вы, скорее всего, уже использовали такие функции в своем коде при использовании функционального кодинга, не осознавая этого.

Функция, принимающая функцию

Это просто обратный вызов – функция высокого порядка принимает в качестве аргумента анонимную функцию.

Функция, возвращающая функцию

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

Функция, которая принимает и возвращает функцию

Последняя форма функции – симбиоз:

Здесь memoize и flow функции высокого порядка, принимают функцию (или несколько) в качестве аргументов и возвращают новую функцию.

Это метод конвертации функции, принимающей несколько аргументов (или кортеж аргументов) в последовательность функций с одним аргументом.

Есть sum, принимающая аргументы a, b и c. Когда sum передается в lodash.curry (функция высокого порядка), она становится новой функцией и продолжает возвращать функции, пока a, b и c не будут обработаны.

Если на вход передать аргументы 1, 2, 3, то функция вернет 6. Если передать только 2, 3 – вернется новая функция, ожидающая еще одного аргумента.

При частичном применении мы можем взять функцию и привязать к ней готовые аргументы оригинальной функции. Рассмотрим пример:

Функция learn Spell, принимающая в параметрах заклинание и волшебника. Если эту функцию с заклинанием передать в lodash.partial, будет создана новая функция, которая обучит мага предопределенному заклинанию (learn Expelliarmus и learn Expecto Patronum).

Подобный пример был рассмотрен в разделе о композиции:

Данные функции частично передают аргумент функции lodash. Это эквивалентно такому блоку:

Это не попытка сократить строки кода – здесь все намного серьезнее:

  • сделать код более читабельным и простым;
  • упростить код для тестов;
  • сделать пользователей счастливее.

Оригинал

proglib.io

Добавить комментарий

Ваш e-mail не будет опубликован.

шестнадцать − тринадцать =