svg-animation
ブログ一覧

API設計で必要なこと。技術よりも先に、使う人の体験から考える

APIは、SPAやモバイルアプリ、Webアプリケーション、IoTデバイス、デスクトップアプリなどが、データを保存したり読んだりするための窓口です。設計には、テクニックや知識、経験、ベストプラクティス、サーバーコストの話がついて回ります。どれも大事ですが、いちばん先に考えるべきものは別にあります。

CX、つまりカスタマーエクスペリエンス(顧客体験)です。技術ファーストより、顧客ファースト。

この記事は、API設計について参考になった記事を自分なりに整理し、そこから考えたことを社内勉強会で話した内容です。前半は参考記事の整理、後半は自分たちの手順です。

内側からではなく、外側から設計する

APIの設計には、2つの向きがあります。

  • インサイドアウト:公開する内部システムやサービスの都合に基づいてAPIを設計する
  • アウトサイドイン:作り上げたい顧客体験に基づいてAPIを設計する

インサイドアウトとアウトサイドインの違い(イメージ図)。インサイドアウトは内部システムの都合からAPIを決める。アウトサイドインは利用者の体験からAPIを決め、内部の実装はあとから合わせる。

利用者がAPIに求めるのは、自分の仕事が簡単になり、生産性が上がることです。その求めに応えるAPIがほかにあれば、利用者はそちらを選びます。だから、まず利用者が何を必要としているかを知り、それに合わせてAPIを作る。これがアウトサイドインです。

この考え方は、Google Cloud のブログ「RESTful Web API 設計のベストプラクティス」で知りました。そこでは設計でつまずきやすい点が6つ挙げられています。読んで自分なりに整理すると、次のようになります。

つまずきやすい点 どうするか
内部の都合で設計している 利用者の話を聞いてユースケースを書き出し、各ケースに必要なデータだけを返すレスポンスの見本を先に作る
利用者にとって複雑すぎる 中は複雑でも、外から見て簡単に見えるAPIにする。ゼロから作る前提で見直し、信頼できる利用者に試してもらう
呼び出しの回数が多すぎる 1つの画面に必要なデータを1回で返す「Experience API」を、細かいAPIと併せて用意する。GraphQLも選択肢
柔軟性に欠けている 必要な項目だけを返す指定、並び替え、ページネーションをクエリで指定できるようにする
人が読めない IDをキーにした入れ子や、意味のない「data」のような名前を避ける。最初の読み手は人
RESTのルールに縛られすぎる 利用者の体験のためにルールを破ることはある。ただし全体で一貫させ、ドキュメントに明記する

例:オンライン書店のAPIを、外側から設計する

アウトサイドインを自分なりに手順に落とすと、こうなります。オンライン書店のAPIを例にします。

  1. ユーザーストーリーを書く:書籍を検索したい。書籍の詳細を見たい。書籍をカートに入れたい
  2. エンドポイントを決める:GET /books(検索)、GET /books/{id}(詳細)、POST /cart(カートに追加)。リソース指向のURLにする
  3. データの形式を決める:やり取りするJSONの形を、利用者が使いやすい形で決める
  4. エラーの返し方を決める:404 Not Found なら { "error": "Resource not found" } のように、明確で一貫したメッセージにする
  5. セキュリティを決める:APIキーによる認証、OAuthによる認可など
  6. 内部を実装する:ここで初めて、データベースから書籍を取り出す処理や、カートに追加する処理を書く

外側のインターフェースを先に固めるので、あとから内部の作りを変えても、利用者には影響しません。長く運用するほど、この順番が効いてきます。

ここから、自分たちはどう考えているか

参考記事は「利用者から考える」という向きを教えてくれますが、実際の案件で最初に何をするかまでは書いていません。そこを自分なりに整理したのが、ここからです。

API設計が必要になる状況は、だいたい次の3つです。

  • すでにAPIサーバーが動いていて、そこに新しいAPIを追加する
  • すでにAPIサーバーが動いているが、出来がよくない。データ定義を変える、リファクタリングする、ライブラリを更新する、インターフェースを変える
  • 新規の案件を受注し、バックエンド開発の責任者になった。まだ何もない

どの場合も、エンドポイントの一覧から書き始めることはしません。順番は次のとおりです。

1. モデルを作る

どんな業務なのか(ドメイン)、誰が使うのか(登場人物)を押さえ、重要なビジネスロジックを中心に大枠のモデルを作ります。

2. 非機能要件を確かめる

どれくらいのデータ量を想定するか。どれくらいの頻度で使われるか。誰が、どこで使うか。求められるセキュリティの水準はどれくらいか。保守は誰がどう行うか。規模感はどうか。ここでの答えが、マイクロサービスにするかどうかの判断につながります。

3. データベースを選ぶ

RDBかNoSQLか、リレーションはどうか、マイクロサービスかモノリシックか、を決めます。判断の軸は次のとおりです。

観点 RDB NoSQL
データモデル 表形式で、スキーマを厳密に定義。関連とトランザクションが必要な場合に向く 柔軟なスキーマ。構造が変わりやすい場合に向く
データの複雑さ 複雑な関係や結合、ACIDトランザクションに向く 単純な構造や、分散して高いスケーラビリティが必要な場合に向く
スケーラビリティ 垂直が主流。水平は可能だが複雑になりがち 水平スケーリングが容易
クエリ 複雑なSQLや結合に強い 単純な検索やフィルタに向く
一貫性と可用性 ACIDで一貫性を保つ。可用性に影響することがある BASEモデルで可用性が高い。一貫性は柔軟

もう一つ、構成上の判断があります。AWS Lambda からRDBへ接続する場合、コネクションプーリングがまだ十分に信用できません。RDBを選ぶなら、Spring、PHP、Pythonなどのモノリシックな構成も視野に入れて考えます。

4. ER図を描く

RDBかNoSQLかで、ここからの進め方が変わります。作ったモデルをどういうテーブル定義にするか、プライマリキーは何かを決めます。

5. APIのインターフェースを決める

RESTにするか、ユースケースごとのAPIにするか。アプリにとって使いやすいのはどちらかで決めます。1つの画面にはコンポーネントごとに必要なデータがあり、それをまとめて取るか、分けて取るか。画面を全部取得してから描画するのか。こうした画面側の視点で、エンドポイントの切り方を決めます。

まとめ

参考記事を整理して分かったのは、API設計で最初に決めるのはエンドポイントの名前ではなく、誰が、どんな体験のために使うのか、ということでした。そこに自分たちの手順を重ねると、モデル、非機能要件、データベース、ER図、インターフェースの順になります。この順で進めると、内部の都合に引きずられた設計になりにくい、というのが今の考えです。

参考:Google Cloud ブログ「RESTful Web API 設計のベストプラクティス」、Google Cloud Community「Designing APIs from the Outside-In」

ブログ一覧