とあるAPIを触っていてなるほど、と思ったので紹介です。この記事で扱うAPIはインターネットを介してJSON形式のデータをやり取りするAPIです。
しばしばAPIの中では配列を扱います。例えばあるユーザーが複数のアイテムを持つ場合、次のように表現できます。
{
"userName": "浜松太郎",
"hasItemList": [
"hoge",
"fuga",
"piyo"
]
}
これはその時に必要なだけのデータ持つ形です。持っているアイテムを配列で持っています。これはシンプルですが、その後の拡張の際がしんどくもあります。もしアイテムについての説明文をつけた情報をやり取りする必要があり、かつ元々のAPIを壊してはいけない場合、次のような形になります。
{
"userName": "浜松太郎",
"hasItemList": [
"hoge",
"fuga",
"piyo"
],
"hasItemDescriptionList": [
"hogeとはテストデータにしばしば使われる名前です。",
"fugaとはテストデータにしばしば使われる名前です。",
"piyoとはテストデータにしばしば使われる名前です。"
]
}
hasItemListとあるけど名前しか持っておらず紛らわしい、hasItemListとhasItemDescriptionListをつなぎ方が配列のインデックスの番号と扱いにくい、という風に問題が出てきます。辛いです。こうなってしまう予防策としてプリミティブな値、いわゆる文字列、数値、真偽値の配列を避ける方法があります。これを考慮すると最初の例は次のようになります。
{
"userName": "浜松太郎",
"hasItemList": [
{"name": "hoge"},
{"name": "fuga"},
{"name": "piyo"}
]
}
一見、無駄に大きくて不格好ですが拡張のしやすさと後方互換性の守りやすさを両立できる形です。こうしておけば次のように拡張できます。
{
"userName": "浜松太郎",
"hasItemList": [
{
"name": "hoge",
"description": "hogeとはテストデータにしばしば使われる名前です。"
},
{
"name": "fuga",
"description": "fugaとはテストデータにしばしば使われる名前です。"
},
{
"name": "piyo",
"description": "piyoとはテストデータにしばしば使われる名前です。"
}
]
}
便利です。プログラミングには余分なものを作るべきでないというYAGNI原則がありますが、今回紹介した例は一度シンプルに作りすぎると取り返しがつかなくなってしまう(古いバージョンのAPIと新しいバージョンのAPIを同居させる必要がある場合など)、プロパティが冗長になるのみで作る時間はそれほど伸びない(IDEの補完や正規表現が使えないと流石に辛いですが)、という点でこの原則を外れることを考慮する価値があると思います。