Последнее время у меня очень мало времени и сил, поскольку после работы я занимаюсь учебой и активно продолжаю ремонт. Активность не исчезла – она просто перешла в лайв-канал. Это временно, честно😵💫
Ремонтом я занимаюсь абсолютно так же, как и прогой – пробую что-то новое без какого-либо опыта, делюсь тем, что получилось и что не получилось. Сейчас новая фаза в работе, которой я буду делиться. Кому интересно – заглядывайте:
https://t.me/chrisonych
Ремонтом я занимаюсь абсолютно так же, как и прогой – пробую что-то новое без какого-либо опыта, делюсь тем, что получилось и что не получилось. Сейчас новая фаза в работе, которой я буду делиться. Кому интересно – заглядывайте:
https://t.me/chrisonych
Telegram
ЧЁРНЫЙ МЕНЧИК
Папапевегимабоди
🔥1
Наконец-то дошли руки поделать хоть что-то более-менее полезное – знакомство с Elixir. Я до последнего старался отложить этот момент, поскольку однажды меня сильно напугал его синтаксис, когда я впервые начал изучать ФП, но я прекрасно знал и понимал, что рано или поздно я дойду до него.
Когда-то давно в компании Ericsson придумали язык программирования Erlang для управления телекоммуникациями. Поскольку сеть должна работать как можно стабильнее, желательно еще и в экстремальных условиях, система должна быть настолько отказоустойчивой и производительной, насколько это возможно. Erlang стал таким языком: он позволяет использовать все доступные ядра для разведения выполнения задач в параллель. При этом если один из процессов (именно процессов, не потоков) падает, его падение никак не аффектит другие процессы – они будут ждать, когда он поднимется (а он обязательно это сделает). Большая часть бэкенда WhatsApp написана как раз на Erlang – в свое время этот мессенджер вызвал такой взрыв, что другие решения могли и не вывезти такого.
Киллер-фича Elixir – это Erlang, сделанный для людей. Придумали приятный синтаксис, положили на виртуальную машину Erlang (BEAM), и все готово. Он всё так же чисто функциональный, но в нем нет такого садизма, как в Haskell.
Из всех функциональных языков программирования, что я успел попробовать (OCaml, Haskell, Gleam, Roc), Elixir является самым близким к продакшену – зрелость экосистемы и баланс простоты и эффективности ощущаются. Только печалит то, что несмотря на зрелость экосистемы, сама по себе она узкая – в течение двух вечеров искал маленькую адекватную библиотеку вроде Express.js для разработки REST API, гуглится только огромный Phoenix (что-то вроде Django, Ruby on Rails, Laravel и прочих больших веб-фреймворков).
Пока изучаю, полёт нормальный🍃
Когда-то давно в компании Ericsson придумали язык программирования Erlang для управления телекоммуникациями. Поскольку сеть должна работать как можно стабильнее, желательно еще и в экстремальных условиях, система должна быть настолько отказоустойчивой и производительной, насколько это возможно. Erlang стал таким языком: он позволяет использовать все доступные ядра для разведения выполнения задач в параллель. При этом если один из процессов (именно процессов, не потоков) падает, его падение никак не аффектит другие процессы – они будут ждать, когда он поднимется (а он обязательно это сделает). Большая часть бэкенда WhatsApp написана как раз на Erlang – в свое время этот мессенджер вызвал такой взрыв, что другие решения могли и не вывезти такого.
Киллер-фича Elixir – это Erlang, сделанный для людей. Придумали приятный синтаксис, положили на виртуальную машину Erlang (BEAM), и все готово. Он всё так же чисто функциональный, но в нем нет такого садизма, как в Haskell.
Из всех функциональных языков программирования, что я успел попробовать (OCaml, Haskell, Gleam, Roc), Elixir является самым близким к продакшену – зрелость экосистемы и баланс простоты и эффективности ощущаются. Только печалит то, что несмотря на зрелость экосистемы, сама по себе она узкая – в течение двух вечеров искал маленькую адекватную библиотеку вроде Express.js для разработки REST API, гуглится только огромный Phoenix (что-то вроде Django, Ruby on Rails, Laravel и прочих больших веб-фреймворков).
Пока изучаю, полёт нормальный🍃
🔥5👍2
this :: IO Diary
в течение двух вечеров искал маленькую адекватную библиотеку вроде Express.js для разработки REST API, гуглится только огромный Phoenix (что-то вроде Django, Ruby on Rails, Laravel и прочих больших веб-фреймворков).
Нашел пару библиотек, но искренне не понимаю, зачем нужно столько лишнего на первый взгляд кода. Есть вайб написать что-то настолько же минималистичное, как микрофрейморк
Хочется, чтобы можно было вообще не париться написанием бэкенда для небольших приложений. Эта магия достигается с помощью макросов, которые, к счастью, Elixir поддерживает
Mike в языке Nim:"/home" -> get:
ctx.send "hello"
"/mike" -> post:
ctx.send("Teapot", Http427)
"/some/route" -> post(x: Header[string], data: Json[SomeObject], page: Query[int]) ->
# Do stuff with parameters here
Хочется, чтобы можно было вообще не париться написанием бэкенда для небольших приложений. Эта магия достигается с помощью макросов, которые, к счастью, Elixir поддерживает
❤1
Думаю, многие видели такие мемы. Но не дайте себя обмануть, в функциональном программировании паттерны тоже присутствуют, и те самые "моноиды в пространстве эндофункторов" являются ничем иным как паттернами. Некоторые из них все мы используем, даже об этом не подозревая, поэтому все обстоит немного проще, чем кажется.
Хотите пост про паттерны в функциональном программировании?
P.S.: когда починю проводку, вдогонку прилетит разбор RAG🙏🏾
Хотите пост про паттерны в функциональном программировании?
P.S.: когда починю проводку, вдогонку прилетит разбор RAG🙏🏾
👍4❤1🔥1
🛤 ROP – обработка ошибок без исключений и null
Представь: ты пишешь код, а в нём — сплошные
Проблема: необходимость обработки ошибок с каждого звена цепочки
Допустим, у нас есть типичный процесс регистрации пользователя. Нам нужно:
- провалидировать данные,
- проверить, нет ли уже такого пользователя,
- создать запись,
- отправить письмо для подтверждения.
На
Каждый шаг — это потенциальное ветвление. Каждая ошибка обрабатывается вручную.
А теперь посмотрите, как ту же логику можно выразить в функциональном стиле с использованием ROP:
Никаких
Но как это работает? Как мы обрабатываем ошибки?
Всё дело в том, что каждая операция может быть либо на «рельсе успеха», либо на «рельсе ошибки».
Что за рельсы?
Честно признаться, чтобы добиться такого же результата, что и в примере на
Здесь в игру вступает pattern matching — одна из самых мощных возможностей функциональных языков. Это достойно отдельного поста, поскольку одна эта вещь заменяет
Обрати внимание: у
- Если пришло
- Если пришло
Таким образом, ошибка, возникшая на любом этапе, «проскакивает» все следующие функции и доходит до
Полный пример: регистрация пользователя
Теперь давай соберём всё вместе:
Что в сухом остатке?
Представь: ты пишешь код, а в нём — сплошные
if-else, проверки статусов, возвраты ошибок на каждом шагу. Знакомо? Как будто хочется что-то исправить, но редко на ум приходит что-то такое, что можно было бы использовать где угодно, где есть какие-то цепочки вызовов. Прошу любить и жаловать – Railway-Oriented Programming!Проблема: необходимость обработки ошибок с каждого звена цепочки
Допустим, у нас есть типичный процесс регистрации пользователя. Нам нужно:
- провалидировать данные,
- проверить, нет ли уже такого пользователя,
- создать запись,
- отправить письмо для подтверждения.
На
Javascript это может выглядеть так:if (!validateData(registrationRequest))
return {status: "error", reason: "Данные не валидны"}
if (checkExistance(registrationRequest))
return { status: "error", reason: "Пользователь с такими данными уже существует" }
const user = createUser(registrationRequest)
if (!user)
return { status: "error", reason: "Не удалось создать пользователя" }
if (!sendEmailVerification(user))
return { status: "error", reason: "Не удалось отправить письмо" }
Каждый шаг — это потенциальное ветвление. Каждая ошибка обрабатывается вручную.
А теперь посмотрите, как ту же логику можно выразить в функциональном стиле с использованием ROP:
registration_request
|> validate_data()
|> check_existence()
|> create_user()
|> send_email_verification()
|> handle_error()
Никаких
if! Никаких промежуточных переменных! Абсолютная читаемость и понятность процесса. Поток данных последовательно передается от начала к концу, и глаз просто скользит сверху вниз.Но как это работает? Как мы обрабатываем ошибки?
Всё дело в том, что каждая операция может быть либо на «рельсе успеха», либо на «рельсе ошибки».
Что за рельсы?
Честно признаться, чтобы добиться такого же результата, что и в примере на
Javascript, нужно немного «достроить» пайплайн. Добавим несколько вспомогательных функций:defp bind({:ok, value}, func), do: func.(value)
defp bind({:error, reason}, _), do: {:error, reason}
defp map({:ok, value}, func), do: {:ok, func.(value)}
defp map({:error, reason}, _), do: {:error, reason}
defp handle_error({:error, reason}), do: IO.puts(reason)
defp handle_error(_), do: :okЗдесь в игру вступает pattern matching — одна из самых мощных возможностей функциональных языков. Это достойно отдельного поста, поскольку одна эта вещь заменяет
if и позволяет выполнять распаковку объектов, перегружать функции и еще много всего интересного. Обрати внимание: у
bind и map есть по две перегруженные версии (клаузы). Elixir автоматически выбирает ту, которая соответствует переданным данным.- Если пришло
{:ok, data} – остаемся на «рельсе успеха», применяем функцию и идём дальше.- Если пришло
{:error, reason} – переходим на «рельс ошибки», просто прокидываем ошибку до самого конца.Таким образом, ошибка, возникшая на любом этапе, «проскакивает» все следующие функции и доходит до
handle_error.Полный пример: регистрация пользователя
Теперь давай соберём всё вместе:
defp validate_data(data) do
# Логика валидации
# Если данные валидны, то возвращаем {:ok, data}
# Если не валидны – {:error, :invalid_data}
end
defp check_existence(data) do
# Логика проверки существования пользователя
# Данные свободны – {:ok, data}
# Иначе – {:error, :already_exist}
end
defp create_user(data) do
# Логика создания нового пользователя
# Удачно – {:ok, %User{}}
# Неудачно – {:error, :creation_failed}
end
defp send_email_verification(user) do
# Логика отправки сообщения
# Удачно – {:ok, true}
# Неудачно – {:error, :email_not_sent}
end
def handle_request(request) do
request
|> map(&validate_data/1)
|> map(&check_existence/1)
|> map(&create_user/1)
|> bind(&send_email_verification/1)
|> handle_error()
end
Что в сухом остатке?
🔥4❤1👍1
- Читаемость: код читается как последовательность шагов, а не как дерево условий.
- Надёжность: ошибки обрабатываются централизованно и не «теряются» по пути.
- Композируемость: мы можем легко переиспользовать, добавлять или убирать шаги в пайплайне.
Railway-Oriented Programming можно описать одной фразой: «Успех идёт вперёд, ошибка — прямиком к выходу». Если однажды попали на «рельс ошибки», то нет ни шанса попасть обратно.
P.S.: Справедливости ради стоит сказать, что такой подход очень легко реализовать в
#functional #patterns
- Надёжность: ошибки обрабатываются централизованно и не «теряются» по пути.
- Композируемость: мы можем легко переиспользовать, добавлять или убирать шаги в пайплайне.
Railway-Oriented Programming можно описать одной фразой: «Успех идёт вперёд, ошибка — прямиком к выходу». Если однажды попали на «рельс ошибки», то нет ни шанса попасть обратно.
P.S.: Справедливости ради стоит сказать, что такой подход очень легко реализовать в
Javascript с помощью then – получается абсолютно то же самое, что и в примере на Elixir. Именно поэтому из всех популярных языков программирования мне нравится именно он – по своей природе он очень близок к функциональным.#functional #patterns
❤4🔥2
Вот он, первый пост из цикла о паттернах в функциональном программировании, и уже он не влез в одно сообщение🫣
Для следующих длинных постов буду искать площадку для хостинга, так как Telegraph мне всё таки не нравится.
Будет интересно почитать, что ты думаешь об этом подходе, и какие решения применял для централизованной обработки ошибок и выстраивания цепочек действий, поскольку с этой проблемой я сталкиваюсь очень часто
Для следующих длинных постов буду искать площадку для хостинга, так как Telegraph мне всё таки не нравится.
Будет интересно почитать, что ты думаешь об этом подходе, и какие решения применял для централизованной обработки ошибок и выстраивания цепочек действий, поскольку с этой проблемой я сталкиваюсь очень часто
❤3👍1
К каждому паттерну я буду прикреплять примеры использования, чтобы не ограничиваться местами абстрактными примерами. Использование ROP можете посмотреть здесь
GitHub
todo-elixir/lib/todo.ex at master · lsdrfrx/todo-elixir
Contribute to lsdrfrx/todo-elixir development by creating an account on GitHub.
❤4⚡1
Пропал на 3 недели, но не просто так – активно преисполнялся в Elixir. В субботу планирую постримить, но не могу выбрать направление:
– Супервизор процессов на Elixir — написать лёгкий менеджер, который будет управлять процессами: запускать, останавливать, перезапускать, мониторить, добавлять в автозапуск. systemd писать не собираюсь, но минималистичный аналог runit — почему бы и нет? Вместе разберемся, как под капотом работают системы инициализации в *nix и напишем свою маленькую, да не абы как, а в функциональном стиле, на Elixir
– Fullstack на Vue3 + Express.js — помогаю товарищу с дипломной работой. В планах: авторизация, чат, вебсокеты и медитативная вёрстка.
Какой путь выбрать — решать тебе. Буду очень рад делегировать выбор на тебя😃
Выбираем реакцией:
Супервизор – 👀
Диплом – 🌚
– Супервизор процессов на Elixir — написать лёгкий менеджер, который будет управлять процессами: запускать, останавливать, перезапускать, мониторить, добавлять в автозапуск. systemd писать не собираюсь, но минималистичный аналог runit — почему бы и нет? Вместе разберемся, как под капотом работают системы инициализации в *nix и напишем свою маленькую, да не абы как, а в функциональном стиле, на Elixir
– Fullstack на Vue3 + Express.js — помогаю товарищу с дипломной работой. В планах: авторизация, чат, вебсокеты и медитативная вёрстка.
Какой путь выбрать — решать тебе. Буду очень рад делегировать выбор на тебя😃
Выбираем реакцией:
Супервизор – 👀
Диплом – 🌚
🌚6👀3👏1
P.S.: нормально настроил OBS в плане баланса звука, запись со стрима будет🫡
🎉4
То чувство, когда большая задача пошла в релиз без правок ни с ревью, ни с тестирования:
This media is not supported in your browser
VIEW IN TELEGRAM
😁4❤1
Начинаю ориентировочно в 12:00. Буду рад всем желающим🙏🏾
https://www.twitch.tv/lsdrfrx
https://www.twitch.tv/lsdrfrx
Twitch
lsdrfrx - Twitch
versatile developer
this :: IO Diary
Пропал на 3 недели, но не просто так – активно преисполнялся в Elixir. В субботу планирую постримить, но не могу выбрать направление: – Супервизор процессов на Elixir — написать лёгкий менеджер, который будет управлять процессами: запускать, останавливать…
Стрим длился рекордные 4 часа 40 минут🫣
За это время успел накидать пару базовых компонентов, построить скелет фронтенда и сделать регистрацию и вход в аккаунт на стороне бэкенда. Попробовал новые для себя фреймворки Hono и Drizzle. Пока всё тяп-ляп, далее буду приводить все в красивый вид – как и структуру, так и визуал
Смотри запись тут: https://www.youtube.com/watch?v=jADfBMvaW4c
За это время успел накидать пару базовых компонентов, построить скелет фронтенда и сделать регистрацию и вход в аккаунт на стороне бэкенда. Попробовал новые для себя фреймворки Hono и Drizzle. Пока всё тяп-ляп, далее буду приводить все в красивый вид – как и структуру, так и визуал
Смотри запись тут: https://www.youtube.com/watch?v=jADfBMvaW4c
🔥3❤1🥰1