Claude CodeとCursorを半年以上使ってきた。便利だが、「PoCは作れるけど本番には...」という感覚が拭えなかった。
その原因を分解してみた。
PoCで終わる3つの理由
1. コンテキストの断絶
AIは会話の文脈は理解するが、「プロジェクト全体の文脈」は理解しにくい。
- なぜこのアーキテクチャなのか
- 過去にどんな失敗があったか
- チームの暗黙のルール
これらは毎回説明する必要がある。
2. エラーハンドリングの甘さ
AIが生成するコードは「正常系」に偏る。
// AI生成コードあるある
const data = await fetch('/api/articles').then(r => r.json());
// エラー時どうする?タイムアウトは?リトライは?
3. 一貫性の欠如
同じ機能を複数回依頼すると、毎回微妙に違うコードが出る。命名規則、エラー処理、ログ出力...全部バラバラ。
実用化に効く工夫
README.mdを「AIへの指示書」として書く
## Architecture Decisions
- State management: TanStack Query(Reduxは使わない)
- Styling: Tailwind CSS(CSS Modulesは使わない)
- Error handling: すべてのAPI呼び出しでtry-catchし、Sentryに送信
## Coding Conventions
- 関数名: camelCase、動詞から始める
- コンポーネント: PascalCase、1ファイル1エクスポート
- 型定義: interfaceではなくtypeを使う
CLAUDE.mdで明示的に制約を伝える
Claude Code用の設定ファイルで、やってほしくないことを明記する。
## Constraints
- 新しいライブラリを追加する前に確認を求めること
- テストは必ず書くこと
- console.logは使わず、専用のloggerを使うこと
小さく依頼する
「ユーザー認証機能を作って」ではなく:
- 「ログインフォームのUIを作って」
- 「認証APIを叩く関数を作って」
- 「認証状態を管理するContextを作って」
と分解する。レビューしやすく、手戻りも小さい。
AIに向いているタスク
- ボイラープレートコード生成
- 型定義の生成(OpenAPI → TypeScript)
- テストケースの追加
- リファクタリング(明確なルールがある場合)
AIに向いていないタスク
- アーキテクチャ設計
- パフォーマンスチューニング
- セキュリティ要件の実装
- レガシーコードの理解
おわり
AIコーディングを「魔法」ではなく「ツール」として捉えると、使いどころが見えてくる。PoCで終わらせないコツは、人間側の準備にある。