Resource-based APIとUsecase-based APIの勘所
#設計 #Web_API #Web_API設計の勘所 #Server_State #リソースとユースケースの分離
バックエンドのWeb APIは2種類に分類できる
Resource-based Web API
Usecase-based Web API
それぞれ一長一短だが、この2種類のAPIをシステム自体のライフサイクルの違いに合わせて分割すると、柔軟な開発サイクルを支えてくれる
UIの改善、ユースケースの再設計に巻き込まれてもしょうがない部分とそうでもなさそう部分を分離する
前者は「ユースケースに対するデータプロバイダー」としてのUsecase-based Web API
後者は「リソースコンテナ」としてのResource-based Web API
業務をユースケース単位に分けてモデリングする
リソース自体に変化があるわけじゃないなら、その部分は残したい
ユースケースに依存する範囲を明確に分けたい
その境界で、バックエンドのサーバーor Web APIごと分けてしまうというモチベーションが生まれる
Usecase-based Web APIが存在しない場合、複雑なユースケースに対応するために以下のどちらかの選択が取られる
-1.クライアントがResource-based Web APIのデータをユースケースに合った形に整形する
-2. Resource-based Web APIが拡張されてユースケースを受け入れはじめる
前者を選択するとクライアントの実装難易度や複雑性が高まっていく
Presentation Model、Container/Presenterパターンの駆使
複雑GUI化していきUI/UX改善の速度が長期的に落ちていく
Resource-based Web API同士の暗黙的な結合が発生する
サーバが意図していないAPIの使われ方をする
権限モデルあたりで事故る確率が高まる
そもそもクライアントのユースケースの中では目的が必ず存在してデータアクセスが生まれる
すごく単純化すると「ID=2のUserのデータがほしい」ではなく「ID=2のユーザーの名前を表示するためのデータがほしい」
そのユースケースにとってはユーザーの名前がUserテーブルのNameカラムに保存されているとかそんなことはどうでもよい
ただユーザーの名前がほしい、というニーズだけがある
Usecase-based Web APIがある場合は、クライアントはユースケースをサーバーに投げつける
ユースケースを定義するのはクライアントの仕事
ここはGraphQLのようにフロントエンドでほしいデータの形を定義するのがマッチする
フロントエンド、Resource-based Web API、Usecase-based Web APIが分かれたとき、それぞれのシステムのライフサイクルは次のようになる
https://scrapbox.io/files/63368ba09d2e3f001dd7ef8b.png
クライアントはまっさきに壊されるが、それは宿命として諦める
Usecase-based Web APIがあることでResource-based Web APIは長生きすることができる
どっちがいいの
基本的にはResource-based Web APIでやっていけばいいんじゃないかな
スケール性に問題が出てきたらUsecase-based Web APIを検討する
GraphQLはスキーマの運用コストや開発コストが高くてメンバー次第では採用するのが難しいかも
Resource-based Web API にこだわること自体が難しいというケースがある
リソースを考察するというスキルが不十分である
リソースを考察することに時間をかけるメリットが少ない
例えばPMF前のプロダクトだと
ドメインモデルがはっきりしない
内部品質よりも初期のスピードが重要である
経験豊富な開発者がいない
作っているものがユースケースに強く依存しているにも関わらずそれをリソースとして捉えようとしてうまくいかない
RESTAPIの場合は明らかにユースケースに依存しているとわかれば、割り切って特定の endpoint にユースケースの名前をつけてしまって (GET /usecase_name) それ専用のものにしてしまえばいい
クライアント側はRESTAPIを利用するアプリケーションロジックの命名にCRUDを持ち込まないことが重要
そうしてもおくことでユースケースに対するスケール性をある程度担保できる
まとめ
Usecase-based Web APIは常にアプリケーションのために存在するが、Resource-based Web APIはアプリケーションが無くても成立する。
基本的にはResource-based Web APIを重視する
設計判断の意思決定において重要なのはリソースの概念と関係性をチーム全体で認知すること
≒ データベースのテーブル設計を良くすること
これをサボると Usecase-based なテーブル設計になるが、より短期間でシワ寄せがくることが容易に想像がつくだろう
データ構造, テーブル設計をきちんとすれば、良いResource-based Web API は8割方完成したようなもの
ここは経験すればするほど上手くなる(良いものを速く作れるようになる)し、自らの成長のためにもサボるべき箇所では決してない
DDDするというわけではなく、ドメインの設計をデータベースのモデルに落とし込む表現力が大事
実はDDDってしっくりこないんです
いいデータ構造はいいアルゴリズムを生む
バックエンド/フロントエンド問わず、どのイベントの発生によりどのリソースが芋づる式に影響するのかは理解しておいたほうが良い
リグレッション管理に役立つ
フロントエンド寄りのkoushisa.icon視点では
Resource-based Web APIでほとんどのケースは十分
最近はReact Hooksでモデリング層作れるので
Render As You Fetchパターン
Presentation Model
Usecase-based Web APIを運用するよりもお互いに適宜コミュニケーション取るほうが楽だと思う
要件次第でモバイル専用のWeb API生やすとかなると流石に限界はあるかもしれない
APIの背後にあるスキーマを運用する知識やそのコミュニケーションの効率化に労力を割くほうが全体最適化に繋がる
BIZ Team, DEV Team,Design Team,QA Team全員の共通言語として利用できる
WEB APIのスキーマは誰のもの?
わかってないこと
GraphQLのqueryでResource-based Web APIとUsecase-based Web APIを両立するのはどうなんだろう?
BaaSだと、Hasura, Supabase, Graphbase, GraphQL Meshなどでいいとこ取りできそうな気もする
2023/12/25 一年ぶりに追記
React Server Componentsをアーキテクチャとしてどう捉えるかというのを色々考えると、 バックエンド API に求めるものは「ページを描画するための全情報を返す API」ではなく「Component を描画するための情報を返す API」という結論になりつむある
参考
https://note.com/qsona/n/n8362e4721748
https://lacolaco.hatenablog.com/entry/2018/07/13/001820
RSCやAppRouterはGraphQLの正統進化で、resolverがJSXを返すようなもの#654811c18660300000feb8bc