web apiの設計という本をまとめる

なぜ読もうと思ったか?

自分がIT企業にエンジニアとして就職するから。また、研究でデータベースを作っているが、そのAPIの設計に役立てられると思ったから。大学の図書館で借りた本だけど、一周してみて良本だったら自分で買おう。ということでさっさと読みましょう。

1章

APIとは何か?APIの設計はなぜ重要か?APIの設計は何を意味するのか?うーん、わかりきっていることですね。

No, a function is not an API (Application Programming Interface) in itself.

A function is a self-contained block of code that performs a specific task or operation. It encapsulates a set of instructions that can be called and executed when needed. Functions can take input parameters and return values or perform actions without returning a value.

On the other hand, an API refers to a collection of functions, protocols, and tools that allow software components to interact with each other. APIs define the interfaces and rules for communication between different software systems, enabling them to exchange data and execute specific operations.

In essence, an API encompasses a set of functions or methods, along with the associated rules and protocols, that define how different software components can communicate and interact with each other. Functions themselves are building blocks within an API that provide specific functionality or perform specific tasks.

と思って、じゃあライブラリはAPIだよね?って聞いたら、

Yes, a library can be considered as an API (Application Programming Interface). A library typically consists of a collection of precompiled functions, classes, or modules that provide specific functionality and can be used by developers when building software applications.

The library acts as an interface between the application and the underlying system or functionality it provides access to. It defines a set of functions, data structures, and other resources that developers can utilize to interact with and utilize the library's capabilities.

The library's API defines the specific functions, methods, and data structures that developers can use to access and utilize the library's features. The API documentation describes how to use the library, including the function signatures, parameters, return values, and any other guidelines or conventions developers should follow.

Developers can link their applications to the library and then call the library's functions or use its classes and methods to access the desired functionality. The library's API serves as a contract between the application and the library, defining how they can interact and enabling the application to leverage the library's capabilities without needing to know the internal implementation details.

So, while a library is not strictly synonymous with an API, the library's API serves as the defined interface that developers utilize to interact with the library and access its functionality.

てかんじですね。 うーん、難化当たり前なことを言っているんですよね。APIはソフトウェアをLEGOブロックに変える!!はいそうですね。ライブラリっもそうです。再利用可能になるとかね。うん、OK.

はい、パブリックapiとプライベートAPIがあるよって話だね。インターネットにつながっているapiがパグリックAPI。バックエンドサーバ (WANとLANの境にあるサーバ) の後ろにいるのがプライベートAPI。特に難しいことはないね。どの会社にもあるだろう。俺が作っているシステムだってある。というか、データベースは言ってしまえばプライベートAPIだろ。

この本でいうAPIっていのはリモートAPI、つまり、WEB APIで、まあ、一般的なプログラマにとってAPIといえばこれを指すっていうのと変わりない。はい、で、 APIは、インターフェースなんです。2つのシステム、対象者、組織などが出会い、やり取りするポイントなんです。

はい、APIは実装を隠すために作られる。その通りだ。抽象化しているんだよね。何当たり前なことを言っているんだ。

まとめだけ書いておこうか。

  1. web APIによりソフトウェアは最良可能なブロックとなり、HTTPプロトコルを使ってネットワーク経由で利用できるようになる。

  2. APIはアプリケーションを構築する開発者のためのインターフェースであり、それらのアプリケーションはAPIのコンシューマとなる。

  3. APIの設計は、パグリックかプライベート化を問わず、すべてのAPIにオッて重要である。

  4. うまく設計されていないAPIは、十分に滑油されなかったり、正しく使われなかったり、まったく使われ無かったりすることがあり、安全ですらないことがある。

  5. よいAPIを設計するには、インターフェースそのものだけでなく、アプリケーションの全体像を考慮に入れる必要がある。

2章

ユーザを意識したAPIを設計する。ということですね。この章ではapiの目的を考えろとか、当たり前すぎることをいっている。入力と出力を考えろとかね。もう普通の関数の設計のときもそれやるよねっていう。 まあ、それでもAPIを作るときは次の質問は有用だろう。

  1. 誰が
  2. 何ができるか
  3. それをどのように行うか
  4. そのために何が必要か
  5. 何が帰ってくるか
  6. 入力はどこから得られるか
  7. 出力はどのように使われるか

この章もまとめだけ書いておこうか

  1. APIをコンシューマにとって理解しやすく使いやすいものにするには、コンシューマの視点に立って設計しなければならない

  2. プロバイダの視点に立ってaPIを設計すると、内部の仕組みが丸見えになり、必然的に理解しにくく使いにくいAPIになる

  3. コンシューマ志向の包括的なゴールリストは、APIにとって、最も強固な基盤である

  4. ユーザは誰か、何ができるのか、それをどのように行うか、そのために何が必要か、何が帰って来るかを特定することは、包括的なAPIのゴールリストを構築する上で重要な意味をもつ

3章 プログラミングインターフェースを設計する

REST APIの説明がされている。大事な部分だけ抜粋する。 HTTPプロトコルについて、何個か大事なことが書かれている。まずは、形式について。サーバのどこにアクセスするかを決めるリソース。そして、ボディー。あとはメソッド。これだね。 で、ここ大事なんだけど、HTTPリクエストとHTTPレスポンスはリクエストされた内容とリクエストを処理した結果に関係なく、常に同じ形式となる。これはすごい。つまり、POSTリクエストのレスポンスで何かしらのデータを送り返すってことも全然やっていいい。 また、httpのボディにはどんなバイナリでも載せられる。独自のフォーマットでも構わない。JSONドキュメントでも、テキストファイルでも、写真でもどんな種類のものでもよい。 HTTPプロトコルは、ステートレスな通信を実施する。 この章もまとめだけ書かせてくれ APIのゴール = アクション + リソース アクションはHTTPメソッドによって、リソースはパスによって表現される。 APIへの入力、そして、出力は必要十分になるように注意する。

REST APIはAPIの設計原則の一つであり、他にも考えられる。これはマジだね。俺がWSを使って作った通信方式は結局の所、オレオレAPIなわけですね。基本的には、アクションと、リソースを特定したいわけだ。オレオレ apiではJSON飲みのやり取りをしていて、メッセージタイプでアクションを特定していた。リソースもメッセージタイプで特定していたね。だから、同じリソースに対して異なるアクションをする場合、メッセージタイプを変更する必要があって、それは確かに面倒だったかもしれない。WSを使った通信では、メソッドが表現できないからね。 結局、restアーキテクチャスタイルはが普遍的に使われているのにはそれなりの理由があるということだ。

  1. クライアントとサーバの分離
  2. ステートレス性
  3. キャッシュ可能性
  4. 階層化システム
  5. コードオンデマンド
  6. 統一インターフェイス

4章 API記述フォーマットを使ってAPIを記述する

この章で述べていることは、RESTful APIを設計するときの設計書のフォーマットが決まっているよって話。それだけである。フォーマットの名前が決まっていて、 OpenAPI Specification (OAS)である。一般的にOASはYAML形式で書かれることが多い。YAMLがなにか?という話だが、これは言ってしまえばJSONと同じで辞書だね。Jsで言うところのObject。KeyとValueが一対一になっているもの。ただ、書き方がJSONと少し違うってだけだよね。全くかんたんな話だ。俺はJSONになれてしまったので、JSON以外で書くきになれないのです。しかし、どうやらプロフェッショナルたちはJSONよりもYAMLを押しているようです。というのも、こちらのほうが簡潔だからですね。まあ、知っておけば大丈夫。 ちなみにYamlはdocker周りにも使われていた気がするのですが。。。。はい、ということでYamlはかけるようになっておいたほうがいいかもですね。

  1. 紙とペンで大まかな設計を考えるこのときに入出力関係には注意しよう。
  2. OAS仕様に落とし込む

この2つ、無意識にやっていたことだった。俺ってスゲくね?って思ってしまうね。 1については、1-3章で説明しているね。しかし、これはもうなんていうか、慣れとかセンスとかだと思う。2については訓練だね。やれば誰でもできるようになる。

  1. OASのドキュメントを作成する。これはそのファイルを準備しろよって話だな。
  2. リソースを記述する。
  3. リソースのアクションを記述する。 Get, Post, Update, Put, とかね。
  4. アクションのレスポンスを記述する
  5. 別のアクションを記述する。

では、Yamlに則って書いたOASをちょっと見てみようか。

openapi: "3.0.0"
info:
    title: Shopping API
    version: "1.0"
paths:
    # リソース
    /products:
        descriptioni: The products catalog
        # アクションのHTTPメソッド
        get: 
            # アクションの短い説明
            summary: Search for products
            # アクションの長い説明
            description: | 
                search for products in catalog using a free query parameter
            # アクションのパラメータリスト
            parameters:
                [...]
            responses:
                "200"
                    description: | 
                    Products matching free query parameter

        # 別のアクションのHTTPメソッド
        post:
            summary: Add product
        ...
        ...
        ...
        的な感じです。

上のOASではparameters […] の部分が書かれていないが、本当はちゃんと書かないといけない。結構面倒くさい。こういうところの設計まで含めてソフトウェアエンジニアの仕事なんだなと、やはり面白いなと。設計が結構大事なんだよね。ものづくりは設計が大事なんです。そうなんです。いやいいねー、、思いっきりJSONだね。この辺は俺が長年独学してやっと掴んだところだったのにこんなにあっさり説明されていりるのはなんか悔しいものもある。

まあ、この辺も慣れだ。実際に設計するときにまた思い出せるようにしよう。APIの設計には手順があって、仕様書もある、ということをね。

5章 単純明快なAPIを設計する

まずは大原則として、ユーザ視点に立って設計を行うべきである。その情報、ユーザにとってどうでもいいのだが??と思われるような情報はとことん削減するべきであるし、内部的に必要なパラメータでもわかりにくい場合はそれをラッピングしてユーザが見たときにわかりやすいパラメータにするのがいい。 その上で、更に単純明快なAPIを設計するときに気をつけるのが以下である。

1.単純明快な表現を設計する

  1. 変数には非常にわかりやすい名前をつけるべきである。
  2. 使いやすいデータ型とデータフォーマットを選ぶべきである。

2.単純明快なインタラクションを設計する

  1. 単純明快な入力を要求する
  2. エラーフィードバックを1つ残らず洗い出す
  3. 情報的価値のあるエラーフィードバックを返す
  4. 情報的価値のある成功のフィードバックを返す

3.単純明快なフローを設計する

ここでは特にステートレスを強く意識しておきたい。これを意識すれば、ある処理に必要なデータ、入力を、それまでに取得したデータのみに限定することができる。 たとえば、馬券購入サーバのように、

  1. 購入馬券を送信
  2. バリデーション
  3. 実際に購入 の3つのアクションが必要になる場合を考える。(本当は一つにまとめたいがSeleniumを使っている以上、時差が生じてしまう)2に必要なのは受付IDだ。受付IDがあれば区別することができるはずだ。3もそうだよね。うん、そういうことだ。ステートレスだから、クライアント側に必要な情報を前もって渡して送って感じだな。

まとめ

  1. すべての表現を人間とプログラムの両方がかんたんに理解できるものにしなければならない
  2. できるだけ情報的価値のある表現にしなければならない
  3. エラーのフィードバックでは、問題を理解して、可能であれば修正するのに十分な要素を提供しなければならない。
  4. 成功のフィードバックでは、何が完了したのかを正つめいしなければならない
  5. ゴールフローはエラーを回避するデータやゴールを追加することによって最適化できる
  6. ゴールフローは、ゴールを集約によって簡略化できるが、機能的な観点から妥当である場合に限られる

6章 予測可能なAPIを設計する

ここに何が書かれているかというと、APIの様々なところに一貫性を持たせよう、という話。 apiのパラメータ名、変数の型とか。 一貫性を持たせるためにもOpenAPI Specification(OAS)はちゃんと書いたほうがいいし、一度書いたら終始それに従って変数を命名するべきである。 一貫性がないとインターフェイスを理解したり、利用したりするのが難しくなる。一貫性を持たせるためのTIPSが書かれている。

  1. APIの内部でも、APIの間でもデータとゴールの一貫性を保つ
  2. 規定の標準を満たす
  3. 他のAPIを堂々とコピーする

1についてはすごくわかる。やはりシステムの中心に吸えるべきなのはデータ、とここにも書いてあるが、データはデータベースからバックエンド、そしてフロントエンドに流れていくわけで、これだけでも3つ以上の変数名定義が必要になるのは大丈夫かな?で、だ。俺がよくやらかしていたのは、同じデータなのにフロントエンドとバックエンドで名前が違うってところね。まじでやめてほしいって思います。

まとめ

  1. APIを設計するときは共通のプラクティスや企画への準拠に一貫して取り組む
  2. 設計をより単純にする
  3. あとは、理解はできるけど、まだ俺のレベルでは自分ごととして考えることが出いない内容である

7章 うまく整理された簡潔なAPIを設計する

ここでは、各APIの仕事の幅?粒度?みたいなのを最適化する方法を説明している。まとめだけ書いておく。

  1. 何から何までやるようなゴールを作成しない。
  2. 可能であれば、データ構造、ゴール、更にはAPIを、より小さく、だが機能的に重要な要素に分割する

第3部

コンテキストに応じたAPIデザイン

8章 セキュアなAPIを設計する

大事なところだと思います。特に金になるようAPIは絶対にユーザセキュリティー周りが重要になてくる。セキュアなAPIを設計し、APIを呼び出すためには、3つのステップが重要になってくる。

  1. コンシューマの登録
  2. APIを利用するためのクレデンシャルの取得
  3. API呼び出しの作成

これを一つ一つ説明していく感じかな。

コンシューマを登録する

セキュアなAPIを利用したい場合は、まずアプリケーションを登録しないといけない。登録は開発者ポータルなどを使ってするのがいい。 このときにどのサービスを使いたいのかを決定する。スコープだね。そして、クライアントIDを取得する。

APIを利用するためのクレデンシャルを取得する

まあ、アクセストークンをもらうってだけだな。アクセストークンとクライアントIDは別物だな。クライアントIDはデータベースに永久に保存される内容で、アクセストークンはクライアントIDに紐付けられるやつだな。アクセストークンをリフレッシュ!とか見るとわかるように、アクセストークンだけでユーザは識別できないよね。

APIを呼び出す

リクエストに発行したアクセストークンを乗っけるだけだ。以上。

で、ユーザがアクセス可能なスコープを見て、アクエス制御をするのも大事だと。すべてのリソースにアクセスできるわけではなく、そこをうまく制御する必要があると。

9章

この章では、APIをバージョンアップさせていくときにインターフェースが変更されて利用者に負担がかかる、と言ったよう事態が生じないように設計時点で予め考えておくべきことについて述べている。まあ、まだいいかな。

10章 ネットワーク効率の良いAPIを設計する

これは俺の研究にも関わるところですね。

ネットワーク通信の効率を最適化するために考えられる工夫にはまあ、いくつかあるが、プロトコルレベルでのネットワーク通信の効率化と設計レベルでのネットワーク通信の効率化がある。

プロトコルレベルの最適化

まずは圧縮である。可逆圧縮でないと行けないが、まあ、大幅に圧縮することが可能だろうね。あとはキャッシュだよね。一回撮ってきたデータをわざわざまた取りに行くのはもったいなくないか?って話。

まあ、設計レベルでのネットワーク通信の効率化については、無駄なく設計がんばれよ、ってことだけだね。 まとめると、

  1. APIの設計者には、ネットワークの通信効率において担うべき役割がある。
  2. ネットワークの最適化に関する最初のステップは、設計レベルではなく、プロトコルレベルでの最適化である。
  3. APIの粒度と適応性はネットワークの通信効率に影響を与える
  4. ネットワークの通信効率の問題は,APIにかけているゴールや不適切なゴールがあるという兆候かもしれない
  5. ApIの設計の最適化は、ユーザビリていlと再利用可能性をお犠牲にするものであってはならない。様々なAPIレイヤを追加雨sると、そうしたブービートラップを回避するのに役立つことこがある。

あとは、付属的なないようなので割愛する。まあ、全部知っているようなことだったね。おつ。

感想

感想としては、APIの設計をシステム設計の根幹に置くべきではないということだな。これは、そうだな、アメリカ人なら誰でも英語話せるのと同じような感じで、ソフトウェアエンジニアなら、APIの設計ぐらいできて当たり前だろ、っていうのと同格。結局APIってのは他人がソフトを使いやすくするためにどうするかって話で。chatGPTにもtwitterにもAPIはあるよね。それよりも大事なのはソフトの中身だよね。これに関してはやはり自分の専門領域を確立するしかないと思っている。HPCとかは手段だよね。ジャンルについても考えるほうが良さそうだ。そうだな、でもやっぱり金融系は今後絶対に亡くならない領域だし、そっち系で希望を出しておくのもいいかもしれないね。周辺知識も一緒に身につくし。いいのではないだろうか???