JavaScript в 2016 году: функциональное программирование пришло всерьез и надолго

https://www.mpscholten.de/javascript/2016/01/15/javascript-in-2016-functional-programming-is-getting-here-to-stay.html
  • Перевод
В 2015 году вы могли заметить перемены в способе разработки приложений на JavaScript. Разработчики уходят от непредсказуемой архитектуры с мутабельным состоянием в сторону более предсказуемой иммутабельной архитектуры приложений.

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

Но сейчас все движется в другом направлении.

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

Библиотеки, основанные на парадигме функционального программирования (тот же Redux), легче расширяются – потому что чистые функции лучше стыкуются. Такие библиотеки обычно имеют меньше строк кода, из чего следует меньшее количество багов и снижение сложности. Ради интереса, взгляните на исходный код Redux. Чтобы его просмотреть, потребуется меньше 15 минут – кода, на самом деле, немного.

Стыкуемость и уменьшение сложности означает, что инструментарий может достигать высочайшего качества. Такие штуки как live reloading и time-travel-debugging невозможно быстро и легко реализовать для приложений, сделанных в императивном стиле. Несмотря на то, что технически это возможно, будут мешать побочные эффекты функций.

Не будем забывать, что фреймворки и библиотеки приходят и уходят. Вероятно, что React не будет самой популярной технологией через год или два. Но вся соль в том, что функциональная парадигма, которая получила распространение благодаря React и другим функциональным библиотекам, останется. Инструментарий настолько хорош, что пути назад уже нет. После того как вы начали использовать live reloading и time-travel-debugging, возвращаться обратно точно не захочется. Эти штуки действительно увеличивают продуктивность.

Будущее – за интерактивной разработкой программ. Если вы хотите познакомиться с примерами, сделанных в рамках интерактивного программирования, посмотрите домашнюю страничку Bret Victors. Обратите внимание на его доклад «Inventing on Principle».

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

Выводы

Даже если React не будет в будущем супер-популярной технологией, философия функционального программирования останется.

Если вы новичок в функциональном программировании, рекомендую посмотреть на Haskell. Книга “Learn You a Haskell for a Great Good” находится в открытом доступе. Изучить Haskell стоит, чтобы получить глубокие знания о программировании, даже если вы не собиратесь использовать этот язык для какого-либо серьезного проекта. Еще рекомендую посмотреть вот эту статью, которая на примерах показывает, где используется функциональное программирование.

Спасибо за внимание. Подписывайтесь на Твиттер автора, если такие истории вам интересны.

Об авторе

Привет! Меня зовут Марк, я разработчик программного обеспечения. Живу в Германии. Обожаю играться с новыми технологиями. Вы можете посмотреть мое приложение на Android и узнать больше фактов обо мне.

Если вам понравился пост, подписывайтесь на мою email-рассылку.
Voximplant
150,00
Облачная платформа голосовой и видеотелефонии
Поделиться публикацией

Комментарии 88

    +31

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

      +16
      Статьи про функциональное программирование тоже очень короткие и простые.
        +3
        Потому что невозможно написать что-либо крупное? ;)
      +3
      Заметил такую тенденцию что статьи западных девелоперов называются очень громко го освещают очень мало
        +12
        Скорее, не хватает нормальных статей для перевода и заполнения всех корпоративных блогов на хабре, а очень хочется.
          0
          Причина проста: такие статьи пишутся для галочек в резюме
          +37
          > функциональная парадигма, которая получила распространение благодаря React

          Кхм.
            +12
            Как же надоели уже стереотипные фанатики ФП, а. Из всех щелей лезут. И ладно бы умные вещи говорили, так очередная капитанская пурга про реакт, редакс и то, что чистые функции и иммутабельные структуры это круто. Причем без обоснований и доказательств (которые, впрочем, уже тоже набили оскомину). И мне кажется, именно такие люди (что автор, что переводчик) оказывают популяризации ФП медвежью услугу.
              –3
              чистые функции и иммутабельные структуры это круто

              а что, нужны доказательства?

                +4
                “Thou shalt not make unto thee any graven image,” или не нужно без нужды плодить идолов. В реальном мире если вы отломите ножку стулу, у вас в руках останется трехногий стул. Как бы ни удобно было работать с иммутабельными объектами, эта концепция противоречит реальному миру и за обходы этого противоречия приходится платить.

                Это не значит, что чистые функции и иммутабельные структуры это плохо. Но это достаточно веский аргумент, чтобы сказать «чистые функции и иммутабельные структуры — это по-разному». Микроскоп, несомненно, более изысканный инструмент, но гвозди лучше забивать утюгом.
                  0
                  Отличный пример ценности иммутабельности. Вы хотите использовать трехногий стул точно так же, как и целый, а ведь это совершенно новая структура со своими функциями (надо сказать, кардинально отличающимися от исходных).
                    +5
                    > Вы хотите использовать трехногий стул точно так же, как и целый

                    Почему это? Это ниоткуда не следует. А может быть, хочу, но учтите, что я пользуюсь стульями исключительно как дровами для печки. Или еще что.

                    Любая фраза про любую парадигму, если она содержит слово «всегда», не является верной. Иммутабельность — это очень хорошо. Иногда. А иногда — нет.

                      –1
                      Следует из семантики слова «стул», иначе это уже не программирование, а демагогия.
                        +2
                        Ой, да вы семантический пурист :)

                        Ну раз вы не умеете мыслить абстрактно, вот вам абсолютно легитимный семантически пример: я арендую квартиру со стульями. Стулья — субстанция хрупкая, иногда ломаются. Покупка нового стула взамен старого — акт, требующий согласования с хозяевами. За каждую же отломанную ножку с меня просто вычтут 10 рублей, пока количество ног у стула более двух.

                        Сидеть я на стульях не планирую, уточню на всякий случай.

                          0
                          То, что вы описали нигде и не называется «стул», не то что в программировании. Это «предмет», «арендная единица», а чаще всего «материальная ценность» с полем «наименование». А отломанная ножка — «порча имущества» с полями «сумма» и «наименование», которая вообще не связана с конкретным стулом.
                            +1
                            Поздравляю, вы наступили на иммутабельные грабли. Если я отломаю три ноги у стула, он перестанет быть стулом, поэтому «порча имущества» со стулом связана (иначе вам никогда не удастся определить стоимость порчи если всего порч было более двух).

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

                            Я в свое время напрямую спрашивал Вирдинга, почему в стандартной библиотеке эрланга нет того, что в эликсире называется «Agent». И он ответил: «GenServer» отлично справляется с этой ролью. И роль эта — хранить мутабельные объекты, даже если особым ревнителям чистой функциональности это не нравится.

                              0
                              iqiaqqivik > Я же, с вашего позволения, продолжу называть стул — стулом, а не «арендной единицей».
                              iqiaqqivik > Сидеть я на стульях не планирую, уточню на всякий случай.

                              Но ведь, позвольте возразить вам, — стул это то на чём сидят!
                                0
                                То есть, если я вас приглашу в гости, укажу перстом на стоящий в углу стул, и спрошу: «что это?» — то вы сначала зададите мне десять наводящих вопросов, прежде чем признаете, что это стул?

                                Кроме того, гостям я позволяю сидеть на сломанных стульях: мне не жалко.
                                  0
                                  iqiaqqivik > Кроме того, гостям я позволяю сидеть на сломанных стульях: мне не жалко.

                                  Как у вас много проблем то появляется. — А надо было всего ничего — не ломать ножки у стула и вопросов бы и не было!
                                  О том и речь была вначале.
                  +1
                  Без доказательств принимаются только религиозные аргументы. Мне прекрасно известны доказательства того, что чистые функции хороши. Автор сего опуса не утрудил себя их приведением, именно поэтому к нему отношение как к очередному недалекому адепту. Если бы привел — отношение было бы чуть лучше, примерно как к капитану очевидность. Однако ни первый, ни второй случай не тянут на статью.
                    0
                    Являются ли две приведённые функции чистыми и иммутабельными?

                    public Int32 GetValue1()
                    {
                        return 1;
                    }
                    
                    public Int32 GetValue2()
                    {
                        Int32 result = 2;
                        return result;
                    }
                    
                      0
                      define «иммутабельная функция»

                      Чистыми — являются.
                        0
                        Значит можно писать вместо:

                        render: function() {
                                return  (<Form></Form>)
                        }
                        


                        вот так:

                        render: function() {
                                let result = '<Form></Form>';
                                return  result;
                        }
                        


                        и оставаться при этом чистым и иммутабельным?
                          +3
                          Ну а какая разница? Переменная result во втором примере остается в области видимости функции и не лезет в глобальную.
                            0
                            Разница огромная. В первом случае я не могу понять что конкретно возвращает моя функция, какого оно типа и существует ли вообще. Во втором, я всегда могу увидеть результат перед возвратом, поставить точку останова, подебажить. Сравните:

                            render: function() {
                                return (
                                  <p>
                                    Hello, <input type="text" placeholder="Your name here" />
                                  </p>
                                );
                              }
                            


                            и например так:

                            render: function() {
                                let htmlInput = '<input type="text" placeholder="Your name here" />';
                                let htmlContent = 'Hello, ' + htmlInput;
                                let htmlResult = '<p>' + htmlContent + '</p>'
                                return htmlResult;
                              }
                            


                            Мой вопрос, остаюсь ли я при этом верным концепту чистоты и иммутабельности?
                              +4
                              Дать ответ вам может только Оракул чистоты и иммутабельности. В полночь, 30 февраля, выйдите на перекресток и потрясите раскрытым ноутом в направлении Сан-Франциско и трижды произнесите: «Марк, благослови мой код».
                                0
                                Вы глумитесь над вопросами, а между прочем об этом нигде не сказано и никак не обсуждается. Везде пропагандируют многостраничный функциональный код, вложенный друг в друга до безумия, начинающийся со слова return. И никто не может подтвердить что можно спокойно по шагам императивно писать иммутабельный код на чистых функциях.
                                  +2
                                  Ваш вопрос звучит глупо, на грани троллинга. Открываем википедию:
                                  чистая функция, это функция, которая:
                                  1. является детерминированной;
                                  2. не обладает побочными эффектами.

                                  Закрываем википедию. Предоставляю вам право, самому ответить на эти два вопроса про ваш код.
                                    0
                                    Пользуясь выданным вами правом самому отвечать на свои вопросы про мой код и всё же надеясь на аргументированную дискуссию, отвечаю:

                                    код
                                    render: function() {
                                        let htmlInput = '<input type="text" placeholder="Your name here" />';
                                        let htmlContent = 'Hello, ' + htmlInput;
                                        let htmlResult = '<p>' + htmlContent + '</p>';
                                        return htmlResult;
                                      }
                                    


                                    является императивным и иммутабельной чистой функцией одновременно
                                      +3
                                      На данный момент единственное упоминание «иммутабельных функций» в гугле — этот тред. Может всё таки расскажите о чём вы?
                                        0
                                        Я хочу понять почему требуется обязательно писать вперед ретурном? Иммутабельность как невозможность изменения состояния объекта после создания это очень хороший принцип, но почему при этом я не могу использовать переменные? Согласен, иммутабельная функция плохо звучит. Скажем так, функция которая для того же набора входных значений она возвращает одинаковый результат (чистая) может или не может внутри себя объявлять переменные и быть императивной?
                                          0
                                          Может. Внутри себя она может хоть интеграл пятого порядка считать. Главное — она не лезет в глобальный контекст и на одинаковые входные данные всегда реагирует одинаково (возвращаемое значение зависит только от аргументов функции).

                                          Что касается переменных — несколько неявных переменных неизбежно объявляются. Конкретно в js это, как минимум, this, arguments, так же совсем внутри есть аналог переменной result и прочее. Так что сам по себе вопрос некорректный, потому что без переменных это не реализуется в принципе. Другой вопрос, что все переменные могут быть иммутабельными, но опять же, совсем совсем далеко внутри неявные мутабельные переменные будут.
                                            0
                                            Пока переменные только локальные — используйте сколько влезет.
                                              0
                                              Добрый день!

                                              Я бы хотел ответить на ваш вопрос, потому что на него никто толком не ответил в тот раз.

                                              Действительно, функция является чистой, когда ее аргументы — это все, что ей нужно для вычисления результата. Она не может никуда больше лазать (делать сайд-эффекты), кроме других чистых функций.

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

                                              Сами эти внутренние переменные называются иначе — локализованное состояние (терминология может отличаться). Это состояние, которое за пределы функции не выходит. В Haskell, например, есть монада ST, которую можно использовать внутри чистых вычислений, но по факту она является императивным состоянием.

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

                                              Еще добавлю, что в Haskell есть так называемые let-биндинги, которые выглядят императивно, но которые на самом деле сахарят вызов функций в виде выражений:

                                              myFunc a b = let
                                              c = a + 1
                                              d = b + 1
                                              e = c + d
                                              in e + 10

                                              Это эквивалентно:
                                              myFunc a b = ((a + 1) + (b + 1)) + 10

                                              Функциональное программирование значительно шире. Оно крутится, на самом деле, вокруг композиции функций, а иммутабельность и чистота этих функций — необходимые условия для композиции.
                                            0
                                            Императивность тут вообще не при чем.
                                            Ваша функция всегда выводит один и тот же результат (при одинаковых входных параметрах)?
                                            Да.
                                            Ваша функция меняет глобальную область видимости?
                                            Нет.
                                            Следовательно она является чистой.
                                            Почитайте «Выразительный яваскрипт» — хорошая книга.
                                              0
                                              Таким образом, вы подтвердаете мое предположение, что внутри чистых функций можно писать в императивном стиле?
                                                0
                                                Вам можно.
                                                  0
                                                  В вашем ответе чувствуется, что внутренне вы несогласны со мной, но предпочитаете сказать «ой всё»
                                                  0
                                                  Да, можете. Чистые функции и иммутабельные данные лишь часть парадигмы функционального программирования. Дело в том, что в данном случае вы используете часть парадигмы — чистые функции, но при этом внутри функции императивны. Ваш вопрос должен быть уровнем выше — является ли код полностью функциональным, и тогда если внутри функции есть изменения локальных состояний, ответ будет нет.
                                                    0
                                                    вы используете часть парадигмы — чистые функции

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

                                                      поддерживаю. Единственное чего я не могу понять из этого обсуждения — откуда взялся термин чистая функция? Всю дорогу (с момента когда я познакомился с программированием) — функция в программировании употреблялась в математическом смысле — и то что она при одних и тех же входных параметрах возвращает одни и те же значения — было вроде как не классифицирующим признаком а следствием. А разделяли функции и процедуры по возврату значения и доступу к environment — если возвращает результат и работа идет только с локальными переменными — функция, все остальное — процедуры. Вроде так было, откуда появились чистые и грязные функции?

                                                        0
                                                        Это знаете, как если женщина с причандалами, то она мужчина, а если мужчина без — он женщина. Вот так и тут. Функция с сайд-эффектами — грязная процедура, функция без — девствственная и непорочная чистая функциональная функция.
                                                          0
                                                          В программировании функции и процедуры — это прежде всего подпрограммы, обычно разделение проходит по тому есть ли возвращаемое значение или нет. Мейнстрим языки если и разделяют (Си, например, не разделяет, там всё функции, Ассемблер (intel-like как минимум) тоже не разделяет — там всё процедуры) функции и процедуры, то только по этому признаку, запрета на побочные действия нет в функциях (а в процедурах практически никогда и нет надобности без побочных эффектов).
                                                  0
                                                  Кажется, вы путаетесь в понятиях. Иммутабельность не является несовместимой с императивностью, так же как и чистота функции таковой не является. Так или иначе, возвращаясь к исходному вашему комментарию — не понимаю, что именно вы хотите донести.
                                                    0
                                                    Ваш код с SSA чисто функционален, чище некуда, и переписывается на пуританский хаскель один-в-один. Вот если бы в нём переиспользовалась одна и та же переменная вместо трёх, ещё можно задуматься.
                                                      0
                                                      > Вот если бы в нём переиспользовалась одна и та же переменная вместо трёх, ещё можно задуматься

                                                      Почему нельзя использовать одну локальную переменную несколько раз? Кто запретил? Чем чревато?
                                                        0
                                                        Как минимум ухудшением читаемости.
                                                          0
                                                          Нарушением иммутабельности состояния. Первое присвоение это _не_ изменение состояния, это его _создание_. Грубо говоря, все ваши переменные должны быть const, выглядеть как const и вести себя как const. Как в математике :)
                                                            0
                                                            > Первое присвоение это _не_ изменение состояния, это его _создание_

                                                            Ну второй раз тоже напишите var перед переменной. Будет создание. В Rust так можно

                                                            А вот в Erlang, например, нельзя. И он не слишком популярен в том числе и по этой причине

                                                            PS: для полного погружения в ФП надо заставить апологетов редукс заменить все for на соответствующие рекурсивные вызовы. Посмотрим как долго они протянут
                                                              0
                                                              > он не слишком популярен в том числе и по этой причине

                                                              Да, это ключевая причина непопулярности Эрланга, прямо в яблочко.
                                                                0
                                                                PS: для полного погружения в ФП надо заставить апологетов редукс заменить все for на соответствующие рекурсивные вызовы. Посмотрим как долго они протянут


                                                                Вот оно что! — На двух стульях думают усидеть!?
                                                                  0
                                                                  Ну второй раз тоже напишите var перед переменной. Будет создание. В Rust так можно

                                                                  Ну тогда это опять-таки будут три разные переменные с одинаковыми именами.
                                                                  Почему нельзя использовать одну локальную переменную несколько раз? Кто запретил? Чем чревато?

                                                                  Можно, но код будет чисто функциональным, только если это переиспользование переменной нельзя пронаблюдать снаружи функции. Например, как в хаскельной монаде ST, или в линейных типах Clean.
                                                0
                                                Только сомневаюсь, что jsx будет правильно работать во втором примере.
                                                  0
                                                  Это чистая функция. Ее результат определяется только ее входными параметрами.
                                                  Иммутабельность к вашим примерам не имеет никакого отношения.
                                            –1

                                            иммутабельные структуры нужны там где они нужны. если у вас state меняется с нескольких источников (нет одного холдера мастер-данных) — то какие тут могут быть иммутабельные структуры? Нет же, лепят, модно же. А потом сидишь и разгребаешь — где данные не обновились, у кого старая копия зависла.

                                              +4

                                              По моему опыту такие баги возникают как раз от развесистого всепроникающего mutable state.

                                                0
                                                Не соглашусь, от всепроникающего mutable state — баги скорее типа «кто-то где-то обновил, но непонятно кто и откуда» :) Т.е. грубо говоря, в первом случае проблема в рассинхронизации состояний (которые каждое само по себе консистентно), а во втором — в неконсистентности (но состояние одно и оно синхронизовано).
                                            +3
                                            Добавлю, что redux, например, феноменально сложный для такого небольшого количества кода.

                                            Реакт сам по себе простой. Фичи для хранения стейта из clojurescript(не интересовался чистым JS, увы) — атомы из clojure.core, курсоры из om, datascript — простые и понятные.
                                            Redux — невыносимо непонятный, и почему его все так форсят для меня загадка. Непонятнее его для меня только cycle.js, наверное.
                                              0
                                              А что есть понятнее для Реакта?
                                                0
                                                Все перечисленное из мира clojurescript нормально работает с реактом. Om — react-based framework, атомы — это абсолютно библиотечная фича для синхроницированного доступа к данным, datascript — это библиотека предоставляющая упрощенную in-memory версию известной в узких кругах БД Datomic.
                                                Итого, один фреймворк поверх реакта и две библиотеки, которые ничто не мешает с ним использовать.

                                                Для JS есть куча разного качества реализаций Flux, но в детали я не вдавался. На redux я посмотрел на волне хайпа, понял, что ничего не понимаю и не очень хочется, и закрыл этот вопрос для себя.

                                                0
                                                Думаю, Redux — это облегчение для тех, кто ранее работал с другой реализацией Flux. От этого и популярность. Да и что может больше подойти для React чем Flux/Redux? Уже в других постах спрашивал об этом, пока не нашлось хорошего ответа.

                                                Добавлю, что redux, например, феноменально сложный для такого небольшого количества кода.

                                                Каждому своё, конечно… А мне вот наоборот, было куда сложнее вначале разобраться с React. С Flux/Redux же разобрался за день и ещё через пару дней освоил что-то вроде «best practices», после чего жизнь стала ещё легче и проще.
                                                  0
                                                  mobx
                                                    0
                                                    Да, это реальный конкурент Redux.
                                                0

                                                -

                                                  +2
                                                  Статью порекомендовал на перевод я :) Что мне в ней понравилось? Идея того, что технологии — фигня. Они получают популярность, когда на них реализовывают крутые штуки. Пришли рельсы с DSL и скаффолдингом — об этих технологиях заговорили. Скаффолдинг много куда заимствовали. Пришел реакт с иммутабельным состоянием — «фанатики ооп лезут из всех щелей». Удобные и полезные штуки, ИМХО, первичны. И я рад, что авторы постоянно экспериментируют и пробуют новые подходы. Hot module replacement мне очень нравится — надеюсь, оно много куда заимствуется.
                                                    0

                                                    Возросший интерес к ФП — это аллергическая реакция на недавно прошедший всплеск ООП головного мозга в JavaScript.
                                                    Согласитесь, когда человек на языке, который позволяет запросто объявить объект, эмулирует класс, чтобы отнаследоваться от него и сэмулировать синглтон — это за гранью добра и зла. Такие чудеса уже кончились и такие чудаки большей частью перевелись, но реакция у сообщества, видимо, замедленная.

                                                      0
                                                      Сегодня синглтон, а завтра уже фабрика объектов.
                                                      Я может, просто не хочу путаться, и всегда завожу классы, и если уж так вышло, что объект мне нужен только один — я его создам через new один раз. Зато буду спокоен, что в случае чего смогу создать их еще 10, если потребуется.
                                                      if(x === 0)
                                                      return;
                                                      — плохо, лучше ведь заранее написать
                                                      if(x === 0)
                                                      {
                                                      return;
                                                      }
                                                      и жить спокойно.
                                                      Я к чему все это… ужасы случаются, но завести заранее класс вместо прямого определения объекта — не страшно.
                                                        0

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

                                                          0
                                                          Можно пример синглтона, который точно точно точно никогда никогда не станет классом?
                                                          Вот вам пример из недавней жизни. На изоморфном сайте есть загрузчик, который грузит первую страницу сайта. Сделаю его объектом в js, подумал я. Сделал, и понял что не могу сразу извлекать элементы через jQuery, потому что страница еще не загружена. document.ready? нет, загрузчик обязан появиться до того, как будет загружен html, вдруг страница — простыня на 2mb. Хорошо, значит нужно инициализировать загрузчик после его html представления. Что же, заведем функцию init? Но зачем мне лишняя сущность init, если я могу сделать класс, и после определения html элементов загрузчика вызвать var preloader = new Preloader. И все сразу хорошо, несмотря на то что у нас по идее preloader — типичный синглтон.
                                                      +2

                                                      Обсуждали же уже много раз, кесарю кесарево. Ни ФП/иммутабельность, ни ООП не являются серебряной пулей per se.


                                                      Time-travel debugging это прикольно, конечно. Примерно как трюк на велосипеде, клево выглядит на ютубе, но вечером ты просто крутишь педали, чтобы попасть домой. Так и с кодом, ты просто хочешь чтоб твой коллега исправил баг до того, как он попадет на прод, и настраиваешь CI и пишешь тесты. Которые, если у тебя действительно чистые функции, можно прогонять в nodejs, не запуская громоздкий браузер в тормозной обвязке (да-да, Karma, я смотрю на тебя).

                                                        0
                                                        Есть еще Jest.
                                                          +1

                                                          Есть прекрасный tape-run, но все равно без браузера быстрее.

                                                            0
                                                            Формально Jest браузер не использует. Но вы явно про DOM говорите.
                                                        0

                                                        Собственно, никто не мешает использовать тот же подход во втором ангуляре.

                                                          0
                                                          Вот такие статьи способны резко снизить мою самооценку… опять учиться?!
                                                            +4

                                                            А вы заканчивали?

                                                              0
                                                              Увы — нет, но поворчать то можно?
                                                            0
                                                            Сижу, смотрю на весь этот дикий оверхед, связанный с неизменяемыми состояниями и уже неудивляюсь, почему Chrome жрет по 200 Мб на вкладку, почему все программы работают все тормознее и тормознее…

                                                            Я глубоко убежден, что несмотря на всю математическую красоту и плюшки в многопоточности — функциональное программирование, охренеть какой ад для клиентских машин. А вы на нем хотите весь front-end писать.
                                                              –1
                                                              Хуже всего — сборка мусора, которая тормозит не только одни функциональные, но и императивные программы тоже.
                                                                0
                                                                > функциональное программирование, охренеть какой ад для клиентских машин

                                                                Армстронг и Вирдинг с недоумением смотрят на этот тезис.
                                                                  –1
                                                                  Поясните, пожалуйста.
                                                                    0
                                                                    Всегда вроде считалось, что эрланг (два чувака из моего комментария — его создатели) помимо прочего как раз очень _нетребователен к ресурсам_.
                                                                      –2
                                                                      Спасибо! Теперь, понял о чём речь.
                                                                0
                                                                Такая маленькая (и почти бессмысленная банальная) статья, и так много комментариев :)
                                                                  0
                                                                  Это говорит о том, что тема ФП то горячая, по крайней мере в JS.
                                                                    +1
                                                                    Мне кажется, что ФП просто само по себе интересно.
                                                                    Программирование, которое ближе к искусству, чем к рутине.
                                                                    Disclaimer: это чисто моё впечатление, не хочу никакого холивара, на ООП написал тоже много :)
                                                                      0
                                                                      Мне кажется, что ФП просто само по себе интересно.


                                                                      Оно новее. Для масс. — Не то что идеи там новые — им 100 лет в обед — но ООП в своё время «выжег территорию». — Сейчас пошёл отскок.
                                                                  0
                                                                  А почему в редаксе не юзают клевое функциональное программирование, а используют грязную, бажную и недостойную процедурщину?

                                                                    function subscribe(listener) {
                                                                      if (typeof listener !== 'function') {
                                                                        throw new Error('Expected listener to be a function.')
                                                                      }
                                                                  
                                                                      var isSubscribed = true
                                                                  
                                                                      ensureCanMutateNextListeners()
                                                                      nextListeners.push(listener)
                                                                  
                                                                      return function unsubscribe() {
                                                                        if (!isSubscribed) {
                                                                          return
                                                                        }
                                                                  
                                                                        isSubscribed = false
                                                                  
                                                                        ensureCanMutateNextListeners()
                                                                        var index = nextListeners.indexOf(listener)
                                                                        nextListeners.splice(index, 1)
                                                                      }
                                                                    }
                                                                  

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

                                                                  Самое читаемое