■ 1. 発端: Claudeが書く長大なコメント
- 設定1行に18行のコメント:
- Go製バックエンドのWebSocket圧縮設定で、
CompressionModeの1行に対し18行のコメントが付いた- 記述内容自体に嘘はなく、ライブラリの仕様も本番でOOMKillが起きた経緯も事実
- コメントの内訳:
- クライアントが既にpermessage-deflateをadvertiseしているため、サーバーは受け入れるだけでよいという説明
- context takeoverは接続ごとにflate.Writer 1.2MBとsliding window 32KBを固定保持するという説明
- gqlgen移行時にContextTakeoverへ変えた結果、本番がmemory limit 2Giに到達しOOMKillした経緯
■ 2. AI自身にとってのコメントの価値
- 長いコメントはAIの読解を助けていない:
- Claude本人に尋ねたところ、助かっておらず、むしろ邪魔になっている方が多いという回答だった
- ファイル読解時に見ているのはコードそのもの:
// ユーザー ID を取得するの類は情報量がゼロで、その分だけコンテキストを占有し周囲のコードが見えにくくなる- 長いファイルほどコメントが多いと実際のロジックの密度が下がり、全体構造が掴みにくくなる
- コンテキスト圧迫という不利益:
- 限られたコンテキストに冗長な行が混ざれば、その分だけ実際のコードが入らなくなる
■ 3. コメントが長くなる理由
- 理解のためではなく出力の癖:
- 説明的で丁寧な出力が好まれるように訓練されている
- 「ちゃんと考えて書きました」を可視化する方向に流れやすい
- 自信のなさが分量に化ける:
- 自信がない箇所ほど言葉で埋めて補強しようとする
- コメントの分量が、その箇所の不確実さの指標になっている
- 本来あるべき挙動:
- 「この実装で合っているか自信がない」と申告すべき場面で、代わりに長い説明が生えている
■ 4. 最初のルール: コードから復元できない情報
- 例外として価値があるコメント:
- 過去の事故、外部制約、直感に反する挙動といった、コードをいくら読んでも出てこない情報
- プロジェクトのルールファイルに明文化:
.claude/rules/coding-principles.mdに、コードから復元できない情報だけを書くという基準を記述- 書くのは、なぜその実装にしたか、外部制約・過去の事故・仕様の由来、直感に反する挙動や罠
- 書かないのは、何をしているか、関数名・変数名の言い換え、「〜を初期化する」系の実況
- 不確実さの伝達方法を分離:
- 自信がない箇所をコメントを盛って補強せず、PR descriptionや回答本文で「ここは未確認」と明示する
■ 5. 計測結果: ルールは半分しか効かなかった
- 測定方法:
- ルール追加コミットの前後の一定期間で、マージしたPR27件のdiffを集計し、自動生成ファイルは除外した
- 比率は半減:
- 追加コードは2,909行から6,448行、追加コメントは777行から624行
- コメント比率は21.1%から8.8%へ低下
- 長いブロックは不変:
- 4行以上の連続コメントブロックは52個から50個とほぼ変わらず
- ブロックの最大は17行から18行へ増加、平均は7.3行から6.2行
- 体感が変わらなかった理由:
- 目に付くのは全体の比率ではなく、スクロール中に現れる十数行の塊の方である
■ 6. 長いブロックが残った理由
- 18行すべてがルールに合致:
- クライアント実装を見ないと分からない情報、ライブラリの内部仕様、過去の事故の経緯のいずれかに該当する
- このルールでは1行も削れない
- 有用だから消せない:
- AIが書くコメントは、無意味だから消せるのではなく、有用だから消せない
- 事実として正しくコードには書かれていない情報が並ぶと、消す根拠が作れない
■ 7. 判断軸の変更: 有用性から置き場所へ
- 新しい基準:
- その情報が有用かどうかではなく、そこがその情報の置き場所かどうかで切る
- 変更履歴はgit logとPRへ:
- 18行のうち後半6行は「移行前はgorillaだった」「移行時に変えたら壊れた」という変更の履歴に当たる
- 半年後の読み手に必要なのは、なぜ今NoContextTakeoverなのかであり、何から何に変えたかではない
- タスクID参照も除外:
(UZU-1234)のような参照は、issueが閉じられれば内容が要約されずに残るだけの識別子になる- 必要な内容はコメントに直接書くべきである
■ 8. 新ルールの設計と3つの変更点
- 配置場所:
- プロジェクトのルールではなくグローバルの
~/.claude/CLAUDE.mdに置いた- コードコメントには非自明なWHYだけを書き、隠れた制約・workaroundの理由・驚く挙動に限定する
- docsやREADMEも同様に、issue参照・経緯・マイグレーション履歴は書かず最新仕様のスナップショットだけを書く
- 禁止リストの形にした:
- 「書く/書かない」の表は判断を委ねる形式で、表にない項目の扱いが曖昧になる
- 禁止対象を名指しする方が、AIにとっても人間にとっても解釈の幅が小さい
- 実際に出てきた違反をそのまま項目にした:
- 変更履歴とタスクID参照を明示的に追加した
- 抽象的な原則を1つ置くより、具体的な違反を列挙する方が効く
- グローバルに移した:
- どのリポジトリでも同じことを求めているため
■ 9. 現状と今後の検証
- 効果は未判定:
- 移してから日が浅く、この置き方が効いているかはまだ判断できていない
- 次は同じ集計を回し、4行以上のブロック数が減ったかを確認する予定
- 測定の重要性:
- ルールを書いた後は、出力が実際に変わったかを測る
- 体感では「効いた/効かない」を取り違える