「すごい!指示しただけでアプリが動いた!」
Vibe Coding(AIへの自然言語指示によるコーディング)は、確かに魔法です。しかし、その魔法には強烈な副作用があります。
それは、**「人間が到底メンテナンスできない、巨大なスパゲッティコードが爆速で量産される」**というリスクです。
AIは「動くコード」を書くのは天才的ですが、「人間が読みやすいコード」や「半年後に修正しやすい設計」を考えるのは苦手です。彼らは疲れを知らないため、平気で1つのファイルに1000行のロジックを詰め込み、似たような処理を何度もコピペします。
放置すれば、あなたのプロジェクトは1ヶ月で**「誰も触れないゴミ屋敷」**と化すでしょう。
この記事では、Vibe Codingのスピードを殺さずに、AIが生み出す「汚染」を食い止め、品質を担保するための3つの防衛策を徹底解説します。
なぜAIは「スパゲッティコード」を書きたがるのか?
対策の前に、敵(AIの癖)を知りましょう。なぜAIはあんなに汚いコードを書くのでしょうか?
1. 「コンテキストウィンドウ」の限界
CursorなどのAIは、プロジェクト全体を「なんとなく」把握していますが、厳密にすべての行を記憶しているわけではありません。そのため、別ファイルに似た関数があることに気づかず、**「とりあえずここで動くロジック」をその場で再発明(重複実装)**しがちです。
2. 「短期的な正解」への最適化
AIへのプロンプトは通常「このバグを直して」「この機能を追加して」という短期的なものです。 AIはユーザーを喜ばせるために、「アーキテクチャを綺麗にする」ことよりも「最短でその機能を動かす」ことを優先します。その結果、既存の設計を無視した「つぎはぎの実装」が生まれます。
3. ファイル分割への消極性
人間なら「長くなってきたからファイルを分けよう」と考えますが、AIにとって100行も1000行も処理コストは変わりません。指示がない限り、永遠にpage.tsxにロジックを継ぎ足し続けます。
防衛策1:AIに「アーキテクチャ」を強制する(ファイル分割の自動化)
最大の防御は、**「1ファイルあたりの行数制限」と「責務の分離」**です。これを人間の精神力ではなく、プロンプトで強制します。
「Vibe」の中に「制約」を混ぜる
機能追加を指示する際、必ず「ファイル構造」についての指示をセットにします。
❌ 悪い指示(スパゲッティの元)
「ユーザー情報を取得して、一覧表示する機能を追加して。データはSupabaseから取ってきて。」
⭕ 良い指示(防衛的Vibe)
「ユーザー一覧機能を追加したい。ただし、以下のルールを厳守して:
- UIコンポーネントとデータ取得ロジック(Hooks)は別ファイルに分割すること。
- Supabaseのクライアントコードは
lib/supabase.tsを再利用すること。- 1つのファイルが150行を超えそうなら、サブコンポーネントに切り出すこと。」
.cursorrules で恒久対策する
毎回指示するのが面倒なら、プロジェクトのルートにある .cursorrules に以下を記述し、AIに「憲法」として守らせます。
Markdown
# Coding Standards
- **Single Responsibility Principle:** 1つのコンポーネントや関数は1つのことだけを行う。
- **File Limits:** コンポーネントファイルは200行未満に保つこと。これを超える場合は、必ずサブコンポーネントとして別ファイルに分割 (`/components/features/...`) すること。
- **Don't Repeat Yourself (DRY):** 同じロジックを2回以上書く場合は、カスタムフックまたはユーティリティ関数に切り出すこと。
これを入れておくだけで、AIが出力するコードの品質が劇的に向上します。
防衛策2:「リファクタリング専用モード」でAIに掃除させる
Vibe Codingでガンガン機能を作っている時は、細かいことは気にしなくてOKです。 その代わり、機能が完成した直後に、必ず**「お掃除タイム(Refactoring Session)」**を設けます。
ここでのポイントは、**「機能追加とリファクタリングを同時にやらせない」**ことです。
掃除専用プロンプト
機能実装が一段落したら、新しいチャットセッションを開き、以下のプロンプトを投げます。
Markdown
現在開いているファイル (`EmployeeList.tsx`) について、機能や挙動は**一切変更せず**に、以下のリファクタリングを行ってください:
1. `useEffect` 内の複雑なデータ取得ロジックを、カスタムフック `useEmployeeData.ts` に抽出する。
2. テーブルの行(Row)部分を、`EmployeeRow.tsx` として別コンポーネントに切り出す。
3. マジックナンバーやハードコードされた文字列を定数定義に移す。
出力前に、何を変更するか箇条書きで計画を提示してください。
人間がコードを書かないのと同様に、人間がリファクタリングをする必要もありません。 「散らかすのもAIなら、片付けるのもAI」です。この「片付けの指示」を出せるかどうかが、2026年のエンジニアの腕の見せ所です。
防衛策3:マッチポンプ式テスト(AIのコードをAIに監視させる)
「AIが書いた複雑なロジックが正しいかどうかなんて、読む気もしない」
それが本音でしょう。だからこそ、テストコードを書きます。もちろん、AIに書かせます。 AIが書いた実装コード(Implementation)に対して、AIにテストコード(Test)を書かせることで、**「AI同士の相互監視」**システムを作ります。
「実装」と「テスト」を別セッションにする
ここでも重要なのは、実装とテストを同じコンテキスト(チャット)でやらせないことです。同じ文脈だと、AIは「実装に合わせた(バグを含んだ)テスト」を書いて通そうとしてしまいます。
手順:
- 実装コードができあがる。
- 新しいチャットを開く。
- 実装コードを貼り付けず、「仕様書(spec.md)」だけを読み込ませる。
- 「この仕様を満たすためのJestのテストケースを書いて」と指示する。
- そのテストに対して、実装コードを走らせる。
もしテストが落ちたら、それは「実装が間違っている」か「仕様の解釈がズレている」かのどちらかです。 このプロセスを経ることで、あなたが一行もコードを読まなくても、機能の担保が可能になります。
まとめ:あなたは「プログラマー」から「コードの管理者」になる
Vibe Coding時代において、エンジニアの役割は以下のように変化します。
- Before: 自ら汗をかいてコードを書く職人。
- After: 暴走しがちな超優秀な部下(AI)を監視し、定期的に「整理整頓」を命じる現場監督。
「AIスパゲッティコード」は、Vibe Codingの必然的な副産物です。 これを恐れてAIを使わないのは愚策です。出るゴミは出させましょう。その代わり、**「ゴミを自動回収する仕組み(プロンプトとルール)」**を構築するのです。
汚いコードと戦うのは、あなたの目と頭脳ではありません。 **「整理整頓のための、もうひとつのAIプロンプト」**なのです。