悪いWeb API設計

悪いWeb API設計

[1] Web API (HTTP による API) の悪い設計例やどう設計するべきかの指針のご紹介です。

[138] 何が良いかは諸説あり宗教的で難しいですが、 悪いものには悪い理由があるので賛否はともかく参考になるはずです。

目次

  1. バージョニング (版付け)
  2. 特殊な要求メソッド
  3. 特殊な認証方式
  4. パスの濫用
  5. 動詞のパスを頑なに拒む
  6. 何でもパスに入れたがる
  7. 用語が一貫していない
  8. 変な状態符号
  9. 変なプロトコル
    1. 意味のない互換性
    2. HTTPS を使っていない
  10. 変な出力データ形式
    1. 変なデータ形式
    2. 内容折衝
    3. エラー応答の形式
  11. 変な MIME 型
    1. 独自の MIME 型
    2. MIME 型引数
  12. JSON データ構造
  13. 変なタイムスタンプ
  14. HTTP ヘッダーの濫用
  15. 変なページング
  16. 人間向けサーバーと API サーバー
  17. 困ったドキュメント
    1. ドキュメント自体の URL
    2. ドキュメントのプロトコル
    3. エンドポイント
    4. 値域
    5. ドキュメントのライセンス
    6. コピペ可能性
  18. 開発環境がない
  19. API の設計ガイドライン

バージョニング (版付け)#

[2] API にバージョンを設けるべきではありません。 API の拡張は、常に後方互換性を保った形で行うべきです。

[3] 従って URLHTTPヘッダーなどにバージョン番号を指定させる必要はありません。

[7] やむを得ず非互換変更せざるを得なくなった時は、非互換な機能のみ、 新しいエンドポイントを設けるべきです。はじめから非互換変更するつもりで準備しておくのは無駄ですし、 非互換変更するための言い訳を用意するようなもので、危険です。

[38] バージョンが複数あるということは、同じものを複数メンテナンスし続けなければならないということです。バグやセキュリティーホールのリスクも増えます。場合によっては、混用された時におかしなことにならないかも注意しなければなりません。

[39] 実際それはつらいので、いつか古いバージョンへの対応をやめようとします。しかし、古いバージョンで問題なく使えていたクライアントは、無駄な変更コストが発生しますし、それによって新たにバグが生じることもあります。面倒に思ったり、コスト上の理由などで、それを機に対応を取りやめるクライアントもあるかもしれません。旧バージョンのアクセスが減ったと思って廃止したら、アクセス頻度が低いクライアントが利用できなくなって困る、というのもありそうです。 バージョンを分ければ変更しやすくなるというのはその場しのぎでしかなく、 問題は先送りされているだけです。

[88] 結局、API 提供者にとっても、クライアント開発者にとっても、クライアント利用者にとっても、嬉しいことは何一つありません。

[40] シェアを背景に API の非互換変更を頻繁に行う FacebookTwitter は、雇用創出のための公共事業で仕様変更をやってるのではないかと揶揄されていますよ。 サーバー側がクライアント側より著しく高い政治力を持つ時だけうまく(?)いくモデルで、 参考にするべきではありません。

[121] あるサービスでは、バージョン番号として日付を指定させています。 そのドキュメントには「現在の日付を指定するな」とわざわざ注記があります。

クライアント開発者にとっては自分の書いたコードが1日でも長く無メンテナンスで使い続けられるのが良いですから、 現在の日付を指定したくなるのもわかります。そのような注記が必要だということ自体、 この方式が失敗していることを象徴しています。

[122] バージョニングは、 Web の他の分野でもアンチパターンとして知られています。

特殊な要求メソッド#

[4] 実用上、 GETPOST (と OPTIONSHEAD) 以外の要求メソッドを使うべきではありません。

[6] 意味的にもすべての操作をこの2つで十分明確に表現できます。

[79] PUTDELETE を使うべきだというのは宗教的な主張なので、 普通は POST で問題ありません。 最近は PATCH 教も人気ですが、 流行に乗ればいいというものでもないでしょう。

[5] 特殊な要求メソッドに対応していないクライアントのための代替手段として X-HTTP-Method-Override: ヘッダー要求メソッドを指定できるようにすることがありますが、 本末転倒です。正しい要求メソッドを使うべきです。


[32] 安全冪等な操作にしか GET を使う(使える)べきではありません。 かつては JSONP のためやむを得ず GET を使うことがありましたが、 今やただのセキュリティーホールです。

特殊な認証方式#

[8] 認証には HTTP 基本認証OAuth 2.0 Bearer を使うべきです。いわゆるAPIキー認証は Bearer で表現できます。 (OAuth 2.0認可フローを実装しなくても、 Bearer だけ使えます。)

[31] キャッシュ (サーバーアプリケーションを構成するプロキシ、 またはクライアントが使っているプロキシのもの。) による問題を防ぐためには、 HTTP認証の仕組みに乗るべきです。その意味で query や独自 HTTPヘッダーAPIキーを指定する方法は、安全ではありません。

[129] Bearer と実質的に同じものなのに、独自の auth-scheme 名としている Web API もありますが、何のメリットもありません。避けるべきです。

[80] 独自の署名を求める方式も、避けるべきです。歴史的には意味があったかもしれませんが、 今や HTTPS が基本ですから、本当に署名が必要な状況は稀です。 署名はデバッグが難しく、開発者を悩ませてきました。

パスの濫用#

[21] URLpath の濫用は慎むべきです。

[22] 例えば検索キーワードなどは URL query で指定するべきです。

[23] path に任意の文字列が指定可能な場合、 クライアント側のパーセント符号化漏れ、 Web API サーバー側の逆プロキシWAF の設定ミスによるパーセント符号化まわりの不具合などが起こりがちです。

[35] path に任意の URL を埋め込めるのは、特に避けるべきです。

動詞のパスを頑なに拒む#

[34] よく path名詞がよく、動詞は好ましくないと言われます。

[48] ただし整理上の都合で動詞を使った方が綺麗になるなら、無理に避けるものでもありません。 たとえば https://host/document/124345 の編集に関する操作は https://host/document/124345/edit への POST に、 削除に関する操作は https://host/document/124345/delete への POST に実装しても何ら問題ないでしょう。

https://host/document/124345/editGET が編集ページ、 https://host/document/124345/deleteGET が削除確認ページになっていると、ちょうど良い。

[65] 動詞を避けることで直感的でなくなったり、複雑になったりするのでは本末転倒です。

[73] >>72 も参照。

何でもパスに入れたがる#

[66] オプションを引数 (URL query要求本体application/x-www-form-urlencoded) ではなくパスの一部に入れたがる人もいるようです。

[67] あまりどちらを使うべきか一概に言えるものでもないのですが、 次のような判断基準はたてられそうです。

  • [68] 省略可能なオプションなら、引数で指定させた方が良い。
  • [69] 値が長くなりそうなオプションなら、 引数で指定させた方が良い。
  • [70] 操作対象を指定する性質が強そうなオプションなら、パスに入れて良い。
  • [71] いくつかのオプションがあって自明な順序がない (包含関係やユーザー○○の投稿××のような親子関係がない) なら、 引数で指定させた方が良い。
  • [72] 動作の指示は引数で指定させた方が良い。
  • [74] 記号を値に含むなら (特に、普段は含まないがたまに含む場合)、 引数で指定させた方がパーセント符号化を忘れるミスは防ぎやすい。

用語が一貫していない#

[81] API に登場する語 (path の一部分、引数の名前、 列挙型引数の値、 JSONオブジェクトに含まれる名前など) は、一貫した命名規則に従うべきです。

[82] 例えば、利用者のことを表すのに、 userusruaccount のような似て非なる語・綴りを混在させるべきではありません。

[83] 省略形よりも完全形の方がわかりやすくて良いとする人もいます。 しかしやたらと長い方がかえってわかりにくくなったり、面倒くさかったりもします。 省略するべきかどうかは適宜判断すればよく、語の長さよりも一貫性の方が重要でしょう。

[93] 英単語を連ねる場合、 camelCase-_.、 区切りなしなどいくつかの流儀があります。プログラミング言語の変数名などと同じく、 色々な人が色々な好みを持っていて、どれが優れているというものでもありません。 これもまた、一貫性を持たせることさえ心掛ければ、どの方法でも良さそうです。

[98] たぶん、これは Web API に限らず、開発プロジェクト全体で用語集を使って統一した方がよいでしょう。

変な状態符号#

[11] 状態符号は適切に選択するべきです。エラーなら 4xx とするべきです。

決め方に迷ったら 4xx 参照。

[47] エラーだろうがなんだろうが構わず 200 を返すものは最悪です。 本文 JSON データでエラーを表している場合でも、適切な状態符号を使うべきです。

[128] ライブラリーによっては状態符号で正常かエラーかを判断したり、 開発者に有用なデバッグ用メッセージを生成したりといった機能があります。 これは応答がおおよそどのような性質のものであるかを状態符号という HTTP 全体で共通の方法で伝達できることの恩恵です。 たとえ詳細なエラーを別の方法で伝える必要があるとしても、 それはそれとして、状態符号は正しく設定するべきです。

変なプロトコル#

[94] 一昔前、 XML-RPCSOAP が若干流行ったことがありました。 しかし今では誰も使っていません。

[95] WebDAVAtom APIAtomPub が使われたこともありました。 今でも皆無ではありませんが、新規開発なら気にする必要はありません。 既存サービスとの互換性のようなことも、考えるだけ時間の無駄でしょう。

意味のない互換性#

[96] Web API のやり取りを共通化するプロトコルはこの他にも色々と提案されてきましたが、 どれも大きな成功を収められていません。 Webアプリケーションはそれぞれに異なる要件と利用形態を持っていて、 どれだけ共通化しても、どうしても収まりきらない部分が出てきてしまいます。 するとサービスごとに独自対応せざるを得なくなりますが、 それならば初めからそれぞれの特性や利用方法に応じた独自の API とした方が、提供側も利用側も楽だったりするのでしょう。 HTTP を使う、 JSON を使うといった基盤といえる部分を除けば、 Web APIプロトコル標準化には馴染まなそうです。

[97] TwitterFacebook は、扱うデータの形態や利用者のアクションだけみれば API を共通仕様に揃えられそうなものですが、 両者の実際の APIエンドポイントデータ構造は全く異なります。 設計思想や歴史的な経緯の違いももちろんあるのでしょうが、 同じように見えても実際には全然異なる機能だったり、 違った形で利用されていたりして、簡単に共通化できるものでもなさそうですし、 それが各サービスの差別化要素にもなっているのでしょう。

[41] 競合他サービスの API に似せた API を提供しようとして、失敗している例をたまに見かけます。

[42] 完全互換ならクライアント開発者のメリットも多いでしょうが、実際には細かな差異がたくさんあったり、他サービスの仕様変更に追随できなかったりして、似て非なるものになっているのが普通です。すると他サービス用のコードを思ったほど流用できなかったり、境界ケースで正しく扱えず不具合が生じたりしがちです。

[44] 困るのは互換性があると信じて有名競合サービスとそれに似せた弱小サービスに対応したクライアントの開発者です。 有名競合サービスが仕様を変更し、弱小サービスが追随できない場合、 細かな分岐を増やすなり、コードを丸々コピーするなりしてがんばって両方への対応を維持し続けるか、 弱小サービスのサポートを終了するか、 弱小サービスのことを忘れていて仕様変更対応後に不具合が出てから気がつくか。 それならはじめから別のサービスは別のコードで実装していた方が良かったのではないでしょうか。

[43] クライアント開発者の視点からすると、 (対象となるサービス自体のデータモデルが似ていることが前提で) 同じ操作が似たような手順で実行さえできればよく、そのエンドポイント名や引数名、応答のデータ構造などは (完全に一致しないなら) 合わせなくても良いように思えます。

HTTPS を使っていない#

[29] 常に HTTPS を使うべきです。平文のHTTP が好ましい理由は何もありません。 歴史的な理由で未だに HTTPWeb API を提供するサービスも少なくありませんが、 それに倣うべきではありません。

[30] 両方を提供する理由もありません。ただのセキュリティーホールです。

[99] iOSアプリから利用する場合、 ATS により標準で HTTPS のみ有効になっています。アプリに設定を変更させるのは危険であり、避けるべきです。

変な出力データ形式#

変なデータ形式#

[9] 出力データ形式は JSON を基本とするべきです。 ほとんどのプログラミング言語フレームワークで、 JSON は標準で実装されています。

[33] XML は追加ライブラリーが必要で面倒なクライアント環境やデータの扱いが面倒なライブラリー API が多いので、極力避けるべきです。

[50] CBORMessagePack のようなバイナリーベースの形式を好む人もいます。 確かにサイズは抑えられ、 (実装次第ですが) JSON より高速に処理できるかもしれませんが、 ほとんどの場合は微々たる差で、より広く普及していてデバッグも容易な JSON の方が適切です。少なくても不特定多数の開発者に公開された API では、 JSON を基本とするべきです。

[12] JSONP は使うべきではありません。ただのセキュリティーホールです。 異なる起源JavaScript からのアクセスが必要なら、 CORS を使うべきです。

内容折衝#

[10] データ形式を選択制にするときは、URL query または拡張子で指定できるようにするべきです。 Accept: による選択は使うべきではありません。 杜撰なキャッシュの実装は Accept: を正しく扱えません。 URL で指定できる方がデバッグが容易です。 サーバーアクセスログに普通 Accept: は記録されないので、URL に含めた方が便利です。

[49] Webブラウザー向けと Web API で同じ URL を使い Accept: によって内容折衝するような実装方法もありますが、 混乱を招くだけで誰も得しないので、避けるべきです。

エラー応答の形式#

[36] クライアントが機械的に処理することを想定したエラー応答は、 JSON など (成功時と同じ) 機械可読な形式で提供するべきです。例えば投稿エンドポイントは、 投稿エラーなら、投稿エラーを説明した JSON 応答を返すべきです。

[37] しかしだからといって、無理にどんなエラーでも JSON で返すようがんばる必要はないでしょう。例えばアプリケーションサーバーが過負荷で応答できないときのリバースプロキシのエラーまで敢えて JSON にしなくても構いません (しても構いませんが)。どうせクライアントは状態符号以上の有益な情報をその応答から得られません。 クライアントはどのみち JSON でない時のエラー処理を実装しておく必要がありますから、 実装の手間も変わりません。

変な MIME 型#

独自の MIME 型#

[123] JSONMIME型application/json です。 ほとんどすべての場合、これをそのまま使って何の問題もありません。

[124] たまに、 application/service-name+json のような独自の MIME型を使っていることがあります。 MIME型は独自なのに、 データは普通の JSON だったりします。 MIME型の仕組みとして間違ったことではありませんが、 何のメリットもない、意味のないことです。

[125] ライブラリーによっては、 MIME型application/json の時 JSON を扱いやすい機能を提供しているのに、独自の MIME型が使われるため、 その便利機能が使えないという可能性もあります。

MIME 型引数#

[78] MIME型引数 (application/example; foo=barfoo=bar のような部分) を使いたがる人がいるようです。一見便利に使えそうな場所ですし、 実際意味的に適切な場合もあるのですが、 MIME型引数の取扱いは相互運用性に欠けるので、 あまりおすすめできません。

実装によって、引数の存在に対応していない、大文字と小文字の扱いが不適切、 複数の引数の指定順序の違いが不適切、 同名の引数が複数あるときの扱いがわからない、 値の特殊文字や非ASCII文字の符号化の方法が混乱している、 といった色々な問題があります。

[142] Web APIversioning に濫用した事案: application/vnd.elasticsearch+json

JSON データ構造#

[45] JSON の場合、最上位は (配列プリミティブ値ではなく) オブジェクトとした方が無難です。何かのリストを返したい時も、 後から他の付加データを増やしたいときに配列だとどうしようもないので、 オブジェクトでくるんでおくと良いでしょう。

[46] 識別子などで桁数の多い数字列を扱う時は、 JSON数値ではなく文字列で表すように注意するべきです。

JavaScript では構文解析時に32ビット整数に丸められてしまいます。

[118] JSONnullブール型数値文字列の違いは、 プログラミング言語によっては区別されないことや違いが曖昧なことがあります。 従って、これらの違いを厳密に扱うことを要求するべきではありません。

[119] 例えば、クライアントから {"foo": true} または {"foo": false} のような値を受け取りたい場合、 JavaScriptToBoolean の挙動に寄せて、

... のようにすると、いろいろなプログラミング言語ライブラリーから無理なく扱えて好ましいと思われます。 (更に Perlbool context の挙動に寄せて、文字列 0とみなすのもありかもしれません。)

[51] HAL のような JSON ベースの言語を採用したり、 JSON Schema のようなスキーマに従って定義したりすることを好む人もいます。 そうしたものが有用な場面もあれば、あまり意味のない場面もありますから、 個別の用途に合わせて何を採用するか決めるべきです。「すべて○○を使うべき」 といった主張は眉唾物です。

変なタイムスタンプ#

[13] 日時形式は、Unix time を基本とするべきです。 ISO 8601の日時形式HTTPの日時形式、その他独自の形式は、 構文解析や生成処理や時間帯処理が面倒でミスを誘発しがちなので、避けるべきです。

HTTP ヘッダーの濫用#

[24] HTTPヘッダーの濫用は避けるべきです。

[25] クライアントによるページングの指定は、 URL query で行うのが伝統的な方法です。 それで何も問題ありません。

[26] サーバーによる前後のページのリンクなどは、本文 JSON データに含めるべきです。 Link: ヘッダーによる指定は構文解析や生成処理が面倒でミスを誘発しがちなので、避けるべきです。 本文に含められない時は、 URL だけを値とする独自の HTTPヘッダーを使うのが次善策です。

変なページング#

[76] 「投稿一覧」や「コメント一覧」のような追加や削除が起こり得る対象の一覧を時刻順で取得する API では、ページングにページ番号や先頭からの位置を取得するべきではありません。 最初のページと次のページの取得時点で位置が変化している可能性があるので、 項目の重複や欠落が発生する可能性があるからです。

[77] 「時刻 t より前、後」のような指定形式が良さそうですが、 同時刻に複数の項目が存在するかもしれないケースでは、 取り扱いが難しくなるかもしれません。 マイクロ秒ナノ秒の精度の時刻を使えば、そのようなケースはほとんど排除できそうです。 の精度では、重複はかなりの頻度で発生します。

人間向けサーバーと API サーバー#

[57] 人間向けサーバーと Web API のサーバーをどのように共存させるかは、 アプリケーションの実装手法やサービスの規模と負荷分散の戦略によって、 いろいろな手法が考えられます。実際、いろいろな方法が用いられています。

[58] 例えば:

[62] 最初は小規模のサービスが大きくなった場合でも、 URL で区別できるなら、 リバースプロキシで接続先アプリケーションサーバーを切り替えられますから、 負荷分散戦略によって URL の設計を過剰に制約する必要はありません。

困ったドキュメント#

[14] 人間による明確なドキュメントを提供するべきです。

[15] 機械的に生成されただけのものは、ドキュメントとは言えません。 むしろドキュメントを整備した気になるだけなので有害です。

[27] 例えば JSON Schema から機械的に生成した HTML ファイル群は、ただの JSON Schema書き下し文であって、 ドキュメントではありません。 もしや有用な情報が含まれているのでは、と読者の期待を煽ってしまうだけなので、 むしろ有害です。

[16] 入出力や処理内容など必要な情報を過不足なく記述するべきです。 エンドポイントごとに一言コメントを並べたようなものは、メモ書きであり、 ドキュメントではありません。

[17] また例示は例示であり、ドキュメントの本編ではありません。 例示をいくつ並べても、エンドポイントの説明とはいえません。

[52] 有名な WebサービスWeb API であっても、 応答JSON の実例を示しただけでまともな説明を加えていない「ドキュメント」 しか無いことがあります。

[131] 主要なプログラミング言語での利用例を示すこと自体は構いませんが、 HTTP でどのような要求を送信すると、どのような応答を受信することになるか、 という説明を怠ってはいけません。 クライアントがどのようなプログラミング言語でどのようなライブラリーを用いていようと、 HTTP という共通のプロトコルで等しく API にアクセスできることが、 Web API の特徴であり、可能性です。

[28] API によってアクセスされる対象であるオブジェクトの説明をがんばっているのに、 肝心の Web API の部分、つまり HTTP でどのような要求が必要で、 どのような応答が送られるのかの説明が雑なことがよくあります。 サービスのオブジェクトモデルの説明は、もちろん重要な情報ですが、 それだけでは Web API のドキュメントになりません。

[63] 一読して理解できないレイアウトは避けるべきです。 API ドキュメントは、 デザイナーやエンジニアの自己表現の場ではありません。

[102] 表示上の固定部分 (position: fixed など) はできるだけ避けるべきです。 ノートPCなどの狭い画面や、広い画面でも開発中のアプリケーションエディターなどと同時表示している場合など、 狭い表示領域しか与えられないことがあります。

[132] 同じ理由で、本文の左右に目次や例示などで広い幅を占有する領域を配置するのは避けるべきです。

[100] 無駄にページ分割された構成は、一見整理されて使いやすく思えますが、 どんな機能があるか全体像をよく理解していない API 利用者にとっては望む機能がどこにあるか探しにくかったりします。 少ないページにまとめられていた方が、どんな機能が提供されているのか眺めやすいです。 例えばエンドポイントごとに別ページに分かれていたりすると、 極めて使いづらいドキュメントになります。

[101] 同じような理由で、見出しをクリックすると詳細説明が展開されるような、 一々細かく操作しないと全体を読めないドキュメントも使いづらいです。

[141] 一つの Web頁に内容がまとまっていれば、 Webブラウザーの標準のページ内検索機能で求めるものを見つけることができて、 便利なのです。


[103] 本サイトへのリンクがどこかにあるべきです。 (ドキュメントトップページへのリンクがあっても本サイトへのリンクがない (かわかりにくい) ことは意外とよくあります。)

[104] 例えば採用サービス候補がいくつかあって比較しているときなどに、 API ドキュメントと本サイトの機能ガイド、価格表などを行き来したいことがままあります。


[139] WebブラウザーWeb頁内検索を呼び出そうと Ctrl + F を押すと、キャンセルして独自の検索機能を表示するドキュメントがあります。 ほとんどすべての場合、 Webブラウザー標準の検索機能の方が優秀なので、邪魔なだけです。 (Webブラウザー事業者で勤務するトップクラスの技術者が時間をかけて作ったものと、 どちらが便利か、少し考えればわかりますよね。)

[140] ドキュメント (複数の Web頁) の横断検索は、あれば便利なので、 別にフォームを用意して貰えればそれで良い。 Webブラウザーの標準機能を潰す必要はどこにもない。

ドキュメント自体の URL#

[110] 他の開発者との情報交換や、 ソースコードコメントなどの形でドキュメントの一部を参照したいことがよくあります。 従って、

  • [111] ドキュメントURL をころころと変えるべきではありません。 新機能の追加などのタイミングでドキュメントを再編したくなるかもしれませんが、 元の URL で新しい場所に簡単にたどり着けるような配慮は絶対に必要です。 (わかりやすいように再編すること自体は問題ありません。)
  • [113] 1つの文書の内容が多岐にわたる場合は、 項目ごとに ID を付与するべきです。 特にエンドポイントデータ型などは、 個別に参照したくなりそうなので、個々に ID を付与することが望ましいです。 できれば、章見出しをリンクとしたり、「§」マーク等でリンクしたりして、 読者が容易に気づけるようにするべきです。
  • [112] 文書の途中にリンクされた時の JavaScript によるスクロール効果など、 読者が求める情報に到達するまでに無駄な時間を浪費する機能を盛り込むべきではありません。
  • [114] フレームや、素片識別子リンクを使わない JavaScript によるスクロール・表示切り替えのような、 アドレスバーの表示と実際の文書URL が異なってしまう技術を使うべきではありません。
  • [115] スクロールに追従して、あるいはクリック等の動作で、 勝手に URL (の素片識別子) を書き換えるのは避けるべきです。 一見便利機能のようですが、読者が共有したいと思った URL がいつの間にか違うものに書き換わっていたりして、案外不便です。

ドキュメントのプロトコル#

[107] ドキュメントWebサイトで簡単に参照できるようにしておくべきです。

ダウンロードできるようにしても構いませんが、必須ではありません。

[108] 素のHTTPではなく、HTTPS で提供するべきです。

[109] Web API 本体が HTTPS なのにドキュメントだけ素のHTTP のサービスがありますが、なぜそうしようと思ったのか理解に苦しみます。 今となっては素のHTTPで提供するのが妥当である理由は何もなく、 サービス提供者の技術力の低さを露呈するだけです。

エンドポイント#

[130] APIURLpath 部分しか示していないドキュメントをたまにみかけますが、 schemeホストも含めてすべて示すか、 その説明にリンクするべきです。なぜなら、 読者 (開発者) は望む機能を探してエンドポイントの説明ページを見て、 それをもとにコードを書くので、その時必要な情報がそこにすぐにあるべきだからです。

[135] 驚くべきことに、ドキュメントのどこにも書かれていないサービスすら存在します (!)。 API 提供者は一度でもその API を実際に使って何かを作ってみようとしたことがあるのでしょうか。 (自分達は API を使わずになんでもできてしまうので、意外となかったりします。 しかしそんな態度で果たして使いやすい API が提供できるかどうか。)

値域#

[84] 可能な値の範囲は、できるだけ明確に文書化するべきです。その際は、 将来の拡張も視野に入れ、限定しすぎず、かといって一般化もしすぎず、 適当な粒度とするべきです。

[85] 例えば、あるサービスの利用者識別子API でやり取りする場合、 おそらくクライアントもその識別子を何らかの形で保存しなければなりませんから、 ストレージ上のデータ型を決めなければなりません。 識別子が数値なのか文字列なのか、含まれる文字の種類は何なのか、 最大の長さはどれだけなのか、といった情報がクライアント側開発者には有用です。

[86] ここで、サーバー側で識別子を32ビット整数型で表現しているとしても、 これをそのまま文書化することが望ましいとは限りません。将来の拡張の余地を残すため、 64ビットで表現可能な非負整数、と説明した方が良いかもしれません。

[87] 加えて、利用者の識別子は利用者によって互いに異なること、 決して他の利用者に再割当てされることがないこと、 といった性質も、説明しておくのが良さそうです。 一方で、識別子は小さい順に連番で割り当てられる、という情報は書かないべきでしょう (クライアント側で有用な情報ではなさそうですし、将来サーバー側で割当方法を変更したくなるかもしれません)。

[116] 「数値」や「タイムスタンプ」や「ISO 8601の日時形式」のような曖昧な説明ではなく、 「1個以上ASCII数字列によって表される十進整数」、 「HTML Standard が規定する妥当な大域日時文字列」 などの明確な説明とするべきです。

現実には残念ながらこれを怠る解説が少なくありません。 例えば「ISO 8601の日時形式」は無数の細かな選択肢がありますが、 それをすべて受け入れていることはほとんどありません。 技術ドキュメントは、異なる背景をもつ技術者同士が曖昧なく意思疎通できなければ意味がありません。

[117] 例示は、説明したことにはなりません。ドキュメントから例示をすべて取っ払ったときにも、 曖昧無く理解可能に記述するべきです。例示は理解の補助に過ぎません。

ドキュメントのライセンス#

[133] クライアントの開発者がドキュメントの一部をコメントとしてソースコードに書き込んだり、 提示されたサンプルコードを改変して利用したりすることは、よくあります。 これを安心して行わせるために、ドキュメントは自由度の高いライセンスで提供するべきです。

[134] 具体的には、 CC0MITライセンスApacheライセンスが適切と思われます。

コピペ可能性#

[136] ドキュメント中の重要な部分は、一般的な Webブラウザー利用者が簡単にコピペできる状態になっているべきです。

[137] ある Webサービスドキュメントは、 エンドポイントURL をクリックすると詳細が開いたり閉じたりする形になっています。 details 要素に相当するものですが、独自実装で、 テキストを選択しようとすると開いたり閉じたりして、選択は解除されてしまいます。 ドキュメントを読む人が、書かれている情報をどう利用するだろうか、 というところにもう少し想像力を働かせるべきでした。

開発環境がない#

[18] 提供されるサービスの性質次第ではありますが、クライアントの開発者が利用できる開発環境が提供されていると大変有用です。

[20] 課金など重大な処理が伴うものや、通常のサービス利用では前提条件を構築するのが難しい処理などは、適当な開発環境が用意されているべきです。

[19] APIホストを書き換える程度の手間で本番環境と切り替えられるのが理想的です。

[53] 有料サービスや審査制のものなどでは、開発者が容易にアクセスできる開発を提供することはとても重要です。 本格的な開発 (や契約その他) の前の評価段階の予備的開発のため、 特別な審査や費用などがなくても利用できるようにするべきです。

API の設計ガイドライン#

[54] プログラミング言語ライブラリーと同様に、 Web API にもこう設計するのが良い、悪いというような指針コーディング規約のようなものが色々とあります。

[55] そうした指針類は、設計に迷った時のヒントとして有用かもしれませんが、 あまり意識しすぎても、無駄な制約でかえって開発しづらくなったり、 設計を歪めたりする危険性があります。

[56] 宗教性の高い指針には、特に自分の信仰と親和性が高そうに思った場合を除き、 従わない方が無難です。

[64] パスなどで単数形にするか、複数形にするか: どうでも良い。好きにすれば良い。その場その場で不自然でないようにすれば十分。

[89] 有名サービスが採用している方針が、 常に好ましい方針とは限りません。真似る場合には、 自身の開発する対象にあわせて適切かどうかを都度検討するべきです。 長く続く有名サービスほど、歴史的な事情が積み重なっているはずです。 当該サービスの開発者自身も、おそらく何らかの不満を持っていることでしょう。

[90] 「宗教性」は、馴染みの薄い人には感じ取りにくいかもしれませんが、 次の各項に該当するなら要注意です。

[106] この指針自体も、ある種の「宗教性」が感じられるかもしれません。 信じるか信じないかはあなた次第です。

[126] Web は、新技術開発が活発に行われ続けている、変化の速い分野です。 設計方針は、時代の変化への追随の足枷になるべきではありません。

[127] 例えば、会社の意思決定の速度が遅い場合には、 会社の方針として設計の指針を定めるべきではありません。