「Web APIの設計」をみて実際に設計してみる 前編

# はじめに

[Web API Advent Calendar 2020 8日目の記事](https://qiita.com/advent-calendar/2020/webapi) です。

こんにちは！PORT新卒エンジニアの[しゅんいち(shxun6934)](https://twitter.com/shxun6934) です！

[「Web APIの設計」](https://www.amazon.co.jp/Web-API%E3%81%AE%E8%A8%AD%E8%A8%88-Arnaud-Lauret-ebook/dp/B08CK2H12H)の本を読んで、自分なりの解釈を残しておこうと思います。

このAPIの話は、[ここの記事](https://qiita.com/shxun6934/items/899073339f95508f6d3a)でちょっとだけ話していますが、
本記事では少し深いところまで話して行きます！


# そもそもなぜ設計するのか・重要なのか

Webアプリケーションやモバイルアプリケーションと同じで、

**正常に動き、安全で、わかりやすい**

ものにするためです！


APIは、技術的なインターフェースではあるものの、使用者は**開発者（つまり人）**なので、ユーザーが**「使いやすい」**と思ってもらえるようなものにしなくてはいけません。

逆にうまく設計されていないと、APIを作成したにもかかわらず**十分に使用してもらえなかったり**、**正しい使い方**をしてもらえなかったりします。最悪な場合は、**危険な**APIになってしまうこともあります。

なので、どんなに小さいものでも**設計を重要視し、十分に行わなくてはいけません！**


## パブリックAPIとプライベートAPI

パブリックAPIは、**他の外部の開発者にサービスを提供しているので**、正常に動き、安全で、使いやすいものになっていなくてはいけません。

では、プライベートAPIはどーでしょうか？？
組織内で共有しているし、ユーザーが自分たちというのもあり、プライベートAPIについてはそこまで設計に重要視しなくてもいいと考える人もいるかもしれません。

しかし、組織に**新しい人**が入ってきたらどーでしょうか？？
その人の目線は、**パブリックAPIでの他の外部の開発者**となんら変わりません。プライベートAPIは正常に動き、安全で、使いやすいものであると思って使用します。

パブリックAPIでもプライベートAPIでも、いつかは**他の開発者によって使用されます！**

そのため、

**その人が問題なくコードを記述できるような設計**

にしなくてはいけません！


# ユーザーを常に意識する設計

APIを作成する上での設計の重要さはわかりました。
では、実際にどーやっていけばいいのでしょうか？？

ここで、常に意識しておくポイントは、**ユーザー**です！！

上記でも述べたように、APIは**インターフェース**で、使用者は**人**です。
WebアプリやモバイルアプリのUI・UX同様に、APIは

**ユーザーが、目標を達成するための手助け**

をしなくてはいけません。

なので、**ユーザーの視点**で考えて設計を行う必要があります！


## 「仕組み」ではなく「目標」に焦点を当てる

アプリケーションの仕組み（ビジネスロジックとかデータのあり方とか）に沿ってインターフェースを組み立ていくと、**複雑になってしまい**、使いづらくなってしまうことがあります。

APIを作成している開発者なら理解できる（コードを書いているので当たり前）ものですが、**他の開発者はわからないと思います。**

**APIを使用するために仕組みを理解しないといけないのは、ユーザーに優しくありません。**

ユーザーのために、ニーズに沿ってインターフェースを組み立ていくと**シンプル**になり、**何ができるかがわかりやすくなるので**使いやすいAPIになると思います！


## APIのゴールを考える

**APIの目的がわからない**と何を設計していいかもわかりません。

そこで、以下の6つに沿って考えていきます。（本書より）
これらが、**API設計の基盤**になります。

> 1. ユーザーは誰か
2. 何をできるか
3. どのように行うか
4. そのために何が必要か　→ それはどこにあるのか
5. 何が返ってくるのか　→　どのように使われるのか
6. 「4 ＋ 5 ＋ 6」 を簡潔に表現する（ゴール）


### 1. ユーザーは誰か

作成するAPIに関わる**全てのユーザー**をなるべく洗い出すことようにしましょう。

> 例：オンラインショッピングする人、オンラインの商品を管理する人...


### 2. 何をできるか

1で出たユーザーたちがAPIを使用して**何ができるか・何がしたいか・何をするか**を考えていきます。

> 例：商品を購入する、商品を管理する...


### 3. どのように行うか

2で出たことについて、**どのように行うか**を考えていきます。

> 例：商品を検索する、商品をカートに入れる、商品をカタログに追加...


### 4. そのために何が必要か　→ それはどこにあるのか

2を実現するために**何が必要になるのか・何がいるのか**を考えます。
そして、それらはアプリケーションで**どこから取得するのか**を考えます・

この項目は、ユーザーが実際に「入力」するものになります。

> 例：カタログ（アプリが提供）と検索ワード（購入者が所有）、商品（検索結果）とカート（購入者が所有）、カタログ（管理者が所有）と商品（管理者が提供）...


### 5. 何が返ってくるのか　→　どのように使われるのか

4で必要になったものを入力した結果、**何が**返ってくるのかを考えます。
そして、それらはユーザーが**どのように使用するのか**を考えます。

この項目は、ユーザーが実際に「出力」するものになります。

> 例：商品（カートに追加する）...


### 6. 「4 ＋ 5 ＋ 6」 を簡潔に表現する（ゴール）

4, 5, 6の項目を言葉で表現すると、それがAPIの目的・目標になります。

> 例：検索ワードを使用してカタログ内の商品を検索する、商品をカートに入れる、商品をカタログに追加する...


# RESTful APIで実際にインターフェースを組み立てみる

ユーザー目線で考えきたものを実際に技術ベースで考えていきます。
今回は、**RESTful API**で考えていきます。

（RESTful APIの説明は以下参考。）
[RESTful APIとは](https://qiita.com/NagaokaKenichi/items/0647c30ef596cedf4bf2)


## APIのゴールをRESTful APIに置き換える

ここで、`6. 「4 ＋ 5 ＋ 6」 を簡潔に表現する（ゴール）`で表現したものを使用します。


### 必要な情報を特定する

まずは、APIに必要な情報を整理します。

欲しいのは、

**アクション、リソース、パラメータ、返り値**

です。

アクションは**主動詞（追加する、検索する...）**、リソースは**主動詞にかかる名詞（商品、カタログ...）**、パラメータは**入力**、返り値は**出力**に当たります。
そこから、**リソース同士の関係性**を調べたり、**アクション**を特定したり、**必要なパラメータや返り値**を特定します。

> 例：カタログ > 商品、追加・検索、商品情報・検索ワードが必要、商品・カタログを返す


### URIやHTTPメソッドで表現する

必要な情報が整理できたら、実際に使うURIやHTTPで表現します。

リソースやアクション、パラメータ、返り値を特定したら、実際にURIやHTTPメソッドで表現します。

URIについては、**リソースの関係性**を考慮し、**ユーザーが見てもわかりやすいもの**にします。

> 例：/catalog/{product_id}, /products/{product_id}...


HTTPメソッドは、**それぞれの役割**に従って行うのがベストです。
役割以上の責務を持たせると、**統一なインターフェースではない（例：POSTでも更新と作成と取得ができるみたいな）**ため、返って使いづらいことになるので、注意が必要です。

> 例：検索する　→　GET、更新する　→　POST...


### データを設計する

URIとHTTPメソッドで表現できたので、実際に使用するデータを定義していきます。
定義するものは、以下4つ。

> 1. 名前
2. 型
3. 必須かどうか
4. 説明（必要であれば）


|名前|型|必須|説明|
|:-:|:-:|:-:|:-:|
|name|string|yes|商品の名前|
|price|integer|yes|商品の価格|
|description|string|no|商品の説明|

実際に返ってくるフォーマットは、**JSON**なので、これらが整理できていればそんなに困ることはありません。


### レスポンス設計　→　パラメータ設計

データの設計ができたので、リソースに基づいたレスポンスを設計していきます。
アクションごとによっては、**必要ないもの・足りないもの**が出てくるので、データの構造を調整する必要があります。

このレスポンス設計ができたら、これを元にパラメータも設計していきます。


# まとめ

こんな感じで大枠の設計をしてきました。

ここからは、実際にJSONのデータ構造や仕様書を書いていきたいと思います。