現場で役立つシステム設計の原則 ch8 アプリケーション間の連携
アプリケーションとアプリケーションをつなぐ
ほかのアプリケーションとの連携がアプリケーションの価値を高める
- Amazonとかの事例
- アプリケーション間の連携はビジネスチャンス
アプリケーションを連携する4つのやり方
- 4つのやり方
- ファイル転送
- DB共有
- Web API
- 非同期メッセージング
- 後ろのものほど...
- 実現できる機能・非機能要件の範囲が広がる
- 設計や運用は複雑になる
- 本章ではWeb API (と一部非同期メッセージング)について説明
Web APIのしくみを理解する
HTTP通信を使ったアプリケーション間の連携の4つの約束事
技術課題 | Web APIによる解決 |
---|---|
物理的にどう接続する | TCP/IP |
通信規格 | HTTP |
データ形式 | JSON, XML |
文字コード | UTF-8 |
- 4つの約束事
- 要求の対象(URI)
- 要求の種類(HTTPメソッド)
- 処理の結果(HTTPステータスコード)
- 応答内容の表現形式(JSON, XML)
要求の対象を指定する
要求の種類を指定する
- 代表的なHTTPメソッド
HTTPメソッド | 意味 | HTTPステータスコード |
---|---|---|
GET | 取得 | 200 OK |
POST | 登録 | 201 Created |
PUT | 登録 | 200 OK, 201 Created, 204 No Content |
DELETE | 削除 | 200 OK, 202 Accepted, 204 No Content |
データを登録するPOSTとPUT
- POSTもPUTも「登録」
- どう違うの
- POST
- 例: POST /books
- API提供側アプリケーション側がリソースの識別番号を発行
- 【補】冪等でない
- 発行した識別番号を201 Createdで返却する
- PUT
- 例: PUT /books/1234
- 呼び出し側がリソースの識別番号(1234)を指定
- 新規作成時: 201 Createdを返す
- 更新時: 200 OK または 204 No Contentを返す
- POST
- PUTよりもPOSTを使うべき
- PUTの場合、識別番号の体系を呼び出し側が知っている必要がある
- 【補】枝番なのかUUIDなのか、とか
- これすなわち密結合
- PUTのHTTPステータスコードは複数あり、決めごとが多い
- これすなわち呼び出し側との密結合
- 呼び出し側と提供側アプリケーションとが密結合だと、修正や拡張の影響が大きい
- PUTの場合、識別番号の体系を呼び出し側が知っている必要がある
更新の依頼もPOSTを使う
- こうじゃなくて
PUT /books/1234
- こう
POST /books/1234/updates
- 更新処理の実装を提供側アプリケーションに委ねる
- 上書きするのか
- 【補】冪等なふるまい
- 履歴をぶら下げるのか
- 【補】冪等でないふるまい
- 上書きするのか
- 呼び出し側は更新処理の実装を意識せず、「更新の依頼」を積むだけ
データを削除するDELETE
- こうじゃなくて
DELETE /books/1234
- こう
POST /books/1234/deletions
- 下記のような呼び出し側との決めごとがいらなくなる
- 削除の実際のタイミング
- 削除の妥当性のルール
- 削除がうまく行かなかった場合の挙動
- 「削除の依頼」を積むだけ
エラー時の約束事
- 4xx系と5xx系の話
- 4xx系: 呼び出し側がなんとかするべき
- 5xx系: 呼び出し側はどうしようもない
- 5xx系エラーの出し方
- 呼び出し側向けエラーには詳細の情報を含めない
- 呼び出し側は詳細を受け取ってもどうしようもない
- セキュリティ的に保護すべき内容
- 提供側アプリケーションサーバ内のログには詳細の情報を含める
- 原因調査の重要な手がかり
- 呼び出し側向けエラーには詳細の情報を含めない
良いWeb APIとは何か
使いにくいWeb API 〜大は小を兼ねるのか?
- One Size Fits AllなAPI
- パラメータも応答のデータ内容も多い
- 利用側の負担が多い
- 提供側もつらい
- パラメータを増やせば増やすほどif文ふえる
- 修正や拡張が困難になり、ビジネスの発展を阻害する
- なぜこういうAPIが生まれるのか
- 連携相手のアプリケーションの理解不足
- 初期に把握できていなかったニーズが明らかになるたびにパラメータを継ぎ足していく
アプリケーションを組み立てるための部品を提供する
- Web APIってそもそもどういう意味?
- 呼び出し側でアプリケーションを組み立てるための部品のセット
- Yes, that's API
- 利用する側でプログラミングせずに利用できる完成品
- むしろ「サービス」
- 呼び出し側でアプリケーションを組み立てるための部品のセット
- APIの粒度と組み立ての特性
APIの粒度 | 実現できる機能の多様性 | 組み立ての複雑さ |
---|---|---|
小さい | 幅広い | 複雑 |
大きい | 限定的 | 単純 |
- 組み立ての多様性を保ちつつ、組み立ての負担が増えすぎないようにしたい
- 【補】GoFのFacade、PofEAAのRemote Facadeが思い浮かぶ
発展性に富んだAPI開発のやり方
単純なことをかんたんにできるAPIの提供から始める/動かしながら設計を発展させていく/APIを利用する側とAPIを提供する側の共同作業の環境を整える
- 仕様書ファーストは今は昔
- 時間かかる
- しかも、いざ実装してみると仕様の不整合や考慮漏れが発覚しがち
- 今日びは実際に作ってみるのが主流
- 実際に作って使ってみることが簡単にできるようになった
- Web API用のフレームワークとライブラリ
- Spring MVCのRestController, Jackson
- APIドキュメントを自動生成するツール
- Swagger
- 動かせる仕様書
- Swagger
- コミュニケーションツールを活用する
- チャットサービス等
- 提供側と呼び出し側とで、互いのニーズや制約を適切に理解する
- APIの成長サイクルを回す
中核となるAPIのセットを設計する
- 登録と参照を分ける
- POSTではリソース内容を返さず、リソースの識別番号のみ返す
- リソースの単位を分ける
GET /members/1234/name
とか- 【補】本章でPATCHメソッドが触れられていない理由が多分これ
- 「リソースの一部を更新」ではなく、「より小さなリソースを丸ごと登録」
Web APIのバージョン管理
http://api.example.com/v2/members
- ↑こういうやつ
- Web API全体のバージョン管理を行うことに意味はない
- 段階的な廃止手順の例
APIを複合したサービスの提供
- 部品としてのAPIだけでなく、まとまった機能をサービスとして提供する
- 2層
- 複合サービス
- 【補】おそらく、Backend for Frontendってやつ
- 基本API
- 複合サービス
- 複合サービス層は、できれば呼び出し側が開発すべき
- 【所感】さもないと依存の向きがおかしい
ドメインオブジェクトとWeb API
データ形式とドメインオブジェクトを変換する際に起こる不一致
導出結果か生データか
- マスタ項目のコードと名称
- 計算ロジック
- 内容による
- 利用側アプリケーション依存のロジックならば生データ
- API提供側に利用側ロジックを持ち込まない
- 日付データの形式
複雑な連携に取り組む
共通部分と個別対応部分を明確にする
APIを進化させる
- 3つのグルーピングを絶えず実状に合わせる
- 共通APIで済むほうが呼び出し側・提供側ともに嬉しい
- 呼び出し側:
- 機能改善・信頼性向上頻度が高い
- 提供側:
- 開発・運用の負担減
- 呼び出し側:
小さなアプリケーションに分けて組み合わせる
- マイクロサービス
- 最初から机上の概念的な設計だけで分割すると失敗しやすい
- マイクロサービスの分割のしかたを気軽に再構成できないため
- 1つのアプリケーション内のクラスやメソッドのリファクタリングとは異なる部分
- マイクロサービスの分割のしかたを気軽に再構成できないため
- 1つのアプリケーション内で、境目がはっきりして設計が安定したところから切り出してしくとよい
- 最初から机上の概念的な設計だけで分割すると失敗しやすい