Я всегда был нацелен на результат. Меня не привлекают псевдоинтеллектуальные концепции, причудливая терминология и пиар. Вместо этого, я всегда стремлюсь к тем инструментам и технологиям, которые помогают развернуть исходный код как можно быстрее. Такой подход был изначально продуктивным, особенно когда я создавал меньшие по объему приложения по (‘proof of concept’) «проверке концепции».

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

У меня было не дающее покоя чувство, что должен существовать лучший, более чистый подход к разработке программного обеспечения. Я краем уха слышал о ФП (функциональном программировании) и о том, как оно позволяет разработчикам прописывать более сжатый и элегантный код. Сам того не зная, я впервые столкнулся с парадигмами и моделями ФП при работе с инструментами React и Redux. Оба эти инструмента объединяют в себе некоторые из принципов ФП, и мне они понравились. Я раньше читал о ФП  —  к своему ужасу, который я вначале испытал, я понял, что эти парадигмы основываются на абстрактных математических концепциях, и что такое видение преобладает в академических кругах. Так как моей целью является максимально быстрое разворачивание продукции, было похоже, что то, чего я пытаюсь достичь, противоречит здравому смыслу. Отучившись 4 года на инженерном факультете, я утвердился во мнении, что в научной среде решались проблемы исключительно теоретического характера, и что вряд ли такая среда когда-либо поможет мне в моих ежедневных разработках.

🤔🤔🤔🤔🤔🤔🤔🤔🤔🤔🤔🤔🤔🤔🤔🤔🤔🤔🤔🤔🤔🤔🤔🤔🤔🤔🤔🤔🤔🤔🤔🤔🤔

Но ФП не давало мне покоя. Элегантные решения и парадигмы периодически появлялись во всех моих любимых проектах с открытым исходным кодом, публикациях в блогах и учебных материалах. Я отложил свой скептицизм в сторону и углубился в изучение ФП.

Let’s just do this FP thang!

Хотя такие концепции содержат новый специальный язык и подразумевают быстрое обучение, я был поражен и по-настоящему взволнован этим «новым подходом». В настоящей серии статей я делюсь своим опытом изучения ФП; моей целью является извлечение и обобщение лучших концепций ФП, что обеспечивает получение опыта более чистых и сжатых разработок. Я постараюсь выстроить интуитивное понимание моделей, которые я обсуждаю, и представить проблемы и предлагаемые решения в максимально простой форме, пропуская излишне сложную терминологию. Для многих изучение ФП представляется несколько пугающим, но, разбивая концепции на маленькие порции, мы сможем легче усвоить эти понятия.

From the amazing Mostly Adequate FP Guide

Основным отличием ФП, в сравнении с другими парадигмами программирования, является декларативный подход (ФП) в отличие от императивного подхода. Прежде чем мы углубимся в формальные определения, давайте рассмотрим их различия на примере.

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

// triple the value of every element in a given array
const triple = (arr) => {
let results = []
for (let i = 0; i < arr.length; i++){
results.push(arr[i] * 3)
}
return results
}

// sum all the elements in a given array
const sum = (arr) => {
let result = 0
for (let i = 0; i < arr.length; i++){
result += arr[i]
}
return result
}

Посмотреть код вы можете тут

Данный код кажется непригодным? А должен быть! Что схожего между указанными выше методами?

  • Главная сложность фрагмента исходного кода происходит от того, что, вместо того, чтобы давать команду компьютеру о том, что мы хотим, чтобы он сделал, мы даем ему инструкции, как это сделать. Код, который дает команду компьютеру, как действовать  —  т.е. обращение к массиву данных с помощью индекса i и (видоизменение) изменение или замена значения называются императивным исходным кодом.
  • Такой код не является надежным (?￰゚リᄆ?). Это очень простой пример, но по мере роста Вашей программы и повышения уровня функциональности, использование данных замкнутых систем создает код, который не является тривиальным и который требует, чтобы наш мозг анализировал внутреннюю работу системы, одновременно следя за индексами, переменными величинами и многим другим. Императивный код повышает когнитивную нагрузку при чтении, и со временем усложняет понимание и логическое осмысление.

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

Давайте перепишем этот фрагмент исходного кода, но в соответствии с декларативным подходом.

// triple the value of every item in a given array
const triple = (arr) => arr.map((currentItem) => currentItem * 3)

// sum all the elements in a given array
const sum = (arr) => arr.reduce((prev, current) => prev + current, 0)

Посмотреть код вы можете тут

.map.reduce? Что за черная магия?

 

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

Короткое примечание в отношении фрагмента декларативного кода —

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

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

Не испытывайте страха перед этим. Мы детально изучим данные удобные встроенные методы в отношении массивов в следующих постах. Но сейчас уже очевидно, что фрагмент декларативного исходного кода является более сжатым, чем фрагмент императивного кода. Он также более легко прочитывается. Вместо того, чтобы давать инструкции программе о том, к каким индексам она должна получить доступ и т.д., я просто выдаю выражение на .map() и .reduce() (в нашем случае это анонимная функция), которое говорит программе, что я хочу, чтобы она сделала в отношении каждого элемента массива.

Декларативный подход будет служить нам согласно полному спектру функциональных возможностей:

  • Изучая и используя шаблоны в Вашем коде, которые являются хорошо известными, понятными и надежными в отношении недопущения ошибок, которые делают код трудным для понимания.

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

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

Перевод статьи Omer GoldbergJavascript and Functional Programming: An Introduction