C++17 std::optionalによるnull回避レビュー|ヌル許容設計から責務を整理してレビューアーが読み解く技術
この記事のポイント
- std::optional導入のレビュー観点を体系整理
- ヌル許容設計をレビューアーがどう読み解き整理するかの実務技術を習得
- API契約粒度の責務整理をレビューで提案可能にする
そもそもstd::optionalとは何か
C++17で導入されたstd::optional<T>は「値の有無を型システムに乗せて表現する設計技術」である。
| 従来 | optional利用 |
|---|---|
| T* | optional |
| nullptr | std::nullopt |
| 存在保証曖昧 | 型で保証強化 |
レビューアーは「この戻り値はoptionalで設計すべき責務か?」を設計脈絡から読み解く力が必須になる。
なぜこれをレビューするのか
- nullptr許容設計が曖昧文化化する現場が多い
- 呼出側が存在確認漏洩事故を頻発させる
- 契約として「存在可能性あり」設計を型レベルで宣言できる武器になる
- レビュー段階で契約粒度整理を支援可能になる
レビューアー視点
- この関数は「値無し」を合法パスとして契約宣言しているか?
- 契約違反 vs 不在許容を整理できているか?
- 利用者が存在確認責務を持つ前提設計か?
- null許容ではなくoptional型で契約宣言されているか?
- 契約ドキュメントに粒度整理されているか?
開発者視点
- optionalは契約型:存在可能性設計宣言ツール
- null許容は極力排除(ポインタ利用は保持契約責務のみ)
- 例外設計と並列活用し役割分離
- 内部表現null許容でも公開APIはoptional統一
良い実装例
例1:検索APIのoptional化
検索API設計
std::optional<User> findUser(int userId) {
if (auto u = db.query(userId)) {
return u;
}
return std::nullopt;
}- 存在可能性 → optional型契約
例2:パーサーAPIのoptional化
パースAPI設計
std::optional<Date> parseDate(const std::string& str) {
if (validFormat(str)) {
return Date::from(str);
}
return std::nullopt;
}- 失敗 → nullopt収束
レビュー観点
- 契約違反ではなく合法パスであると設計明文化されているか
- ポインタnull許容とoptionalが混在排除されているか
- 利用者側責務で存在確認が明文化されているか
- 統一的な戻り値粒度が維持されているか
- std::nulloptによる初期化統一が実施されているか
良くない実装例: ケース1(nullableポインタ混入)
nullableポインタ型
User* findUser(int userId);
@Reviewerポインタnull許容は設計契約が曖昧になります。optional<T>型に統一してください。
改善例
改善例(optional型統一)
std::optional<User> findUser(int userId);良くない実装例: ケース2(戻り値不統一)
API粒度崩壊
std::optional<User> find();
bool exists();
@Reviewer同一責務API内で戻り粒度が崩壊しています。契約統一してください。
改善例
改善例(粒度統一)
std::optional<User> find();良くない実装例: ケース3(契約粒度混乱)
不在通知混在
User findOrThrow(int userId);
@Revieweroptional統一文化に対し例外分離が混在しています。契約統一指針を決定してください。
改善例
改善例(契約文化整理)
std::optional<User> find();PlantUML:optional責務整理図
optional適用優先パターン一覧
| 適用領域 | 代表API |
|---|---|
| 検索API | findById, getByKey |
| パースAPI | parseDate, parseConfig |
| 設定読込 | getOptionalParam |
| 条件分岐 | filterOptional |
レビューアーは「ここはoptional型に統一できます」提案を常時提供できることが重要。
ロギング統合例
optional存在確認
auto userOpt = repository.findUser(userId);
if (!userOpt) {
logger.warn("User not found: id={}", userId);
monitoring.notify("USER_NOT_FOUND");
}- 不在判定と通知を統一整理
契約責務レビュー支援質問集
| 質問例 | 意図 |
|---|---|
| この戻り値は設計的に存在可能性がありますか? | optional適用可否確認 |
| null許容とoptionalが混在していませんか? | 契約型統一確認 |
| 呼び出し側はhas_value確認責務を負っていますか? | 利用者責務確認 |
| 契約粒度がAPI群内で統一されていますか? | 統一文化確認 |
レビューアーは契約設計可視化レビュー文化を現場に定着させる役割を持つ。
観点チェックリスト
まとめ
レビューアーがoptionalレビューで常に問うべきは
「この値の有無は契約上許容なのか、それとも契約違反なのか?」
です。
- optional → 契約責務型表現文化
- nullable → 契約曖昧排除文化
- 利用者責務 → has_value統一文化
- 統一契約文化 → 設計粒度整理文化
レビュー現場では
「存在可能性を契約型に収束させるレビュー文化」
が現場品質と設計統一性を大幅に向上させます。
