
t0mmy
2020年12月30日に参加
学習履歴詳細
API デザインパターン 5章 データ型とデフォルト値 読了
やったこと
- API デザインパターン 5章読了 # 学んだこと
ポイント
- 「データが存在しない」をきちんと定義する
- 各データ型ごとに、デフォルト値には要注意
学び
- 「データが存在しない」状態は、何種類か考えられる
- APIにとって「データが存在しない」状態は統一する
- 意図をもって何種類か使い分けたい場合は、その意図をきちんと文書化する
- 数値型の強みは「四則演算可能なこと」であり、この恩恵を全く得られない用途(識別子など)で数値型は使うべきではない
- 数値は、コンピュータやプログラミング言語によって扱いが異なるため、APIでは数値型の値を色々気にかける必要がある
- デフォルト値も設計のうち
- 意味のあるデータ(マップの
{}
)なのか - 利用者に対して適した値を挿入してほしい旨を示すデータ(マップの
null
)なのか
- 意味のあるデータ(マップの
気づき
- リスト要素数にも上限を設けるべき、について
- AWS dynamoDBの scan のイメージか
- 要素数が数千万や億単位となると、確かにAPI利用者がびっくりする
メモ
データの入力・保持・出力にあたって、データの型は常に考える必要がある。
データ型入門
APIを誰でも(≒どんな言語でも)利用できるよう、汎用フォーマットにシリアライズ/デシリアライズする。
- JSONやXMLが代表
汎用フォーマットへ変換する過程で、特に型情報が欠落してしまう。
そのため、クライアント側と、送受信するデータの型やプロパティ名について、ドキュメントなどで認識を合わせる必要がある。
「データが存在しない」状態は、いくつか考えられる。
- フィールドが存在しない
- フィールドは存在するが、値が
null
- 文字列を文字列を期待するフィールドは存在するが、値が空文字
APIのデータについて、「データが存在しない」状態は統一する必要がある(でなければ、予測可能でないAPIとなってしまう)。
上記の状態それぞれに意味があるのであれば、その旨を利用者が理解できるよう、きちんとドキュメント化する必要がある。
ブール値
ポイント
- 一般に、肯定を示す変数の方が、理解しやすい
- 否定の方が良い場合もあるため、ケースバイケース
数値
色々な意味を持つ数値(長さ、大きさ、距離、通貨価値など)を、数値型としてまとめて扱う。
数値型の強みは「四則演算可能なこと」であり、この恩恵を全く得られない用途(識別子など)で数値型は使うべきではない。
数値の扱いは、コンピュータやプログラミング言語によって大きく異なる。
そのため、APIでは以下のような点に気を配る必要がある。
- 数値の上限と下限、最大値と最小値
- 64ビット整数値が安泰
- ゼロの値(特に
null
とmissing
と同じ感覚でデフォルト値にゼロを設定する場合)- 安易に「0」を使用すると、計算の結果設定した「0」なのか、デフォルト値としての「0」なのか区別が付かない
- 非常に大きな値を扱うか否か
- 64ビットを超えるような、非常に大きな(あるいは高精度な)値を扱う場合、文字列で表現する方が無難
文字列
APIフィールドの大部分は文字列のため、文字列の扱いは重要。
- 文字列も、サイズ(≒文字列の長さ、API次第ではバイト数)を気にするべき
- 特に、RDBでサイズ制限付きの文字列を取り扱っている場合は考慮必須
- サイズを超えるようなデータは拒否すると良い
- サイズを超えた分は切り捨てて処理を続行する...といった実装は、大抵よろしくない
- デフォルト値には、"default"という文字列を使用できる
- Nullや空文字は有効な値ではない場合があるため、デフォルト値としては使用しない
- エンコーディングは一種類に統一すること
- 最有力はUTF-8
列挙型
WebAPIの世界では、使用を避け、文字列などで代替する。
新しい値を後から追加する可能性がある場合は、特に列挙型の使用を避ける。
- クライアントライブラリの再コンパイルが必要となり、非常に高コスト
列挙型は、強い型付けをサポートしているプログラミング言語では有効だが、WebAPIの世界ではデメリットが強い。
リスト
- 一括処理したいデータをまとめたいときに最適なデータ構造
- 言い換えると、「ある一つの要素だけ変更したい」というユースケースには不適当
- 複数の個所で保存・管理するべきではない
- リストの項目は、JSONエンコード可能な形で保持すると良い
["str",5,true]
のように、 一つのリストに、複数のデータ型を格納するべきではない- 要素数制限を設けた方が良い
- そして、サイズを超えるような入力は、拒否するべき
- 切り捨てて処理を続行するのはよろしくない
- API利用者側が、大量のデータに驚き混乱する...といった事態を防ぐことが出来る
- サイズの見積もりが困難であれば、インラインでリストを保持するのをやめよう
- リソースのサブコレクションとして扱う
- そして、サイズを超えるような入力は、拒否するべき
- デフォルト値は空のリストが有力候補
マップ
- 構造が未確定な動的データを扱うのに適している
- 定義済みのカスタムスキーマという選択肢もある
- こちらは、データが事前に分かっており、より扱いやすく構造化したいときに使用する
- 要素数制限を設けた方が良い
- キーとバリューの長さにも制限を設けると良い
- いずれも、「マップのデータが肥大化し、歯止めがきかなくなる」状況を防いでくれる
- デフォルト値には、
null
と{}
が選択できる{}
はデータが全く存在しないことを示す値として、null
は利用者が最善のデータを設定することを示す値として活用すると良い
- なお、カスタムスキーマはデータ構造が決まっている(≒要素数がはっきりしている)ため不要
扱うこと
- データ型とは何か
- 値が無いものと、NULLの違い
- ア様々プリミティブデータ型とコレクションデータ型
- 様々なデータ型に対するシリアライズ方法
まとめ
- 全ての値で、
null
、undefined
(またはmissing
)の両方を考慮する必要がある - ブール値はフラグに最適
- 変数名は、肯定を示す名前の方が良い
- 数値型の強みは「四則演算可能なこと」であり、この恩恵を全く得られない用途(識別子など)で数値型は使うべきではない
- 適切な数値表現を持たない言語では、数値を文字列へシリアライズする
- 大きな数値や浮動小数点演算問題を避けるため
- 文字列はUTF-8でエンコードする
- 文字列を識別子として使用する場合は、標準化形式Cで正規化する
- 列挙型は使用せず、代わりに文字列を使用する
- この文字列の検証は、サーバ側で行う(言い換えると、クライアント側で検証しない)
- リストは一括処理したいデータをまとめる際に最適
["str",5,true]
のように、 一つのリストに、複数のデータ型を格納するべきではない
- リスト、マップは、要素数を制限する
- 更に、マップではキーとバリュー両方のサイズを制限する
WebAPI
2023年06月03日(土)
2.0時間