Заждались тредов? Их есть у меня. Cегодня поговорим про такую мегаважную штуку как "идемпотентность", про то как она позволяет проектировать более надежные системы. Ретвитим, не стесняемся! Небольшой опрос. Насколько вы в курсе про идемпотентность?
Идемпотентность – это свойство какой-либо операции, например, вызова функции или выполнения HTTP-запроса. Операция считается идемпотентной, если повторные выполнения приводят к тому же результату что и первое выполнение. Рассмотрим кучку примеров из самых разных направлений
Возьмем команду mkdir в линуксе. Она создает директорию: mkdir jopa. Что будет если выполнить эту команду два раза? Во второй раз мы получим ошибку. То есть операция не идемпотентная. Тоже самое справедливо и для многих других команд работающих с файловой системой. Что дальше?
А дальше делаем выводы. Если мы напишем какой-то скрипт, выполняющий подготовку файловой системы, например создающий базовую структуру для нового проекта (типа ./prepare.sh /lala), то отсутствие идемпотентности начнет серьезно мешать. Что может пойти не так?
Во время и после отработки: 1. Отключат свет 2. Не хватит прав 3. Мы что-то случайно удалим и захотим все восстановить 4. Кончится место. И так далее, список может быть большим. Во всех этих ситуациях понадобится повторный запуск и тут бах, он начинает падать с file exists
Соответственно придется вообще все удалять и запускать скрипт так, как будто его раньше не запускали. Мягко говоря это неудобно. Но мы можем обеспечить идемпотентность самостоятельно. Для команды mkdir достаточно добавить флаг -p и повторный запуск перестанет падать с ошибкой
Не все команды имеют флаги идемпотентности, местами нужно прямо писать код с условиями. В конечном итоге подобные sh скрипты превращаются в ад. Именно поэтому появились инструменты управления конфигурацией типа Ansible, одна из основных задач, которых обеспечивать идемпотентность
Докер тоже решает эту задачу. Так, при сборке образа на основе Dockerfile нам не важно что было раньше, то идемпотентность обеспечивается автоматически. Именно поэтому bash команды внутри Dockerfile это не тоже самое что и реальные bash скрипты. А сборка легко кешируется
Обязательно посмотрите статью в блоге Хекслета, где подробно рассмотрена идемпотентность в bash-скриптах ru.hexlet.io/blog/posts/poc…
Перед тем как пойти дальше, напомню что мы ищем преподавателей и наставников. notion.so/hexlet/c6406ed… Мы находимся на пути создания школы наставников, где мы учим как эффективно работать с людьми, давать обратную связь, вдохновлять и поддерживать. Тимлидам мастхев.
Теперь про идемпотентность в HTTP. Там она закреплена прямо на уровне спецификации: datatracker.ietf.org/doc/html/rfc72… Очень рекомендую читать именно спеку. В случае протоколов это невероятно полезное и, что удивительно, интересное чтиво. Просто статьи по http почти всегда сильное упрощение
Например GET, по спецификации, является идемпотентным методом, а POST нет. Тут стоит оговориться что, сам по себе, HTTP этого обеспечить не может. Все зависит от разработчиков. И не знание этих особенностей или игнорирование может приводит к довольно серьезным последствиям. =>
Из доки: For example, if a client sends a PUT request and the underlying connection is closed before any response is received, then the client can establish a new connection and retry the idempotent request.
Идемпотентность позволяет безопасно делать ретраи и кешировать запросы
А вот то что POST не идемпотентный нам подсказывает даже браузер. Помните когда после POST-запроса пытаешься сделать f5, то браузер предупреждает о повторной отправке данных и что это не безопасно. Если пройдет валидация, то что-то случится два раза, например выполнится оплата
Тут мы приходим к интересному моменту. Представьте что вы работаете с платежным сервисом типа Stipe. Как обезопасить себя и клиентов от повторных списаний денег при отправке запросов? Это легко случается, когда возникают сетевые ошибки при повторных запросах.
Стандартный способ – добавления ключа идемпотентности. То есть при отправке запроса на списание денег, мы указываем специальный параметр, идентификатор транзакции. Обычно это номер заказа. А платежный сервис на его основе обеспечивает идемпотентность. stripe.com/docs/api/idemp…
Stripe, кстати, делает это на основе драфта tools.ietf.org/id/draft-idemp… Это потенциальный стандарт, который унифицирует работу с идемпотентностью в HTTP мире. Пользуйтесь на здоровье)
Небольшая самостоятельная работа. Является ли метод DELETE в HTTP идемпотентным? Отвеьте себе и дальше посмотрите спецификацию. Там все написано)
Ой, случайно пару сообщений отправил вне треда. Щас добавлю их сюда
Стандартный способ – добавления ключа идемпотентности. То есть при отправке запроса на списание денег, мы указываем специальный параметр, идентификатор транзакции. Обычно это номер заказа. А платежный сервис на его основе обеспечивает идемпотентность. stripe.com/docs/api/idemp…
Stripe, кстати, делает это на основе драфта tools.ietf.org/id/draft-idemp… Это потенциальный стандарт, который унифицирует работу с идемпотентностью в HTTP мире. Пользуйтесь на здоровье)
Идемпотентность особенно важна при работе с очередьми, типа rabbitmq. В этой части ретраи неизбежны и возникает скорее обратная проблема, как остановить то что надо остановить. Тут могут помочь автоматы и превращение at-least-once в at-most-once, но это тема отдельного треда)
Еще одна область – миграции в базе, особенно миграции данных. Здесь просто без вариантов, если миграция не будет идемпотентная то быть беде. А еще с миграциями данных полезно исключать мигрированные данные через where, что уменьшит количество запросов после ретрая
Как все это ложиться на код? Многое из того что я описал, обеспечивается кодом, который мы пишем. Каждый раз когда вы создаете код, выполняющий побочные эффекты на уровне ввода/вывода (фс, сеть), задумайтесь об идемпотентности. Вполне вероятно она тут очень в тему.
Давайте немного порефлексируем. Теперь стало понятно где нужно об этом задумываться и как оно вам поможет в проектах? Что-нибудь нужно дораскрыть?
На собеседовании я всегда начинаю разговор с вопроса "где вы сейчас работаете и чем там занимаетесь?". Вопрос простой, но при большой выборке скапливается довольно много интересных, смешных и грустных ответов. Ниже я расскажу о всяких забавных ситуациях и об идеальном ответе =>
Самое страшное когда говорят "начну с самого начала". Началом может оказаться школьные годы и долгий тернистый путь к себе настоящему. Однажды чувак мне сказал "щас я коротко про себя расскажу". Через 30 минут пришлось его останавливать
В любом случае, многие рассказывают про весь свой путь чуть ли не с самого первого дня работы программистом. Как собеседующий я бы хотел пропустить эту часть и говорить про текущую работу, так как это съедает кучу времени. Если понадобиться уйти в прошлое, то я задам вопрос.
Через час-два тред про функции. Многим кажется, что функции это просто, но нет. Хорошие функции выглядят просто, но реализовать их тяжело. Какими руководствоваться правилами? Об этом и поговорим. #functions
Поехали! Обычно, от функций ожидают сокращения дублирования кода. Да, функции устраняют дублирование, но лишь в дополнение к тому, зачем они нужны. Настоящий смысл функции – повышение уровня абстракции. Звучит немного абстрактно, поэтому раскроем подробнее =>
Мир сложная штука, но эта сложность спрятана за простыми и понятными вещами. Например, работать с клавиатурой может даже ребенок, но лишь потому что она хорошо спроектирована и прячет от нас детали реализации. Нам не нужно знать физических законов для ее использования
Метатред по серии "Автоматное программирование". Рассказываю тут про флаговое программирование, явно выделенное состояние, автоматы на бекенде, автоматы на фронтенде и кидаюсь кучей полезнях #FSM
1. Автоматы как способ моделировать процессы вокруг нас
Третий тред по автоматному программированию. Поговорим про бекенд на разных языках. Ситуации, связь с базой, готовые либы и применимость. Ретвиты приветствуются! Вопрос: Используется ли в вашем проекте либа для автоматов?
Краткий пересказ прошлых частей. Автоматы есть всегда, главное их увидеть и заменить флаги на явно выделенное состояние. А в бекенде еще и автоматизировать работу с ними. Как?
Независимо от выбранного стека, состояние практического любого проекта отражается на базу данных. Заводятся либо флаги, либо поле state/status куда записывается название текущего состояния. В отличии от фронтенда, с автоматами в беке надо быть гораздо более аккуратными
Вторая часть про Автоматное Программирование. Сегодня поговорим со стороны фронтенда, а следующим тредом про бекенд. Не забываем лайкнуть и пошарить, дабы добро дошло до всех уголков твиттера. Поехали! #fsm
Напомню что конечный автомат это удобная модель, с помощью которой естественным образом описываются процессы с дискретным состоянием. Простой пример – модальное окно. Оно может быть закрыто или открыто и его можно закрыть или открыть. 2 состояния, 2 перехода.
Состояния влияют на то что можно делать с объектом о котором идет речь, а переходы это собственно то что мы программируем. Кстати иногда возможны переходы в самого себя. Про это поговорим отдельно в бекенд истории.
И так поехали тред про конечные автоматы (fsm, state machines). Одной из ключевых тем в разработке софта касающуюся всех программистов без исключения. Будет много примеров для разных языков. После этого треда вы, вероятно, увидите мир другими глазами. Лайк, шер, алишер, погнали!
Существует заблуждение что автоматы это что-то, из математики, не имеющее отношение к реальной жизни. Их используют в лексическом анализе для написания парсеров. Многие помнят лабы на си, где нужно было разбирать строчку. Да это тоже автоматы, но совсем другие.
Мы же поговорим об автоматах с точки зрения моделирования бизнес-процессов, которые мы программисты по большей части и программируем. Сразу предупрежу, что тема автоматов ну очень глубокая, они бывают совсем разные и к ним нужен разный подход. Поэтому что-то останется за кадром