株式会社クリアコード > ククログ

ククログ


リファレンスマニュアルの記述方法

Rubyではライブラリのリファレンスマニュアル作成のドキュメントツールとしてRDocが標準となっています。これは、古くからあるという理由とRuby本体に標準添付されているという理由からです。しかし、RDocはそれほど活発に開発されていないため、最近のドキュメントツールとして機能不足と言わざるをえません*1。どのような機能が足りないのかについては別の機会にします。

数年前からYARD(Yey! A Ruby Documentation Tool)というドキュメントツールが開発されています。YARDはRDocとの互換性を残したまま機能を拡張しているため、RDocからの移行も容易です。実は、YARDは第2回フクオカRuby大賞(SSLの証明書の期限が切れているので警告がでます)に「Improving Documentation in the Ruby Community」というタイトルで応募していたので知っている人もいるのではないでしょうか*2

そこで、ドキュメントツールとしてRDocではなくYARDを使う方法を紹介します。と、いきたいところですが、その前にプログラミング言語に依存しないレベルでライブラリのリファレンスマニュアルの記述方法について振り返っておきます。

記述方法

ライブラリのリファレンスマニュアルを記述する方法には大きく分けて以下の2つの方法があります。

  1. ソースコードの中にドキュメントも埋め込む
  2. ソースコードとは別にドキュメントを記述する

ソースコードに埋め込む方式でも、インターフェイスを記述しているファイル(CやC++ならヘッダーファイル)に埋め込む方式や実装を記述しているファイルに埋め込む方式などいくつか違いがあります。また、コメントとしてドキュメントを記述する方式の他にも、言語が提供するdocstringという仕組みを利用する場合もあります*3。これらは採用しているドキュメントツールや言語などに依存することなので、ここでは深く考えないことにします。

ソースコードに埋め込む方式を採用しているドキュメントツールはDoxygenJavadocGTK-Docなどです。RDocやYARDもこの方式です。この方式の方がソースコードと分離する方式よりもメジャーです。分離方式ではなくこの方式を採用しているドキュメントツール・プロジェクトの方が多いです。

ソースコードとは別に記述する方式を採用しているドキュメントツールはSphinxBitClustTexinfo、RDtool*4などです。Sphinxを利用しているプロジェクトはPythonなどです。BitClustを利用しているプロジェクトはRubyの日本語リファレンスマニュアルを整備しているるりまプロジェクトです。Texinfoを利用しているプロジェクトはGaucheなどです。RDtoolを利用しているプロジェクトはRuby-GNOME2プロジェクトなどです。

分離方式は、ドキュメント量が大きいプロジェクトや、より厳密に公開したいAPIだけを選別したいプロジェクトのリファレンスマニュアルを作成する場合に使われることが多いのかもしれません。例えば、プログラミング言語を開発しているプロジェクトにはそういうニーズが多いのかもしれません。また、動的に生成するコードのドキュメントはソースコード中に対応するドキュメントを埋め込めません*5。この場合は埋め込み方式は使えないため、埋め込み方式でなんとかやりくりするかこの方式を利用します*6。これについては後述します。

記述方法によるメリット・デメリット

ソースコードに埋め込む方式と分離する方式ではそれぞれにメリットとデメリットがあります。これらについて検討して自分のプロジェクトにあった方式を選びましょう。「どちらでもいいな」と思ったらよりメジャーな埋め込み方式を選ぶとよいでしょう。

埋め込み方式のメリット・デメリット

ソースコードに埋め込む方式のメリット・デメリットは以下の通りです。

メリット
  • ソースコードの近くにドキュメントがあるので、ソースコードだけ変更してドキュメントの変更を忘れるということを防ぎやすい*7
  • ドキュメントを書いていなくてもドキュメント対象(メソッドなど)を自動的に収集してくれるため、ドキュメントが不足していても多少は役に立つことがある。
デメリット
  • ソースコードファイル中にコードよりもドキュメントの方が多くなってしまってコードが読みにくくなる(と感じる場合がある)*8
  • 自動でドキュメント対象が収集されるため、意図していないAPIがドキュメント化されてしまうことがある。
  • プログラミングとドキュメント作成を分業しづらい。
  • ドキュメントツールだけの仕組みでは複数の(自然)言語用のドキュメントを作成できない*9

埋め込み方式では網羅的にAPIのリファレンスマニュアルを整備しやすくなります。よって、すでにソースコード中にドキュメントを記述するスタイルの場合や特にこだわりのない場合はこの方式を採用するとよいでしょう。

ただし、同じ方法で英語と日本語など複数の言語向けのリファレンスマニュアルを作成することはやめた方がよいです。この方式で複数の言語をサポートする場合はドキュメント中に「言語タグ」のようなものを仕込んで、対応する言語のドキュメントをすべてソースコード中に記述することになります。例えば以下のようになります。

1
2
3
4
5
# @en logs message on debug mode.
# @ja デバッグモードのときだけmessageを出力する。
def debug(message)
  puts message if $DEBUG
end

しかし、このやり方にはいくつも問題があります。まず、このやり方に対応したドキュメントツールがありません。また、あったとしても、メリットの1つである「ソースコードとドキュメントの不整合を防ぎやすくなる」を実現できなくなります。これは、ソースコードを変更する人がすべての言語のドキュメントを書けるわけではないからです。例えば、GNOMEは174の言語で利用できます*10が、GNOMEの関係者全員がすべての言語を読み書きできるわけではありません。GNOMEは特に多言語サポートが進んでいるプロジェクトですが、これほどでなくても、対応する言語が3言語以上になったらソースコードを書きながらドキュメントも整備することは無理でしょう。

なお、より現実的に複数の言語に対応する方法については別の機会に紹介します。

ドキュメント分離方式のメリット・デメリット

ソースコードとドキュメントを分ける方式のメリット・デメリットは以下の通りです。

メリット
  • 公開したいAPIだけを選別して公開しやすい。
  • 開発とは別のペースで進めやすい。
  • 複数の(自然)言語をサポートしやすい*11
デメリット
  • ソースコードの更新に追従するために変更分を確認するツールが必要になる。
  • ドキュメント化するAPIを収集するツールが必要になる。

埋め込み方式のドキュメントツールにはAPI収集機能が確実についています。それと同じようなAPI収集機能を用意できるのならば、小さなプロジェクトでも分離方式を採用できます。Ruby-GNOME2プロジェクトはAPIを収集するツールを作ってこの方式を採用しています。

プロジェクトに関わる人数が多くなってきたり、複数の言語に対応したい場合はこの方式のメリットが大きくなるかもしれません。そうでない場合は埋め込み方式で十分でしょう。

まとめ

ドキュメントツールとしてRDocではなくYARDを使う方法と、複数の言語に対応したリファレンスマニュアルの作成方法を書くつもりだったのですが、その予備知識としてリファレンスマニュアルの記述方法に書いたら長くなってしまったのでそれだけで一区切りとしました。

読みやすく利用しやすいリファレンスマニュアルを作成するためにも、使いやすく書きやすいドキュメントツールを採用したいですね。

*1 Ruby 1.8に標準添付されていた頃のTest::Unitみたいですね。

*2 受賞はしていません。RubyやRuby周辺をよくするツールが評価される機会がもっと増えるといいですね。

*3 Lisp系の言語やPythonなど

*4 =beginと=endを使うことにより埋め込み方式でも利用可能です。Yuguiさん、ありがとうございます!ただ、メソッドを抽出する機能がないので他の埋め込み方式よりは不便です。

*5 最新のYARDではこのケースにも対応できる仕組みを提供しています。

*6 RubyやLispでevalしたりCやLispでマクロを使う場合など。

*7 確実に防げるわけではないことに注意。ソースコードとドキュメントが違うことを言っていて苦労した覚えはありませんか?

*8 ドキュメントの中にコードがある状態。

*9 少なくとも現実的ではない

*10 2011/05/05現在。

*11 ただし、言語毎にファイルなどを分けている場合に限る。Gaucheは1ファイル中に英語と日本語を書いているためそれ以上の言語のサポートは難しい。

2011-05-05

«前の記事: milter managerとは? 最新記事 次の記事: RDocとYARDの比較»
タグ:
年・日ごとに見る
2008|05|06|07|08|09|10|11|12|
2009|01|02|03|04|05|06|07|08|09|10|11|12|
2010|01|02|03|04|05|06|07|08|09|10|11|12|
2011|01|02|03|04|05|06|07|08|09|10|11|12|
2012|01|02|03|04|05|06|07|08|09|10|11|12|
2013|01|02|03|04|05|06|07|08|09|10|11|12|
2014|01|02|03|04|05|06|07|08|09|10|11|12|
2015|01|02|03|04|05|06|07|08|09|10|11|12|
2016|01|02|03|04|05|06|07|08|09|10|11|12|
2017|01|02|03|04|05|06|07|08|09|10|11|12|
2018|01|02|03|04|05|06|07|08|09|10|11|12|
2019|01|02|03|04|05|06|