t0mmy

2020年12月30日に参加

学習履歴詳細

API デザインパターン 5章 データ型とデフォルト値 読了

やったこと

  • API デザインパターン 5章読了 # 学んだこと

ポイント

  • 「データが存在しない」をきちんと定義する
  • 各データ型ごとに、デフォルト値には要注意

学び

  • 「データが存在しない」状態は、何種類か考えられる
    • APIにとって「データが存在しない」状態は統一する
    • 意図をもって何種類か使い分けたい場合は、その意図をきちんと文書化する
  • 数値型の強みは「四則演算可能なこと」であり、この恩恵を全く得られない用途(識別子など)で数値型は使うべきではない
  • 数値は、コンピュータやプログラミング言語によって扱いが異なるため、APIでは数値型の値を色々気にかける必要がある
  • デフォルト値も設計のうち
    • 意味のあるデータ(マップの {})なのか
    • 利用者に対して適した値を挿入してほしい旨を示すデータ(マップの null )なのか

気づき

  • リスト要素数にも上限を設けるべき、について
    • AWS dynamoDBの scan のイメージか
    • 要素数が数千万や億単位となると、確かにAPI利用者がびっくりする

メモ

データの入力・保持・出力にあたって、データの型は常に考える必要がある。

データ型入門

APIを誰でも(≒どんな言語でも)利用できるよう、汎用フォーマットにシリアライズ/デシリアライズする。

  • JSONやXMLが代表

汎用フォーマットへ変換する過程で、特に型情報が欠落してしまう。
そのため、クライアント側と、送受信するデータの型やプロパティ名について、ドキュメントなどで認識を合わせる必要がある。

「データが存在しない」状態は、いくつか考えられる。

  • フィールドが存在しない
  • フィールドは存在するが、値が null
  • 文字列を文字列を期待するフィールドは存在するが、値が空文字

APIのデータについて、「データが存在しない」状態は統一する必要がある(でなければ、予測可能でないAPIとなってしまう)。
上記の状態それぞれに意味があるのであれば、その旨を利用者が理解できるよう、きちんとドキュメント化する必要がある。

ブール値

ポイント

  • 一般に、肯定を示す変数の方が、理解しやすい
    • 否定の方が良い場合もあるため、ケースバイケース

数値

色々な意味を持つ数値(長さ、大きさ、距離、通貨価値など)を、数値型としてまとめて扱う。

数値型の強みは「四則演算可能なこと」であり、この恩恵を全く得られない用途(識別子など)で数値型は使うべきではない。

数値の扱いは、コンピュータやプログラミング言語によって大きく異なる。
そのため、APIでは以下のような点に気を配る必要がある。

  • 数値の上限と下限、最大値と最小値
    • 64ビット整数値が安泰
  • ゼロの値(特に nullmissingと同じ感覚でデフォルト値にゼロを設定する場合)
    • 安易に「0」を使用すると、計算の結果設定した「0」なのか、デフォルト値としての「0」なのか区別が付かない
  • 非常に大きな値を扱うか否か
    • 64ビットを超えるような、非常に大きな(あるいは高精度な)値を扱う場合、文字列で表現する方が無難

文字列

APIフィールドの大部分は文字列のため、文字列の扱いは重要。

  • 文字列も、サイズ(≒文字列の長さ、API次第ではバイト数)を気にするべき
    • 特に、RDBでサイズ制限付きの文字列を取り扱っている場合は考慮必須
    • サイズを超えるようなデータは拒否すると良い
      • サイズを超えた分は切り捨てて処理を続行する...といった実装は、大抵よろしくない
  • デフォルト値には、"default"という文字列を使用できる
    • Nullや空文字は有効な値ではない場合があるため、デフォルト値としては使用しない
  • エンコーディングは一種類に統一すること
    • 最有力はUTF-8

列挙型

WebAPIの世界では、使用を避け、文字列などで代替する。
新しい値を後から追加する可能性がある場合は、特に列挙型の使用を避ける。

  • クライアントライブラリの再コンパイルが必要となり、非常に高コスト

列挙型は、強い型付けをサポートしているプログラミング言語では有効だが、WebAPIの世界ではデメリットが強い。

リスト

  • 一括処理したいデータをまとめたいときに最適なデータ構造
    • 言い換えると、「ある一つの要素だけ変更したい」というユースケースには不適当
  • 複数の個所で保存・管理するべきではない
  • リストの項目は、JSONエンコード可能な形で保持すると良い
  • ["str",5,true] のように、 一つのリストに、複数のデータ型を格納するべきではない
  • 要素数制限を設けた方が良い
    • そして、サイズを超えるような入力は、拒否するべき
      • 切り捨てて処理を続行するのはよろしくない
    • API利用者側が、大量のデータに驚き混乱する...といった事態を防ぐことが出来る
    • サイズの見積もりが困難であれば、インラインでリストを保持するのをやめよう
      • リソースのサブコレクションとして扱う
  • デフォルト値は空のリストが有力候補

マップ

  • 構造が未確定な動的データを扱うのに適している
    • 定義済みのカスタムスキーマという選択肢もある
    • こちらは、データが事前に分かっており、より扱いやすく構造化したいときに使用する
  • 要素数制限を設けた方が良い
    • キーとバリューの長さにも制限を設けると良い
    • いずれも、「マップのデータが肥大化し、歯止めがきかなくなる」状況を防いでくれる
    • デフォルト値には、 null{} が選択できる
      • {}はデータが全く存在しないことを示す値として、 nullは利用者が最善のデータを設定することを示す値として活用すると良い
    • なお、カスタムスキーマはデータ構造が決まっている(≒要素数がはっきりしている)ため不要

扱うこと

  • データ型とは何か
  • 値が無いものと、NULLの違い
  • ア様々プリミティブデータ型とコレクションデータ型
  • 様々なデータ型に対するシリアライズ方法

まとめ

  • 全ての値で、 nullundefined (またはmissing)の両方を考慮する必要がある
  • ブール値はフラグに最適
    • 変数名は、肯定を示す名前の方が良い
  • 数値型の強みは「四則演算可能なこと」であり、この恩恵を全く得られない用途(識別子など)で数値型は使うべきではない
  • 適切な数値表現を持たない言語では、数値を文字列へシリアライズする
    • 大きな数値や浮動小数点演算問題を避けるため
  • 文字列はUTF-8でエンコードする
    • 文字列を識別子として使用する場合は、標準化形式Cで正規化する
  • 列挙型は使用せず、代わりに文字列を使用する
    • この文字列の検証は、サーバ側で行う(言い換えると、クライアント側で検証しない)
  • リストは一括処理したいデータをまとめる際に最適
    • ["str",5,true] のように、 一つのリストに、複数のデータ型を格納するべきではない
  • リスト、マップは、要素数を制限する
    • 更に、マップではキーとバリュー両方のサイズを制限する
WebAPI

2023年06月03日(土)

2.0時間