Как стать автором
Обновить
34.28

Erlang/OTP *

Функциональный язык программирования

Сначала показывать
Порог рейтинга
Уровень сложности

Гарантийное обслуживание конечных автоматов

Уровень сложностиПростой
Время на прочтение5 мин
Количество просмотров1.3K

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

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

Подписаться, чтобы посмотреть код

Новости

Акторная модель для дошкольников

Уровень сложностиПростой
Время на прочтение7 мин
Количество просмотров1.6K

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

Рассказ рассчитан на тех, кто хотя бы поверхностно знаком с концепциями ООП и (или) ФП. Ниже вы не найдёте всех тех запутывающих псевдонаучных объяснений, которые вам услужливо предоставит Вика или Анжела (или как там вы называете свою любимую LLM в приватных чатиках).

Текст написан именно сегодня, когда Алану Каю исполнилось 85! Поздравляем, Алан, ты — гений, спасибо тебе за всё!

А теперь про акторную модель

Не складывайте медленный код в жобу

Уровень сложностиПростой
Время на прочтение5 мин
Количество просмотров1.4K

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

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

В самой по себе параллельности ничего сверхъестественного нет: надо просто за недельку привыкнуть к тому, что результат получается не сразу, и всё. Проблема в другом: в том бесчисленном количестве костылей, нагроможденных претендующими (на звание неглупых) людьми, чтобы «упростить жизнь медиокра за клавиатурой».

В любой мало-мальской экосистеме обязательно будет такая штука, как «job runner». Чтобы линейный, простой как полено, код — мог иметь дело с длительными вычислениями. Нужен отчёт, а его генерация занимает полчаса? — Нет, мы не сделаем правильно, не поправим наши схемы, не озаботимся триггерами и persistent views, на это у нас нет ни времени, ни денег, мы стартап, поэтому делегируем: пусть весь неэффективный медленный код идёт в жобу!

Почему job runners — зло

Конфиг, сделанный по уму

Уровень сложностиПростой
Время на прочтение5 мин
Количество просмотров2K

Когда к нам пришел докер и — как тот муж из анекдота — перее^W научил нас отказоустойчивости на свой манер, я написал бесчисленное количество костылей, чтобы действительно отказоустойчивый (а главное, долгоживущий) код продолжал нормально работать в условиях, где сброс горячего кэша из-за внезапного перезапуска контейнера, вызванного близостью Андромеды к Меркурию, — норма.

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

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

Вот как это было

Undo/Redo своими руками

Уровень сложностиПростой
Время на прочтение3 мин
Количество просмотров2.2K

Больше двадцати лет назад мне довелось поработать в одном берлинском стартапе, где мы пилили визуальную трансформацию UML в код и обратно. Пользовательский интерфейс на свинге, изоморфная (в теории) обработка кода и диаграмм — на хаскеле. Было весело, потом полопались доткомы, кончилось финансирование и мы еще почти год пытались как-то дотянуть до продукта без денег. Капитализм победил, и продукт погиб (насколько я знаю) — так и не родившись.

Из интересного (помимо того, что я сам нарисовал почти полсотни иконок для нашего приложения, что до сих пор считаю самым выдающимся собственным достижением в IT) — там был придуманный и воплощенный мной механизм Undo/Redo, о котором я и собираюсь сегодня рассказать.

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

Как ту же самую задачу решает несдержанный на язык швед финского происхождения?…

— Правильно, пишет git!

Распределенные системы и горизонтальное масштабирование

Уровень сложностиСредний
Время на прочтение5 мин
Количество просмотров2.9K

Я не устану повторять, что воткнуть еще пачку независимых нод (реплик, инстансов) за балансером — не имеет ничего общего с горизонтальным масштабированием. Страшно вообразить, какое количество костылей было придумано, чтобы не решать оригинальную задачу размазывания нагрузки. В настоящей распределенной системе между нодами нет разницы: не имеет никакого значения, какая именно нода приняла тот, или иной запрос из внешнего мира.

Вместо этого мы понапридумывали всякие sticky sessions, умный роутинг, да даже web-сокеты выросли не из целесообразности сохранения состояния соединения (что хорошо, правильно и часто нужно), а из приклеивания к инстансу сервера (что никогда не нужно, и что практически во всех решениях мешает открыть два вебсокета и получать данные вперемешку из обоих, как это можно сделать с брокером сообщений).

Приклеивать сессию к физическому инстансу (ноде, условно говоря, к IPv4/IPv6) — бред, лишний слой для обеспечения этого только мешает и всё портит, ведь сервер всегда обладает всей необходимой информацией для того, чтобы принять запрос на ноде A, выполнить его на ноде B, а потом ответить всё с той же ноды A. Но делегация выполнения функции на соседнюю ноду — существующая уже сорок лет в эрланге — это же какой-то прям рокетсаенс. Поэтому когда к нам всё-таки приходит понимание того, что иногда одной ноды для полной обработки запроса недостаточно, — мы городим микросервисную архитектуру поверх редисов, или даже брокеров сообщений, и выдумываем саги о каких-то совершенно в данном случае ненужных форсайтах и прочий хайтек — вокруг тривиальной задачи.

А как иначе?

Телеметрия, диагностики и компилятор

Уровень сложностиСредний
Время на прочтение6 мин
Количество просмотров803

В современном мире невозможно себе представить взрослое приложение, которое не экспортирует телеметрию. Метрики — важнейший атрибут поддерживаемого софта; для всех более-менее профессиональных технических специалистов термин «visibility» давно вытеснил прочие остальные баззворды наподобие «test coverage» и «continious integration».

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

Отсюда вырос знаменитый «слоган» эрланга «Let It Crash!», высмеиваемый и всегда неверно трактуемый теми, кто неутомимо отслеживает все исключительные ситуации… и спотыкается об отсутствие нужного для их корректной обработки контекста в месте ловли. «Let It Crash» — означает не «Хрен с ними, с ошибками», а «Случилась какая-то ерунда в рантайме, но мы к ней готовы».

¡NB! В тексте нет прямых примеров использования телеметрии в ООП/ФП проектах, но я глубоко убежден, что этот текст будет полезно прочитать, даже если вы просто перекладываете джейсоны из пустого в порожнее на шарпах, котлине или хаскеле.

Telemetry it!

Иммутабельность и диоптрии

Уровень сложностиСредний
Время на прочтение6 мин
Количество просмотров1.1K

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

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

Линзы: использование и абьюз

Лучше самому изобрести колесо, чем ездить на арендованном квадратном

Уровень сложностиПростой
Время на прочтение5 мин
Количество просмотров9.1K

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

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

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

Изобретайте колёса и стройте велосипеды!

Брокер сообщений своими руками

Уровень сложностиСредний
Время на прочтение5 мин
Количество просмотров3K

В эрланге (и эликсире) мне всегда недоставало способа организовать «потоковый» обмен сообщениями, наподобие того, который обеспечивает какой-нибудь Message Broker. Нормальные разработчики смиряются с ограничениями, которые им задают их фреймворки: в Финиксе есть PubSub, в OTP — :gen_event, в эликсире — депрекейтнутый еще до рождения GenEvent.

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

узнать, какими именно

AST — Absolutely Superior Treatment

Уровень сложностиСредний
Время на прочтение8 мин
Количество просмотров1.6K

Я часто говорю, что если язык лишен встроенных средств работы с AST — абстрактным синтаксическим деревом — то этот язык спроектирован не очень умными людьми. Идолопоклонники могут с пеной у рта доказывать, что AST никому не нужно, или что хорошего API к AST — достаточно, или что прикрученное сбоку AST-представление закрывает потребности…

Это все детский лепет, и ниже я собираюсь рассказать, почему. Оба самых «популярных» (читай: хайповых) языка программирования современности — Rust и Go — не обошлись без этой родовой травмы (если вы считаете, что экспорт AST при помощи костыля rustc_ast::ast — решает эту проблему, вы просто не понимаете, что такое AST и зачем он нужен).

Ленивые comprehensions на AST

Тупиковый синьёр или при чем тут эрудиция?

Время на прочтение5 мин
Количество просмотров16K

С появлением LLM люди разделились на три лагеря: тех, кто верит в повышение КПД при помощи автодополнения и тех, кто относится к хайпу крайне скептически. Третий лагерь — это сами LLM, они же тоже что-то там про себя думают, наверное.

За долгие годы работы с кодом я привык слышать от среднего уровня разработчиков (и от тех, кто выбрал языки, которым требуется бесконечная генерация бойлерплейта): «Продуктивность программиста напрямую зависит от IDE». При том, что я всегда производил в несколько раз больше самого сложного в компании кода, используя vim с минимумом плагинов. Подсветка синтаксиса мне помогает, тут (как, впрочем, и почти везде) я с Пайком не согласен. Автодополнение — уже нет, я его иногда включаю «еще раз попробовать, вдруг это со мной что-то не так», и когда читаю курсы — но в основном мне мешают выскакивающие окошки: отвлекают, распыляют внимание, наталкивают на ложный путь.

А теперь про эрудицию и карьеру

Нужно ли «развитие» языкам программирования

Уровень сложностиСредний
Время на прочтение6 мин
Количество просмотров4.5K

TL;DR: Нет. Хорошо спроектированный язык в развитии не нуждается.

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

Более того, ниже я постараюсь уложиться в нескольких абзацев, чтобы рассказать, какие требования лично я предъявляю языку программирования в 2025 году, и почему этому «идеалу» просто некуда «развиваться».

Опять школота против ООП и ФП

Ближайшие события

Песочница своими руками

Уровень сложностиСредний
Время на прочтение5 мин
Количество просмотров1.3K

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

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

Не так страшен eval, как его противники

Нужны ли FSM синхронные вызовы?

Уровень сложностиСредний
Время на прочтение8 мин
Количество просмотров2.4K

TL;DR: Нет, не нужны.

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

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

Полностью асинхронный конечный автомат

Этот мир — асинхронный, и что вы ему сделаете

Уровень сложностиСредний
Время на прочтение7 мин
Количество просмотров3.7K

Все современные средства разработки — практически без исключения — наделены двумя родовыми травмами. Они не дают доступа к чуть более низкому софтверному уровню (синтаксическому дереву) без помощи сторонних хаков и ориентированы на синхронное исполнение.

Прежде, чем продолжить, я сразу оговорюсь: я не имею в виду узкоспециализированные задачи, типа написания драйверов, программирования контроллеров и прочей околожелезной разработки; там другие правила. Я говорю про мир приложений: от инди-игр до энтерпрайза. Языки высокого уровня, на которых сегодня ведется более (оценка навскидку) 98% всей разработки продуктов для конечного пользователя, лишены примитивов представления AST и параллельного (не путать с асинхронным) исполнения.

Но мир ничего не знает о наших абстракциях

Никогда не читайте перед обедом книг по специальности

Уровень сложностиСредний
Время на прочтение6 мин
Количество просмотров13K

Книги делятся на две категории: fiction и non-fiction. Технические книги — внезапно — не исключение, и поддаются точно такой же классификации. Между учебником по научной дисциплине, начинающегося с аксиоматики и продолжающегося доказательствами теорем, — и практически любой современной литературой по «Computer Science» — лежит пропасть. Что происходит, когда люди долгое время оказываются рабами одной-единственной книги (с продолжениями), нам хорошо известно из истории. Возникает религия.

99% процентов литературы по ООП — это талмуд. Вероятность того, что вам подойдет «паттерн» — примерно 50%. Как встретить динозавра на Невском. Знание паттернов полезно в той же степени, что и теология, — и примерно тем же по специальности людям. Всегда полезно уметь отличать по запаху Пана от простого фавна, но практических применений такой эрудиции — не существует.

Несколько примеров и торжественный вывод

Язык разметки типа маркдауна с тонкой настройкой под себя

Уровень сложностиСредний
Время на прочтение6 мин
Количество просмотров2.6K

Когда Грубер со Шварцем выкатили маркдаун, он был как глоток свежего воздуха. Минимум разметки, читаемый текст даже до обработки, достаточный для рядового средней руки блогера набор красивостей.

Спустя пару лет мне стало мучительно недоставать возможности тонкой настройки. Я никогда не использовал маркдаун для разметки научных статей и документов с вложенными в нумерованные списки таблицами, а CommonMark двигался, почему-то, именно в этом направлении. Не, серьёзно, цитата с вложенной таблицей, в одной из ячеек которой — список? Кому вообще может прийти в голову реализовывать это на маркдауне?

Я сделал полностью настраиваиваемый парсер

YAGNI — друг, или враг?

Уровень сложностиСредний
Время на прочтение5 мин
Количество просмотров2.1K

Один из самых вредоносных принципов в разработке, когда-либо получивших широкую известность — YAGNI. Его озвучил Рон Джеффрис в 1998, а спустя более двадцати лет — еще и Кармак подлил керосин в огонь со своим: «Неопытным разработчикам трудно оценить, как редко разработка архитектуры с учетом будущих требований приводит к успеху».

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

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

Ты чё, пёс, против великого YAGNI?

Перенос процесса с одной ноды на другую

Уровень сложностиСредний
Время на прочтение5 мин
Количество просмотров1.8K

Есть несколько стандартных вопросов для собеседований на позицию разработчик эрланг/эликсир. Речь не идёт про веб, там от людей обычно требуется умение писать код на Phoenix, который настолько хорошо абстрагирует OTP от ранимого разработчика, что можно годами клепать на нем сайты и не иметь представления о том, что такое акторная модель.

Но если речь идёт о понимании парадигмы, людей обычно спрашивают примерно о таких вещах:
  ▸ [junior] чем отличается GenServer.call/2 от GenServer.cast/2 и от Process.send/3
  ▸ [middle] как реализована модель синхронных вызовов (GenServer.call/2) и зачем в колбэке нужен второй параметр
  ▸ [middle] зачем нужен колбэк init/1 и в каких случаях из него имеет смысл вернуть кортеж {:ok, state, {:continue, arg}}
  ▸ [senior] как перенести процесс на другую ноду

Поскольку на хабре все без исключения носят лычку Синьёр++, сегодня мы поговорим о переносе процесса.

Собирайся, ты едешь в Кушку
1
23 ...