この記事のポイント

  • finally構文不在のC++におけるRAII設計をレビューアーが読み取る技術を体系化
  • スコープ離脱保証の実務設計責務をレビュー支援で明文化可能にする
  • finally相当処理をRAII設計に統一変換し安全設計に導けるレビュー力を習得

そもそもfinallyとは何か

C++はfinally構文を持たないが、Java・C#・Pythonなどではfinally節で後始末を保証する構文が存在する。

try {
    // 本体処理
} finally {
    // 後始末
}
  • 正常系/例外系の両経路で必ず実行

C++ではRAII (Resource Acquisition Is Initialization)というスコープ離脱保証設計でこれを代替する。

レビューアーは「ここでfinally的保証責務をRAIIで安全化できるか?」を常に設計観点で読み取る。

なぜこれをレビューするのか

  • finally的責務保証が設計者によって毎回コーディング分岐化されやすい
  • 例外経路漏れが混入しやすい
  • finally的責務が冪等設計不備で副作用を起こす危険設計が頻発
  • RAII統一設計で責務分界をレビューで固定化支援できる

レビュー段階でRAII統一文化を作れるかが現場設計品質を大きく左右する。

レビューアー視点

  • このfinally相当処理はRAII化可能か?
  • 副作用位置をスコープ先頭/末尾に整理可能か?
  • 冪等保証・二重呼出抑止が設計統合されているか?
  • close/dispose責務が漏洩しないRAII化が行われているか?
  • 例外安全をスコープ構造だけで保障できるか?

開発者視点

  • スコープ侵入でリソース獲得
  • スコープ離脱で自動解放
  • リソース管理責務をコンストラクタ/デストラクタ内に統合
  • 明示呼出は原則排除(例外は明示的release提供型)

RAIIの基本構造例

基本RAII構造
class FileHandle {
public:
    FileHandle(const std::string& path) {
        file_ = fopen(path.c_str(), "w");
    }
    ~FileHandle() {
        if (file_) fclose(file_);
    }
private:
    FILE* file_;
};

void save() {
    FileHandle f("data.txt");
    // 処理
}
  • 例外経路でも必ずfclose実行保証

finally構造での問題点比較

finally構造模倣
FILE* file = fopen("data.txt", "w");
try {
    // 処理
} catch (...) {
    fclose(file);
    throw;
}
fclose(file);
  • 例外経路分岐を都度記述 → 読解困難

レビューアーはRAII適用余地の可読性負債をレビュー指摘可能であるべき。

レビュー観点

  • スコープ侵入での即時リソース獲得統合が行われているか
  • 破棄責務が明確にデストラクタ内に集約されているか
  • 例外安全保証が自動構造で保証されているか
  • 二重開放防止の冪等設計が組み込まれているか
  • 明示close責務が混入していないか

良くない実装例: ケース1(明示close多発)

明示破棄型
FILE* file = fopen("data.txt", "w");
if (!file) return;
try {
    // 処理
} catch (...) {
    fclose(file);
    throw;
}
fclose(file);
@Reviewer
finally責務が手動記述されています。RAII統合可能です。自動化統一してください。

改善例

改善例(RAII統一)
FileHandle f("data.txt");

良くない実装例: ケース2(二重破棄)

二重破棄危険型
void closeFile(FILE* f) {
    if (f) fclose(f);
}

void save() {
    FILE* f = fopen("data.txt", "w");
    closeFile(f);
    closeFile(f);
@Reviewer
二重close保護が実装依存です。RAII統合し構造的保証を優先してください。
}

改善例

改善例(RAII冪等保証)
~FileHandle() { if (file_) fclose(file_); }

良くない実装例: ケース3(例外経路漏れ)

例外経路抜け型
FILE* file = fopen("data.txt", "w");
write(file);
fclose(file);
@Reviewer
write内例外発生時にfcloseが漏洩します。RAII統合が必要です。

改善例

改善例(例外安全保証)
FileHandle f("data.txt");
write(f);

PlantUML:RAIIスコープ保証責務図

UML Diagram

高頻度RAII適用候補一覧

リソース種別 代表例
ファイル FILE*, fstream
メモリ new/delete → unique_ptr
ミューテックス std::lock_guard
データベース接続 Connectionオブジェクト
ソケット Socketハンドル

レビューアーはRAII化対象自動判別能力を日常的に身につける。

スコープ離脱保証失敗パターン分類

失敗分類 典型設計誤り
例外漏洩 catch書き忘れ
二重破棄 冪等設計不在
早期return漏洩 複数return経路設計
goto分岐破壊 後始末飛ばし事故

レビューアーは「ここはスコープ離脱保証になっているか?」を毎回レビュー確認する。

ロギング統合例(破棄失敗検出)

破棄失敗通知
~FileHandle() {
    if (fclose(file_) != 0) {
        logger.error("File close failed");
    }
}
  • RAII内破棄失敗も通知統合文化形成

観点チェックリスト

まとめ

レビューアーがfinally責務RAII化レビューで常に問うべきは
「この後始末はスコープ離脱保証になっているか?」
です。

  • finally排除文化 → スコープ構造活用文化
  • 副作用前後整理 → 獲得即破棄保証文化
  • 冪等設計 → 二重破棄安全文化
  • ログ統合 → 破棄失敗通知文化

レビュー現場では
「後始末はRAII文化で統一しましょう」
をレビュー文化で徹底できる現場は設計事故が激減します。