Как начать думать функционально в JavaScript

Перевод статьи How to Start Thinking Functionally in JavaScript с сайта itnext.io для css-live.ru, автор — Алекс Рицкован.

Photo by Denys Nevozhai on Unsplash Фото Denys Nevozhai с Unsplash

Функциональное программирование – это стиль программирования, который требует от специалиста думать на более высоком уровне абстракции. Как правило, когда мы учимся программировать, мы рассматриваем задачи в весьма императивном и процедурном стиле: сначала делаем это, потом – то и т.д.

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

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

Чтобы освоить навык функционального программирования – или ФП, как его иногда называют по-модному – потребуется время; но как только вы вникнете в суть, вам откроется целый новый мир. Вы также сможете разрабатывать код, который легче поддается анализу.

С помощью ФП вы сможете перейти от императивного стиля кодирования к более декларативному.

Обычно разницу между ними объясняют так: декларативное программирование направлено на то, что именно программа должна выполнить, а императивное – на то, как она должна этого достичь.

Если не совсем понятно, ничего страшного. Просто давайте сядем и разберемся с этим вместе.
Рассмотрим простой пример в JavaScript.

Императивный способ

Допустим, у нас есть массив домашних животных.

Каждый элемент массива – это объект, определяющий питомца.

Предположим, что в бизнес-требованиях предусмотрена фильтрация объектов по следующим критериям: питомец старше 7 лет черного окраса.

Для каждой совпадающей записи нам нужно создать строку в следующем формате:

<petName>, возраст: <age> лет, цвет: <color>.

Теперь, когда мы знаем, каким должен быть результат, как мы его получим?

Сначала рассмотрим императивный способ решения задачи. Код будет таким.
всё очень императивно!

В строке 1 мы создаем новый массив для сбора результатов, удовлетворяющих бизнес-требованиям. Затем в строке 2 создаем цикл for. В каждой итерации цикла получаем название питомца в строке 3 и проверяем его свойства в строке 4, чтобы увидеть, подпадает ли он под наши критерии.

Если условие выполняется, вставляем новую строку в массив outputArr.

Наконец, в строке 8 мы вызываем метод console.table(), который выводит новый массив в консоль.

Мы получили такие выходные данные.

отфильтрованные записи в консолиотфильтрованные записи в консоли

Обратившись к исходным данным, мы увидим, что наш код работает правильно. Есть только 2 записи, которые соответствуют критериям фильтрации.

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

Есть ли лучший способ? Думаю, да. Давайте его рассмотрим.

Декларативный способ

Давайте отвлечемся и подумаем о том, что мы хотим сделать, с более глобальной точки зрения. К чему мы придем? Скажу простыми словами:

“Я хочу отфильтровать массив по ряду критериев и вывести строку данных.”

Я намеренно не думаю о реализации. Мои мысли парят не в трех метрах, а в трех километрах над задачей.

Слова, которые первыми приходят на ум – отфильтровать и вывести строку. Это можно записать так:

pets.filter().map()

а вот фактическая реализация
декларативная версия № 1

Выглядит лучше, правда? Почти как предложение на английском. Именно это люди имеют в виду, когда говорят, что ФП носит декларативный характер: мы объявляем, чего хотим достичь. Конечно, нам в любом случае приходится прописывать логику фильтра, но само решение выглядит более элегантным и его легче анализировать. Нам не нужно изучать каждую строку цикла for, чтобы понять, что происходит.

Но я бы пошел ещё дальше. Следуя правилу DOT (Do One Thing, одна функция – одно действие), я бы сделал такой рефакторинг кода.
декларативная версия № 2

Я разбил логику фильтра на две отдельные функции (помните: одна функция – одно действие) и добавил логику создания строки.

Теперь, чтобы получить необходимые выходные данные, нужно просто последовательно соединить функции .filter() и .map() и передать новые функции в качестве аргументов (строка 5). Выходные данные в консоли точно такие же.

код чище – выход тот жекод чище – выход тот же

Выводы

1. Функциональное программирование – это стиль программирования, в котором задачи рассматриваются на более высоком уровне абстракции.

2. Большинство из нас учится программировать на процедурном и императивном уровне, поэтому для начинающих переход к ФП может быть трудным.

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

4. Функциональный код проще поддерживать и модифицировать.

Ресурсы

Чтобы продолжить знакомство с ФП, ознакомьтесь с книгой “Eloquent JavaScript” (бесплатно).

И как всегда, спасибо, что прочитали статью! Если она вам понравилась, посмотрите другие мои записи здесь на Medium.

P.S. Это тоже может быть интересно: