Сегодня я пробно постримил на на твиче. Причин этого не делать я не нашел, поэтому все заметки по разработке редактора партитур перенесутся в формат стримов с записью. Лайв-кодинг, всё такое😃
Я буду стримить там не только что-то связанное с разработкой — сегодня я стримил, как добиваю 80 уровень шамана в World of Warcraft. Связанные с кодингом стримы я буду отдельно анонсить здесь
Сразу можете оформить подписочку:
https://www.twitch.tv/lsdrfrx
Я буду стримить там не только что-то связанное с разработкой — сегодня я стримил, как добиваю 80 уровень шамана в World of Warcraft. Связанные с кодингом стримы я буду отдельно анонсить здесь
Сразу можете оформить подписочку:
https://www.twitch.tv/lsdrfrx
Twitch
lsdrfrx - Twitch
versatile developer
❤3
А лайв-кодинг будет очень и очень скоро — я участвую к хакатоне ЛЦТ. Задача предстоит интересная, но об этом я расскажу завтра🤫
❤🔥2
Сегодня на стриме разбираем, что такое Backend Driven UI. Лайв-кодим💪🏾
Я буду на Vue3 выстраивать интерфейс на основе конфигураций, получаемых с бэкенда. Покажу, как это работает изнутри.
Предварительное время начала: 13:00
Кто будет – тыкните реакцию 👀
#frontend #livecoding
Я буду на Vue3 выстраивать интерфейс на основе конфигураций, получаемых с бэкенда. Покажу, как это работает изнутри.
Предварительное время начала: 13:00
Кто будет – тыкните реакцию 👀
#frontend #livecoding
👀4❤1
Как и обещал, делюсь дотфайлами:
https://github.com/lsdrfrx/arch-dots
Запись со стрима нужно немного обработать, по готовности залью сюда🫡
https://github.com/lsdrfrx/arch-dots
Запись со стрима нужно немного обработать, по готовности залью сюда🫡
GitHub
GitHub - lsdrfrx/arch-dots
Contribute to lsdrfrx/arch-dots development by creating an account on GitHub.
❤2👍1🔥1
Как и обещал, сегодня продолжаем тему Backend Driven UI. Запускаю стрим в 18:20, буду дальше разбираться в том, как это все работает под капотом.
Записи сегодняшнего и прошлого стрима по BDUI выложу завтра — будет что посмотреть на выходных😃
Запускаюсь в 18:20 🎥
Тем временем работаю над большим разбором RAG (Retrieval-Augmented Generation). К субботе планирую запостить статью, в которой без воды и заумностей:
– Объясню на пальцах, что это такое
– Докажу, что это сильно проще, чем кажется на первый взгляд
– Наглядно покажу, как запустить базовый RAG и завернуть его в API
– Разберу, как расширить его возможности с помощью дополнительного контекста
– Расскажу, когда это действительно нужно.
Пишу уже достаточно долго, но усердно. Кто ждёт – покажите это реакцией 🔥
Записи сегодняшнего и прошлого стрима по BDUI выложу завтра — будет что посмотреть на выходных😃
Запускаюсь в 18:20 🎥
Тем временем работаю над большим разбором RAG (Retrieval-Augmented Generation). К субботе планирую запостить статью, в которой без воды и заумностей:
– Объясню на пальцах, что это такое
– Докажу, что это сильно проще, чем кажется на первый взгляд
– Наглядно покажу, как запустить базовый RAG и завернуть его в API
– Разберу, как расширить его возможности с помощью дополнительного контекста
– Расскажу, когда это действительно нужно.
Пишу уже достаточно долго, но усердно. Кто ждёт – покажите это реакцией 🔥
🔥9😢1
Очень сильно переоценил себя – решил в один момент и пост дописать, и 7 часов отснятых стримов отсмотреть, и ремонт продолжить. Чтобы не закапываться в дела и не пропадать надолго, буду делать немного меньше.
Записи стримов для меня сейчас недоступны (я разобрал стол в процессе ремонта, комп некуда ставить). Пост про RAG ещё не дописан, поэтому анонсы записей и статьи будут немного позже. А сегодня, чтобы не было тишины, я выскажусь о наболевшем – что такое ООП и ФП на самом деле.
Этот канал про мой опыт и ошибки, так что по-честному делюсь – переборщил немножко😃
Записи стримов для меня сейчас недоступны (я разобрал стол в процессе ремонта, комп некуда ставить). Пост про RAG ещё не дописан, поэтому анонсы записей и статьи будут немного позже. А сегодня, чтобы не было тишины, я выскажусь о наболевшем – что такое ООП и ФП на самом деле.
Этот канал про мой опыт и ошибки, так что по-честному делюсь – переборщил немножко😃
😁3🔥1
🧠 Программирование как философия мышления
Очень часто я становлюсь свидетелем холиваров о том, что лучше – ООП или ФП. Из чата в чат оопшники считают, что достаточно следовать паттернам проектирования и делать как можно больше классов, избегая функций как огня, а тру функциональщики думают, что использования стрелочных функций и ФВП достаточно. И очень часто в этих холиварах я вижу полнейшее непонимание того, что означает термин парадигма. Поэтому я выскажу свое непопулярное мнение на эту тему и бежать не буду.
Проблема большинства споров об истинном ООП или чистом ФП в том, что спорщики видят в парадигме инструмент, а не мышление. Люди спорят о классовой иерархии, наследовании, монадах или стрелочных функциях, как будто эти элементы сами по себе создают парадигму. Но это как спорить, можно ли стать философом, просто купив толстую тетрадь и перьевую ручку. Парадигма – это не то, что ты пишешь, а почему ты это делаешь именно так.
Это о том, как ты воспринимаешь проблему и строишь решение в своей голове – а не о количестве аннотаций, паттернов или модных слов.
Если завернуть абсолютно императивную логику в класс, гвоздями к нему прибить реализацию источника данных, тоже завернутую в класс – это не ООП. Это не про классы, не про интерфейсы, не про SOLID. Это про абстракции, которые позволяют тебе мыслить объектами, взаимодействующими между собой как живые сущности. Объект – это не контейнер для методов и данных, это единица ответственности и поведения, которую ты можешь осознать, описать и изолировать. Когда ООП превращают в "фабрику фабрик", "менеджер менеджеров" и наследование ради наследования – это не ООП, это императивный код в костюме
ООП – это про качество абстракции – про то, чтобы модель кода была зеркалом модели реальности, а не свалкой паттернов.
Абсолютно та же мысль применяется к функциональной парадигме: если писать
ООП и ФП – это не разные языки, а разные точки зрения на сложность.
ООП говорит: “Раздели мир на сущности и взаимодействия между ними”.
ФП говорит: “Опиши поток данных и преобразования, не думая о состоянии”.
Обе парадигмы – инструменты для осмысления, а не для догматизма. И программист, мыслящий парадигмами, а не паттернами, легко переключается между ними, потому что понимает суть – управление сложностью через абстракцию.
#philosophy
Очень часто я становлюсь свидетелем холиваров о том, что лучше – ООП или ФП. Из чата в чат оопшники считают, что достаточно следовать паттернам проектирования и делать как можно больше классов, избегая функций как огня, а тру функциональщики думают, что использования стрелочных функций и ФВП достаточно. И очень часто в этих холиварах я вижу полнейшее непонимание того, что означает термин парадигма. Поэтому я выскажу свое непопулярное мнение на эту тему и бежать не буду.
Проблема большинства споров об истинном ООП или чистом ФП в том, что спорщики видят в парадигме инструмент, а не мышление. Люди спорят о классовой иерархии, наследовании, монадах или стрелочных функциях, как будто эти элементы сами по себе создают парадигму. Но это как спорить, можно ли стать философом, просто купив толстую тетрадь и перьевую ручку. Парадигма – это не то, что ты пишешь, а почему ты это делаешь именно так.
Это о том, как ты воспринимаешь проблему и строишь решение в своей голове – а не о количестве аннотаций, паттернов или модных слов.
Если завернуть абсолютно императивную логику в класс, гвоздями к нему прибить реализацию источника данных, тоже завернутую в класс – это не ООП. Это не про классы, не про интерфейсы, не про SOLID. Это про абстракции, которые позволяют тебе мыслить объектами, взаимодействующими между собой как живые сущности. Объект – это не контейнер для методов и данных, это единица ответственности и поведения, которую ты можешь осознать, описать и изолировать. Когда ООП превращают в "фабрику фабрик", "менеджер менеджеров" и наследование ради наследования – это не ООП, это императивный код в костюме
UML. ООП – это про качество абстракции – про то, чтобы модель кода была зеркалом модели реальности, а не свалкой паттернов.
Абсолютно та же мысль применяется к функциональной парадигме: если писать
map вместо for, а вместо function использовать стрелочные функции – это не ФП, а точно такой же императивный код. Функциональное мышление – не про синтаксический фетишизм, а про контроль над изменением, про использование функций как строительные блоки, где каждый из них – как атом, не зависящий от внешнего мира. Данные не меняются, функции не лгут, а побочные эффекты происходят только с разрешения разработчика в строго описанном им месте.ООП и ФП – это не разные языки, а разные точки зрения на сложность.
ООП говорит: “Раздели мир на сущности и взаимодействия между ними”.
ФП говорит: “Опиши поток данных и преобразования, не думая о состоянии”.
Обе парадигмы – инструменты для осмысления, а не для догматизма. И программист, мыслящий парадигмами, а не паттернами, легко переключается между ними, потому что понимает суть – управление сложностью через абстракцию.
#philosophy
👍7
Чего я только не слышал: что паттернам нужно следовать, будто ООПшники какие-то культисты, что в ФП нельзя делать составные типы и можно работать только с примитивами, что ФП быстрее чем ООП, просто потому что🫣
😁1
Последнее время у меня очень мало времени и сил, поскольку после работы я занимаюсь учебой и активно продолжаю ремонт. Активность не исчезла – она просто перешла в лайв-канал. Это временно, честно😵💫
Ремонтом я занимаюсь абсолютно так же, как и прогой – пробую что-то новое без какого-либо опыта, делюсь тем, что получилось и что не получилось. Сейчас новая фаза в работе, которой я буду делиться. Кому интересно – заглядывайте:
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