状態に応じて可能な操作を返すAPIは業務規則の重複を減らす

クライアントが操作名と引数を自由に組み立てるAPIでは、その操作が現在有効かをクライアントも判断しがちである。 たとえば注文画面でキャンセルボタンを出すには、クライアントが「注文済みなら取消可能」「発送済みなら取消不可」といった状態遷移を知ることになる。 サーバーにも同じ検査が必要なので、業務規則が二か所に重複する。

応答に現在可能な操作を含めれば、操作可否の判断をサーバーへ集められる。 注文済みの応答には支払いと取消へのリンクを含め、発送後の応答からは取消を除く。 クライアントは返された操作を表示して実行するだけなので、状態名から可能な操作を推測せずに済む。

{
  "id": 42,
  "status": "PLACED",
  "_links": {
    "payment": { "href": "/orders/42/payments" },
    "cancel": { "href": "/orders/42" }
  }
}

これは、現在の表現に含まれる遷移候補を選ぶことで次のアプリケーション状態へ進む、RESTのハイパーメディア制約に当たる。 クライアントが接続先を組み立てず、サーバーがリンクを変更できる点でも結合を減らせる。

ただし、クライアントから業務知識がすべて消えるわけではない。 クライアントは payment や cancel というリンク関係の意味と、その入力形式を知る必要がある。 既知のリンク関係の意味を変更すればクライアントにも影響するため、変更耐性が得られるのは接続先や未知の操作を独立して変えられる範囲に限られる。

可能な操作の列挙は、注文処理や小さな状態機械のように候補が限られる場合に向いている。 座標や金額のように入力の組合せが巨大または連続的なら、「この範囲で操作できる」という引数付きの操作を返す必要があり、無効な入力を表現できないという利点は弱まる。

返されたリンクが何をできるか示すことと、リンクの所持者に実行権限を与えることは別である。 この違いはアフォーダンスとケイパビリティの区別として扱う必要がある。

https://koriym.github.io/blog/2025/03/31/cubist-coding/

https://speakerdeck.com/swlaschin/designing-with-capabilities

https://ics.uci.edu/~fielding/pubs/dissertation/rest_arch_style.htm

#api-design #rest #hateoas #state-machine #domain-model