API設計とURLの命名規則
追記 2024/05
GoogleのAPIデザインガイドが参考になると思います。
書籍
APIデザイン・パターン (Compass Booksシリーズ)
ただしカスタムメソッド:method
が適用できるかどうかは使っているフレームワークのルーティングに夜と思います。
結論
完全リソースベースの命名、完全コマンドベースの命名ではなく、リソースベースにうまくコマンドを取り入れるとAPIが設計しやすい。またコマンドが増えすぎたときは、そこにリソースが隠れていないか探し、APIのリファクタリングを行う。
Restの流行とリソースベースの命名規則
Railsの影響でRestfulが流行って、URLをリソースの階層とそれに対するHTTPメソッドで表現する方法が流行った。
例えばユースケース
- 猫一覧表示
- 猫新規作成
- 猫情報更新
- 猫情報削除
の場合はつぎのようになる。
- #GET /cats
- #POST /cats
- #PUT /cats/:id
- #DELETE /cats/:id
しかし、これを習ったとき、理解したつもりになっても、実際に実装しだすと、そう簡単には物事は進まなくなる。
たとえば猫のステータスをACTIVE状態にしたいAPIがあったとき、どう表現すべきか?
無理やりリソースで考えると次のようになる。
ステータスの変更と考えて
- #PUT /cats/:id
もしくは、ステータスが`ACTIVE`なリソースを定義して
- #POST /active-cats
putで単純に終わらせてしまうのも、単純化しすぎだし、意図が消えてしまう。
また、このためだけにactive-cats
というリソースを定義するのも、無駄にコントローラーが増えて大変そう。
コマンドベースの命名規則
ここでいうコマンドベースとはすべてPOSTメソッドを使って、やりたいこと(コマンド)をURLで表現する方法。
- #POST /get-cats
- #POST /create-cats
- #POST /update-cats
- #POST /delete-cats
リソースベースほど整理できない。
リソースベースとコマンドの融合
API設計をしていると経験を積んだ人ほど無意識にやってるかも。リソースベースの問題点は更新(UPDATE, PUT) の扱いにくさにある。そこで、基本的なリソースベースな書き方は維持しつつ、更新の派生的な特殊なユースケースに対してコマンドにする。
一般的なユースケース
- 猫一覧表示
- 猫新規作成
- 猫情報更新
- 猫情報削除
- #GET /cats
- #POST /cats
- #PUT /cats/:id
- #DELETE /cats/:id
「猫のステータスをACTIVE状態にしたいAPI」などの特定のユースケース。
- #PUT /cats/:id/activate
これは、オブジェクト指向的な考え方(まず物があって、それに対していくつかメソッドがある)にも相性がよい。
リソースベースとコマンドの融合の注意点
コマンドではなく、リソースに変えたほうがいいときもある。
例えば、ACTIVE
状態の猫に対して複数のAPIがあったとき、こうするのは整理できていない。
- #PUT /cats/:id/do1-for-active
- #PUT /cats/:id/do2-for-active
- #PUT /cats/:id/do3-for-active
むしろ、こういうときは新しいリソースを見出したほうが、APIも作りやすくなる。
- #PUT /acitve-cats/:id/do1
- #PUT /acitve-cats/:id/do2
- #PUT /acitve-cats/:id/do3
Discussion