私のコーディング規約 [C/C++版]

## コメントが少ない他人のコードを読むのは大変
昨日、ファイル・関数ヘッダない、コメントが少ないのコードを「解読」していることをTweetしたので、自分はどうしているかを書いておく。


<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">今日明日は久しぶりにリーマンサット の作業で、RSP-01 ソフトのドキュメント作成です。<br>メンバーが作ったコードを見ていますが、ファイル・関数ヘッダがないし、コメントも少ないので解読しなきゃならない（作り自体はちゃんとしてるからなんとかなりそう）</p>&mdash; SONODA Takehiko (@OzoraKobo) <a href="https://twitter.com/OzoraKobo/status/1348222677857628160?ref_src=twsrc%5Etfw">January 10, 2021</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

かつての仕事（受託開発）では、お客様のコーディング規約で決まっていることがあり、やらざるを得なかった。そして、自社開発やその他でも、ヘッダとコメントは書くように自分に課していた、今もそうしている。（テストプログラムのように自分しか見ないコードには書かないけどね。）

### ヘッダ・コメントを書く利点

* いつ頃、誰が書いたかわかる
* 関数ヘッダはAPIリファレンスとして使える
* 時間が経つと自分が書いたコードでも忘れるが、コメントがあれば思い出しやすくなる
* 他人が読む時の助けになる
* 処理のポイントをコメントにすることによって、整理される
* 変数の意味・目的がつかみやすくなる

## 例

自作のmbedのシリアル通信クラス(C++)のコードで一例を示す。

### ファイルヘッダ

```c++
/******************************************************************************
 * @file    SerialCom.cpp
 * @brief   SerialCom シリアル通信 クラス
 * @auther  SONODA Takehiko
 * @date    2018/09/29 新規作成
 * @par     
 * Copyright (c) 2018 SONODA Takehiko All rights reserved.
 ******************************************************************************/
```
* Doxygen対応
* これは初版だが、変更があれば日付と変更内容も記述する

### 関数ヘッダ
```c++
/******************************************************************************
 * @fn      SendBinData
 * @brief   シリアル通信 データ送信（バイナリ）
 * @param   pBuffer : 送信データバッファへのポインタ
 * @param   iSize   : 送信データサイズ
 * @return  受信終了動作結果
 *          - SERIAL_COM_SUCCESS     : 正常
 *          - SERIAL_COM_PARAM       : パラメータエラー
 * @sa
 * @detail  送信データバッファのデータを送信データサイズ分送信する
 *          バイナリデータの送信可能
 ******************************************************************************/
```
* 引数があれば、引数名と意味、必要に応じて値の範囲を記述
* 戻り値は、少なくとも内容を下記、必要に応じて値の範囲や意味を記述
* 戻り値がなければ、void
* @detailに簡単な概要を記述することもある
* @dateに変更履歴を記述することもある

### 変数のコメント
```c++
    int     _baud;               /* ボーレート */
    bool    _bEchoback;          /* エコーバック有無 */
    uint8_t *_pRecvBuffer;       /* 受信バッファへのポインタ */
    int     _iRecvLength;        /* 受信バッファ長 */
    int     _iRecvDataLength;    /* 受信データ長 */
    bool    _bRecvCompleted;     /* 受信完了フラグ */
    uint8_t _ucTerminationCode;  /* 終端コード */
```
* 変数の定義には必ずその変数を表す意味を記述する
* 関数の内部変数では、値に意味のある変数は記述するが、単純なテンポラリ変数には記述しないこともある

```c++
    // ワーク用変数
    _pRecvBuffer = pRecvBuffer;     /* 受信バッファへのポインタ */
    _iRecvLength = iRecvLength;     /* 受信バッファ長 */
    _iRecvDataLength = 0;           /* 受信データ長 */
    _bRecvCompleted = false;        /* 受信完了フラグ */
```
* 値を設定、初期化するときも記述する

### 処理ポイントのコメント
```c++
/******************************************************************************
 * @fn      RecvFunc
 * @brief   シリアル通信 受信割り込みハンドラ
 * @param   void
 * @return  void
 * @sa
 * @detail  受信割り込みコールバック関数から呼ぶこと
 *          受信データを受信データバッファに格納する
 *          受信データが終端コードなら受信完了にし、受信データが取得可能になる
 *          受信データバッファが一杯になったときも受信完了にする
 ******************************************************************************/
void SerialCom::RecvFunc()
{
    uint8_t     ch;     // 受信文字

    if (readable()) {     
        // 読み込み可能な文字あり
        // 受信文字取得
        ch = (uint8_t)_getc();
        if (_bEchoback) {
            // エコーバック有効
            // 受信文字を出力する
            _putc((int)ch);
        }
        if (!_bRecvCompleted) {
            // 受信完了状態なら読み飛ばす
            if (ch == _ucTerminationCode) {
                // 受信文字が終端コードなら受信完了
                _bRecvCompleted = true;
                _pRecvBuffer[_iRecvDataLength] = '\0';
            }
            else {
                // 受信文字≠終端コード
                // 受信バッファに受信文字を追加
                _pRecvBuffer[_iRecvDataLength++] = ch;
                if (_iRecvLength - 1 <= _iRecvDataLength) {
                    // 受信バッファサイズ - 1 ≦ 受信データ長
                    // 受信完了にする
                    _bRecvCompleted = true;
                    _pRecvBuffer[_iRecvDataLength] = '\0';
                }                
            }
        }
    }
}
```
* 条件文のブロックの先頭に、そのブロックに入る条件を記述
* 処理のまとまり毎に処理の内容を１行で記述
* 処理内容は、必要ならより詳しく書くこともある
※ご指摘によりバッファオーバーフローを引き起こすコードを修正しました。

ここに挙げたところだけでも押さえていただけると、読み手としてはかなり助かる。

仕事のコードではもっとちゃんと書いているのだが、公開できないので、その点はご了承いただきたい。