image

Разработчики из американской компании Gaslight написали интересный материал о том, почему организация, известная своей любовью к Ruby и Ruby on Rails, решила инвестировать в освоение новых технологий — например, Clojure. Мы в «Латере» развиваем биллинг для операторов связи «Гидра» и тоже работаем с этим языком программирования, поэтому решили выделить главные тезисы команды Gaslight в отдельный материал.

Итак, почему стоит изучать Clojure и использовать его в реальных проектах?

Не только Ruby и RoR


По словам Джеффа Лэйна, написавшего пост в блоге Gaslight, с помощью Clojure его команде удается решать задачи, которые не по плечу Ruby. Он иллюстрирует этот тезис словами одного из основателей Gaslight Дуга Алкорна:

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

Лэйн говорит, что в компании все еще трепетно относятся к Ruby. Здесь все еще считают Rails лучшим решением для написания веб-приложений. Но, как и у любого инструмента, у него есть свои ограничения:

  • Ruby — не лучший выбор для многопоточного программировании, несмотря на существование JRuby и наличие библиотек вроде Celluloid.
  • Ruby и Rails почти всегда достаточно быстры. Почти, но не всегда.
  • Объектно-реляционное отображение (ORM) может не подходить для решения конкретных задач.
  • Объектно-ориентированные языки — это в принципе не всегда лучшее решение.

Функциональное программирование как альтернатива


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

«Функциональное программирование — раздел дискретной математики и парадигма программирования, в которой процесс вычисления трактуется как вычисление значений функций в математическом понимании последних».

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

Clojure работает на сервере
Возьмем описание работы языка с сайта Clojure.org:

«Clojure достигает своих целей, четко следуя стандартам индустрии и используя открытую платформу JVM. Это модернизация хорошо знакомого Lisp. Он обеспечивает функциональное программирование стабильными и устойчивыми структурами данных. Предоставляет встроенную поддержку многопоточного программирования с помощью софта для транзакционной памяти и асинхронных агентов. Clojure — это быстрые и надежные решения ваших задач».

Итак, Clojure работает на виртуальной машине Java (JVM), а значит, обладает несомненными преимуществами, которые предлагает этот инструмент:

  • высококачественный сборщик мусора;
  • высокопроизводительные встроенные потоки;
  • портативность.

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

Clojure работает в браузере
Еще одна цитата. Вот как описывает преимущества языка ClojureScript Wiki:

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

ClojureScript легко компилируется в JavaScript и запускается в браузере. Все это обеспечивает совершенно новый подход к созданию клиентских приложений. В сообществе разработчиков JavaScript по многим причинам недолюбливают. Clojure же можно назвать вполне самостоятельным отпрыском Lisp, удобным, лаконичным языком с отличной асинхронной поддержкой, пишет Лэйн. Он может взаимодействовать с другими библиотеками JavaScript. Это позволяет использовать один и тот же язык для клиентской и серверной части, избегая ненужных жертв и потери времени.

Обеспечение полного сохранения текущих состояний (statefullness) в приложениях для клиентов – штука непростая. И пока JavaScript-фреймворки (например, React или Ember) только подступаются к этой проблеме, стоит задаться вопросом – а не сменить ли кардинально сам подход? Возможно, найдется язык в пару к одному из этих фреймворков, способный научить нас лучше управляться с подобными сложностями.

Безусловно, не существует универсального инструмента, который бы подходил для решения всех типов задач. Однако тот факт, что Clojure можно использовать «по обе стороны баррикад» клиент-серверного взаимодействия — его несомненное преимущество.

Игра на опережение


Лэйн цитирует также великого хоккеиста Уэйна Гретцки:

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

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

Без лишней инновационности


В мире технологий иногда возникают вещи настолько передовые и новые, что польза от них не очевидна — хоть когда-то в будущем и может быть существенной — а применение несет в себе большие риски. Для обозначения таких технологий придумали специальный термин — «bleeding edge». Работать с ними комфортно только любителям всего нового.

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

Фундамент Clojure — хорошо знакомые технологии, например та же JVM, работа над которой ведется более 15 лет. Поэтому, работая с Clojure, можно использовать и все высококачественные библиотеки Java, существующие на данный момент.

Любопытство — двигатель прогресса


Ну, и самый последний аргумент «за» изучение Clojure — это любопытство и желание узнавать нечто новое. Всегда есть желание быть на передовой, владеть и уметь обращаться с лучшими технологиями на рынке. Clojure идеально подходит для этих целей. Всегда интересно ставить перед собой новые задачи. А находить для них решения – ни с чем не сравнимое удовольствие.

Сейчас в Латере мы используем Clojure выполнения команд по управлению оборудованием. Специфика задачи заключается в требованиях к одновременности при исполнении команд и гибких ограничениях. С одной стороны нельзя «завалить» одно устройство командами, с другой стороны — исполнять все команды последовательно неэффективно, потому что они могут параллельно исполняться на различном оборудовании. Эта задача с легкостью решается библиотекой core.async, которая добавляет поддержку go-блоков и каналов, знакомых по языку Go, где с помощью них реализованы взаимодействующие последовательные процессы (термин, больше известный как CSP).

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

Даже если вы на дух не переносите Lisp, вам стоит ознакомиться с концепциями, которые заложены в язык, многие из них заставляют по-новому взглянуть на программирование.

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


  1. IvanPanfilov
    02.04.2016 16:37
    -1

    kotlin лучше


    1. SerCe
      03.04.2016 16:08
      +3

      Эм? Языки из разных миров, совсем.


      1. solver
        03.04.2016 17:00
        +2

        Не обращайте внимание на таких, это обычная толстота…


      1. IvanPanfilov
        05.04.2016 11:08
        -1

        как из разных?
        оба крутятся на jvm, и под js kotlin будет скоро тоже

        так что кложа остается неудел
        и это никакие не «новые технологии» это уже прошлое


        1. anjensan
          05.04.2016 11:24
          +1

          Толще надо быть, толще.
          А по теме, как минимум static vs dynamic typing. Вам этого мало?


    1. vdonich
      03.04.2016 17:45

      Так не Лисп же.
      [сарказм офф]


  1. AndersonDunai
    02.04.2016 17:02
    -4

    HL3 Confirmed!


  1. wombtromb
    03.04.2016 00:36
    +7

    с помощью софта для транзакционной памяти

    Звучит очень коряво. Software transactional memory, SТМ, по-русски, обычно называют программная транзакционная память. Не мог не откомментить.


    1. Lure_of_Chaos
      03.04.2016 01:51
      +4

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


  1. lybin
    03.04.2016 10:20
    +1

    Статье имхо более подходящее название: "Мнение: Почему стоит уходить с Ruby и RoR на Clojure" :)


    1. slonopotamus
      03.04.2016 12:45
      +1

      Из статьи не следует почему стоит уходить именно на Closure.


      1. lybin
        03.04.2016 14:04

        Вырвано из контекста :)

        Clojure идеально подходит для этих целей.


    1. getElementById
      08.04.2016 15:05

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


  1. PerlPower
    03.04.2016 12:40
    +1

    Что меня смущает в ClojureScript так это то что несжатый helloworld на нем весит больше мегабайта, в ужатом и гзипнутом виде меньше 100 кб. Ну да ладно, его можно ужать и при росте объема полезного кода поверх рантайма ClojureScript рост размера будет не таким уж серьезным. Но это полбеды, ClojureScript хорош если вы пишите серьезную логику на клиенте, где структуры данных языка и его остальные возможности вам что-то упростят, но если вы как и большая часть людей вокруг делаете фронтенд из кусков всяких фреймворков и компонентов, то есть вероятность что вы просто устанете бороться с тем, что все эти куски заточены под языковые особенности JS а не ClojureScript.
    Вот 2 примера кода на ClojureScript и Javascript которые делают одно и то же с использованием фреймворка KnockouJS:

    (ns hello-clojurescript)
    
    (defn app-view-model []
      (this-as this
               (set! (.-firstName this) (.observable js/ko "Bert"))
               (set! (.-lastName this) (.observable js/ko "Bertington"))
               (set! 
                 (.-fullName this)
                 (.computed js/ko 
                   (fn []
                     (str (.firstName this) " " (.lastName this))) this))
               (set!
                 (.-capitalizeLastName this) 
                 (fn []
                   (.lastName this (-> this .lastName .toUpperCase)))))
      nil
      )
    
    (.applyBindings js/ko (app-view-model.))

    function AppViewModel() {
        this.firstName = ko.observable("Bert");
        this.lastName = ko.observable("Bertington");
        this.fullName = ko.computed(function() {
            return this.firstName() + " " + this.lastName();    
        }, this);
        this.capitalizeLastName = function() {
            var currentVal = this.lastName();     
            this.lastName(currentVal.toUpperCase());
        };
    
    }
    
    ko.applyBindings(new AppViewModel());


    1. SerCe
      03.04.2016 16:07

      Так стоит использовать идеоматичные фреймворки, обычно react-based
      https://reagent-project.github.io/
      https://github.com/omcljs/om


    1. tkukushkin
      03.04.2016 17:44

      Для ClojureScript есть библиотеки, исполняющие роль «прослойки», такие как Reagent, Om итп.


  1. atc
    03.04.2016 17:46

    Функциональные языки в отличие от объектно-ориентированных Ruby и JavaScript предлагают совершенно иной подход к решению задач.
    Но когда JavaScript успел стать объектно-ориентированным, позвольте спросить? Скорее его можно назвать мультипарадигменным, так как он включает неплохой набор инструментов как для функциональной парадигмы, так и для прототипной\объектно-ориентированной.


  1. l27_0_0_1
    03.04.2016 17:46
    +5

    Почему бы не Elixir?
    1) Функциональный
    2) Работает в проверенной временем и быстрой Beam VM, как бонус простая и эффективная многопоточность
    3) От одного из core разработчиков рельс
    4) Phoenix — прекрасный web framework похожий на рельсы, но имхо намного круче
    5) ОЧЕНЬ быстрый


    1. grossws
      03.04.2016 21:35

      простая и эффективная многопоточность

      Эффективная — спорно, копирование из кучи в кучу на каждый чих — довольно дорогая операция. Мне куда более импонирует использование immutable-объектов для межакторного взаимодействия, как это делается в akka.


      1. develop7
        03.04.2016 22:51

        намекаете ли вы, что в рантайме возрастом 30 лет ничего подобного нет?


        1. grossws
          04.04.2016 00:43

          По тому, что я читал раньше, beam копировал данные из кучи в кучу при отправке сообщений.

          Посмотрел на актуальные статьи (2015), пишут что это осталось справедливым для мелких объектов (до 64 байт), что даёт небольшие накладные расходы на копирование. А сообщения с большими объектами содержат только указатель на объект, который хранится отдельно. Так что, сейчас реализация вполне может быть достаточно эффективной.


          1. develop7
            04.04.2016 10:25

            «Сейчас», ха. Binaries впилили в BEAM VM в 1995-1996.


            1. grossws
              04.04.2016 12:44
              +2

              Ну извините. Спеки, которой соответствует beam'а (в отличии от jls/jvms) я не видел, насколько понял её просто не существует. И в куче разных статей про erlang, написанных в нулевых-десятых годах видел упоминания, что при отправке сообщения оно копируется в кучу процесса-получателя.

              В erlang efficiency guide написано:

              All data in messages between Erlang processes is copied, except for refc binaries on the same Erlang node.

              В общем, я в некоторых сомнениях. Если сможете — ткните на какой-нибудь источник или место в исходниках, где описано, что большие сообщения автоматически конвертируются в binaries. В актуальных исходниках R16B03 copy_struct не копирует refc binaries, как и написано в efficiency guide. В erl_message.c erts_send_message использует copy_struct. Всё выглядит так, будто сообщение копируется вне зависимости от размера, а binaries используются явно.


              1. develop7
                04.04.2016 14:19
                -1

                Если сможете — ткните на какой-нибудь источник или место в исходниках, где описано, что большие сообщения автоматически конвертируются в binaries.
                Автоматической конвертации нет. Но и ваше «копирование из кучи в кучу на каждый чих» несправедливо в случае binaries, которыми пользуются чаще, чем может показаться стороннему наблюдателю.


    1. getElementById
      08.04.2016 15:11

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


  1. Saffron
    03.04.2016 17:46
    +2

    Огромное количество пустых высказываний в духе «никогда не поздно узнавать новое», но самый главный секрет так и не открыт — чем clojure лучше старого доброго вполне зрелого common lisp


    1. PerlPower
      03.04.2016 22:47

      А есть ли более менее живой транслятор из Common Lisp в JS?


      1. ElMachete
        05.04.2016 13:48

        Parenscript?


    1. anjensan
      05.04.2016 11:44

      Многие считают (я тоже склоняюсь к этому мнению), что Clojure не совсем и лисп. Так что сравнивать напрямую их не совсем корректно.
      А так то кложа намертво привязана к платформе. Например, долго не было функций для работы со строками — мол используйте методы java.lang.String. Такой подход дает и плюсы, и минусы. Из минусов, постоянно придется деражать в голове то, что мы работаем под JVM (как таковой абстракции над ВМ нету). Зато интеграция с другими JVM языками прозрачна и легка. Ну и возможности JVM при должном умении можно использовать на всю катушку.
      Ну и кложа более ФП-ориентированная — все такое прям неизменяемое и дружелюбное к concurrency.


  1. pav5000
    03.04.2016 23:17

    Есть еще Хаскель ведь, там плюсом статическая типизация, правда, без jvm, но зато рекурсию можно нормально использовать и скобочки на клавиатуре не сотрутся. Хаскельскрипт тоже умеет компилиться в js.


    1. nehaev
      04.04.2016 12:51

      Пожалуй, наиболее близкий вариант на JVM — это Scala. Функциональный язык со статической типизацией, нормальной рекурсией и трансляцией в js.


  1. axxackall
    05.04.2016 13:45

    Ждем подобную статью про F#.