電八開発倶楽部 ― Doxygenコメント


コメントの義務

他のコメント同様doxygenコメントも義務ではありません。コメントを付けようと思うとき、doxygenコメントにすることも義務ではありません。普通のコメントが付いていれば誰かがdoxygen形式に直します。たぶん。

ただし、コメントを付けるときにDoxygenコメントに配慮することは義務です。doxygenコメントは以下のコメント書式で始まりますので、ドキュメントに出力される必要の無いコメントはこのコメント書式を避けてください。

/**
/*!
//!
///


Doxygenコメントの書き方

以下では、doxygenコメントの電八ソースにおけるルールを示します。つまり、doxygen自体の使い方は主眼ではないです。より良いルールに改訂するためにご意見をお待ちしています。

doxygenは割とメジャーなツールなので、使い方自体はウェブ上に大量の参考になるページがあります。使われたことのない特殊なコマンドが使いたくなったら、その前に相談した方が良いかもしれません。

参考リンク

(先頭へ)

概要

大体、ソースにあるコメントを真似すれば大丈夫だと思います。無理に細かい機能を使う必要はありません。コメントは大事だけど、コードの方がもっと大事です。 以下の点だけはコメントを見ても気づきにくいので、特に記します。

コメントを一見しても判らない注意点

(先頭へ)

全般

全般のコマンドに関して説明します。ファイル、クラス、関数などの形式については後述します。

コマンド

@で始まる語はdoxygenへのコマンドです。\でも良いのですが、@で統一します。もともと、doxygenはQt由来の\が標準のようですが、@の方が見易いと思います。@はJAVADOC由来の形式の様です。

コメント形式

Qt形式を使います。

/*! ~ */
//!
/*!< ~ */
//!<

箇条書き

@arg @li - (インデントした行頭ハイフン) は全て番号無しリストとして出力されます。-# とすると順序付きリストになります。コマンド一つでリストの1アイテムです。改行してもリスト1アイテムです。

引数のリストとして@arg、文中の箇条書きとして - が推奨です。

- だけはインデントの深さを変えて使うことでネストしたリストを表現出来ます。

リストの終了は(インデントを合わせて) . だけの行を置きます。リストを終了し、それまでのパラグラフを継続します。ファイルコメント参照。

段落(パラグラフ)

@par で段落開始します。パラグラフタイトルを引数に取ります。タイトルがない場合はコマンドのみで改行してください。ブロックではないコマンドに空行を入れるとセクションが終了してしまうので、これを使います。

注意(Attention)と覚え書き(Note)と警告(Warning)

これらは見出しが各々異なるだけのパラグラフコマンドです。言葉の意味の上でもあまり違いがないのですが、以下のような使い分けをしましょう。

@attention 注意。現在の仕様で、使用時に他の説明から判断できない注意点を書きます。詳細説明や引数説明に書く様な内容ではあるけれど分量が多い場合や、特筆したい内容を書きます。
@warning 警告。開発者向けに動作仕様からは判らない重要な注意事項があれば書きます。例えば、動作を変更するときに同時に変更しなければならないものが他にある場合など。
@note 覚え書き。開発中に参照するためのメモ。たとえば、検討はしたが不採用の実装案、参照した規格文書の転記など。

参照(see also)

@sa 参照すべき箇所を列挙します。文中にも使えます。@see でも同じです。

コードブロック

@code この間のテキストはコマンドが全て無効になり、テキストがそのまま出力されます。コードサンプルを書きたいときに使います。@verbatim~@endverbatimと同じですが、こちらだとリンクが張られます。 @endcode

生テキスト

@verbatim この間のテキストはコマンドが全て無効になり、テキストがそのまま出力されます。サンプルコードを書くときは@code~@endcodeを使いましょう。 @endverbatim

バージョン

@version バージョン文字列。使用方法検討中。

時期

@since 関数などが何時から存在するか。使用方法検討中。

関連

@relates 関連する事項。使用検討中。

オーバーロード

@overload オーバーロード関数の関数コメントに付けます。ドキュメント出力にオーバーロードがあることが表示されます。

例外

@exception 送出する例外のリスト。

バグ

@bug 使用検討中。バグリストとして一覧が出力されますので、@dateの代りに使って履歴として使う手もあります。また、@dateは複数列べて書くと結合されて一つのパラグラフになりますが、@bugはパラグラフ結合されないという違いがあります。

内部記述

@internal これ以降コメントブロックの最後までを内部用としてマークします。doxygenの出力時にオプションによって、この内部用としてマークされた部分を出力に含めるかどうかを制御出来ます。内部用/外部公開用のドキュメントを作ることができるわけですが、電八ソースではそういう区別は無いので使用していません。そんなことには関係なくモジュール内部用関数のマークとして使うという手もありますが。

説明コピー

@copydoc 指定したリンクオブジェクトの説明をその場所にコピーします。コピーします。全く同じ説明を何度も書かなくて済みます。

(先頭へ)

ファイルコメント

ファイルの先頭に書きます。ファイルコメントだけ意図的に整形がちょっと違います。

/*! @file  ファイル名。そのままファイル名。実はファイル名は書かなくても良いんですが、識別子と違ってファイル名はわざわざ書かないとファイル内には現れないので、書きましょう。
    @brief 要約説明。一覧で表示され、詳細の見出しになるので、名詞が良いです。「XXXクラスヘッダ」とか「XXクラス実装ファイル」とか簡潔に。

    ファイルについて詳しいコメントの必要があれば書いてください。
    前後には空行が必要です。@briefも只のパラグラフなので、複数行書けるからです。
    @descriptionというコマンドもがありますが、簡潔に空行とします。
    ソース整形上改行を入れて折り返しても良いですけど、途中に空行が入ると終了してしまいます。
    '\n'とか'<BR>'で強制改行できますが、文章上の意味のない改行は止めましょう。代りに次のようなコマンドを使いましょう。
    @par ここに何か書くとパラグラフにタイトルが付きます。無ければ省略すればいいです。
         ここはパラグラフ本文です。インデントは必須ではありません。
    @par
    タイトル無しならこれでいいかも。
    - で箇条書きが出来ます。
    - ネストできます。
        - インデント数を認識しているので、タブ幅4でインデントしてください。
        - リスト終了はインデントを揃えて.のみの行を書きます↓
        .
    - 空行だと詳細説明セクションが終了します。

    @attention や
    @note や
    @sa があればここに書きます。

    @author 作成者の名前を書きます。書かなくても良いです。@dateのところにパッチ作成者名を書くかも知れないし、パッチの作成者として判るので。
    @date No.68881 オレオレ 変更内容。
          変更履歴を書きます。日付の代りにパッチ番号を使用します。
          - 変更内容が何も書かれていなければ新規作成した、ということです。でも、XX対応で追加とか書くことはあります。
          - パッチ番号は無ければパッチ統合時に入れます。プレースホルダとして先にMLへメールを投げて番号取ってから自分で入れるという手もありです。
          - 日付や変更者名は義務ではないです。パッチから判ることですし。
    @date No.68882
          ファイルとしての変更履歴にクラスのメンバーの変更などをいちいち書くことはしません。それらのコメントに書けば充分でしょう。ファイル全体に関わるもの、クラス自体などファイル直下の新規作成や削除は書いた方が良いでしょう。
          履歴専用のフォーマットはされないです。おまけに@dateは複数有る場合は一つのパラグラフに結合されますので、桁揃えなどは自分でやりましょう。例えばこんな感じです。
 */
(先頭へ)

関数コメント

関数定義の前に書きます。

/*!
 @brief 説明要約。ファイルコメント参照。

        関数の詳しい説明。ファイルコメント参照。

 @attention 概要参照。
 @note 概要参照。
 @sa 概要参照。関連する型の定義や、関数など。

 @param [in]     仮引数名      引数の説明。\n
                 @paramは引数を採り、フォーマットされるので、引数名と説明を : で区切ったりしてはいけません。
                 ソース上の整形として、改行・空白(半角スペースとタブ)文字による桁揃えはして構いません。でも、あんまり長いようなら、関数の詳細説明に書いた方が良い内容かもしれませんよ。
 @param [out]    仮引数名2     引数の型名を書く必要はありません。これが表示される位置には関数の宣言もあるからです。
                改行したときにあまり深くインデントしなくても良いです。
 @param [in,out] 仮引数名その3 引数のタイプは[in][out][in,out]です。ポインタ及び参照の引数を内部で変更している場合は、その変更が呼び出し側から無意味であっても、outも付けるべきです。
 @param [in]     仮引数名4    引数の値の範囲が限られている場合は@argで列挙します。数が多い場合は値の定義を@saで参照させればよいでしょう。
                 @arg 引数の取り得る値1 : その説明。@argは実際にはただのリストなので空白文字でで勝手に桁揃えされたりはしません。区切りとしてコロンを入れておきます。
                 @arg 引数の値2       : その説明。つまり、各々の桁を揃えたければこの様にスペースを挿入する必要があります。

 @return 戻り値の説明。無いときはなるべく「なし」と書くべきです。BOOL値やエラーコードなど値が何種類か決まっている場合には@retvalで列挙します。
         引数と同じく型は必要有りませんが、型がPODでないときにオブジェクト自体(値、一時コピー)を返すのか、参照(ポインタ)を返すのかを注意を喚起する意味で書いた方が良いと思います。
 @retval 戻り値の例  とその意味。種類の数だけ列挙します。
 @retval 戻り値の例2 @retvalは引数を取り、[値] と[意味]の間の空白で桁揃えされます。空白文字は複数連続しても良いのでソースコメント上で揃えたい場合はご自由に。
 @retval その他     数が多い場合にはこの様に、主な物と「その他」で良いです。

 @author ファイルコメント参照。
 @date ファイルコメント参照。
 */
(先頭へ)

クラス、構造体、列挙型コメント

定義の前に書きます。ヘッダーファイルはなるべく簡潔にしたいので、クラス、構造体のメンバで別に実装があるメンバーは実装側に書きます。

/*!
 @brief ファイルコメント参照。

        ファイルコメント参照。

 @attention 概要参照。
 @note 概要参照。
 @sa 概要参照。参照すべき関連項目があれば書きます。

 @author ファイルコメント参照。
 @date ファイルコメント参照。
 */
class foo : public bar
{
    inline void func();   // 宣言だけなのでdoxygenコメントにしないこと
    //! 書いても良いけど、実装部分の@briefの内容に合わせること。
    void func2();

    int 変数宣言1;   //!< この変数の説明は一行だけ @date パッチ番号 @date パッチ番号 変更履歴もちゃんと書けます。
    int 変数宣言2;   /*!< この変数の説明は複数行書きたいとき、
                          こんな感じで複数行書けます。 @date パッチ番号 */

    /*! 前に書くことも出来ます。
        @date パッチ番号    */
    int 変数宣言;

    /*! 列挙型も各メンバーに説明が書けますよ。
        @date パッチ番号    */
    enum foo_values
    {
        EFooFirstVal,  //!< こうやって、各メンバの説明を書けます。
        EFooLastVal    //!< こうやって、各メンバの説明を書けます。
    }

    /*!
     @brief 列挙型や変数の詳細なコメント

            列挙型や変数でも必要ならばクラスなどと同じように詳しく書いても良いのですよ。

     @attention 概要参照。
     @note 概要参照。
     @sa 概要参照。
     @date パッチ番号
     */
    enum foo_values
    {
        EFooFirstVal,   //!< こうやって、各メンバの説明を書けます。
        EFooLastVal     //!< こうやって、各メンバの説明を書けます。
    };
};

/*!
 @brief インライン関数

        定義がある場合はヘッダーファイル内でもコメントを書きます。詳細は関数コメント参照。
 */
inline void foo::func()
{
    // ちょっと複雑なインライン関数の実装は
    // クラス定義内からは追い出した方が簡潔
    // になる。
    // でも使用箇所と翻訳単位が同じである必
    // 要があるからクラス定義の後ろ、ヘッダ
    // ファイルの末尾に書く。.inlファイルに
    // 別けて、ヘッダファイルで#includeする
    // という手もあり。
}
(先頭へ)

その他

クラスのメンバーを参照してください。