冪等性についての思索
冪等性の定義
冪等性とは、処理を1回行っても複数回行っても同じ結果となるような性質のことである。
冪等性の定義は入力に対する振る舞いについては何も言っていない
SELECT文は冪等か
以下はuser
表から全レコードを取得するSELECT文である。
select * from user;
このSQLは冪等だろうか。user
表の中身が常に変わらないなら冪等だし、ある回の実行時からuser
表の中身が変れば、次の回の実行時の結果は別のものになるから、冪等でない。
つまりSELECT文が冪等であるためには、参照する表の内容が変わらないことという前提が必要である。
暗黙の入力
このSELECT文を呼び出す処理があったとすると、その入力はテーブルデータという外部リソースであり、出力は取得したレコードになる。プログラム上、テーブルデータやファイルのような外部リソースは明示的に処理の入力としては定義されないかもしれないが、暗黙的な入力であるといえる。
以下で入力と言った場合は暗黙の入力も含むものとする。
何らかの変化を生むことにアプリケーションの意味がある
入力を受け取った後、何もしない処理は冪等である。しかしそんな処理を実装したところで意味があるのだろうか。
常に状態が変わらないテーブルから値を取得する処理は冪等である。しかしそんな処理は一度呼び出せば十分ではないだろうか。
我々がアプリケーションに対して期待していることは、変化する入力に対応して何らかの変化が起こった結果を出力することである。
冪等性に期待するのは「同じ入力に対して一度だけ変化を生む」こと
冪等性を持つ処理の一例としてupsert
処理がある。あるレコードを表に登録するとき、そのキーがまだ存在しなければinsert
、すでに存在する場合はupdate
を行う。
この処理の主目的は、入力した値が表に登録されることであり、upsert
の持つ冪等性は、「処理を何度呼び出したとしても登録が1度だけ行われることが保証される」という点において役に立っている。
(上の例において「入力した値が表に登録された状態」に注目することもできる。これは「宣言的」というワードで表現される。宣言的な処理は冪等性をもつ。)
「2回目以降は変化しないこと」よりも「1度限りの変化を起こせること」に根本的な価値がある。
冪等性が担保された処理は「いつ何回呼び出すか」を考えなくて良い
手が滑って送信ボタンを2度押してしまった、ジョブが中断したので、本来の起動時刻ではないタイミングで再実行したい、といったケースで冪等性が活躍する。
冪等性が担保された処理は、呼び出すタイミングが変わっても何度呼び出しても、入力が同じでさえあれば結果として同じ状態を得ることができる。
冪等性の次に考えること
先に述べたように、冪等性が担保された処理であっても入力の変化には気を配らなければならない。
暗黙の入力を洗い出してそれらをコントロールできるようにすることが重要である。