Нет, это не очередная попытка объяснить монады. Я не знаю, как это сделать и не могу представить, как бы я, например, из настоящего мог бы объяснить это себе из прошлого.

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

Я даже не знаю, как ответить на более простые вопросы. Несмотря на то, что пишу на Scala больше 3 лет, я не могу на пальцах объяснить преимущества языка для человека извне. Например, пару месяцев назад мне довелось провести не лучшую дискуссию.

Всё началось с вопроса: “А для кого вообще ваш язык написан?”.
В моей голове вертелись все эти иммутабельности, функции высшего порядка, великая система типов, сайд-эффекты и прочие монады, но я понимал, что это всё не то. Последовавшее уточнение окончательно отправило меня в нокаут: “Вот, например, Java – это язык для белых воротничков”. Тот диалог закончился какой-то несвязной ахинеей про невозможность объяснить разницу без практики.

Мы не умеем продавать FP

Это не просто пересказ личного опыта. Все мы, пользователи функциональных языков, находимся примерно в идентичной ситуации. Мы прекрасно понимаем огромную разницу в сравнении с Blub языками, но остальной мир не хочет нас слышать. Конечно, можно злиться на ограниченность консерваторов, которые хавают “Г”, преспокойно несут чушь, пересказывают друг другу мифы и сказки, твёрдо и уверенно вступают в дискуссии о вещах, на которые даже пары часов не потратили. Можно также винить огромные корпорации с их отрядами маркетологов.

Но мне кажется, в первую очередь, проблема в том, что мы сами не умеем продавать FP. Да, это нелегкая задача. Хотя, когда я вспоминаю, как люди принимают решения, как и какие вещи входят в тренды, то начинаю думать, что это возможно.

В разработке всегда что-то не так.

  • Процессы медленные! И вот уже через несколько лет каждое утро, во всех офисах страны люди, стоя у доски, перетаскивают стикеры из одной колонки в другую.
  • Деплой медленный! И вот вооруженные ценностями devops, мы делаем по 10 релизов в день, в то время как новое поколение админов заливают это тоннами ruby, python и yaml.
  • Приложения сложные! И вот команды в 2-3 разработчика сооружают новую микросервисную архитектуру, детально продумывая ответственности каждого сервиса и делая по 10 пул-реквестов на одну маленькую правку.

Не то чтобы я считал все эти повальные увлечения в индустрии плохими. Просто у них тоже есть немало недостатков. И не все умели или умеют их правильно готовить. Отсутствовал или отсутствует удобный тулинг. Тем не менее, эти подходы стали “де-факто” стандартными для индустрии. И хотя обсуждения про docker в продакшене для некоторых кажется еще не закрытым вопросом, всё уже произошло.

Я уверен, то же самое может произойти и с функциональными языками. Да, это не совсем корректно – сравнивать языки программирования с методологиями и подходами. Но нам есть что позаимствовать в их позиционировании для себя. У всех них есть строго определённая проблема, которую они решают. И это скорость: разработки, коммуникаций, планирования, деплоя, внесения изменений…

Почему мы забываем сказать о самом главном?

В тоже время, с точки зрения позиционирования функциональных языков программирования, сложно сказать что у них есть четкая и понятная цель. Языкосрачи “FP vs OOP” обычно быстро скатываются в мерянье фичами и концептами, ценность которых мало понятна OOP-лагерю. Статьи и доклады формата “Вы посмотрите, как эти монады великолепно композируются” чаще закрепляют в людях мнение, что это им не нужно, чем вдохновляют попробовать. Все эти взаимодействия, крайне редко отвечают на вопрос “А зачем это все?”. Красиво и лаконично? Ну в лучшем случае будет упомянуто о меньшем количестве ошибок.

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

Да, это звучит слишком просто и даже очевидно.

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

Стоит перестать строить из себя умников, сходу раскидываясь терминами направо и налево, доказывая превосходство своего любимого ЯП над Blub. Вместо того, чтобы доказывать полезность фичи X, гораздо проще ее использовать как объяснение какого-то более понятного свойства. Если это получилось у других техник, возможно, нам тоже пора уже взять на себя ответственность и твёрдо заходить с очевидных и простых вещей.

Так что в следующий раз при сложностях ответа на вопрос "А зачем?" не стесняйтесь заходить с козырей, таких как: более высокая скорость разработки, более дешевая поддержка, меньшее количество разработчиков.

Ах, и еще. Ивенты для сообществ тоже играют не малую роль в позиционировании!
Поэтому, мы ждем всех неравнодушных к FP на единственной функциональной конференции в России — FPURE — Казань — 24-25 мая.
В программе: Haskell, Scala, Elixir, Clojure, теория и практика, и конечно же много единомышленников с кем найдется о чем поговорить!

Комментарии (95)


  1. vvm13
    30.04.2019 16:47
    +1

    Smalltalk продавали так же («более высокая скорость разработки, более дешевая поддержка, меньшее количество разработчиков») — но продать не сумели.


    1. exception13x
      30.04.2019 17:55

      Идеи Smalltalk вполне себе живут в Erlang.


      1. napa3um
        01.05.2019 01:54

        Повлиял на: Objective-C, AppleScript, C#, Dylan, Groovy, Io, Java, Lisaac, NewtonScript, Python, Ruby, Scala, Self, C++
        © Wiki
        тысячи их )


  1. muhaa
    30.04.2019 16:50
    +5

    Я не знаю, как это сделать и не могу представить, как бы я, например, из настоящего мог бы объяснить это себе из прошлого.

    Вот здесь чуть больше чем за час физик сумел объяснить что такое бозон Хигса людям, не знающим физику. При наличии кристально четкого понимания предмета можно объяснить кому угодно что угодно. Нужно просто последовательно описать область применения, круг решаемых проблем и собственно способ их решения.


    1. red75prim
      30.04.2019 21:07
      +1

      А они потом смогли сделать свой бозон Хиггса? Или хотя бы сечение рассеяния на электроне посчитать? Программистам приходится.


      1. muhaa
        01.05.2019 09:52

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


        1. red75prim
          01.05.2019 10:40

          Да, но это — в любом случае сложнее, чем сказать: «Как вы здорово всё объяснили, я понял». С теми же монадами тоже не так всё просто — им соответствует множество концепций, на первый взгляд никак не связанных: вычисления на списках, передача состояния, ввод/вывод и т.д.

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

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


  1. ksbes
    30.04.2019 16:58
    +3

    Сразу хочу сказать — тезис поддерживаю. Статья понравилась, хотя и коротковата. Хотелось бы более развёрнутого ответа:

    Так что в следующий раз при сложностях ответа на вопрос «А зачем?» не стесняйтесь заходить с козырей, таких как: более высокая скорость разработки, более дешевая поддержка, меньшее количество разработчиков.


    Простые констатации меня, ярого ООПшника не убедят. Я не вижу более высокой скорости разработки. Не вижу более лёгкой поддержки. Малое количество ФПшиков — вижу. Но это скорее недостаток, чем достоинство.

    Разработка — это же не простое кодирование. В нормальном процессе разработки сначала идёт понимание, выраженное в документе. Сначала идёт описание. Текстовое. Устно или письменно. И лишь потом код.

    И, как показывает практика, выражать свои мысли, обмениваться ими, пользуясь терминологией и подходом ООП — просто. Понятно даже тем, кто не знает ООП. Собственно под «естественное понимание человеком» этот подход и разрабатывался.

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

    А раз люди друг друга не понимают — то о какой скорости разработки может идти речь? О какой поддержке?


    1. LMnet
      30.04.2019 17:46
      +3

      А вы случаем не путаете "просто" и "знакомо"? Проектирование систем в фп стиле не означает, что система проектируется с использованием таких штук как "функтор" или "монада". Это проектирование, в котором иммутабельные данные проходят через ряд преобразований внутри функций. А функторы и монады — это уже детали реализации. Фп никаким образом не влияет на возможность людей договориться. Это просто немного другой подход. И, более того, на практике он не сильно отличается от тех же ооп best practices.


      1. ksbes
        30.04.2019 18:09
        +1

        Не путаю.

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

        Ещё раз повторяю: разработка — это не просто по клавишам потыкать. Если не можешь на бумажке со стрелочками объяснить как оно работает, то это коддинг в самом плохом смысле этого слова.

        И мой вопрос как эти стрелочки выглядят для программы на ФП?


        1. LMnet
          30.04.2019 18:15
          +2

          Точно так же, как и для ооп.


          Я открою вам страшный секрет — из одной и той же "архитектуры на листочке" можно сделать программу как в фп стиле, так и в ооп. Никто не проектирует "морфизмами".


          1. solver
            30.04.2019 20:05

            Никто не проектирует «морфизмами»

            Это вы так думаете)
            А адепты ООП, ничего кроме ООП не видели. И «проектируют» архитектуру объектами.
            И в документах описывают объекты. И думают, что все так делат. Потому, что их большинство и ничего другого они во круг не видят… Да и желания у них посмотреть как можно по другому, то же нет. Вот и получается замкнутый круг…


            1. trix
              30.04.2019 20:58

              Предметная область в скала-проекте будет описана всё теми же объектами.


              1. solver
                01.05.2019 20:32

                Э… вы правда думаете, что ООП это когда есть объекты? ))

                Ну тогда вы только подтвердили мой комментарий…


                1. trix
                  01.05.2019 20:54

                  не стоит приписывать оппоненту слова, которые он не говорил.


            1. areht
              02.05.2019 21:16

              А где смотреть то?

              Я сколько статей про ФП вижу — там про функторы и монады. Как будто и правда никто ничего не проектирует.

              Ну вот я возжелал посмотреть, открываю вики ООП, вижу раздел «Проектирование программ в целом»

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

              Открываю соседнюю вики ФП и вижу вместо него «Стили программирования» с
              Императивные программы имеют склонность акцентировать последовательности шагов для выполнения какого-то действия, а функциональные программы к расположению и композиции функций, часто не обозначая точной последовательности шагов.

              Чувствуете пропасть между интересами писавших это людей? Наверное, в ФП тоже кто-то проектирует, но продавать все пытаются функторы, монады и примеры на 2 строчки:
              # функциональный стиль
              # языки ФП часто имеют встроенную функцию compose()
              compose2 = lambda A, B: lambda x: A(B(x))
              target = map(compose2(F, G), source_list)
              


              1. graninas
                03.05.2019 12:45
                +1

                Вот, смотрите, я пректирую (и пишу книгу про это):

                www.patreon.com/functional_design_and_architecture

                Монады там тоже есть.


                1. areht
                  04.05.2019 07:30

                  Спасибо, интересно было полистать. Жаль только половина книги, тема TDD не раскрыта.

                  Но в целом, та же фигня: много низкоуровневого описания возможностей, а чуть выше — ну, типа, сами придумаете.

                  > In FDD methodology, brainstorming is the preferred method for gaining a deep understanding of things.

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

                  PS. «if we don't have a bird’s-eye view of the software we are going to create, how can we make architectural decisions?» — Как обычно: как можем, так и решаем. Потом переделываем. А что, у вас бизнес-требования не меняются вплоть до переписывания с нуля?


          1. JC_IIB
            30.04.2019 21:42

            Мне в этом плане понравился ответ Druu в одном из давних постов graninas, цитирую полностью:

            «Ну вам чтобы использовать абстрактную фабрику требуется знание какой-то особенной теории? Думаю, нет. Так и с монадами/функторами — смотрите на это как на определенный интерфейс, который предоставляет определенные возможности.»


            Так же и здесь. Никто не пишет «а вот тут абстрактная фабрика будет генерировать… что-нибудь».


        1. trix
          30.04.2019 21:18

          Вы каждый if будете описывать на бумаге? Например, в Яве8 наконец-то появились лямбды и стримы, и народ их начал вполне эффективно использовать, ибо давно наболело. Это самое что ни на есть ФП (\шёпотом\ и даже с монадами, хотя большинство разработчиков даже не знают, что они используют монады), просто ООП это тоже не отменило.


        1. muhaa
          01.05.2019 10:20

          Если система (например, банковский биллинг) строится на ООП, то она должна и описываться в терминах ООП в документации.
          ИМХО ФП — это прежде всего метод, позволяющий совладать с очень сложными алгоритмами (сложными алгоритмически а не в смысле количества внутренних интерфейсов и бюрократических процедур, которым алгоритм должен поклониться). Это могут быть алгоритмы для некого принятия решения, оптимизации. Условно говоря, это когда функция получает на входе простой запрос и доступ на чтение к доменной модели, выполняет алгоритм на несколько тысяч строк и возвращает простой ответ. В подобных случаях преимущества ФП бесспорны: четко видно что принимает и выдает каждая часть кода, нет необходимости изобретать кучу странных классов, нет проблем с много-поточностю, хранение промежуточных данных в имутабельных структурах итоге проще, чем в каких-то запутанных временных объектах. Если же проектировать нечто вроде биллинговой системы, то это все равно будет много взаимодействующих компонентов и общая схема системы будет одинаковой для проекта на ООП и на ФП.


    1. graninas
      30.04.2019 18:08

      > А ФП теряет своего слушателя уже на втором использовании слова «морфизм» и на первом использовании слова «функтор». Я слабо себе представляю как люди проектируют рабочие системы пользуясь диаграммами из теории категорий в техническом задании.

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


      1. ksbes
        30.04.2019 18:15

        Подсистема, интерфейс, имплементация — это термины ООП. И если люди их используют, то они программируют на ООП, хоть и кодят в ФП. Тогда и не надо говорить о «программировании на ФП». Тогда и понятен провал — на раскоряку сидеть неудобно.


        1. graninas
          30.04.2019 18:28
          +3

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


        1. knotri
          01.05.2019 13:33

          интерфейс ~= контракт ~= сигнатура ~= типы параметров функции
          имплементация = реализация
          подсистема = подсистема (хмм, лол)
          как это относится к ООП???


    1. sshikov
      30.04.2019 18:31

      >Простые констатации меня, ярого ООПшника не убедят. Я не вижу более высокой скорости разработки. Не вижу более лёгкой поддержки. Малое количество ФПшиков — вижу.

      Ну, мы верим. Собственно, текст об этом — что надо лучше продавать. Надо подать так, чтобы вы увидели.

      Я вот вижу слегка другое. Например, ФП в Java-сообществе довольно долго было «на задворках». Кто знает, что была и есть такая штука, как functional java, существующая очень давно? Да почти никто пожалуй и не знает. Зато с появлением Java 8, где некоторые части ФП стали частью языка, вот это вот все, скорость разработки, легкая поддержка — они видны всем, кто вообще хоть как-то интересуется. Яркий пример — то, как преобразились широко известные паттерны ООП с появлением функций в таком виде, что с ними стало реально удобно работать.

      Они видны всем, кто работает и с такими вещами, как Spark. Хотя да, было бы очень неплохо не просто сказать «а я это вижу», но и померять.

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

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


      1. Kakadout
        01.05.2019 10:42

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


        sshikov, a можно пример или ссылку на пример?


        1. sshikov
          01.05.2019 10:55

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


      1. pin2t
        01.05.2019 17:43

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


        Для любого произвольного и не надо, системы проектируются под конкретную клиентскую задачу. Система для любого произвольного применения — ОС. Только надо сначала программу написать :) а так любую задачу решает.

        Не бывает абстрактных задач, все задачи конкретные.


        1. sshikov
          01.05.2019 20:53

          Так я и хочу сказать, что ООП не панацея для любой задачи. Какие-то задачи на нее неплохо ложатся, а какие-то приходится как сову на глобус.


          1. TheShock
            02.05.2019 03:22

            а какие-то приходится как сову на глобус.
            Какие к примеру?


            1. red75prim
              02.05.2019 08:00

              Библиотеки линейной алгебры, например. Иерархия чисел (целые, с плавающей точкой, комплексные и т.п.).


            1. sshikov
              02.05.2019 09:05

              Из того, что мне лично попадалось недавно, это пожалуй интеграционные задачи разного рода. Их обычно описывают в терминах так называемых EIP (enterprise integration pattern), которые сами диаграммы, и на ООП они ложатся так себе. Не то чтобы их нельзя было в таких терминах описать — а просто пользы от такого описания не будет, и реализация обычно не в этих терминах все равно.

              При этом описание другого бизнес-проекта почти на 100% состояло из одной здоровой ER-диграммы, и все отображалось в объекты и манипуляции с ними.


          1. pin2t
            02.05.2019 11:38

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


            1. sshikov
              02.05.2019 11:56

              Ну, я в штуках не считал, поэтому про большинство говорить не стану. У меня — где как, в последних проектах на спарке от ООП по большей части тоже рожки да ножки.

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


            1. nlinker
              02.05.2019 19:29
              +2

              1. Описать с помощью ООП как корова щиплет траву (там будет корова.щипать(трава), трава.бытьОщипанной(корова) или Природа.поедание(корова, трава)?).


              2. Есть лужа (совсем необязательно являющаяся сечением шара), в лужу бросили камень (вектор скорости совсем необязательно перпендикулярным поверхности). Задача: описать поведение волн с течением времени. Вот здесь бесполезность ООП лично для меня очевидна — задача поставлена, есть необходимость её решать, но ООП здесь совершенно никак не вклеивается — можно конечно создать классы "Лужа" и "Камень", и описать метод "взаимодействовать", но это даже на миллиметр не приблизит нас к моделированию действительности.



              PS: А приблизит нас тоненькая брошюрка "Введение в динамику жидкости" товарища Бэтчелора и такая же тоненькая "Вычислительная математика" Тихонова+Самарского. В первой книжке мы найдём как выписать систему уравнений Навье-Стокса для нашей лужи, а во второй книжке мы найдём методы, как решать системы диффур численно. Покроем лужу достаточно мелкой сеткой, напишем алгоритм числнного решения (с прицелом на кластер) и вот тогда мы приблизимся таки к моделированию нашей действительности. И тут — о чудо — появятся объекты, да. Например, vector, matrix, обёртки над сокетами и тому подобные технические сущности. Причём набор этих сущностей будет существенно зависеть от выбранного способа решения. Однако куда делись лужа с камнем?


              1. pin2t
                02.05.2019 19:49

                Лужа с камнем никуда не делись, камень изменил свои координаты и теперь лежит в луже. Просто Ваше внимание переключилось с лужи и камня на волну, которая возникла на поверхности лужи, для описания формы которой Вы читаете Бэтчелора, Тихонова+Самарского и составляете систему уравнений Навье-Стокса.


              1. pin2t
                02.05.2019 19:59

                1, 2. Вы просто как, видимо, функциональщик, акцентируете внимание на действиях, «щипать» и «бросать». НУ в этом смысле да, если «не замечать» объекты, то как бы их и нет :) есть только «функции».


                1. leon_nikitin
                  02.05.2019 20:24

                  Вообще-то, программирование — это составление программ, т.е. алгоритмов (описания действий). ОПП, ФП, Структурное программирование и т.п. и т.д. — это все о том, как декомпозировать программу (алгоритм). На какие части и как. О том, как сделать кирпичики, чтобы из них собрать программу (алгоритм).

                  Описание требований и т.п. — это не программирование. И тут ООП не причем. Декомпозиция и описание ИС — это не совсем про программирование, т.е. написания программы.


              1. TheShock
                02.05.2019 20:46

                Описать с помощью ООП как корова щиплет траву (там будет корова.щипать(трава), трава.бытьОщипанной(корова) или Природа.поедание(корова, трава)?).

                Ну такой глупый пример и в обратную сторону сработает. На ФП как? Так?
                новаяКорова = кушать(стараяКорова, трава)


                Или, может так:
                новаяКорова = кушать(трава, стараяКорова)


                Что будет, если я передам траву тигру?
                новыйТигр = кушать(трава, тигр)


                Можно ли так?
                новыйТигр = кушать(корова, тигр)


                Сработает ли тогда так?
                корова3 = кушать(корова1, корова2)


                1. solver
                  02.05.2019 21:00
                  +1

                  Очень корявое передергивание…
                  Вы пытаетесь глупыми, за ранее корявыми примерами сместить фокус обсуждения с абсолютно корректного вопроса проектирования в ООП в плоскость семантики конкретного языка.

                  P.S. Если писать на JS, то все ваши вопросы открыты и ответы зависят от компетенции разработчика. Если писать например на Haskell, то большинство ваших примеров просто не скомпилятся ввиду несоответсвия типов.


                  1. TheShock
                    02.05.2019 21:15

                    Я же сразу сказал — это глупый пример в ответ на глупый пример. Вам ваш пример не кажется глупым потому что вы — фанбой. Вся критика ООП кажется глубокой и остроумной, как та глупость с паттерны-против-функций

                    И вопрос не в семантике. Как бы вы не писали эти примеры — вопрос остается тот же.


                    1. nlinker
                      03.05.2019 12:42

                      Да в том-то и дело, что проблемы подобные коровам и траве в реальных проектах встречаются повсеместно, и разработчики далеко не всегда выбирают нужный класс удачно (это во многом зависит от ответственностей, которые навешивают на классы впоследствии). Кроме того, есть много ошибок, связанных с компромиссом "богатый интерфейс + удобство использования vs минималистичный интерфейс + удобство реализации". SOLID опять же, понятие "single responsibility" может варьироваться в широких пределах в зависимости от конкретного человека и его понимания — что для одного single, для другого — multiple.
                      Теперь как решать указанную задачу в Хаскеле например:


                      eat :: Cow -> Grass -> Cow
                      eat cow grass = ... newCow -- да, вернём новую корову

                      попытка подсунуть траву тигру, или траве корову закончится ошибкой от компилятора. Если же так получилось, что мы вынуждены использовать функцию Grass -> Cow -> Cow, а нам удобно Cow -> Grass -> Cow, то это делается одной строчкой:


                      -- используем HOF flip :: (a -> b -> c) -> b -> a -> c
                      eatFlipped = flip eat

                      Если вам будет угодно, можете flip считать паттерном "Адаптер" на кончиках пальцев (а кроме этого есть ещё более легковесный карринг), её можно определить локально, как только она где-нибудь понадобится.
                      В любом случае, мне не пришлось решать дилеммы выше (куда приклеить функцию eat, достаточно ли Single Responsible полученная Корова или Трава, и нужно ли добавлять метод size в корову или и так сойдёт (ведь size можно посчитать просто как сумму частей!).


                      1. TheShock
                        03.05.2019 12:50

                        Почему в вашем коде тигр не может съесть корову?


                        1. develop7
                          03.05.2019 13:40

                          не обучен


                        1. nlinker
                          03.05.2019 15:59

                          А должен?


      1. hexproof
        01.05.2019 21:26

        всякие мат алгоритмы на haskell быстрее же писать?


        1. sshikov
          01.05.2019 21:41

          Подозреваю что да. Я разве говорил что-то обратное?


    1. trix
      30.04.2019 21:30
      +2

      Простые констатации меня, ярого ООПшника не убедят. Я не вижу более высокой скорости разработки. Не вижу более лёгкой поддержки


      И не увидите, скорость и простота поддержки зависят в куда большей степени от разработчика, а не от того, на чём он пишет. Тут можно было бы сказать «если нет разницы, зачем платить больше», но у нас есть отличный пример того, как сам ОО подход принимался индустрией. Сначала большинство разработчиков тоже не понимало, зачем так всё усложнять. А потом рост сложности проектов ярко показал выгоды.
      ФП существует очень давно, но теперь его внедрение толкает вперед индустрия больших данных и параллельных вычислений, чем больше людей становятся знакомы с ФП-концепциями, тем больше они начинают находить им применение в самых разных областях, Так что лет через 10 говорить будут не «ФП даёт более высокую скорость/лучше поддержку», а «проекты такого уровня сложности никто уже давно не делает на голом ООП».


  1. ppopoff
    30.04.2019 17:25

    Как мне кажется, с задачей "Объяснить монаду" неплохо справился Миран Липовича в своей книжке с голубым слоном. Но в Scala, не используя scalaz/cats это сделать не просто, скажем так.


    1. nlinker
      01.05.2019 19:39

      Да, согласен


  1. time2rfc
    30.04.2019 18:19

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


    https://www.youtube.com/watch?v=dWyGM3MnN0A


  1. sergey-gornostaev
    30.04.2019 19:56

    Пол Грэм ещё в 2001 всё необходимое сказал по этому поводу в статье "Побеждая посредственность".


    1. dos65 Автор
      30.04.2019 21:07

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


    1. bjornd
      01.05.2019 11:16

      Люди постоянно упускают из виду что современная коммерческая разработка уже давно не про абстракции, ФП, ООП, etc. Она про взаимодействие между людьми. По ссылке пример успеха Пола Грэма с Viaweb написанном на Lisp'е и вроде как ставшим успешным как раз благодаря Lisp'у. Но это же полная чушь, Viaweb был куплен Yahoo! за $45m благодаря организационному таланту и инвесторской проницательности Грэма, а не благодаря Lisp'у. Сколько успешных проектов написано не на языках ФП, сколько проектов обвешаных монадами кануло в безвестности? Люди > технологии. Если вы можете найти команду отличных специалистов ФП среди которых не будет примадон занимающихся самообразованием вместо решения проблем бизнеса — отлично, вам повезло. Но в большинстве случаев вам придется делать проекты с теми разработчиками, которые есть на рынке.


      1. sergey-gornostaev
        01.05.2019 12:05

        Статья не про то, как Грэм продавал проект Yahoo!, а про то, как этот проект делался. Центральная мысль статьи о том, что команда проекта играючи душила конкурентов благодаря возможности легко и быстро изменять код, что в свою очередь было заслугой Lisp'а. Можно быть сколь угодно хорошим предпринимателем, но если инструмент зарабатывания денег не позволяет быстро реагировать на требования рынка, успеха не достичь. Многие современные тенденции в отрасли, упомянутые dos65 — гибкие методологии, DevOps, микросервисная архитектура — предназначены как раз для этого, как можно более быстрой реакции на требования рынка. И мы ещё не затрагиваем вопрос того, что стоимость поддержки существенно выше стоимости разработки, а ФП может помочь эти затраты снизить.

        Я в целом согласен, что люди значат больше, чем технологии. Но и тут у ФП преимущество, если верить отзывам компаний, нанимающих clojure-программистов. Они заверяют, что Clojure стоило выбрать уже за то, что тот открыл им рынок высококачественных соискателей и возможность формирования превосходных команд. Впрочем, я думаю, что это связано с относительно высоким порогом входа и пока ещё низким спросом. Уверен, лет через 10 вероятность напороться на примадону будет одинакова как при найме джависта, так и кложуриста.


        1. sshikov
          02.05.2019 12:13

          >Центральная мысль статьи о том, что команда проекта играючи душила конкурентов благодаря возможности легко и быстро изменять код, что в свою очередь было заслугой Lisp'а.

          Наверняка же знаете такой анекдот: а я на машинке умею быстро-быстро печатать! Такая х-ня получается :) Я тоже могу код легко и быстро изменять, это всегда можно было, только проблема как правило не в коде.

          У бизнеса (который обычно представляют аналитики) уходят месяцы на обдумывание. У поддержки уходят месяцы на то, чтобы обнаружить проблему. Разработчик меняет код за 15 минут.


  1. Gorthauer87
    01.05.2019 00:35
    +1

    Вообще справедливости ради ФП не отменяет ООП, он скорее противоположен императивному программированию.


    1. sergey-gornostaev
      01.05.2019 05:34

      На днях как раз видел хорошее высказывание по этому поводу от умного человека
      image


  1. 4lex1v
    01.05.2019 01:06

    Спасибо за статью, надеюсь Вы не бросите попыток освоить глубины функционального программирования!

    Нет, это не очередная попытка объяснить монады. Я не знаю, как это сделать и не могу представить, как бы я, например, из настоящего мог бы объяснить это себе из прошлого.


    Могу предположить, что Вам неоднократно задавали похожий вопрос, интересно, что Вы отвечали?

    Монады весьма забавная концепция, я до сих пор вряд ли смогу объяснить внутреннюю математику в рамках категорий, но с практической точки зрения всегда определял как абстракцию вычислительного процесса. Что такое вычисления понимают все, а абстракция просто говорит о том что мы описываем вычисления не вдваясь в детали контекста (происходит ли это асинхронно, есть результат или нет, может упасть с ошибкой или вернуть результат и т.д). Scala к сожалению скрывает суть за синтаксическими нагромождениями.

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


  1. vpatryshev
    01.05.2019 08:32

    Чудесно!

    По мне так ответ на эту загадку простой — эти люди сойдут со сцены, и придут те, кто «понимает монады». У нас в группе как-то с этим не видно проблем, например.

    Я насмотрелся в жизни и страха перед фортраном, и страха перед си++, и страха перед джавой, и страха перед ООП, и страха перед ФП; теперь вот все баяцца монад. Ну пусть боятся; эти люди ж не вечно на арене. Придут те, что не боятся. map и flatMap для них естественная вещь. Я этих людей вижу каждый день.

    Ну и монада не конец света, конечно. Линзы (и вообще оптика), свободные монады (я в них не верю, там нужно сохранение фильтрованных копределов), расширения Кана… жизнь идет. А «любители ООП» (можно подумать, они родились с ООП в голове) уйдут на пенсию, будут ныть там.


    1. amarao
      01.05.2019 11:10

      Главная проблема «монады» в её названии. Что такое объект? Что-то, что можно взять, положить, посмотреть во внутрь. Что такое тред? Что-то, что вьётся, у чего есть продолжительность, начало и конец. Что такое pipe? На вход что-то, на выход оно же.

      Простые, ясные, бытовые аналогии.

      А теперь, какие бытовые свойства у монады? Например, быть непонятной.


      1. nlinker
        01.05.2019 20:05

        > А теперь, какие бытовые свойства у монады? Например, быть непонятной.

        Сохранение порядка эффектов независимо от способа вычисления (энергичного, параллельного, или какого-нибудь из ленивых — неважно)


        1. amarao
          01.05.2019 21:04

          Это вы уже придумали. Откуда слово «монада»? Почему «это» решили назвать «монада», а не «сепулятор»? Очевидно, что все свойства сепулятора так же выполняются.

          Я повторю, что для центрального объекта для программирования, использованное слово — катастрофа семантического масштаба.

          Сравните с трейтами. Внутри — предикаты на типах. А снаружи? «черты характера, типаж». Мы хотим от структуры иметь такие-то черты характера. Блистательная аналогия.

          А монады — семантическая бездна. Кто, вообще, притащил её в математику, откуда и чем объяснял?


          1. nlinker
            01.05.2019 22:43

            То есть вас интересует просто этимология термина monad? Лично я не в курсе, но я уверен, это можно разыскать, было бы желание.
            Я бы предпочёл вести более содержательную беседу, чем спор о терминах.

            Монада для разработчика на Haskell, например, имеет вполне конкретный смысл безо всяких аналогий (это тайпкласс вместе с требованиями на его инстансы).
            Если вам легче, можете это назвать Chainable, Sepulator или LittleFuzzyThing, но тем самым вы уничтожите шанс быть понятым другими.

            А аналогии вообще вредны почти всегда, ибо дают ложное ощущение понимания.


            1. amarao
              01.05.2019 22:57

              Если бы аналогии были вредны, то компьютеров у вас бы не было. Все хорошие компьютерные слова, которые у вас есть, придуманы талантливыми людьми, которые считают термины очень содержательными.


              Вот, например, ваши… файлы? Почему это файл? Да ладно, файлы. У вас на экране окно браузера. (два термина, очень хороших). В вашем хаскеле у вас данные организованны в списки и массивы, а память выделяется из кучи. Возвращаемые значения и адреса возвратов складываются в стек, ваши монады называются Maybe и Either, а память вашего компьютера считается в байтах. Каждое из этих слов построено на аналогиях, крайне вредных.


              Мы же знаем, что на самом деле ijk f l_n z^k, и те, кто не способен понять смысл этого без "аналогий" просто не хотят тратить время на более содержательную беседу, чем спор о терминах.


          1. vpatryshev
            02.05.2019 00:02

            Монаду не притащили, а открыли путем наблюдений над самыми различными явлениями. Которые обобщаются примерно на такое — «функтор с pure и flatten».

            Но, как я погляжу, тут ан масс невежды протестуют против математики. Да не хрен ли с ними, с невеждами. Математику они не отменят; отменят они только самих себя.


            1. amarao
              02.05.2019 10:42

              Вы можете сказать, что такое «монада» в отрыве от математики? Происхождение слова?

              Вот, например, я понимаю бытовой смысл слова «предел». И слово «решётка» у меня тоже не вызывает вопросов. Даже континуум, каким бы крипи он не был, всё равно имеет бытовой смысл. А «монада»?


              1. vpatryshev
                02.05.2019 18:08

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


                1. amarao
                  02.05.2019 18:13

                  Приложение — слово появилось за долго до компьютеров и подразумевало что-то дополнительное (к компьютеру). Что-то, что делает его «прикладным» (слово появилось до компьютеров и используется в быту).
                  Функция — вполне используется в быту. (Функция компьютера — считать)
                  Переменная — вполне вошло в быт, и смысл очевиден из названия (что-то, что меняется).
                  Мораль в бытовом языке используется похлеще, чем в философии.

                  Ещё вопросы?


                  1. JC_IIB
                    02.05.2019 19:20

                    Ещё вопросы?

                    Так что там с моральным законом-то? Какова бытовая метафора?


                    1. amarao
                      02.05.2019 19:33

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


                      1. JC_IIB
                        02.05.2019 20:16

                        Слово мораль — бытовое.

                        Смысл слова «переменная» очевиден из названия, а вот очевиден ли из названия смысл слова «мораль»?


                        1. mk2
                          02.05.2019 21:33

                          Объяснять базовые понятия — это боль. Например, слово «точка». Да, я могу потыкать в. и сказать, что вот это точка — но к четкой формулировке это нас не приближает.

                          Другое дело, что с точками все знакомятся в школе.


                  1. vpatryshev
                    03.05.2019 02:54

                    Отвык я уже вести ученые беседы с троллями, несущими херню.


                    1. TheShock
                      03.05.2019 12:07
                      -1

                      Дано:
                      amarao, 200 статтей, 20000 комментариев, 280 кармы
                      vpatryshev, 0 статтей, 34 комментария, -2 кармы

                      Внимание, вопрос: Кто из этих двоих — тролль?


                      1. areht
                        03.05.2019 13:17

                        Ну вот вы явно троллите.

                        Статей, кармы и комментариев у вас ближе к amarao.


                        1. TheShock
                          03.05.2019 13:20

                          В каком месте я, вдруг, троллю?


                      1. develop7
                        03.05.2019 13:41

                        никто?


                        1. TheShock
                          03.05.2019 13:47

                          Вполне возможно, тогда зачем вообще поднимать вопрос на счет троллинга?


                      1. red75prim
                        03.05.2019 14:49

                        Не вижу почему бы благородному дону немного не потроллить. По крайней мере очень похоже.


                      1. vpatryshev
                        03.05.2019 16:46

                        О, действительно, не тролль — масса интересных статей у него. Спасибо.


                  1. akryukov
                    03.05.2019 22:09

                    Переменная — вполне вошло в быт, и смысл очевиден из названия (что-то, что меняется).

                    Не знаю, в чей именно быт вошло слово "переменная". Но описывать ее смысл словами "что-то, что меняется" некорректно. На мой взгляд, упущены такие факты:
                    1) Переменная всегда как то именуется. Без имени нет никакой определенности в изменении. По имени можно записать значение и прочитать значение.
                    2) При чтении значения из переменной, оно из переменной не пропадает.
                    3) При записи нового значения, старое исчезает бесследно.
                    Есть бытовая аналогия, которая выдерживает все эти пункты?


                    Функция — вполне используется в быту. (Функция компьютера — считать)
                    Переменная — вполне вошло в быт, и смысл очевиден из названия (что-то, что меняется).

                    Исходный вопрос вообще был о функции четырех переменных, как о цельном понятии. Что то мне подсказывает, что в этом термине у слова "функция" совсем не то значение, которое вы объяснили.


      1. vpatryshev
        02.05.2019 00:10

        Это не свойство монады, это свойство, э, русских программистов, извините. Все непонятное вызывает страх. Ну, счастливого пути, конечно.


    1. sshikov
      02.05.2019 12:15

      Вот не надо про пенсию. К возрасту это никак не относится. Я тоже каждый день вижу тех, кто не боится flatMap — и среди них есть люди самого разного возраста.


  1. andreyverbin
    01.05.2019 10:13

    А кто сказал, что ФП что-то ускоряет? Я видел как знание предметной области, задачи, железа, ОС, языка, алгоритмов и библиотеки ускоряет разработку. Ещё я видел как разработку замедляет отсутствие нормальных IDE, средств отладки, мониторинга и профилирования. Ещё очень сильно разработку замедляет увлечение всякими «концепциями» типа ООП, ФП при отсутствии знаний перечисленных выше.


  1. 411
    01.05.2019 10:45

    Для меня вот пока не особо понятно, какие материалы(книги/статьи/и т.д.) являются хорошими по ФП, чтобы почитать самому и порекомендовать потом другим. Хоть и многие вещи из ФП используются довольно часто мною.


    1. trix
      01.05.2019 21:02

      попробуйте
      Functional Programming, Simplified by Alvin Alexander


      1. 411
        02.05.2019 13:39

        Спасибо, попробую


  1. amarao
    01.05.2019 11:07

    Аргументы про иммутабельность — удел слабаков, которые не осилили borrow/ownership model. Объект может быть либо общим, либо мутабельным в один момент времени. И всё, никаких больше проблем и undefined behaviour. А вот как уж язык может это энфорсить — это вопрос открытый.


  1. helions8
    01.05.2019 13:42

    Не туда воюете, IMHO, и смешиваете понятия. Например, странно видеть такую «ФП-приватизацию» иммутабельности. Есть Erlang, который со всех сторон иммутабельный, но который же и один из самых ООП из всех ООП языков, просто не в понятиях «разложим код по классам и методам». ADT есть во вполне себе императивных Rust и TypeScript, функции высшего порядка вообще были много где десятилетиями в явном (JS тот же) или не явном виде (реализация интерфейса с единственным методом apply).

    Может, стоит вообще начать с того, чтобы как-то выйти за пределы Blub-области в целом? Что ООП это не Borsch borsch = new Borsch(), а ФП это не только Клейсли ваш любимый, а просто стримы из Java, которые 1) содержат в разы меньше кода 2) ленивые 3) вы уже их используете, бояться поздно. А с ADT было бы удобно обрабатывать ошибки, не выхватывая NPE в щи.

    Абстрактные аргументы про «скорость разработки» и «меньше ошибок» без хорошей статистики ничего не стоят, а «легкая композиция» вообще из области вкусовщины.


    1. nlinker
      02.05.2019 10:11

      В Эрланге есть функция с побочным эффектом (send, !, посылка сообщения процессу), и этот эффект настолько мощный, что на базе него реализуетмя и мутабельное состояние, и ввод-вывод, и исключения и много чего ещё. И из-за этого также образуются всё те же проблемы, как в оопе — гонки, дедлоки, лайвлоки и прочие. Благодаря иммутабельности объектов, проблем удаётся избежать на уровне процессов, но проблемы уезжают на уровень взаимодействия между процессами.


      1. helions8
        02.05.2019 11:55

        С этим нельзя не согласиться, но вроде как и не противоречит тому, что я написал.


        1. nlinker
          03.05.2019 12:46
          +1

          Не сразу понял посыл вашего сообщения, да, не противоречит. Считайте, что я дополнил ваш ответ.


    1. sshikov
      02.05.2019 12:25

      Насчет стримов… несомненно это тоже ФП. Хотя и частично. Могло бы быть и лучше, но и так неплохо прижилось.

      Легкая композиция — да, попахивает вкусовщиной, так как не формализована.

      Но с другой стороны, я уже года три как поймал себя на мысли, что вместо try/catch пишу Try.of(()->...). И возвращаю Try вместо String.

      Почему? Да все потому же — потому что легкая композиция. Потому что даже если получатель этого Try все еще может сделать .getOrElse(""), и проигнорировать ошибку, по неопытности обычно, но если пару раз дать по рукам, и научить таки пользоваться flatMap, то все становится сильно проще. И это все видят, и тот кто пишет, и тот кто читает.