どーもー。くまちゃんです。
jackブログもできたし何か書いて残しておこうかな&アドベンドカレンダー出遅れたということで勝手にExtendするよ。26日目。
内容は他の人があまりやらないだろう「ドキュメントの自動生成」について書くよ。
はじめに
さて、あなたはコメントをちゃんと書く派ですか?(爆弾投下)
私は可能な限り書きたくない人です。めんどくさいもの。
クラスや関数、変数のみで伝えられればいいけどさすがに厳しいところがある。使えるのせいぜい数単語だし。だから関数にその関数の説明(クラスや関数名だけじゃわからない内容)をコメントで書く。あとは特殊な実装や悩んだところを注記するぐらい。
それで、なんでコメントの話をしたかというとドキュメントの存在意義に繋がってくるから。
コメントを書く意義は主に2つあると私は思っていて、(さっきも書いたけど)ひとつ目は「何をしているのかすばやく把握できるようにする」、ふたつ目は「コードで書けない意図を示す」というもの。
ひとつ目の意義についてなのだけれど、なんでそうするのかというと、プロジェクトへの参入コストを低くするため。このプロジェクトへ参入するというのは他人だけではなく、時間を置いた作者にもあてはまるよ。そのような人たちがプロジェクトを把握するのに、人から聞いたりコードを読み解いたりするのは効率が悪い。関数単位でまとめたコメントがあれば、その関数を探すというコストはかかるものの関数がどういうものかと調べるコストを減らせる。
その関数を探すというコストも減らすのがドキュメントなの。(すごい)
コメントのみでは、コード内に散らばっていて目的のものを探すのがめんどくさい。エディターの進化によってコメントを辿りやすくなっているけど、一覧から探すというのにはやっぱり不向き。
ということで、プロジェクトを把握するためのドキュメントにメリットがあることが伝わった(と信じたい)と思うけど、ドキュメントをわざわざ作成するのもめんどくさい。コードの更新ごとにドキュメントも...…というのは正直嫌だ。
それを解消するのがこの記事で紹介するドキュメント自動生成ツール。ドキュメント自動生成ツールはコードに書いたコメントからドキュメントを生成してくれる。つまり、コメントをちゃんと書いて更新しておけばいい感じにまとめてくれる。やったね。
ツールは使う言語によって別のツールが必要になる。私の記事で紹介するのは、使ったことのある「DocFX」「Doxygen」「RustDoc」の3つ。順番は使い慣れている順で特に意味はない。では、紹介していくよ。
DocFX
DocFXは .NET系の言語(C#・VB.net・F#など)で使えるドキュメント生成ツール。正確にはXMLコメントからドキュメントを生成するツールで、公式のリポジトリはここにあって詳細はこちらを参照してね。
実はUnityのドキュメントもオリジナルのテーマを使ったDocFX製。
急に出てきたXMLコメントというのは .NET系の言語で使えるクラスや関数などに対して使う特殊なXML形式のコメントのこと。具体的にクラスと関数にXMLコメントをつけるとこんな感じになる。
/// <summary>
/// データを受け渡し・送受信するためのインターフェース.
/// </summary>
/// <typeparam name="T">やり取りするデータの型名.</typeparam>
public interface IDataTransmitClient<T>
{
/// <summary>
/// データを受け取り・受信する.
/// </summary>
/// <param name="key">渡すときと共通のキーまたはURL.</param>
/// <returns>受け取ったデータ.</returns>
public T Get(string key);
}
クラスや関数の上に///とタグをつけたコメントを書くとXMLコメントになる。タグはここで書いたやつ以外にもいろいろあるけど詳細を知りたかったら公式ドキュメントを参照してね。タグがいろいろあってめんどくさいと思うかもしれないけどVisual Studioの補間が効くのでそうでもない。
ここで書いたサンプルコードは私が参加している侍蹴球のコードから取ってきたものなのだけれど、これをDocFXでドキュメントにするとこんな感じになる。
あとはこのような生成したページをいい感じに整理して静的ファイルを出力してくれる。あと、別でMarkdownの文章もページにすることもできて、Markdownでプロジェクト全体の説明、コメントでそれぞれの説明とするとわかりやすくなる。
Doxygen
DoxygenはC++、C、Java、Pythonとかいろいろな言語に使えるドキュメント生成ツール。決められた形式でコメントを書くとドキュメントを生成してくれるよ。公式のページはここ。
コメントの書き方は2種類あるけど簡単な紹介だから片方だけ紹介するね。
/**
* @brief 送信に関する情報を持つクラス.
*/
class SendInfo {
std::unique_ptr<Packet> send_data;
public:
/**
* @brief 送信情報のコンストラクタ.
* @param [in] main_channel 送るメインチャネル.
* @param [in] sub_channel 送るサブチャネル.
* @param [in] slot 送るタイムスロット.
* @param [in] data 送るデータ.
*/
SendInfo(int main_channel, int sub_channel, int slot,
const std::vector<std::complex<double>>& data)
: position(ChannelPosition(main_channel, sub_channel, slot)),
send_data(std::move(std::make_unique<Packet>(data))){};
}
DocFXと同じようにクラスや関数の上に決められた形式のタグ付きコメントを書くといい感じのドキュメントを生成してくれる。
このコードから生成したものは次のようになる。(一部機密保護のために黒塗り弁当になっているけれど。)
私としてはクラスなどの関係図がグラフとして出してくれるのが評価の高いポイント。
RustDoc
RustDocはその名の通りRust用のドキュメント自動生成ツール。標準でついてきてらくらく。チュートリアルは公式のRustBookで。
そしてコメントはMarkDownで書ける。すばらしい。
さっそく書いてみる。
/// シミュレーションを行う環境.
#[derive(Clone, Debug)]
pub struct Enviorment {
groups: Vec<Group>,
channel_count: u32,
max_time: u32,
min_time: u32,
}
impl Enviorment {
/// 環境を作製する.
///
/// Arg:
///
/// channel_count: この環境で使用できるチャネル数.
pub fn new(channel_count: u32) -> Self {
Self {
groups: Vec::new(),
channel_count,
max_time: 0,
min_time: u32::MAX,
}
}
}
これも構造体や関数の上にコメントを書く。Markdownで書けるから自由に書いて~という感じ。私の書き方は他のやつに影響されててほめられたものではないけど。
生成したものは次のようになる。
ライブラリであればlib.rsに\\!として全体の説明用のコメントをかけたり、ただのMarkdownファイルをhtml・js・cssに変換できたりする。
おわりに
3つのドキュメント自動生成ツールを紹介したけど、結局重要なのは初見に易しいコメントやドキュメントを維持することなのかなと思ったり。あと、CI/CDに組み込んで更新ごとに自動で生成するようにしてGithub Pagesが更新されるようになると精神的にリッチになったり。
では、すてきな開発ライフを。