Функциональный JavaScript — лекарство для ленивых
Одной из основных концепций, которые побуждали меня искать знания о методах программирования, всегда была моя собственная лень. В конце концов, когда я впервые начал играть с компьютерами, меня привлекла мысль о том, что они могут что-то для меня сделать. Все, что мне нужно было сделать, это сесть и сказать им, что я хотел.
Но я быстро понял, что компьютеры очень буквальны. Если я не скажу им точно, чего я ожидал, в ясных и недвусмысленных выражениях, используя язык, который они понимают, они редко вернут мне то, что я имел в виду. И, будучи ленивым, я не хотел работать больше, чем нужно, для выражения своих намерений.
Затем я увидел, как JavaScript превратился из нескольких императивных однострочников в большие и запутанные объектно-ориентированные приложения, и казалось, что этой сложности не видно конца.
Я начал искать способы сделать программирование проще и веселее. И этот поиск привел меня прямо к функциональному программированию.
Новые взгляды на проблемы
Впервые я познакомился с функциональным программированием, когда был старшим фронтенд-инженером в небольшом стартапе в Сан-Франциско. Однажды мастер программирования, работавший глубоко в недрах исследовательской группы компании, услышал, как я жалуюсь на какой-то беспорядочный код, зависящий от состояния, над которым я работал, и заманил меня в конференц-зал с причудливыми обещаниями. Там он продолжил импровизированное трехчасовое введение в Haskell, классический язык функционального программирования, включая беглое объяснение философии функционального программирования.
Он озадачил меня рассказами о функторах и монадах, когда я наблюдал, как исчезают переменные, а методы распадаются и сливаются вместе под незнакомыми сигнатурами типов. В то время все это казалось странным колдовством, но он заверил меня, что у JavaScript тоже есть функциональные возможности и что они приведут меня к спасению.
Это обещание не давало мне покоя, когда я начал копаться в этом экзотическом царстве. Я считал, что методы функционального программирования могут предложить мне лучшие способы разбить проблему на части и решить ее небольшими, сфокусированными кусочками. Я был в восторге от возможности сделать свой код чище, более переносимым, более управляемым, более читабельным и простым в обслуживании.
Попутно я обнаружил некоторые удивительные вещи о функциональном программировании в JavaScript, которые я углублюсь сегодня.
Функции высшего порядка
Одной из вещей, которая делает JavaScript способным обрабатывать методы функционального программирования, является тот факт, что он поддерживает функции более высокого порядка. В JavaScript функции рассматриваются как объекты первого класса. Это означает, что функция может принимать другие функции в качестве параметров и в результате возвращать функцию. Поскольку это встроено непосредственно в JavaScript на фундаментальном уровне, синтаксис уже знаком.
Использование функций высшего порядка — это первый шаг к представлению о вашем коде как о наборе независимых однозадачных компонентов, которые можно разобрать и снова собрать разными способами для решения разных задач. Функцию можно легко написать для вызова любой другой функции, просто передав ее, а затем вызвав ее во время выполнения, при необходимости возвращая новую функцию для повторного вызова позже. Поскольку функции передаются по ссылке, они несут с собой свой контекст в замыканиях, поэтому они могут работать в состоянии, которое существовало в момент их вызова, а не полагаться на возможности изменения внешнего состояния.
Чистые функции без побочных эффектов
Функциональное программирование также приносит с собой некоторые твердые мнения о том, как должны быть написаны функции. Чистая функция в функциональном программировании — это идеал. Чистые функции не взаимодействуют ни с какими переменными, существующими вне их самих. Они не вносят никаких изменений в переменные, не определенные в их собственной области видимости, и не полагаются на внешние значения, кроме переданных в качестве параметров.
Чистые функции всегда возвращают один и тот же результат при одинаковом наборе входных данных, что упрощает создание устойчивых и надежных тестов. Это означает, что вы можете рассчитывать на то, что результат функции останется прежним, пока параметры, которые вы передаете, одинаковы. Это также позволяет вам выполнять некоторые оптимизации, такие как запоминание, избегая сложных вычислений, сохраняя результаты в массиве внутри функции и проверяя этот массив перед выполнением вычислений при поступлении нового ввода.
Состав и разложение
Когда вы начнете строить свою программу из чистых функций, шаблоны, которые вы будете создавать, будут в большей степени связаны с тем, как вы строите сложные операции, используя простые взаимозаменяемые части. Благодаря способности JavaScript использовать преимущества функций более высокого порядка, небольшая библиотека сфокусированных чистых функций, специфичных для задач, которые они пытаются выполнить, может быть составлена вместе по мере необходимости для выполнения очень сложных операций.
Еще одним преимуществом чистых функций является то, что они выполняют одну задачу и возвращают один результат. При правильном именовании эти чистые функции становятся почти самодокументируемыми. И чем больше вы строите свой код из независимых однозадачных функций, тем меньше вложенных сложностей вам нужно поддерживать и документировать. Ваша задача состоит в том, чтобы подумать о том, как разбить вашу проблему на маленькие кусочки, а затем скомпоновать их разумным образом.
Встраивание в существующий JavaScript
Поскольку JavaScript превратился из простых однострочников в браузерах в сложную экосистему для поддержки приложений, синтаксис языка также развивался. В ECMAScript 5 массивы стали функторами, изначально поддерживающими метод Map для применения функции к каждому элементу массива и возврата нового массива. Массивы также теперь имеют собственные методы для функциональных приемов, таких как сокращение и фильтрация.
Новые функции в ECMAScript 2015 и более поздних версиях включают удобные функции стрелок, которые упрощают и делают более интуитивно понятным написание кода с анонимными встроенными функциями. Операторы деструктуризация и расширение также облегчают работу с массивами, которые могут содержать неизвестное количество элементов на момент их вызова. А генераторы дают нам нативный доступ к некоторой магии ленивых вычислений, точно так же, как наши друзья, использующие Haskell и Ruby, делали это в течение многих лет.
Самое главное, я понял, что функциональные техники — это только один из способов решения проблем. JavaScript предлагает множество альтернатив, и в некоторых случаях императивный или объектно-ориентированный подход имеет больше смысла. Добавление функционального программирования в мой репертуар только расширило диапазон возможностей, которые я увидел, когда столкнулся с проблемой. В настоящее время я обычно не настаиваю на функциональных методах для всего моего кода JavaScript, но я обычно нахожу, что добавление некоторой функциональной волшебной пыли делает рассуждения о каждой проблеме программирования более доступными.
Новый способ изучения функционального программирования
Когда я начал применять функциональные методы, я увидел, что мои программы, мои навыки решения проблем и мои отношения с моими коллегами-инженерами улучшились. Мой код был чище, лучше самодокументировался, его было легче поддерживать и обсуждать. И я делал меньше работы и больше наслаждался процессом.
В конце концов, мне захотелось поделиться этим сфокусированным, функциональным образом мышления со всеми, кого я встретил. Поэтому я начал писать статьи для SitePoint о функциональном JavaScript, рассказывая о некоторых тайнах, с которыми я столкнулся много лет назад в том маленьком конференц-зале. Популярность этих статей привела меня к созданию курса по функциональному JavaScript, который я был очень рад увидеть в начале этого года. К счастью, я наблюдал, как другие с энтузиазмом начали изучать функциональные методы и применять их в своей практике разработки с положительными отзывами.
Я надеюсь, что вы пойдете и изучите различные методы программирования, которые работают для вас и вашей команды. Если вам интересно узнать о преимуществах использования функциональных методов, вместо того, чтобы гадать, попробуйте этот курс и дайте мне знать, как он повлияет на ваш код, ваши мыслительные процессы и ваши профессиональные отношения. Это оказало значительное влияние не только на мою работу, но и на мою профессиональную карьеру. Я думаю, вы обнаружите, что добавление функционального решения проблем в свой арсенал программирования — это не просто лень, это также продуктивно и весело.
Стоит ли заниматься функциональным программированием на JavaScript?
Станьте разработчиком, который знает разницу между функциональным и императивным кодом.
Станьте разработчиком, который может переключаться между объектно-ориентированным программированием и функциональным.
Определите, когда лучше использовать технику, а не другую.
Вот как: я покажу вам свой курс функционального программирования. Добавьте рекурсию, композицию, сопоставление и многое другое в свой пояс инструментов разработки, чтобы сделать ваш код более удобным для чтения и менее повторяющимся.
- Что такое функциональное программирование?
- Работа с рекурсией
- Понимание каррирования
- Карта, уменьшение и фильтрация
- Функциональные композиции
- Что мы узнали