The Design of Web APIsの読書感想文(7章まで)

www.manning.com

The Design of Web APIsは我流でAPI設計をやってしまっていた自分にとって良書でした。 知らなかった事・気がついた事等を忘れないように箇条書きにしました。 7章以降も少しずつ読んでいこうと思います。

ch1: what is api design?

  • APIの基礎的な部分を説明した章
  • 酷いドローンのコントローラ設計を題材にして話が進んでいく
  • public apiの場合、コロコロ使い勝手を変えることが出来ないし収益に関わる部分だから、設計がより一層シビアになる
  • RPC, SOAP, REST, gRPC, GraphQL等いろいろな通信のための手段があるが、そこだけを勉強しても良いAPI設計を作ることが出来ない
  • APIを使う側のユーザが達成したいゴールを意識することが大事
  • どのように使われるのか、誰が使うのかといったユースケース的な情報が大事になってくる

ch2: Designing an api for its users

  • ずっと押しっぱなしにしとかないと動かない酷い設計の電子レンジとショッピングサイトのwebAPIが題材になっている
  • ユーザー目線を持つことが大事
  • 内部の仕様を漏らすようなことをしない。ユーザーが知らなくていい部分には蓋をして見えなくする
  • APIの実装漏れや分かりやすさを追求するために「API goals canvas」を作成する
  • API goals canvas: Whos, Whats, Hows, Inputs, Output, Goalに着目する
  • コンウェイの法則(組織内部でとっているコミュニケーションがシステム設計に現れる法則)
  • ビジネスロジックアーキテクチャ、DBの名前等がAPIに漏れ出していたら注意。※ ユーザのゴールに着目すること

画像は自分で作ってみた動物園APIAPI goals canvas

ch3: Designing a programming interface

  • RESTの説明から入る
  • ch2で作ったAPI goals canvasをもとにRESTに書き起こしていく
  • リソースの関係性を洗い出すことが大事。has a, has many
  • goalを書いてその動詞に注目する。add, replace, create, delete等
  • addとsearchの関連性に注目
  • 例えば、productにitemを追加する。productからitemが検索される。productとitemを親子関係で表現できる
  • itemを作ったらIDを返却する
  • PATCHは部分更新
  • PUTは更新だけでなく存在しない場合に作成しにかかる。save的な感じ。
  • DELETEは更新をかけてユーザから見えなくする"ソフトデリート"でもDELETEを使ってOK
  • ユーザーが達成したいゴールを見直してパラメータを削っていく
  • HTTP メソッドにマッピングできなかった場合 => アクションリソース(checkoutみたいな)
  • 名詞ではなくcheckoutのような動詞混ざりのエンドポイントの場合RESTで表現するのが難しくなる
  • 無理やりRESTに全てハメこむのはユーザフレンドリーではない。アクションリソースで整えるのも大事。
  • RESTの原則と可読性のバランスを取ることが大事。

ch4: Describing an API with an API description format

  • OASを紹介する章
  • スプレッドシートを使うよりOASを使った方が他のライブラリを適用できるため恩恵がある
  • swagger以外にもReDocなどOASファイルを表示するUIに関しては複数ある
  • 以降記述の仕方等は前職で使っていたので流し読み
  • 次の職場で使う時に以下のopenapi-mapに目を通しておいた方がよさそう

openapi-map.apihandyman.io

ch5: Designing a straightforward API

  • 使いやすく・分かりやすいAPIを定義するためにどうすればいいのかを考える章
  • バックエンド側でenumを変換してnameに変換する(前職ではフロントで実施してしまっていた。フロントの責務が増えるので確かに微妙だった)
  • フォーマット関連の処理はMUIのDataGrid等のライブラリで提供されてはいるもののバック側でやってしまった方がいいかも。(SPA構造にする時だけ使うものだった?)
  • この章ではエラーを3つに分離(Surface: 400, Business: 403, InnerControl and Unexpected: 500)
  • 前職では、SurfaceとBusinessを同じステータスで返却してしまっていた
  • 分かりやすいエラーメッセージを返却するために要素ごとに情報を作成する
{
  message: XXX,
  errors: [
    {
      要素名: A,
      エラー種別: XXX,
      メッセージ: XXX
    },
    {
      要素名: B,
      エラー種別: XXX,
      メッセージ: XXX
    },
  ]
}
  • 成功ステータスは200以外にも201と202が存在する
  • 作成した時は201を返却する
  • 遅延処理が発生するかもしれない処理が成功した事に対して202を使用する
  • 201の場合、すぐに完了したことを表現し202の場合、まだ処理中のことを表現する(送金中とかメール送信中とか)
  • 前職では全て200で返却してしまっていた
  • 遅延処理の場合、HTTPステータスだけでは不十分なので別途通知を送るなど対応が必要なので注意

ch6: Designing a predictable API

  • 5章に引き続きさらにAPIを使いやすくする方法が掲載されている
  • 命名規則の統一(createdAt,DateTimeOfUpdateなどごちゃつかせない)
  • Formatの統一(色々な時間フォーマットで返さない)
  • データ構造の統一
  • content negotiationに包めるものは、parameterに入れない

developer.mozilla.org

  • ページネーションにRangeヘッダーを使う例も乗っていたがバイナリーファイルを扱うのが目的なのでpageSizeとpageで管理した方がよさそう

developer.mozilla.org

  • ソートパラメータの指定方法の一例: sort=-amount,+date
  • meta_data: paginationに必要なデータやアクションが実行可能なことを表現するデータ。返却するデータの本質とは関係ない。操作に関連する物。
  • hypermedia APIs: レスポンスの中にurlが入っているAPI
  • URLを事前に知らなくても情報に辿り着ける。利用者(フロント側)でURLを定義しないくていいので改修がスムーズになる。
{
  _links:{
    self:{ 
      href: "url",
    },
  
    next: {
      href: "URL"
    },
    prev: {
      href: "URL"
    }
  },

  properties:{
    ...
  }
}

stateless.co

ch7: Designing a concise and well-organized API

  • データ構造のまとめ方について紹介する章
  • ネストさせてデータをグループ化させ可読性を向上
{
  memberName: xxxx,
  school:{
    name: xxxx,
    address: xxxx
  }
}
  • 重要なプロパティを上にする
  • OAS: タグ付けしてAPIをグループ化
  • 入力は可能な限り少なくネストも少なくする(推奨3段階まで)
  • 出力のネストも可能なら三段階までを推奨
  • Avoid creating does-it-all goals(何でも出来るゴールの設定をしない)