JSON Hyper-Schemaのようなサービスディスクリプションがうまくいかない理由

RubyKaigiの発表のために考えていたのですが、発表本編に詳しく入れられなくなりそうなので、まとまりないですがブログに書いてみます。


SOAPでいうWSDL(Web Service Definition Language)のような、サービスのインタフェースを定義・記述するためのしくみを総称してIDL(Interface Description Language)と呼びます。
JSON Hyper-Schema*1もIDL、サービスディスクリプションの一種といえます。
WebのIDLは今までにもたくさん出てきて、しかしうまくいっていません。
なぜでしょう?

@yohei さん曰く、

RESTは統一インタフェースなんだから、そこにさらにインタフェースを定義するのはおかしい

API Meetup #1 質疑応答より)

これはどういうことかというと、

HTTP method + URL という統一インタフェース(Uniform Interface)が相互運用性(interoperability)の源であり、付け足すとuniformでなくなるため相互運用性が損なわれる、ということです。

「いや、それだけじゃどこのURLにどのメソッドでどういうパラメータ投げればいいかわからないでしょ。だから定義しなきゃ」この発想が間違いの元です。

「どこのURLにどのメソッドでどういうパラメータ投げればいいか」はインタフェースとして集約して記述されるのではなく、ハイパーメディアコントロール(リンクやフォーム)としてそれぞれの表現の中に自己記述されるのが適切です。

集約することが必ずしも悪いわけではなく、効率的な面もあります。
データの意味に関すること(application semantics)は集約して記述していいでしょう。
URL、メソッド、パラメータに関すること(protocol semantics)は集約してはいけません。(ただしメディアタイプで定義する場合を除く)
集約は自動生成の誘惑を生み、密結合が構成されます。すると全く変更できなくなってしまいます。

サービスディスクリプションがうまくいく道

IDL派がやろうとしていることは、独自の問題領域に固有なメディアタイプの定義であると考えれば筋は通っているし、参考にするべきところが多いです。しかしそれはいったん定義すると変更できなくなり、interoperabilityは低下し、閉じこもる道になってしまいます。

例:Heroku Platform APIJSON Hyper-Schemaを使用してinterfaceを記述し、独自のメディアタイプ application/vnd.heroku+json を定義しました。

定義した独自メディアタイプがデファクトスタンダードになって広く普及すれば、ある意味でIDLの成功になるでしょう。変更できないものになりますが。

追記 (8/29)

Twitterでコメントをいただきました。ありがとうございます。

全体の前提として「変化できるpublic Web APIをつくるには」ということを考えていたのですが、書き落としていました。すみません。

「だから定義しなきゃ」は「だからどこかにまとめて定義を記述しなきゃ」というほうが正確でした。

「自動生成」が問題なのではなく、「事前の静的な自動生成」が問題、というべきでした。
ランタイムに動的に処理(生成)するのが良い方法で、そうすればむしろ変化に強いといえますし、密結合にはなりません。
しかし傾向として、集約されたマシンリーダブルなサービスディスクリプションが存在すれば、そこから静的にコード生成したくなるのではないか、と思います。

「最初にAPIを呼び出すとき」は、「最初にWebページを見るとき」と同じ考え方でかまいません。どこかほかのサイト(API)からのリンクで来るかもしれませんし、「ホームページ(/)」を直接GETするかもしれません(これが現実的でしょう)。
エントリポイントは暗黙に決まっていて欲しいという需要もありますので、RFC5785では Well-Known URI というものを定義しています。これを採用してもいいと思います。

*1:JSON Hyper-SchemaはJSON Schemaの一部ですが、JSON Schema自体はバリデーションなどに便利に使えると思います。