0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

AI時代のコードコメント術:WHY/NOTEで意図を残す5パターン

0
Posted at

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 なのか、なぜキャッシュが必要なのかが重要。

まとめ: コメントの魔力とは

  1. 意図を残す (WHY:) - コードは what を示す。コメントは why を示す。
  2. 文脈を残す (NOTE:) - 存在しないものを説明する。
  3. 警告を残す (IMPORTANT:) - 抽象的ではなく具体的に。
  4. 構造を残す (フェーズコメント) - 長いコードの地図を提供する。
  5. 失敗を残す - 同じ過ちを繰り返させない。

コメントの魔力は「未来の読者との対話」にある。その読者は、3ヶ月後の自分かもしれないし、OSS コントリビューターかもしれない。

良いコメントは、読者が「なぜ?」と思う前に答えを用意している。コードの説明ではなく、意思決定を速く安全にするためのメタデータとして設計すると強い。

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?