AI時代のコードコメント術:WHY/NOTEで意図を残す5パターン
AI支援のコーディングでは変更が速く回るぶん、設計意図(なぜ)と前提(文脈)が失われやすい。
この記事では WHY/NOTE/SECURITY などの"型"で、意図と前提をコメントに残す方法を5パターンで紹介する。
(例は TrayLingo(Rust/Tauri)から抜粋)
先に結論:この5つを押さえる
| パターン | 役割 |
|---|---|
WHY: |
意図(なぜそうしたか)を残す |
NOTE: |
前提・不在の理由を残す |
IMPORTANT: / SECURITY:
|
事故条件を具体例で残す |
| フェーズコメント | 複雑な処理の「地図」を作る |
| 失敗の履歴 | 同じ過ちを繰り返させない |
1. WHY: - 意図を残す最強のプレフィックス
コードは「何をしているか」を示すが、「なぜそうしているか」は示さない。WHY: はその隙間を埋める。
セキュリティの意図を残す
// WHY: Use absolute path to reduce risk of PATH manipulation.
const SECURITY_CMD: &str = "/usr/bin/security";
なぜ /usr/bin/security とフルパスなのか? security だけでいいのでは?
このコメントがなければ、リファクタリング時に「冗長だから削除しよう」と思うかもしれない。しかし特権を持つツールを呼び出す場面では、PATH manipulation のリスクを減らすために絶対パスを使う意図がある。
魔力: 未来の自分や他の開発者が「なぜ?」と思う前に答えを提供する。
失敗から学んだ設計判断
/// Global Sentry guard to keep the client alive for the entire program lifetime.
/// WHY: Moving the guard into Tauri's managed state caused the client to become
/// disabled. Keeping it in a static ensures it lives as long as the process.
static SENTRY_GUARD: Mutex<Option<ClientInitGuard>> = Mutex::new(None);
「なぜ Tauri の managed state を使わないのか?」という疑問への回答。
これは実際に managed state を試して失敗した経験から来ている。コメントがなければ、誰かが「Tauri らしく managed state を使おう」とリファクタリングし、同じ失敗を繰り返す。
効果: 失敗の歴史を残し、車輪の再発明を防ぐ。
ライブラリの罠を警告
// WHY: tauri-plugin-global-shortcut fires twice (Pressed + Released).
// Only handle Pressed to prevent duplicate translation requests.
// See: https://github.com/tauri-apps/plugins-workspace/issues/1748
if event.state != ShortcutState::Pressed {
return;
}
外部ライブラリの予期しない挙動を記録。Issue へのリンク付き。
効果: 「なぜこの early return があるのか」という疑問と、その根拠(Issue リンク)を同時に提供。
2. NOTE: - 重要な文脈を残す
WHY: が「なぜ」なら、NOTE: は「知っておくべきこと」。
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Settings {
// NOTE: API key is stored in macOS Keychain, not here.
// See src/keychain.rs for Keychain operations.
/// Selected model
pub model: String,
// ...
}
Settings 構造体に api_key フィールドがないことに疑問を持つ人への回答。
効果: コードの「不在」を説明する。存在しないものは grep で見つけられない。
3. IMPORTANT: / SECURITY: - 絶対に見落とせない警告
// IMPORTANT: Privacy Protection - Sentry PII Masking
// This app handles sensitive user data (clipboard text for translation).
// We MUST scrub any text content before sending to Sentry.
単なる「重要」ではなく、なぜ重要かを説明している。
// WHY: Users paste sensitive content (emails, passwords, private messages)
// for translation. This data MUST NOT be sent to external services.
if (event.breadcrumbs) {
event.breadcrumbs = event.breadcrumbs.filter(/* ... */);
}
「clipboard」「translation」「private messages」という具体例が、なぜこのフィルタリングが必要かを即座に理解させる。
効果: 抽象的な「セキュリティのため」ではなく、具体的なシナリオで伝える。
4. フェーズコメント - 複雑な初期化の地図
// =========================================================================
// Phase 0: Save the REAL default panic hook BEFORE sentry::init
// =========================================================================
// WHY: sentry::init installs PanicIntegration which overwrites the panic hook.
// We save the default hook here so we can call it later without triggering
// Sentry's handler (which would cause duplicate events).
let default_hook = std::panic::take_hook();
// =========================================================================
// Phase 1: Early Sentry init (captures panics during Tauri initialization)
// =========================================================================
// NOTE: DSN is injected via build-time env var (SENTRY_DSN_BACKEND).
長い run() 関数を論理的なフェーズに分割。各フェーズに番号とタイトル、そして WHY/NOTE を添える。
効果: 500行の関数でも迷子にならない。diff を見るときも「Phase 2 の変更か」と即座に把握できる。
5. 境界を示すコメント
/// Returns the new clipboard text if changed, None if timeout.
///
/// NOTE: First trigger after app launch often times out (works on second try).
/// This may be due to:
/// - macOS accessibility permission delays
関数の doc comment に既知の制限を記載。
効果: バグレポートを減らす。「これはバグではなく、既知の制限です」という情報を関数に埋め込む。
アンチパターン: 効果のないコメント
当たり前のことを書く
// Bad: Increment counter
counter += 1;
コードを読めばわかることを繰り返すだけ。
実装詳細を書く
// Bad: Use HashMap for O(1) lookup
let cache: HashMap<String, String> = HashMap::new();
HashMap を使っていることはコードを見ればわかる。なぜ HashMap なのか、なぜキャッシュが必要なのかが重要。
まとめ: コメントの魔力とは
-
意図を残す (
WHY:) - コードは what を示す。コメントは why を示す。 -
文脈を残す (
NOTE:) - 存在しないものを説明する。 -
警告を残す (
IMPORTANT:) - 抽象的ではなく具体的に。 - 構造を残す (フェーズコメント) - 長いコードの地図を提供する。
- 失敗を残す - 同じ過ちを繰り返させない。
コメントの魔力は「未来の読者との対話」にある。その読者は、3ヶ月後の自分かもしれないし、OSS コントリビューターかもしれない。
良いコメントは、読者が「なぜ?」と思う前に答えを用意している。コードの説明ではなく、意思決定を速く安全にするためのメタデータとして設計すると強い。