swagger-playやswagger-akka-httpのようなフレームワーク連携swaggerドキュメント生成ライブラリは概ね役に立たない

swagger-playやswagger-akka-httpのような、フレームワークと連携してswagger ドキュメントを自動生成してくれるようなライブラリがある。 このようなライブラリは直接API仕様をyaml/jsonで書く必要がなくなり、swagger仕様も読み解く必要がないため一見便利に見えるが使ってみたところ以下の欠点があり現時点ではプロダクトで使うには足りなかった。

1. フレームワークとの統合に限界があり、それほど自動生成してくれない

ライブラリがフレームワークから自動生成してくれる情報はせいぜいAPIパスとメソッド(GET/POST/...)などで、ヘッダ情報やレスポンスのステータスコードのパターンなどは結局自分で書く必要がある。

2. アノテーション情報が非常にコード品質を落とす

上で述べた通りほとんどの情報は自動生成されないのでメソッド/クラスへのアノテーションとして各種情報を書く必要があるが、swaggerドキュメントの品質をあげようとするとこのアノテーションは1APIにつき簡単に10行以上にもなりコードの可読性を著しく下げる。 そのためswaggerドキュメントの品質を上げようとするとコードの品質が下がり、コードの品質を上げようとするとswaggerドキュメントの品質が下がるというジレンマが発生する。

3. ライブラリのコード品質が低い

上のような欠点により多くの人が早めに見限るので、ライブラリの品質が基本的に低い。 swagger-akka-httpswagger-playを試したがどちらも有名ライブラリと連携している割にはstarが少なく、またコードの品質が低かった。 具体的には以下を指す。

  1. アノテーションで表現できないswagger仕様がある
  2. swagger仕様のバージョンアップに追従していない
  3. case classとswagger modelを紐付けるなど比較的簡単に思いつきそうな機能がない

結論

swaggerドキュメントとコードは切り離して管理したほうが良い。 その方がコード/ドキュメントそれぞれの品質が上げやすくなる。 コードとドキュメントの歩調を合わせる手間の問題についてだが、個人的にはAPIサーバのrootにアクセスしたときswagger UIでそのAPIサーバのswaggerドキュメントが動くAPI仕様として使えるようにすればかなり楽になると思う。 例えば https://api.petshop.io/api/v1/xxxx のようなAPI集合がある場合、https://api.petshop.io/ へアクセスしたときswagger UIで https://api.petshop.io/api/v1/xxxx 系のAPIの仕様すべてを表示する。 これには以下の利点がある(番号が若いほど重要)。

  1. API利用者がswaggerドキュメントの場所を探す必要がなくなる
  2. 動くAPI仕様書は使いやすく、その結果API使用者・記述者両方がよく利用するようになる。その結果仕様の間違いや足りない記述などが発見されやすくなり、ドキュメントを修正しやすくなる。最終的にAPI仕様書の質が上がるようになる
  3. APIの追加/機能変更とドキュメントの更新を同じパッケージ(jar)で賄うことができ、それによりswaggerドキュメント変更とコード変更の歩調が簡単に合わせられる
  4. Swagger UIと対象APIが同じホスト名ならCORSを考慮する必要がない

動くAPI仕様書と実際のAPIを同じドメインにまとめることの利点はWeb API Design(その4) - winplusの日記の「ひとつのサブドメインに、APIのリクエストをまとめる」でも語られている。