現場で役立つシステム設計の原則 Chapter 8 アプリケーション間の連携

## WebAPI の仕組みを理解する

### URI とは

- Web API が扱う対象データをリソースという
- URI はネットワーク上のリソースを指定するための識別子形式
- `https://api.example.com/books/1234` のようなもの
  - スキーム://ホスト名/リソースへのパス
    | 部分 | 説明 |
    | --- | --- |
    | https:// | 通信方式（HTTPS を使用） |
    | api.example.com | API のホスト名（API サーバーのドメイン） |
    | /books/1234 | 書籍データのリソース（書籍 ID 1234） |

### HTTP メソッドとは

HTTP メソッドとは Web API に対してどの様な操作を要求するかを指定するもの。基本的には以下の 4 種

#### GET

- データの取得
- 以下の?以降をクエリパラメータという 検索条件の指定のために用いる
- `GET https://api.example.com/books?category=ソフトウェア設計&within=1年`
- リソースの指定はなるべくパスによって行い、クエリパラメータは検索条件の指定に用いる

#### POST と PUT

- POST

  - POST は以下のようにして識別番号の指定なしの登録を行う
  - `POST https://api.example.com/books`
  - つまり、新規登録用となる
  - レスポンスとしては、201 Created が返却される

- PUT
  - PUT は以下のようにして識別番号の指定ありの登録を行う
  - `PUT https://api.example.com/books/1234`
  - 識別番号を指定した新規登録や特定のリソースの更新に用いられる
  - レスポンスとしては、200 OK / 204 No Content が返却される

POST に比べて PUT はリソースを特定するため、結合が密で独立性が損なわれるため、POST を使用が望ましい。

#### POST で更新する

POST で更新することもできる。
PUT による更新はサーバが更新をどの様なデータ形式で行うのかを把握した上で行われ。
しかし、POST による更新は渡されたデータをどの様に更新するかをサーバ側が判断する。
そのため、POST による更新は PUT に比べて独立性が高く低結合だと言える。
しかし、クラシアンが渡したデータの処理にサーバが対応していないと、クライアントが期待した更新が行われない可能性がある。
そのため、サーバは、せめてどの様にデータを更新したのかをクライアントに通知するとよい。

#### DELETE

DELETE は PUT 同様にサーバの仕様を把握しておく必要があり密結合となる。
POST で行うことによって低結合とすることができる。

- `DELETE https://api.example.com/books/1234`
- `POST https://api.example.com/books/1234/delete`

### HTTP ステータスコード

- 400~: クライアントエラー
  - 400: Bad Request
    - リクエストが不正である
  - 401: Unauthorized
    - 認証が必要である
  - 403: Forbidden
    - リクエストが許可されていない
  - 404: Not Found
    - リクエストされたリソースが存在しない
- 500~: サーバエラー
  - 500: Internal Server Error
    - サーバ内部でエラーが発生した
  - 503: Service Unavailable
    - サーバが一時的に利用不能である

## 良い WebAPI とは何か

### 肥大化した API

- 必要なパラメータの数がやたら多い API のことを One-size-fits-all API という
- 大は小をかねるようであるが、非常に使いずらい
- 利用者にとっては把握することが多い
- 提供する側も条件分岐が増える

### API が肥大化する原因

- API の新たなニーズに対応するためパラメータを一つ追加する
- その分、レスポンスデータの JSON のデータ項目を一つ追加する
- これの繰り返し

## 発展性に富んだ API 開発のやり方

### SwaggerUI

#### **Swagger UI の要約 🚀**

**Swagger UI** は、**API ドキュメントを自動生成し、テスト環境を提供するツール**  
主に **OpenAPI Specification (OAS)** に基づいて動作し、API の仕様を視覚的に確認・試すことができる。

---

#### **✅ Swagger UI の主な機能**

1️⃣ **API ドキュメントの自動生成**

- OpenAPI (JSON / YAML) 形式で記述された API 仕様を元に、ブラウザで閲覧できるドキュメントを作成。

2️⃣ **API のテスト環境を提供**

- フォーム入力でリクエストを送信し、レスポンスを確認可能。
- `curl` コマンドの自動生成も対応。

3️⃣ **プログラミング言語に依存しない**

- Java (Spring Boot)、Python (FastAPI)、Node.js (Express.js) など、多くの言語で利用可能。

4️⃣ **リアルタイム更新 & 仕様変更に対応しやすい**

- API の更新があれば、ドキュメントも自動的に反映されるため、管理が楽になる。

---

#### **✅ Swagger UI のメリット**

- **開発者・利用者が API の仕様を直感的に理解できる**
- **API の試験・デバッグを簡単に行える**
- **API の仕様変更時にドキュメントを手動で更新する手間が省ける**

---

#### **✅ まとめ**

**Swagger UI は、API の設計・開発・テスト・利用をスムーズにする強力なツール！**  
**特に、API のドキュメント管理や仕様共有を簡単にしたい場合に最適。** 🚀

### 小さな WebAPI が理想的

後者のような最低限を行う小さな WebAPI の方がアプリケーションを組み立てる上では都合が良い
・POST のレスポンスとして、予約内容の詳細を返す
・POST のレスポンスは予約番号だけを返し、予約内容はその予約番号で別途 GET する
| 目的 | API | 説明 |
|------|-----|------|
| 予約の登録 | POST reservations | レスポンスとして予約番号 2345 を返す |
| 予約の確認 | GET reservations/2345 | 予約番号 2345 の内容を返す |

### API の廃止の流れ

・① 新しい API を追加しても、互換性のため古い API も提供する
・② 古い API は残すが、「303 See Other」を返すように変更する（新しい API の情報を返す）
・③ 古い API のレスポンスとして「404 Not Found」を返すように変更する
・④API 自体を削除する

## ドメインオブジェクトと Web API

### ドメインオブジェクトと JSON の変換

DB に格納されているドメインオブジェクトとクライアント側の JSON は違う構造の場合もある。
そのため、受け渡しに際しては変換の必要性がある。
変換が複雑な場合は、BookResponse や BookRequest のようなクラスを作成してその内部で変換を行う。

### Response の形式 -- コードか名称か両方か

| 方式          | メリット                                                           | デメリット                                                   | 適用例                                                                          | 具体例                                                                                                                       |
| ------------- | ------------------------------------------------------------------ | ------------------------------------------------------------ | ------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------- |
| コードのみ    | データが軽い<br> シンプルな管理が可能                              | 追加の API 呼び出しが必要<br> クライアント側で変換処理が必要 | ID で一意に管理したい時<br>（内部データ管理）                                   | { "type_ids": [1, 3] }<br>→ クライアントが ID から「ほのお」「ひこう」を取得                                                 |
| 名称のみ      | シンプルで分かりやすい<br> 追加の API 呼び出しが不要               | 名前の変更に弱い<br> データの一意性を保証できない            | ユーザー向け表示<br>（一覧画面やラベル表示）                                    | { "types": ["ほのお", "ひこう"] }<br>→ クライアント側でそのまま表示可能                                                      |
| コード + 名称 | 柔軟性が高い<br> ID で一意に管理できる<br> 追加の API 呼び出し不要 | データ量が増える<br> クライアントが不要な情報を持つ可能性    | ほとんどの API に適用可能<br>（フロントエンドとバックエンドのバランスが取れる） | { "types": [ { "id": 1, "name": "ほのお" }, { "id": 3, "name": "ひこう" } ] }<br>→ 一意性を保ちつつ、UI でもそのまま表示可能 |

### 日付データの形式

2016-10-16T14:30:15+09:00 のような ISO 8601 や RFC 3339
を使用するのではなく、
2016-10-16 や 14:30:15 のように
日付か時刻に分け、タイムゾーンも UTC に統一して提供し、
タイムゾーンによる調整が必要ならばクライアント側で行うのが望ましい

## 複雑な連携に取り組む

### WebAPI を３種類にグルーピングする

WebAPI を利用するアプリケーションが複数になると、API の管理が複雑になってしまう。
これを避けるため、WebAPI を常に次の３種類に分類しておくとよい。

- コアとなる基本 API: 共通利用される小さな API
- 拡張 API: コア API を組み合わせた複合的な API
- 個別対応 API: 特定のアプリケーションに向けた API

### マイクロサービス

- アプリケーションは開発と共に形を変えていく
- その過程で、クラスの追加やロジックの移動などの設計の微調整も行われる
- しかし、このような微調整を複数のマイクロサービス間で行うのには大変なコストがかかる
- 業務知識や良い設計について深く理解し、設計が安定した上で行うことが望ましい

### JSON よりも XML が適しているケース

- JSON はデータの複雑な構造を表現するのに適していない
- データの複雑な構造を表現するのには XML が適している
- XML は HTML と同じマークアップ言語
- データの構造化、要素の属性指定、メタ情報の追加などをすることができる

### 非同期メッセージングの利点

通常、WebAPI による「いいね」のようなイベント処理は以下のような流れで行われる

1. クライアントが「いいね」を行う
2. サーバが「いいね」を受け取る。
3. サーバが「いいね」を DB に保存する
4. サーバが通知データを DB に保存する
5. サーバがクライアントに通知を送る
6. サーバがクライアントに 200 OK を返す

しかし、非同期メッセージングでは以下のような流れで行われる

1. クライアントが「いいね！」を行う
2. サーバが「いいね！」を受け取る
3. サーバが「いいね！」を DB に保存する
4. サーバがメッセージキューにイベントを送信し、クライアントに 200 OK を返す
5. 通知処理サーバがメッセージキューを監視し、メッセージを受信する
6. 通知処理サーバが通知データを DB に保存する
7. 通知処理サーバがクライアントに通知を送る

非同期メッセージングの利点は以下の通り

- WebAPI による「いいね」の処理
  - 店は料理の注文から料理の提供までを一括して行う
  - 客の待ち時間が長くなる
  - 行列ができる
- 非同期メッセージングによる「いいね」の処理
  - 店は客の注文を受けると厨房に通知だけし、客を席に通し、次の客の注文を受ける
  - 客は待たされることはない
  - 行列もできない