Pull to refresh

Comments 34

Эх, побольше бы таких текстов, чтобы у публики на брейнстормах не было лиц суррикатов, когда произносишь слово «idempotency» вслух.

Одно замечание:

что вы решили обновить свой образ, заменив футболку

Это PATCH, а не PUT, и он не идемпотентен (и не безопасен). Если для формирования «образа» кроме футболки я надел на себя что-то еще — то PUT должен принести замену всему, что на мне надето. Потому что если пока я развлекаюсь с мнимой идемпотентностью смены футболки, с меня стащат штаны — образ после второй смены футболки будет сильно отличаться. В общем, PUT — это тот же POST, только идемпотентный. Он обязан принести с собой слепок всего объекта, а если он приносит только некоторые части (футболку) — это PATCH.

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

Нет, конечно. Вы не сможете придумать такой формат дельты, который учтет все вызванные извне изменения, произошедшие с объектом между двумя вашими вызовами. Или это будет дельта, изоморфная всему объекту, что фактически означает «looks like PATCH, walks like PATCH, quacks like PATCH — let’s call it PUT».

Почему же?

Если говорить про json api, и оставить за скобками массивы (там и правда есть сложности), то достаточно выкинуть из схемы все неизменяемые и вычисляемые поля, а остальные сделать необязательными.

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

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

Интересно получается, ничего не поняли вы, а недостаток понимания - почему-то у меня...

Да я просто на словах «json api» перестал читать, потому что оно тут вообще не пришей кобыле хвост.

Интересно, кто это заминусил автора выше, ведь он правильно сказал «json api» причем тут он вобще. должны быть мухи отдельно а котлеты отдельно.

DELETE идемпотентен

Какой эгоцентризм. Вы же не в транзакции работаете. Сосед мог напостить нового между двумя делитами.

И что? По спецификации DELETE идемпотентен. Если ключи могут переиспользоваться, DELETE по ключу просто противоречит спецификации. С переиспользуемыми ключами и PUT не идемпотентен, представляете себе?

Я не со спекой спорю, а с тем, как это описано в статье.
Если угодно, мой кот не понимает.

Результат окажется один и тот же независимо от того, постил сосед между делитами или нет. В этом и суть идемпотентного удаления.

Тогда всю статью переписывать надо. Потому что там утверждается, что второе применение не вызывает изменений.

Не вызывает изменений если идёт сразу после первого.

Выражаясь языком математики, f(f(x)) = f(x)

Это неверное определение, неясно откуда вы его взяли. Выражаясь языком математики, `f(g(f(x))) ≡ f(x), ∀g ∈ F(x) → F(x)`

Я-то своё определение взял из учебника математики, а вы свою чушь откуда взяли?

Господи, вы бы с реальностью и экспериментом как-нибудь соотносили ваши учебники.

Мы про определение в вебе? Поздравляю, по вашему определению и любой PATCH идемпотентен. Про математику — надо смотреть как минимум определение на афинных полугруппах (потому что непрерывных параметров в вебе не бывает, печаль).

Эрудиция — прекрасная штука, но интеллект, как известно, не заменяет.

Определение в вебе соответствует математическому.

Поздравляю, по вашему определению и любой PATCH идемпотентен.

Неа, не любой. К примеру, стандартный diff для текстовых файлов неидемпотентен.

Про математику — надо смотреть как минимум определение на афинных полугруппах (потому что непрерывных параметров в вебе не бывает, печаль).

А где в формуле f(f(x)) = f(x) хотя бы намёк на непрерывный параметр?

стандартный diff для текстовых файлов

Стандартный кто? PATCH в вебе — описан в RFC 5789. У стандартного diff, как минимум, два аргумента, он вообще из другой оперы.

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

PATCH в вебе — описан в RFC 5789

Формат патча в RFC 5789 не описан, он определяется реализацией (а также Content-Type), и может быть любым. В том числе тем, что используется в утилитах diff и patch.

У стандартного diff, как минимум, два аргумента, он вообще из другой оперы.

Очевидно, я говорил не об утилите, а о формате, в котором она выводит различия. Если бы вы сосредоточились на попытках меня понять, а не оскорбить -= вы бы это поняли.

Если бы вы сосредоточились на попытках меня понять, а не оскорбить

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

Формат патча в RFC 5789 не описан

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

Ну и чтобы вам понятнее было. Когда я говорил «по вашему определению и любой PATCH идемпотентен» — мне надо было сказать «по вашему определению гигантское количество патч-запросов, которые все адекватные люди (и консорциум) назовут неидемпотентными — оказываются идемпотентными».

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

А где в формуле f(f(x)) = f(x) хотя бы намёк на непрерывный параметр?

Да, а вот тут погорячился я.

Про методы GET, POST, PUT, DELETE довольно странные мысли. Любой из методов можно сделать идемпотентным или не идемпотентным. Метод - это лишь вариант интерфейса.

Не так давно я работал с API банка, у которого вообще все было сделано через GET, причем параметры через url. И добавление заказов, и удаление, и запрос статуса... все-все-все :)

Можно, но тут речь про спецификацию, а не про то, как её можно извратить.

Видимо, да. Но об этом остается только догадываться. Если бы я не был немного в теме, я бы не понял того, что речь о спецификации этих методов. Этого не понятно ни по названию, ни по содержанию статьи. Ну и не помешало бы разъяснение, что это лишь рекомендации, которые соблюдаются далеко не всегда. Я бы даже сказал, что редко соблюдаются...

Важная часть, которую надо бы вынести большими буквами для новичков в начало статьи - методы PUT и DELETE ДОЛЖНЫ быть идемпотентный в соответствии с RFC, но в реальной жизни всегда проверяйте, что нашкодили программисты, потому что никто этого не гарантирует. По сути это все го лишь слова для разграничения разных методов, а что они делают зависит от кода, и GET с POST могут использоваться для удаления записей.

И, кстати, да, по RFC идемпотентными являются в явном виде только PUT и DELETE, GET не обязан быть таковым.

Метод без побочных эффектов всегда идемпотентен.

Неа, не любой [PATCH идемпотентен]. К примеру, стандартный diff для текстовых файлов неидемпотентен.

ваши слова?

Метод без побочных эффектов всегда идемпотентен.

тоже ваши?

Простейший силлогизм: diff имеет побочные эффекты. Внимание, вопрос: какие именно?

Применение патча формата diff к файлу, очевидно, меняет этот самый файл. Это и есть побочный эффект с точки зрения стандарта HTTP.

Изменение сущности на которую указывает идентификатор ресурса при вызове небезопасного метода — побочный эффект с точки зрения стандарта HTTP?

Я сдаюсь. Искренне завидую, если вам удается зарабатывать деньги не астрологией и не финансовыми махинациями.

А что не так-то? Основной результат запроса - это ответ сервера. Всё остальное - побочные эффекты.

И, если что, "метод без побочных эффектов всегда идемпотентен" написано прямо в стандарте:

A sequence that never has side effects is idempotent, by definition
-- https://datatracker.ietf.org/doc/html/rfc2616#section-9.1.2

(одиночный запрос является тривиальной разновидностью последовательности запросов, если вы решите ещё и тут придраться)

О, пошло в ход вырывание слов из контекста. Полная цитата, а не те три слова, которые вам выгодны, звучит так:

A sequence that never has side effects is idempotent, by definition (provided that no concurrent operations are being executed on the same set of resources).

Когда для человека веб — однопоточная неконкурентная среда — и не такие аберрации сознания, конечно, происходят. На всякий случай уточню: я понял, что вы имеете в виду одиночный запрос (по определению неконкурентный), и что для вас

Основной результат запроса - это ответ сервера. Всё остальное - побочные эффекты.

Попробую в последний (клянусь) раз: запрос, который по идентификатору ресурса меняет значение числового поля этого ресурса на модуль его значения. Функция взятия модуля — идемпотентна (в вашей этой математике, если я правильно помню). Условию `f(f(x)) ≡ f(x)` удовлетворяет. А запрос, гад, неидемпотентен. Потому что если между двумя такими патчами прилетит запрос, меняющий это значение на его квадратный корень, — результаты окажутся разными.

Ссылку на то, что изменение ресурса по идентификатору не является по спецификации сайд-эффектом мне искать лень, да и вряд ли ее модно вообще найти, настолько это всем очевидно.

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

Могу инвайт выслать — сможете мне еще раз поднасрать в карму с другого аккаунта.

А правильный ответ: идемпотентность зависит от того какими кривыми руками спроектировано АПИ. Я так понимаю тут речь про канонический REST. В реале довольно часто встречается следующее: [POST] "/object-type/:id" для обновления объекта, а вот если вызвать без параметра в урле, то будет создан новый объект.

Sign up to leave a comment.

Articles