あなたの.cursorファイルは、エラーを減らすか?
開発プロジェクトの80%が、ルールファイルをコピー&ペーストして使っています。しかし、その95%は機能していません。なぜでしょうか。
理由は単純です。他人の問題を解決するルールで、あなたの問題は解決できないからです。
このブログでは、Cursorルールファイルを例に「なぜこの構造なのか」を分解します。本質を理解すれば、あなたのプロジェクトに最適なルールを自分で作れるようになります。
ルールの正体:それは問題のカタログ
ルールファイルを開いてください。最初に3つの基本方針があります。「日本語対応」「ステップバイステップ」「エラーハンドリング」。
これらは単なる推奨事項ではありません。過去に起きた具体的な問題の記録です。
日本語のコメントがなかった結果、チームメンバーがコードを理解できず、3日間の作業がやり直しになりました。大きな変更を一度に行った結果、バグの原因特定に2週間かかりました。エラーハンドリングがなかった結果、本番環境でアプリケーションが停止し、顧客からクレームが来ました。
ルールファイルは「失敗のアーカイブ」です。各ルールの背後には、誰かの痛い経験があります。
命名規則が存在する本当の理由
get_reminder_settingsとReminderService。前者はsnake_case、後者はPascalCaseです。なぜ統一しないのか。
答えは「認知負荷の削減」です。
人間の脳は、パターンマッチングで動作します。コードを読むとき、文字を一つずつ読んでいません。形状を認識しています。snake_caseを見れば「関数」、PascalCaseを見れば「クラス」と瞬時に判断します。
統一すると何が起きるか。すべての名前が同じ形になります。脳は「これは何か」を判断するために、名前を最後まで読む必要があります。1秒の遅延が、1日で数百回発生します。これが積み重なると、コードレビューに1時間余計にかかります。
命名規則の本質は「視覚的な区別による認知負荷の削減」です。あなたのプロジェクトで命名規則を決めるときは、「チームメンバーの脳がパターンを認識できるか」を基準にしてください。
データベースアクセスの回数が、すべてを決める
ルールファイルに「N+1問題を回避せよ」とあります。これは何か。
100件の予約データがあります。各予約には顧客情報が紐づいています。
悪いコード:予約を100件取得する(1回目)。各予約の顧客情報を1件ずつ取得する(2〜101回目)。合計101回のデータベースアクセス。
良いコード:予約と顧客情報を同時に取得する指示を出す。1回のデータベースアクセス。
データベースへの1回のアクセスは約10ミリ秒かかります。101回なら1秒以上です。ユーザーは画面が固まったと感じます。1回なら一瞬です。
この原則は、データベースに限定されません。API呼び出し、ファイル読み込み、外部サービスへのリクエスト、すべてに適用できます。
本質は「外部リソースへのアクセス回数を最小化する」ことです。プログラムの中で、外部とのやり取りが最も遅いからです。
エラーハンドリングの目的は、エラー防止ではない
すべてのAPI呼び出しにtry-catchを書けと指示されています。
多くの開発者は誤解しています。エラーハンドリングの目的は「エラーを防ぐこと」ではありません。エラーは必ず発生します。ネットワーク切断、サーバーダウン、予期しない入力。これらは避けられません。
真の目的は「エラー発生時に、何が起きたか理解できること」です。
try-catchがない場合の流れ:エラー発生 → アプリケーション停止 → ユーザーは画面が固まる → 開発者はログに何も記録されていないため原因不明 → 再現できない → 解決不可能。
try-catchがある場合の流れ:エラー発生 → エラーをキャッチ → ログに記録 → ユーザーにメッセージ表示 → 開発者はログから原因特定 → 修正 → 解決。
エラーハンドリングは「未来の自分への投資」です。今は面倒でも、1ヶ月後に必ず役立ちます。
コード構造に順番がある理由
Reactコンポーネントの構造:useState → useEffect → カスタムフック → イベントハンドラ → JSX。この順番は任意ではありません。
理由は「依存関係の方向」です。
useEffectはstateに依存します。イベントハンドラはstateとカスタムフックに依存します。JSXはすべてに依存します。
依存される側を上に、依存する側を下に配置すると、コードは上から下へ一方向に読めます。逆にすると、何度も行ったり来たりする必要があります。1つのコンポーネントを理解するのに5分かかるか、30秒で済むかの違いです。
この原則は、Reactに限りません。すべてのコードに適用できます。「依存関係を一方向に揃える」だけで、コードの可読性は劇的に向上します。
禁止事項リストは、損害額の記録
git push --forceの禁止。.envファイルのコミット禁止。any型の多用禁止。
これらは単なる禁止事項ではありません。それぞれに具体的な損害があります。
git push --forceを実行した結果、チームメンバー3人の2日分の作業が消失しました。損害:6人日。
.envファイルをGitHubにコミットした結果、APIキーが流出し、不正利用されました。請求額:$2,400。
any型を多用した結果、型チェックが機能せず、本番環境で予期しないエラーが発生しました。緊急対応:8時間。
禁止事項リストは「過去に支払った代償」の記録です。あなたのプロジェクトで禁止事項を決めるときは、「これをやったら何が壊れるか」「損害額はいくらか」を明確にしてください。
あなたのルールファイルを作る5ステップ
ここまで読んで、気づいたはずです。ルールファイルはコピーするものではありません。
ステップ1:問題を列挙する
過去3ヶ月で発生したすべての問題を書き出します。コードレビューで繰り返し指摘される内容、バグが頻発する箇所、チームメンバーが混乱するポイント。これがルールの原料です。
ステップ2:原因を特定する
各問題がなぜ起きるのか分析します。「命名がバラバラ」なら、なぜバラバラになるのか。「エラーハンドリングがない」なら、なぜ書かれないのか。原因が不明なら、ルールは作れません。
ステップ3:3つだけルール化する
最も重要な3つだけをルールにします。ルールが10個あると、誰も守りません。3つなら記憶できます。
ステップ4:損害額を明記する
各ルールに「これを破ると何が起きるか」「過去の損害額」を記録します。金額が示せない場合、時間で表現します。理由が明確なら、チームは納得して守ります。
ステップ5:3ヶ月後に見直す
プロジェクトの成長に合わせて、ルールも進化させます。機能していないルールは削除します。新しい問題には新しいルールを追加します。
技術選定の背後にある基準
このルールファイルは、FastAPI、React、PostgreSQLを使用しています。
FastAPIを選んだ理由:型ヒントによるバグ削減、ドキュメント自動生成による学習コスト削減。
Reactを選んだ理由:コンポーネントの再利用による開発速度向上、大規模なエコシステムによる問題解決の容易さ。
PostgreSQLを選んだ理由:トランザクションの信頼性、複雑なクエリのサポート。
しかし、これはこのプロジェクトの選択です。あなたのプロジェクトには別の選択が最適かもしれません。
技術選定の基準は3つです。チームが使いこなせるか。要件を満たせるか。5年後もメンテナンスできるか。
ルールを破るべき瞬間
最後に、重要な事実を伝えます。ルールは絶対ではありません。
ルールは「平均的なケース」を想定しています。特殊な状況では、ルールを破る必要があります。
例:「200行を超える関数を避ける」というルール。しかし、複雑なアルゴリズムを実装するとき、分割すると逆に理解が困難になることがあります。その場合、300行でも構いません。
重要なのは「なぜ破るのか」を3行で説明できることです。説明できるなら、ルール違反は許可されます。説明できないなら、ルールを守るべきです。
ルールは「思考の放棄」のためのツールではありません。「判断の補助」です。
結論:問題を解決するのは、あなただ
Cursorルールファイルの本質は、問題解決です。
命名規則は、認知負荷の問題を解決します。エラーハンドリングは、デバッグの問題を解決します。データベース最適化は、パフォーマンスの問題を解決します。
あなたがルールファイルを作るときは、「何の問題を解決したいのか」を最初に決めてください。問題が明確なら、ルールも明確になります。
最高のルールファイルは、あなたのチームが、あなたのプロジェクトのために、あなた自身で作るものです。他人のルールをコピーした瞬間、それは機能しなくなります。