Idempotency: Difference between revisions

From Helpful
Jump to navigation Jump to search
mNo edit summary
Tag: Redirect target changed
 
(3 intermediate revisions by the same user not shown)
Line 1: Line 1:
<!--
#redirect [[Some abstractions around programming#Idempotency]]
 
In most contexts, the point of an idempotent operation is that it has no ''additional'' effect if it is done more than once.
 
 
For a tactile example, consider an industrial machine has an separate 'on' and a separate 'off' button.
: Regardless of the state before, if you press the 'on' button, it is going to be on afterwards
: Regardless of the state before, if you press the 'off' button, it is going to be off afterwards
: ...also regardless of how often you press that same button afterwards.
 
 
In comparison, the power button on most computers ''toggles'' (and is only a ''request'' to change - unless held for 4 seconds as per ATX specs)
: ...so you won't know entirely for sure about its state afterwards
:: so it's ''not'' idempotent. 
:: (the fact that that's because action depends on the current state just happens to be the main reason, not a ''defining'' part of this non-idempotency)
 
 
 
Stoplight crosswalk buttons are idempotent (with few exceptions)
: in that you can press them more than once, but it'll just stay in 'requested' mode until the system acts on it.
: (and sometimes nullipotent, meaning the light will schedule you regardless of whether you pressed, and it's there just to make you feel in control)
 
* elevator call and floor buttons are idempotent (with few exceptions)
: ...even if people like to hold on to their magical thinking about special modes that make it go faster
 
 
 
In math and computing, it doesn't change the output if called more than once, with the same input parameters.
 
For example
* anything that makes no changes
: e.g. HTTP GET, HEAD, OPTIONS, TRACE
:: though people do abuse GET (e.g. allowing sets from GET requests, not just POST, is moderately common)
 
* adding or removing an item to the set
: e.g. HTTP DELETE
 
* various string operations, e.g. uppercasing a string
 
 
 
Such a property happens to be useful, in design, and in talking about design,
in particular APIs, because you're typically modeling what should happen on the other end,
and are usually not inspecting or policing every step.
 
Say, it's really useful to know that if an identical operation is sent to a server several times,
it leaves the server in the same intended state.
 
Around updating state, this can e.g. simplify complex state management to 'just retry until is says OK'.
 
 
For the HTTP examples,
: It's just defined that way so that HTTP clients can assume certain things.
: it's not that you can't break that, by mistake or even by choice. In particular GET is sometimes not idempotent in practice.
 
 
----
 
There are some introductions that say that "same result" sort of means both "no side effects" and "is idempotent" which is... misleading.
 
In programming, an idempotent operation is an operation that ''does'' have [[side effects]] (because it alters state),
but where running it multiple calls has the same ''end result'' as running it once.
 
----
 
 
The thing about computing examples is that when there is any amount of concurrency,
the meaning shifts a little.
 
An operation may may be entirely idempotent in itself, and effectively idempotent if called adjacently,
but is not when there are multiple clients.
 
Or still is. Depending on timing.
 
This usually doesn't matter, because in most cases it's not about this property,
it's about it doing the thing you wanted it to do,
and only sometimes about correctness.
 
 
Usually we care about idempotency in a "would this do the wrong thing in edge cases" way.
: For example, in the "if we send this twice, would it do the ''wrong'' view,
:: "increment counter" isn't idempotent
:: "set value to 51" is idempotent
:: "increment counter from 50 to 51" ''can'' be made idempotent on the backend (if not necessarily correct)
:: "increment counter if you haven't seen token (random number) recently" can be both idempotent and correct
 
 
 
So even fetch won't necessarily return the same thing every time
: ...but it will not be part of ''making'' a change
 
: yes, this is only true while there are no other actors. This is a stretch of the concept.
 
 
 
 
You can argue technicalities when there are many steps.
 
Say, an elevator button may well involves little state changes in communication,
even if it eventually doesn't change the behaviour.
 
 
 
and then the final thing to do with it 'call elevator?' is not.
 
 
 
 
 
 
 
 
so the following are more of a "...usually"
 
* HTTP HEAD, HTTP OPTIONS and HTTP TRACE is supposed to be idempotent (in that it does not attempt to make changes)
 
* a HTTP GET is ''expected'' not to (you ''should'' use HTTP POST if it probably changes state)
 
* an SQL SELECT and is idempotent in that it doesn't even ''try'' to change state
 
 
* an HTTP PUT and HTTP DELETE, and SQL DELETE are often assumed to be idempotent
 
 
* a HTTP POST is expected to often not be idempotent (but may be in some cases)
 
* an SQL UPDATE is expected to often not be idempotent
:: it would be if you give it a constant value
:: but there are a bunch of things SQL allows that are not
 
 
* an SQL INSERT or HTTP POST is assumed ''not'' to be idempotent
: in that 'add record' may add a record each time
 
* An SQL backup dump
** is idempotent if running it produces the data as we saw it -- which usually amounts to it being "drop table; create table; insert data"
** is not idempotent if it just inserts data
 
 
Notes:
* the HTTP examples mostly just extend into REST
: because they are the CRUD operations that REST is typically made of
 
 
----
 
 
 
 
 
 
 
 
This is useful to know/guarantee for reasons like
* it usually being used in a "will not break things if run repeatedly"
: which may be relevant e.g. around parallelism, locking
 
* it usually being used in a "will not do incorrect things if run repeatedly"
: which may be relevant e.g. around ordering systems, money
 
* People also use it in a "it won't change state"
 
* it's a useful property when running tests
: in that when expect idempotent result, you can test for it
 
 
 
* settling protocol semantics
: e.g.
:: HTTP GET should be idempotent (you ''can'' have GET do alterations, but UAs following HTTP semantics mean that's a bad idea)
:: HTTP DELETE and PUT are also intended to be idempotent (because storing the same thing just means it's saved again, or deleting the same thing just means it's still gone)
:: HTTP POST is not expected to be idempotent
 
* describing function behaviour
: pretty-printing data/code is generally expected to be idempotent, in that if it already was, it won't change it further
: you can imagine many other string functions being idempotent in this way - a test for uppercase like if str==str.upper() counts on it
 
 
 
Lookups are typically idempotent (except e.g. if there's something counting lookups)
 
Updates may or may not be
: add/subtract operations won't be
: "place order" is not idempotent
: while e.g. "set address to new thing" can be accidentally clicked five times and it will really not change what happens
 
 
 
 
 
 
 
 
And often more specifically, 'will not change any state further if run repeatedly'.
 
 
Which of those two it is depends on how strict and mathematical you want to get.
 
 
 
'''Idempotency is sometimes a nice detail to writing code.'''
 
Say, if 'remove value from set' would be fine if it's there and error out if not,
that's two cases you need to handle separately.
 
If it effectively is 'ensure it's not in the set' and idempotent in that it'll just do nothing,
then the calling code doesn't have to care about that distinction.
 
 
 
 
'''Idempotency can be a really useful part of the semantics of interaction.'''
 
For example, [[REST]] makes a point that a HTTP GET should not change state -
e.g. so that if a GET fails, you can safely repeat it until it succeeds.
 
And a HTTP DELETE on a single resource will have the same result if repeated.
 
 
This makes it a lot easier for someone using that REST interface to know
what's happening without double checking all the time.
 
 
 
 
 
Note however that there are various weasel words in there.
 
https://stackoverflow.com/questions/1077412/what-is-an-idempotent-operation
-->
 
 
 
[[Category:Progamming]]

Latest revision as of 11:40, 19 September 2023