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

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

Параллелизм

Одно из преимуществ Эликсира, о котором больше всего говорят, - это параллелизм. В Discord также упоминалось, как они обрабатывают 5 000 000 одновременных пользователей с помощью Elixir. Давайте сначала взглянем на модели параллелизма других языков, чтобы понять Elixir.

Сценарий: 2 пользователя (клиента) обращаются (заказывают еду) к нашему веб-приложению (кухня). Как каждый язык будет обрабатывать запросы обычным образом?

Параллелизм в NodeJS

NodeJS использует асинхронную обработку запросов. Это означает, что покупатели не будут ждать в очереди, чтобы сделать заказ. Кухня принимает все входящие запросы и велит им сесть и подождать (возвращая обещание). А кухня выполняет несколько вещей одновременно и отправляет еду (ответ) всякий раз, когда сначала выполняется какой-либо запрос. Это очень хорошо для максимального использования имеющихся ресурсов. Однако он не может хорошо использовать все ядра ЦП, если мы не используем порождение процессов.

Параллелизм в Ruby on Rails

Параллелизм в Ruby on Rails довольно прост. Кто первым придет, тот первым отправит запрос. А следующему покупателю нужно дождаться, пока первый покупатель получит еду. Такой способ помогает упростить программирование, но при этом плохо используются ресурсы. Например, пока приложение ожидает ввода-вывода, оно больше ничего не делает.

На практике мы используем воркера или запускаем несколько кухонь или экземпляров Rails для приема запросов. Обратной стороной является то, что воркером не очень просто управлять, а один экземпляр Rails может съесть до 500 МБ памяти! Нам приходится много платить за облачный сервис, который позволяет разместить всего 20 экземпляров, для которых требуется 10 ГБ памяти.

Параллелизм в Эликсире

В Elixir для каждого нового заказа может создаваться новая кухня для обработки запроса. Так что он такой же простой, как Ruby, но мощный. Возможно, мы сможем написать бизнес-логику без асинхронных частей. И он будет использовать все существующие ядра ЦП в полной мере. Кроме того, сбой одного из экземпляров не повлияет на другие экземпляры и запросы.

Более того, каждый экземпляр, который мы называем «Процессом» (процесс Erlang, не то же самое, что и процесс ОС), будет обрабатываться супервизором. Супервизор будет отслеживать и перезапускать каждый дочерний процесс. Вот почему у него отличная отказоустойчивость. Мы можем годами запускать «голое» приложение с Эликсиром, не падая.

И, что самое приятное, 1 процесс Erlang часто занимает менее 1 МБ памяти. И это может быть всего несколько килобайт для очень простого процесса. Таким образом, мы можем легко запустить 10 000–100 000 процессов на собственном портативном компьютере.

Возможности параллелизма в этом Elixir взяты из OTP Erlang (Open Telecom Platform, not One-Time Password 😂), созданного инженерами Ericsson. Их цель состояла в том, чтобы создать платформу для обработки миллионов соединений и маршрутизации телефонных звонков в распределенной системе с минимальной задержкой и без сбоев даже при развертывании новой версии.

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

Таким образом, Elixir или Erlang - отличный выбор для приложений реального времени или WebSocket с огромным количеством одновременных пользователей, таких как приложение для чата.

Итак, мы выбрали Elixir из-за параллелизма?

Ответ… не совсем. Мы были в восторге от параллелизма, но это не самое главное.

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

Но для стартапа очень важны продуктивность и скорость итераций. Мне лично нравится Ruby on Rails с точки зрения производительности. При использовании Rails мы тратили большую часть времени на решение бизнес-задач, а не на решение проблем с фреймворком или выбор инструментов.

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

Однако масштабировать в Rails не так просто. Итак, когда мы нашли Elixir, он сочетал в себе опыт разработчиков Rails и мощь 33-летнего Erlang, который, я считаю, Elixir станет одним из наиболее предпочтительных языков в будущем.

К счастью, поскольку я когда-либо работал в Omise Payment, наш технический директор и многие коллеги-инженеры, такие как Elixir, и я видели несколько проектов в Elixir, которые действительно впечатлили меня, насколько ясна может быть база кода. И эти проекты действительно доказывают, что работа в Elixir практична для решения общих задач. Этот опыт убедил меня в том, что я выбрал Elixir для собственного стартапа.

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

Что еще более важно, всякий раз, когда мы изучаем новый язык, новую структуру, это создает для нас сдвиг парадигмы. Так же, как когда я изучил Ruby on Rails после использования NodeJS, он научил меня чистому и надежному способу организации приложений ООП. В результате я написал лучшие приложения NodeJS. Таким образом, Elixir - это еще одна парадигма, позволяющая нам научиться лучше решать проблемы.

Плюсы и минусы Эликсира

Из того, что упоминалось ранее, вот еще несколько моментов, касающихся плюсов и минусов, с моей точки зрения.

О плюсах я объясню подробнее в более поздней части.

Что касается минусов, то при изучении Erlang нам почти не нужно знать Erlang, но лучше кое-что знать, особенно часть OTP. И некоторая библиотека-оболочка Erlang может выдавать трассировку стека ошибок Erlang, что может сбивать с толку.

Что касается учебных ресурсов, то при запуске нам не хватает передового опыта и образцов для реальных проектов Phoenix. Нам потребовалось некоторое время, чтобы добраться до хорошей организации кода. Тем не менее, спасибо OmiseGO за создание хорошего проекта на Эликсир с открытым исходным кодом, на котором мы можем учиться.

В сообществе он все еще небольшой, но очень дружелюбный и активный. Мы можем задавать вопросы об Elixir на форуме и часто будем видеть ответы от José Valim, создателя Elixir. Я открыл очень маленький пиар для Ecto, основной библиотеки Elixir, и он пришел к слиянию через 15 минут 🤣.

Покажи мне код!

Хорошо, я собираюсь провести вас через различные проблемы, чтобы увидеть, как Elixir помогает нам решать проблемы с ясностью.

Неизменяемость

Одна проблема, с которой я часто сталкивался в Ruby или JavaScript, заключается в том, что я не уверен, были ли изменены данные в объекте. Это действительно зависит от замысла разработчика.

JavaScript - данные внутри могут измениться.

Эликсир - все неизменно.

Оператор трубы

В некоторых случаях изменчивость действительно делает код чище. Попробуем разработать решение для этой процедуры на JavaScript и Elixir.

JavaScript - простой и понятный, когда мы делаем его изменяемым

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

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

Давайте воспользуемся оператором конвейера |>. И это становится прямым и простым, как документированная процедура ❤️

Соответствие шаблону

В Elixir сопоставление с образцом очень мощное средство. Когда мы видим знак равенства =, это не оператор присваивания, а оператор сопоставления.

После того, как мы установили Elixir, мы можем набрать iex в консоли и начать играть.

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

Новый способ решения проблем

Давайте посмотрим на более практическое использование. Предполагая, что вам нужно разработать функцию сопоставления Tinder match(my_feeling, target_feeling). Давайте сделаем паузу и немного подумаем, как бы вы реализовали это на предпочитаемом вами языке?

Позвольте мне попробовать на JavaScript.

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

Давайте посмотрим на быстрое решение в Elixir.

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

Можно также использовать сопоставление с образцом на уровне параметров, чтобы написать подобное.

Еще образец!

Развиваем программу Фибоначчи. В обязательном порядке (нефункционально) мы могли бы сделать цикл for для его решения. А как в Эликсире?

Не задумываясь, мы можем попробовать перечислить вывод из ввода

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

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

Мы можем использовать when n < 2 для управления объемом параметров, входящих в метод. Мы назвали это ограничение guard

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

Тестирование в Эликсире

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

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

Он отображает строку кода, которая идет не так. И он просто сообщает значение left и right, что мне нравится.

Документация

Elixir имеет первоклассную поддержку документации. Например, у него есть синтаксис для описания модуля и метода с помощью @moduledoc и @doc.

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

Допустим, мы напишем ниже неправильный пример.

А когда мы запускаем тесты, он на нас кричит!
Обратите внимание, что нам также нужно ввести doctest Fibonacci в тест.

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

Более того, мы можем легко добавить hex библиотеку для автоматической генерации HTML-документов с помощью команды mix docs, которая дает нам прекрасную документацию из документации по исходному коду!

И все библиотеки Elixir используют инструмент hex для создания документов. Таким образом, мы увидим везде одинаковый и красивый формат документации. 🥰

Единая и богатая экосистема

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

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

Попробуйте!

Надеюсь, эта статья поможет вам получить больше идей об Elixir за короткое время. Но вы действительно не поймете, если не попробуете сами. Зайдите в Школу Эликсира, чтобы увидеть инструкцию по установке, и вы можете открыть консоль, чтобы быстро изучить ее. Возможно, вы найдете Elixir подходящим инструментом для ваших следующих проектов. 😊

Давайте научимся лучше решать проблемы реального мира! ✨

Бонус

Наша команда в Flipay создает мир банковского дела без границ, создавая шлюз для людей и бизнеса, чтобы получить доступ к мощи криптовалюты и цифровой сборки t беспрепятственно.

Сейчас мы нанимаем инженеров-программистов, которые присоединятся к нашей международной команде в Бангкоке! Если вы заинтересованы в создании потрясающих продуктов с помощью Elixir, 🔫 напишите мне сообщение или напишите мне по адресу [email protected] в любое время :)