メインコンテンツまでスキップ

第07章:部:テスト・観測・実務運用(23〜24章)🧪👀✅

この章のゴール🎯✨

  • GET / PUT / DELETE が「なぜ冪等にしやすいのか」を、言葉で説明できる🙂
  • 「冪等っぽいけど実は危ない実装」を見抜ける👀⚠️
  • ミニ注文APIで、冪等なふるまいのコードが書ける🧑‍💻💕

Concept


まずここだけ覚えよう💡(Safe と Idempotent 🚦)

HTTPの公式仕様(RFC 9110)では、

  • Safe(安全):基本「読み取り専用」=サーバー状態を変えない想定📖
  • Idempotent(冪等)同じリクエストを何回送っても、サーバーへの“意図された効果”が同じ🔁

と定義されているよ📚✨ (rfc-editor.org)

そして、仕様上はこう👇

  • GET / HEAD / OPTIONS / TRACE は Safe(=冪等でもある) (rfc-editor.org)
  • PUT と DELETE は Safe じゃないけど冪等 (rfc-editor.org)

🌟ポイント:冪等だと「通信が怪しくて再送しても、壊れにくい」から超重要! 仕様でも「通信失敗時に自動リトライしやすい」ことが理由として書かれてるよ🔁 (rfc-editor.org)


1) GET は「読むだけ」だから冪等🫶👀

GET の意味(ざっくり)

GET は「そのリソースの表現(データ)をください」っていうメソッド📦 (MDNウェブドキュメント) なので普通は 何回 GET してもデータを読むだけ=冪等&Safe になりやすいよ✨ (rfc-editor.org)

✅ 良い例(注文の参照)📦

  • GET /orders/ord_001

    • ord_001 の注文を返すだけ
    • 10回押しても「読むだけ」🙂🔁

⚠️ 落とし穴(GET で状態を変える)😱

仕様でも「Safe に見えるけど、実装が危険なことはある」と注意されてるよ⚠️ (rfc-editor.org)

たとえば👇

  • GET /orders/ord_001/confirm みたいに **GET で“確定”**させる(アウト!)💥
  • GET するたびに「ポイント付与」「決済」「在庫減らす」みたいな副作用(超アウト!)💳📦

🧠コツ:GET は “何があっても読むだけ” に寄せると設計がキレイ✨


2) PUT は「置き換え」だから冪等にしやすい🔁🧱

PUT の意味(超大事!)

PUT は 「対象リソースを、この内容で丸ごと置き換える」 が基本✨ (MDNウェブドキュメント) つまり「同じIDに、同じ内容を PUT」すると、結果は毎回同じになりやすい=冪等🥰

✅ 良い例(注文を“この形にする”)🧾

  • PUT /orders/ord_001
  • body:{ ...注文の完成形... }

これを2回送っても、サーバーの注文は「その形」になるだけ🔁✨

⚠️ PUT を壊す典型パターン(実は“足し算”)🚫➕

PUT なのに中身がこうなってると危険👇

  • 「毎回、明細行を1行追加する」
  • 「履歴テーブルに毎回“新規レコード”を追加する(それが仕様上の効果)」
  • 「毎回 updatedAt を必ず更新して“別状態”にしてしまう」⏱️😵

冪等の定義は「意図された効果が同じ」だから、リクエストが同じなのに状態が変わり続けるなら、あなたのAPIは冪等じゃなくなるよ⚠️ (rfc-editor.org)

🌸やり方:PUT は「結果の形を指定する」 ❌「追加する」系は PUT でやらない(やるなら設計を工夫する)

🌟 PUT の“あるある”Q&A

Q:PUT で、存在しないIDに送ったら? A:仕様上は「作る」使い方もありえるよ(サーバー設計次第)🙂 初回は 201、2回目は 200 でも、状態が同じなら冪等だよ👌✨


3) DELETE は「消す」だから冪等にしやすい🗑️🔁

DELETE の意味

DELETE は「そのリソースを削除する」💥 (MDNウェブドキュメント) 削除って、2回やっても最終状態は「消えてる」だから冪等にしやすい🥰 (rfc-editor.org)

✅ 良い例(注文の削除)

  • DELETE /orders/ord_001

    • 1回目:消える
    • 2回目:もう無い(でも“無い状態”は同じ)🔁

🤔 2回目は 404? 204?

どっちでも設計としてはよくあるよ🙂

  • 常に 204(No Content):クライアントがシンプル✨
  • 無ければ 404:状態を厳密に返す

どちらでも「最終状態が同じ(存在しない)」なら、冪等の考え方と相性はいいよ🫶

⚠️ DELETE を壊す典型パターン(“二重取り消し”)😱

  • DELETE のたびに「返金を実行」💳💥
  • DELETE のたびに「在庫を戻す」📦↩️
  • DELETE のたびに「ポイントを戻す」🎫↩️

こういう“外部効果”があるなら、DELETEを“消すだけ”にせず、設計を分ける(例:取消の状態遷移を作る)ほうが安全だよ⚔️✨


ちょい寄り道:POST/PATCH はなぜ別扱い?🚧

MDN でも「POST と PATCH は、冪等が保証されない」って整理されてるよ📚 (MDNウェブドキュメント)

  • POST:だいたい「作成」=増える=連打で増えやすい😵
  • PATCH:部分更新だけど、内容によっては「加算」になって冪等じゃないことがある⚠️

🌟ただし「設計で冪等にする」ことは可能(冪等キー方式など)だけど、それは後半でガッツリやるよ🔑✨


ミニ注文APIで体感しよう🍰🧑‍💻

例のデータ型(超ミニ)🧩

type OrderId = string;

type Order = {
id: OrderId;
userId: string;
amount: number; // 合計金額(仮)
status: "draft" | "confirmed";
};

// 超ミニなインメモリDB
const orders = new Map<OrderId, Order>();

GET:読むだけ(冪等&Safe)👀🔁

function getOrder(id: OrderId): Order | null {
return orders.get(id) ?? null;
}

PUT:「この形にする」(冪等にしやすい)🧱🔁

function putOrder(id: OrderId, body: Omit<Order, "id">): Order {
// 「置き換え」なので set 一発が分かりやすい
const order: Order = { id, ...body };
orders.set(id, order);
return order;
}

✅ これなら、同じ id と同じ body を2回送っても、Map の中身は同じだよ🔁✨

DELETE:「存在しない状態にする」(冪等にしやすい)🗑️🔁

function deleteOrder(id: OrderId): void {
// すでに無くても、最終状態は「無い」で同じ
orders.delete(id);
}

演習コーナー✍️🧠(手を動かすと最速で理解できるよ!)

演習1:PUT で冪等になる例を書こう🧾🔁

  1. PUT /orders/ord_001 の body を考える
  2. 同じものを2回送ったら、注文の状態はどうなる? を1文で書く🙂

演習2:危険なPUTを“安全なPUT”に直そう⚠️➡️✨

次の仕様は危険かも?😵

  • 「PUT するたびに amount に +100 する」

✅ これを「置き換え」設計に直すなら、どういう body にする? (ヒント:最終状態を送る!)

演習3:DELETE のレスポンス設計を決めよう📨

  • 2回目 DELETE のとき

    • 204 にする? 404 にする?
    • それぞれのメリットを1行で✨

AI活用🤖💞(“理解するため”に使うやつ!)

① メソッド選択クイズを作ってもらう🎮

「GET/PUT/DELETE のどれが自然か」を10問作らせると強いよ💪 例プロンプト👇

あなたはAPI設計の先生です。
GET/PUT/DELETEの使い分けクイズを10問作ってください。
各問に、1行の理由も付けてください。
対象は「注文API(注文作成/参照/更新/削除)」です。

② “危険な実装”チェック係にしてもらう👀⚠️

自分のPUT/DELETE案を貼って、 「冪等性を壊してる可能性ある?」って聞くのが超便利✨

このPUT/DELETE設計は冪等性を壊す可能性がありますか?
壊すなら、どの副作用が原因になり得るかを箇条書きで指摘して。
その上で、冪等に寄せる修正案を2つ出して。

まとめ🧁✨(この章のチェック✅)

  • GET は基本「読むだけ」=冪等&Safe 🫶 (rfc-editor.org)
  • PUT は「置き換え」=同じ入力なら同じ状態にしやすい🧱 (MDNウェブドキュメント)
  • DELETE は「存在しない状態にする」=2回やっても最終状態が同じ🗑️ (rfc-editor.org)
  • でも!メソッド名だけじゃなく 実装の副作用で冪等は簡単に壊れるよ⚠️ (rfc-editor.org)