C++17 例外型依存API設計妥当性レビュー|例外型を契約に用いる設計の是非をレビューアーが読み解く技術
この記事のポイント
- 例外型依存API設計のレビュー観点を体系整理
- 例外型のAPI契約活用の妥当性をレビューアーが読み取る技術を習得
- API設計における型責務整理と利用者負荷をレビューで整理提案可能にする
そもそも例外型依存API設計とは何か
C++ではAPIの契約として例外型を事実上API仕様に含める文化が存在する。
void saveUser(const User& u);
// 例外: std::invalid_argument, DatabaseUnavailable- 正常系は戻り値不要
- 異常系は例外型がAPI契約を担う
レビューアーは「このAPIの異常系契約は例外型に依存して整理されるべきか?」を読み解く責務を持つ。
なぜこれをレビューするのか
- 例外型契約が設計責務整理に寄与もすれば、逆に設計負債も生む
- 利用者がAPI呼出時に「捕捉すべき例外型」を認知できる構成か確認が必要
- 契約資料に例外型依存契約が明文化されず属人文化化しやすい
- レビュー段階で例外型契約妥当性を支援整理する必要がある
レビューアー視点
- 例外型契約が設計責務整理に適切活用されているか?
- 利用者が契約違反系/障害通知系を型から即時判別可能か?
- 例外型濫用で型爆発を招いていないか?
- API利用時にcatch網羅性が設計文化として定着しているか?
- 例外型契約が保守拡張性に耐える構造になっているか?
開発者視点
- 契約違反 vs 通信障害 vs 外部依存失敗で例外型を役割整理
- 例外型は「層移動責務表現」+「障害粒度分類」に活用
- 標準例外 vs カスタム例外を契約層毎に整理
- 利用者向けcatchサンプル提示文化を設計資料に明文化
良い実装例
例1:層責務別例外型整理
void registerUser(const User& u);
// throws:
// - std::invalid_argument // 入力不正
// - DatabaseUnavailable // DB障害
// - ExternalServiceFailure // 外部API失敗- 契約違反 vs 障害通知 vs 外部依存系 → 型分離整理
例2:契約型をドキュメント化
/**
* API契約:
* @throws std::invalid_argument if user.id <= 0
* @throws DatabaseUnavailable if DB unreachable
*/
void registerUser(const User& u);- 契約型の利用者向け明文化
レビュー観点
- 例外型の責務分類が整理されているか
- 契約資料に例外型契約が明文化されているか
- 利用者がcatch網羅文化を持てる構成か
- 標準例外/カスタム例外の役割分離が明確か
- 型爆発が抑制設計されているか
良くない実装例: ケース1(契約型無明文化)
void save();
@Reviewer例外型契約がAPI設計資料に明文化されていません。利用者は捕捉例外型不明になります。契約整理してください。
改善例
// throws: DatabaseUnavailable, std::invalid_argument
void save();良くない実装例: ケース2(型濫用爆発)
class DBError : public std::exception {};
class CacheError : public std::exception {};
class LoggerError : public std::exception {};
@Reviewer例外型が責務分界せず部品粒度で濫用されています。障害層別型整理してください。
改善例
class StorageSubsystemFailure : public std::exception {};良くない実装例: ケース3(利用者責務不明確)
try { api.save(); } catch (...) { log(); }
@Reviewer利用者catch網羅責務が崩壊しています。catch対象型明示文化を徹底してください。
改善例
try { api.save(); }
catch (const std::invalid_argument& e) { log(); }
catch (const DatabaseUnavailable& e) { alert(); }PlantUML:例外型契約責務整理図
例外型整理テンプレート表
| 役割分類 | 推奨例外型 |
|---|---|
| 入力契約違反 | std::invalid_argument |
| 外部API失敗 | ExternalServiceFailure |
| DB障害 | DatabaseUnavailable |
| 通信系断絶 | NetworkTimeout |
レビューアーは層粒度設計と型分類整理を同時思考できる技術力を養成する。
例外型契約ドキュメント例
/**
* API契約:
* - 正常時: 完了
* - 異常時:
* - std::invalid_argument: 入力条件違反
* - DatabaseUnavailable: DB障害
* - ExternalServiceFailure: 外部依存障害
*/
void registerUser(const User& u);- レビューで必須確認対象
catch網羅支援文化整理
| 支援技法 | 実施内容 |
|---|---|
| ドキュメント契約明文化 | throws宣言記述 |
| サンプルコード提示 | 推奨catch例記述 |
| ユニットテスト網羅 | 発生例外型実証記述 |
| ライブラリ契約統一 | フレームワーク例外型統一文化 |
レビューアーは利用者が自然にcatch網羅設計できる文化支援が重要。
ロギング統合例
try {
service.registerUser(user);
} catch (const std::invalid_argument& e) {
logger.warn("Validation failed: {}", e.what());
} catch (const DatabaseUnavailable& e) {
logger.error("DB unavailable: {}", e.what());
}- 障害分類文化もcatch系統で連動整理
典型レビュー質問集
| 質問例 | 意図 |
|---|---|
| このAPI契約で投げうる例外型は整理明文化されていますか? | 契約可視化確認 |
| 利用者はcatch網羅文化を習得可能な構成ですか? | 利用者支援確認 |
| 例外型爆発リスクは抑制整理できていますか? | 型文化整理 |
| 契約違反 vs 障害通知が型分離整理されていますか? | 層責務整理確認 |
レビューアーは例外型契約整理レビュー文化を現場標準に定着支援する。
観点チェックリスト
まとめ
レビューアーが例外型依存API設計レビューで常に問うべきは
「このAPI契約は誰が何をcatchすれば責務が果たせるか?」
です。
- 層粒度 → 例外型粒度整理文化
- 契約型 → throws明文化文化
- 利用者支援 → catch網羅文化
- 型統一文化 → 拡張耐性文化
レビュー現場では
「API契約は例外型粒度で固定化するレビュー文化」
を育成できる現場が設計品質を大幅に安定化させます。
