Я программировал почти всю свою взрослую жизнь. Я перепробовал кучу языков, в основном основные; Basic, Pascal, Java, C, PHP, Python, куча других и, конечно же, JavaScript. Но также меня хранили в блаженстве святого мира императивного программирования и объектно-ориентированного программирования.

Итак, перенесемся всего на пару лет назад. Я начал везде читать термин «Функциональное программирование» (и его всегда присутствующий спутник: Haskell), хотя и не совсем чуждый мне. Я знал, что это один из «формальных» методов программирования. Он был глубоко укоренен в математике и логике и был совершенно бесполезен в реальных приложениях. Я даже использовал некоторые «функциональные возможности» в python и даже в JavaScript (позже я узнал, что Брендан Эйх задумывал JavaScript как полностью функциональный язык, очень похожий на scala, до того, как Netscape ударил его бизнес-правилами, которые не включали функциональное программирование).

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

Это. Дул. Мой. Разум. Вот некоторые вещи, которые я узнал, применяя функциональное программирование к своему коду:

1. Назад к основам: разделяй и властвуй

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

Я пытался в игровой форме решать головоломки, используя это ограничение. Мало-помалу я начал смотреть на проблемы по-новому (по-старому): большие задачи решаются только путем разложения на маленькие, более простые части, которые можно решить с помощью чистых функций. Это было возвращение к основам: разделяй и властвуй; и отдельные заботы.

2. Тестировать снова весело

Вы знаете, как это происходит. Вы соглашаетесь на TDD, пишете свои утверждения и с гордой улыбкой на лице начинаете устранять все неудачи при тестировании. Но довольно скоро один из ваших классов начинает использовать другой класс для извлечения данных, чтобы обеспечить надежный сервис, вы используете синглтон (или, как я их называю: Повелители демонов пастафарианского ада), и вы неизбежно начинаете тратить больше времени на написание макетов. чем фактическое кодирование. Вскоре вы начинаете понимать, что ваши юнит-тесты стали почти E2E-тестами (или, как я их называю: Мерзости планеты Врул в 23-й туманности от Нуг и Йеб).

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

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

3. Найдите новый способ выразить смысл

Еще одна основа FP (больше похожая на мантру, по крайней мере для меня) заключается в том, что функциональный программист не пишет «инструкции» или «рецепты», а скорее определяет вещи через функции. Мой код теперь больше похож на словарь, чем на кулинарную книгу, и это хорошо. Это действительно самодокументированный код. Я определяю, как данные выглядят для этой цели. Я не выбрасываю обычную документацию, вы все равно должны писать правильную документацию; но следуя другим передовым методам, например: присваивать значениям осмысленные имена. Написание коротких чистых функций сделало мой код более читабельным и легким для понимания.

4. Меньше кода. Больше абстракции

Теперь я пишу меньше кода на каждой итерации. Это идет рука об руку с концепцией «разделяй и властвуй» в пункте № 1. Если вы организуете свой код в виде небольших функций, которые решают определенные компоненты проблемы, легко обнаружить шаблоны, и как только вы обнаружите шаблон, вы сможете абстрагировать функциональность и вызывать свою абстракцию в любое время, когда вам это нужно.

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