ESDocという(多分)モダンなドキュメンテーションツールの紹介

こんにちは丸山@h13i32maruです。

僕は2015年からESDoc*1というJavaScript向けのドキュメンテーションツールを開発しています。

最初のリリースから2年、昨日ようやくv1.0をリリースできました🎉 いやー、ここまで長かったです。今ではRxJSSketchAPIなど、様々なツールで使用されています。

この2年間、ESDocは2つのゴールを目指して開発してきました。

  • ドキュメントの作成・メンテナンスを快適にする(ドキュメントを書くの楽しい!という状態)
  • ソフトウェアの使い方を簡単に理解できるドキュメントを作成する(ソースコード読まなくても大丈夫!という状態)

この2つを満たすためにESDocは色々な機能を提供しています。 今日はそれらの機能の中でも(多分)モダンで特徴的なものを幾つか紹介します。 モダンと書いたのはJS界隈のドキュメンテーションツールの中ではモダンだと思ったからです。 他の言語だとどうかはちょっと自信はありませんが・・・

ちなみに今回紹介する機能はJavaScript特有ではない機能がほとんどなので、他の言語をメインで使っている開発者の方にも参考になると思います。 願わくば、他の言語のドキュメンテーションツールにも同様の機能が入ると良いなと思っています。

APIリファレンス

ソースコード中にDoc Commentと呼ばれる形式のコメントで専用のタグを書くことでクラスやメソッドに対してドキュメントを書きます。

そしてESDocではこのコメントを読み取り、HTMLに整形してドキュメント(APIリファレンス)を作成します。 このHTMLは見やすさを重視し、気持ちよくドキュメントを見られるようにと意識しています。 そしてこれは見る人だけではなくドキュメントを書く人にも良い影響を与えると思っています。

f:id:h13i32maru:20170729131543p:plain ソースコードにコメントを書いておくと f:id:h13i32maru:20170729130255p:plain こういうHTMLが出力される

ESDocが対応しているタグや形式につてはこちらに詳細があります。

ちなみにESDoc自身からESDocでドキュメントを生成するとこんな感じになります

ドキュメントのカバレッジ

テストにはテストカバレッジがあります。ソースコードのどれだけをテストしているかというものです。 ESDocではこのテストカバレッジと同じように、ドキュメントのカバレッジを測ることができます。

つまりソースコードのどれだけにドキュメント(DocComment)が書かれているかを数値化してみることができます。 そしてどこにドキュメントが書かれていないかも簡単にわかります。

f:id:h13i32maru:20170729130941p:plain ファイルごとのカバレッジが見れる f:id:h13i32maru:20170729131145p:plain ドキュメントが書かれていない箇所がハイライトされる

これによって、ドキュメントの抜け漏れに気づくことができ、ドキュメントの網羅性を向上させるのに役立ちます。 そして、人間、数値が見えると数値を保持・向上させたくなるものです。つまり継続的にドキュメントを書き続けるモチベーションを引き出します。

ちなみに、compodocというAngular用のドキュメンテーションツールではESDocにインスパイアされ、カバレッジが実装されたようです。

ドキュメントのlint

ESDocではドキュメント(タグ)とソースコードをチェックして、不正だと思われるものを警告表示します。 この警告を見てドキュメントのどこに間違いがあるのか簡単にわかるようになります。

f:id:h13i32maru:20170729131813p:plain:w600

これによってドキュメントの間違いに気づくことができ、ドキュメントの正確性を向上させるのに役立ちます。

マニュアルの統合

ソースコード中に書くドキュメントは所謂APIリファレンスと呼ばれるものを作成するのには便利です。 しかし一般的にドキュメントといえば、インストール方法や設定方法、サンプルなどAPIリファレンス以外にも色々な内容が必要です。

そこでESDocはマニュアルとして任意のMarkdownファイルを読み込んでAPIリファレンスとともにドキュメントとして出力します。

f:id:h13i32maru:20170729131939p:plain マニュアルのトップページ f:id:h13i32maru:20170729132025p:plain マニュアルの詳細

これによってソフトウェアを使うのに必要なドキュメントの要素を含むことができます。

テストコードの統合

テストコードはフレームワークやライブラリの使い方を理解するのに良い情報源になります。

そこで、ESDocではテストコードもドキュメントに含めることができるようになっています。 そして単純にテストコードを含めるだけではなく、専用のタグを書くことでテストコードとidentifier(クラスやメソッドなど)を関連付けることができます。 例えばParamParserのAPIリファレンスを見ているときに、ParamParserに関連するテストコードをすぐに参照することができます。

f:id:h13i32maru:20170729132250p:plain:w600 @test というタグを使ってテストコードとidentifierを関連付ける。

f:id:h13i32maru:20170729132434p:plain クラスのドキュメントにテストコードへのリンクが貼られる f:id:h13i32maru:20170729132447p:plain テストコードにクラスへのリンクが貼られる

ちなみにソースコードもドキュメントに統合され、identifierとソースコードは相互に行き来することができます。

組み込み検索

中規模のライブラリやフレームワークになるとドキュメントをただ参照するというより、 機能や使い方を探しながらドキュメントを読むという使い方をすることが多いと思います。

そこでESDocでは検索機能が組み込まれており、ドキュメント内のAPIや説明を検索することができます。 そして機能はAPI名や説明文だけではなく、ソースコードやテストコードも検索対象としています。

f:id:h13i32maru:20170729132807p:plain:w300

ちなみにこの検索機能は非常にナイーブに実装されています。 ドキュメント生成時に検索用のインデックスファイルをJSONで作り、検索時にそのJSONから単純な部分文字列検索をしているだけです。 今のところパフォーマンスは特に問題なさそうですし、検索対象も自然言語ではないので形態素解析やNgramなどを使わなくてもそこそこ実用できると考えています。

型推論(的なもの)

メソッドや関数に対してドキュメントを書き忘れてしまうと、APIは存在するのにドキュメント上には書かれないということが起きてしまいます。 そんなときにソースコードから分かる情報をもとにドキュメントを自動的に生成できれば、この問題をある程度防ぐことができます。

ESDocではメソッド名や引数名から自動的にドキュメントを生成することができます。 ですが、JavaScriptは動的型付け言語なので、引数や戻り値の型はソースコードには明示されていません。 そこで、簡易的な型推論(と呼ぶには粗末ですが)によって自動的に型をドキュメントに含めることができます。

これによって、少なくともドキュメントには漏れがないという網羅性を保証できます。

f:id:h13i32maru:20170729133332p:plain ドキュメントを全く書いてなくても f:id:h13i32maru:20170729133316p:plain コードから出来る限りドキュメントを作成する

ちなみにESDocで実装されている型推論はデフォルト引数やreturnから組み込み型(string, number, boolean, Array)を推論するという非常に簡易的なものです。 推論できなかった方は任意の型となります。

Plugin Architecture

ESDocでは早い時期からプラグインの仕組みを提供していました。プラグインの仕組みによってドキュメント生成の過程に外から介入し、生成されるドキュメントをカスタマイズすることができます。フックポイントとしては主に以下のタイミングに対応しています。詳細はこちらを参照してください。

  • プラグイン読み込み時
  • 設定ファイル読み込み時
  • ソースコード読み込み時
  • ソースコードのパース時
  • AST読み込み時
  • DocComment読み込み時
  • ドキュメント生成時

一方、ESDoc自身はこのプラグインの仕組みは使っておらず、モノリシックなコードとして実装されていました。しかしこれでは新しい機能を追加していくのが徐々に大変になってきました。そこで、ESDoc v1.0からはESDoc自身もこのプラグインの仕組みを使い機能を提供するようにしました。これにより、およそ20個ほどのプラグインに機能が切り出されました。プラグインはesdoc/esdoc-pluginsにホストされています。

f:id:h13i32maru:20170729151748p:plain:w300

Plugin Architectureになったことにより、ざまざまなメリットが得られました。

  • 機能追加を行ってもコードの肥大化を防げる
  • 実験的な機能も気軽に提供できる
  • ESDoc自身がプラグインの仕組みに依存しているので、プラグインの仕組みを改良するモチベーションを得られる
  • サードパーティのプラグインを作るための生きたサンプルコードになる

逆にデメリットとしては

  • どこで何が行われているのか把握しづらくなった
  • ESDocを使う人にとっては手間が増えた

特に2つ目のデメリットは影響範囲が広いと思ったので、標準的に使われるプラグインをまとめたesdoc-standard-pluginを提供することで解決しています。

言語拡張(proposal, flow, typescript)

ESDocはES2015以降を対象にしています。しかしJavaScriptの世界にはまだ検討中の機能であったり、altJSと呼ばれるJSにトランスパイルされる言語があります。 そこでESDocではプラグインを使って、これらに対応しています。

  • esdoc-ecmascript-proposal-plugin
    • ECMASCript Proposalに対応するためのプラグインです
    • 内部的にはbabylon(ESDocが使用しているESパーサ)のオプションを変更してコードをパースするようにしています
  • esdoc-flow-type-plugin
    • Flowに対応するためのプラグインです
    • 内部的にはbabylonのオプションを変更してコードをパースするようにしています
    • また型アノテーションからドキュメントを生成するようにもなっています
    • 僕がFlowを使っていないということもあり、このプラグインはPoCな状態です
  • esdoc-typescript-plugin
    • TypeScriptに対応するためのプラグインです
    • 内部的にはTSCを使ってJSに変換してからESDocに渡すようにしています
    • また型アノテーションからドキュメントを生成するようにもなっています
    • 僕がTypeScriptを使っていないということもあり、このプラグインはPoCな状態です
    • ※ babylon7ではTSをパースできるようになるので、TSCから乗り換えるかも?

ホスティング

ESDoc自体の機能ではないのですが、ESDocのホスティングサービスをhttps://doc.esdoc.orgで提供しています。GitHubのURLを入力すれば、そこからESDocの設定ファイルを読み取りドキュメントを生成してホスティング上で見れるようになります*2

f:id:h13i32maru:20170729151807p:plain:w300

ホスティングサービスを提供しているのは以下の理由からです。

  • 気軽にドキュメントを公開できるようにするため
  • 同じ場所で同じようにドキュメントを見られるようにするため
  • ドキュメントを検索することで、JavaScriptのパッケージ見つけられるようにするため

しかし、僕があまりサーバサイドに強くないことや時間を避けていないせいで中途半端な状態になってしまっています。具体的には以下の点が微妙な状態です。

  • GitHubとの連携がイマイチ
    • OAuth連携していないので、任意のリポジトリのドキュメントも作れる(特に害はないが微妙)
    • WebHookに対応していない(ドキュメントを更新するためのAPIは提供している)
  • サンドボックス内でのドキュメント生成になっていない
    • これにより、任意のプラグインの使用を禁止せざるをえない(権限管理されているとはいえ怖い)
  • Elasticsearchが落ちる
    • メモリが足らなくてちょいちょい落ちる(さくらのVPSにもっとお金を積めば解決しそう)

というわけで、もしホスティングサービスの改良・メンテに興味がある人がいればh13i32maru at gmail.comまでご連絡ください。


という感じでESDocでは色々な機能を提供しています。

これらの機能を実装していく中で、ドキュメントに求められる要素について以下のようなものが必要だと思うようになりました。

要素 具体的な内容
導入 ソフトウェアのインストール方法や環境構築の方法
操作 ソフトウェアの設定方法やコマンドライン・GUIなどの使い方
参照 APIの使い方やその説明(所謂APIリファレンス)
事例 使い方のサンプルやREPL
履歴 ソフトウェアやドキュメントの更新履歴

参照についてはソースコードからAPIリファレンスを作成し、それ以外の要素についてはマニュアル機能でカバーできるようになっています。

そして、ドキュメントに求める性質は以下の様なものがあると考えるようになりました。

性質 性質を満たすためにESDocが提供している機能
継続性 良いルック&フィール、ドキュメントのカバレッジ
網羅性 簡単な型推測によるドキュメントの自動生成
検索性 組み込み検索、ホスティングの全文検索
関連性 クラス間の継承関係、ソースコードやテストコードの統合
正確性 ドキュメントのlint

このあたりについての詳細は以下を御覧ください

今後の機能拡張はこれらの性質をより広く・深くカバーするようなものを考えて行く予定です。 例えばGitと連携してメソッドの中が大きく変更されているのにドキュメントが変更されていない場合に警告を表示したり(正確性)、マニュアル中のクラス名やメソッド名とAPIリファレンスを相互に関連付けられるようにする(関連性)などを考えています。なのですが、v1.0をリリースしたのでESDocはしばらくお休みして、もう一つ個人で開発しているソフトウェア(Jasper)の方にしばらく時間を使って行こうと思っています。

ESDocに興味を持たれた方は是非使ってみてください。REPLのサイトもhttps://try.esdoc.orgで提供しています。

今後フレームワークやテストと同じくらいドキュメントについても話題になると良いなと思っています。

以上ESDocの紹介でした。

*1:他の言語だとJavaDoc、YARD、pydocなどがあります。JavaScript向けだとJSDocやdocumentationjsなどもあります。

*2:似たサービスとして、https://inch-ci.org/もあります