Vibe Coding を試してみた感想

## はじめに
簡易的なリストの並び替え機能（いわゆるToDoリスト）の実装を通じて Vibe Coding を試してみました。

月並みな感想ですがプロンプト入力後に「バァーっとコードが勝手に書かれていく」のは未来感がありました。
ただし（筆者のスキル・知見不足も相まって） **人間の認知能力ではコード生成速度が速すぎて管理し切れないのでは？** とも感じました。
（※「ボトルネックは人間」とか言われている所以はこういったところにあるのかも？）

AIは課題解決を最優先に、**特定ファイルに留まらずAI自身の自律的な判断の上で色々なファイルを凄まじい速度で修正・更新**していきます。

指示された内容の解決を最優先とするためそうなっているのかもしれませんが、保守や運用、可読性、拡張性といったものをそこまで考慮せずに修正範囲を広げられると管理しづらい（というか管理不能では）と筆者は感じました。

なので現状では、**Vibe Coding できる（しても良い）案件と、できない（するのは危険な）案件とを明確に分けて活用したほうが良い印象**です。

::: note info
ところで、Vibe Coding（雰囲気コーディング）とは、「AIがコードを自動生成し、開発者は自然言語でAIに指示を出すだけでアプリケーションを開発できる、新しいプログラミング手法」を指します。
:::

今回試してみた内容は以下になります。

- `GitHub Copilot`×`Claude 3.5 Sonnet`（エージェントモード）
- `Cline`（VSCode拡張機能）×`gemini-2.0-flash-001`
    - 余談ですが[`Gemini`は現在無料でAPIキーを発行できる](https://aistudio.google.com/app/apikey)のでお試しチャンスです
    上記リンク先で[APIキーを作成]を押下で生成できます。
- `Cursor`×`Auto`
初期設定のままで使ったのでモデルは`Auto`になります。
ちなみに`Auto`に関しては以下の説明。

![スクリーンショット 2025-05-07 13.10.45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3368730/62dceff9-94f8-4cef-a174-38f40ec6b8b8.png)

> Cursor helps you select the best premium model, based on performance and speed（訳：Cursor は、パフォーマンスと速度に基づいて最適なプレミアムモデルの選択をサポートします）

どのモデルを使っているか名言していないので、`Cursor`が良しなに適宜選んでくれてるのでしょうかね？🙄

--- 

これらを比較した上での筆者の所感を述べていきたいと思います。

::: note warn
- 比較検証なので、各AIには後述する同じプロンプトや参考画像などを渡した**同じ条件を元に作業**してもらっています
- 筆者は個人PCで`Windows 11`、会社PCで`Mac M1 12.7.6`を使用しており、各機でも同じ作業を実施して比較検証しました
:::

今回は比較対象するにあたって以下を制約としました。
- 事前に環境をこちらで用意（構築）しておく
`vite` × `React`で環境を用意（`npm create vite@latest`）しておく。
[`Tailwind CSS`も公式サイトを参照に事前インポート及び設定](https://tailwindcss.com/docs/installation/using-vite)しておく
- プロンプトはマークダウン形式で記述
ただし、一度やり取りが始まれば基本的にはプレーンテキストで行い、適宜必要に応じてマークダウンを用いる

上記に関して**事前に環境を構築しておく**のは、作業効率的に重要だと感じました。
後述しますが、AI側での作業時にインストールエラーなどが起きてうまく進めなくなった状況に遭遇したので、家事で言うと「食洗機の前にサッと水洗いしておく」的な**人間の手による素地づくりを行っていたほうが良い**と感じました。

### プロンプト
色々な記事を漁ったり、日々キャッチアップする中で（まだ今は）プロンプトが重要という話を伺ったのでマークダウン形式でAIフレンドリーな記述を意識しました。

```
## タスク
リストの並び替え機能の実装をお願いします。
参考としてキャプチャ画像を添付します。

## 背景・条件
- 汎用的に利用できるリストUIを作成したい（Todoのようなタスク管理を一つの事例）
- 次項の入力欄に私のアプローチ方法を記載します。これが適切かチェックして下さい

## 入力
※これはあくまで私のアプローチがどうか知りたい壁打ち希望の記述です。
実際の実装は以下のアプローチを無視して行ってください。

1. コンテンツ管理用のリストState（※バニラJSの場合はDOM要素）を用意して、項目をラップする要素にdraggable属性を付与しておく

2. リストの並び替えはaddEventListenerのdrag系のイベントハンドラーで処理（※Reactの場合、useEffect内で随時クリーンナップ処理を入れる）

3. （並び替え）処理した結果の各要素の固有識別子を取得
```sampleContent = {id:0,name:'hoge',age:12}```
上記のようなコンテンツを想定するとsampleContent.idが固有識別子。（※Reactの場合、その値を数値型配列（id_state: number[] =[]）にセット）

4. 数値型配列（※バニラJSの場合はリストのDOM）をデータベースまたはlocalStorageに保存して次回参照時にリストStateを固有識別子でfilterした更新済みリストStateに更新（※バニラJSの場合は親要素にappendChildする）。
※Reactの場合はdragendイベントハンドラーを実行次第、固有識別子でfilterした更新済みリストStateに更新しても良い

## 出力
-  入力欄の私のアプローチ方法が適切かをチェックしてください
-  React / TypeScript / Tailwind CSS で実装
-  CRUD機能も可能なら実装
-  コードには必ずコメントを付けて処理や意図の解説をしてください
-  コード内に記述不要と判断した「補足情報」や「タスク対処へのステップ・バイ・ステップでの思考」などについては別途.mdファイルで出力してください
-  当該プロジェクト（`自分が環境構築したファイル名`）に直接（自由に）記述・実装してください
```

AIへの依頼では**否定形を避けて肯定形で行う**ほうが良いという情報もあったので、「壁打ちなので**参考にしない**でください」というよりも「**無視して行って**ください」という肯定形を意識しました。

あと、今回のプロンプトでは筆者の壁打ちチェックの部分もあって**純粋なコード生成依頼の観点でいうとノイズが入っている**と思います。

### 参考キャプチャ画像
![スクリーンショット 2025-05-02 7.46.57.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3368730/1af7ce06-2a97-4354-b3f5-f15e9ba3f871.png)

## 筆者の所感
結論を先に書いておきます。

これらを使ってみて、総合的に自分に合っていると感じたのは以下の順序でした。

`GitHub Copilot` > `Cursor` > `Cline`

あと、今回の検証を通じて得た所感は以下になります。
- 事前にある程度、環境を用意（構築）しておいた方が効率的
- プロンプトは否定形ではなく肯定形で依頼
- 機能要件（ユーザー管理機能やデータ処理、外部連携の有無など）を細かく伝えることで、AIがより正確な設計を提案してくれる。**作業依頼（タスク）とは異なり、設計部分は詳しければ詳しいほど良い**
- 依頼する**タスクは極力小さく、細かく区切った方が効果的**（かつ互いに楽）
- すべてをAIにお任せは、現状ではまだ厳しそう
- Vibe Coding や AI を用いたコーディング・プログラミングには前提知識が求められる
    - 例えば、スタイルの修正依頼ひとつ取っても`ドロップシャドウ`や`ブラー`、`ホバー`などの用語を知っていないと適切かつ端的な修正指示ができない
    - 作業依頼に関する補足情報または実装イメージがしっかりしないとうまく指示を出せない
    例えば、`CRUD`機能やデータベースの種類、データベースを用いない簡易なデータ管理方法（`localStorage`）など、**要件定義や技術選定に関わってくるような「何がしたいのか」を具体的に伝達できる知識が必要**だと感じた
- 副次的に論理的思考力を磨くトレーニングにもなる
- **Vibe Coding は知らない記述・記法や未知のライブラリの勉強になるし、その場で聞けるのでキャッチアップ効率も高まる**

::: note info
- Vibe Coding や AI を用いたコーディング・プログラミングには前提知識が求められる

上記について補足しておきます。

課題解決の実行部分（例：コーディングやプログラミングなど）は今後AIが担っていくことを前提とした話です。

筆者は、未知への挑戦や課題発見、アイデアの実現といった**上流工程において「課題把握力」と「課題想起力」が大切**だと個人的に考えています。
そして、それらを活用して導き出した **「課題解決の方針やアプローチを実施」させる（例：Vibe Coding）上で必要となるのは「適切な指示（プロンプト）」で、それを用意（指示草案）するには前提知識が求められる**と思うのです。
:::

あと、冒頭にも書きましたが、現状では **Vibe Coding できる（しても良い）案件と、できない（するのは危険な）案件とを明確に分けて活用したほうが良い印象**です。

AIは課題解決を最優先に、特定ファイルに留まらずAI自身の自律的な判断の上で色々なファイルを凄まじい速度で修正・更新していきます。

指示された内容の解決を最優先とするためそうなっているのかもしれませんが、保守や運用、可読性、拡張性といったものをそこまで考慮せずに修正範囲を広げられると管理しづらい（というか管理不能では）と筆者は感じました。

### 機能面
`Cline`以外、どのAIも**機能実装面では、ほぼ一発で期待通りの成果物を提供**してくれました。

::: note warn
ほぼ一発という理由は、生成開始までに設定や環境構築で何度かやり取りしたものの「コード書き初めの段階で言うと一発目で期待通りの成果物を提供」してくれたためです。

先ほど載せた筆者のプロンプトには生成に関係のないノイズ（筆者の壁打ちチェック部分）が入っていたのでそれが邪魔をしたのかもしれません。
筆者が情報収集する中では**タスクは極力小さい粒度・単位で依頼する**方が良いという情報があったので、その点に鑑みると筆者のプロンプトは色々と盛り込んでしまっている印象です。
:::

::: note info
- `Cline`に関して
個人PC（`Win11`）では他のAIと同様にほぼ一発で期待通りの成果物を生成してくれたのですが、会社PC（`Mac M1`）では**ずっと`package.json`の設定エラー対応を行っていて実装まで進みません**でした。
個人PC（`Win11`）と会社PC（`Mac M1`）での違いは、**作業開始前の言語設定で「日本語」にしているか否か**という違いでした。

![スクリーンショット 2025-05-07 15.25.42.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3368730/837f1e0b-7411-450f-bc99-c4ae7beb49cd.png)

作業開始前に、`ユーザー`と`ワークスペース`ともに日本語設定していた会社PC（`Mac M1`）では先ほど説明した通り、ずっと初期設定（環境構築）で詰まっていました。

筆者だけの特異な事例かもしれませんが、`Cline`は初期設定（英語）で作業させたほうがいいかも？です。
:::

### UI（スタイル）面
UI面では以下のような所感です。

- 個人PC（`Win11`）
```
Cursor == Cline > GitHub Copilot
```
`Cursor`と`Cline`は概ね違和感のないレベルのUIを生成してくれました。

`GitHub Copilot`は破綻してはいないものの、項目（要素）ごとの余白感や揃いといったデザインの四原則で言う「近接や整列」の調整不足が気になりました。
しかしこれは、一番初めに試した`GPT-4o`を使った状態の時でして、今回の検証対象である`Claude 3.5 Sonnet`の場合は他のものと同程度のUIを生成してくれました。

- 会社PC（`Mac M1`）
```
Cursor > GitHub Copilot
```
`Cursor`（`Mac M1`ver）が参照画像に一番寄せたUIを生成してくれました。

#### `Cursor`
`Cursor`は`Win11`, `Mac M1`ともに安定して違和感のないレベルのUIを生成してくれました。

- `Win11`
![cursor.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3368730/d748496d-c515-43fa-8d25-850162f56554.png)

- `Mac M1`
![スクリーンショット 2025-05-07 13.22.01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3368730/c3330e40-88b5-476c-b301-612943d13849.png)

プロンプトや参考画像が全く同じという条件でも成果物のUIは結構違いますよね。

#### `GitHub Copilot`
- `Win11`
![copilot-02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3368730/fe367801-96da-48d2-8fc8-6edf2c603565.png)
    一番初めは編集項目がなかったのですが、追加実装を指示すると上記のように既存UIに適した形で実装してくれました。<br><br>

- `Mac M1`
![スクリーンショット 2025-05-07 14.28.40.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3368730/cbe177ee-12bc-42e4-9820-506dc72de30f.png)

`Cursor`と違って、`GitHub Copilot`は成果物のUIが結構似ていますね。

#### `Cline`
先ほど説明したように`Mac M1`では生成まで進めなかったので`Win11`のみになります。

![cline.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3368730/3cc29286-2f8e-48be-905e-37dcaf375da9.png)

上部がパツパツですが、本当にこの通りで`padding-top`や`margin-top`もあたっていないスタイルでした。

今回の比較対象の中では一番質素なUIでした。

あと、言語設定が英語なので入力欄のプレースホルダーや各種ボタンも英語表記になっていますね。

### 追加修正・改善依頼に対するパフォーマンス面
どのAIも**全てを任せきりとはいかず、こちらで手を加える必要**がありました。

例えば、どの成果物も全て**ソート機能は働いているものの、他の削除機能や更新機能はうまく働いていない**という状態だったのです。

事前情報通り「0 -> 1」の生成はどのAIもスムーズに行ってくれたのですが、**生成した成果物の調整・微修正などには詰まった**印象です。

自身のエラー対応を何度も繰り返し続けて抜け出せなくなっているのを見て「これが『pit of death』か」とか思っていました。

> CursorやClineでAIにコーディングさせていると、いずれpit of death（エラーから抜け出せない、同じ失敗を繰り返す、etc・・・）が訪れます。これを復帰させるには、人間の開発者の手による修正が必要です。

https://zenn.dev/dyoshikawa/articles/developers-still-need-to-understand-ais-code

#### AIがハマっていた具体例
##### リストの編集や削除機能
どのAIも全てハマってました。
原因としては、どのAIもUI/UX向上の観点からドラッグ系のライブラリを導入してくれていたのですが、**そのライブラリのドラッグ系のイベントと、編集や削除を実施するボタンクリックや編集入力に関するイベントが競合してしまっていた**のです。

そこで対応としては対象関数に[`stopPropagation`](https://developer.mozilla.org/ja/docs/Web/API/Event/stopPropagation)を記述したり、
ラベル要素（ソートのドラッグ操作機能を担う特定の記述`{...listeners}`が付与された要素）の子要素だった各種ボタン要素を兄弟要素の関係にしたりして解消しました。

- `stopPropagation`を記述
```diff
// キーボードイベントの処理
const handleKeyDown = (e: React.KeyboardEvent) => {
+ e.stopPropagation(); // 親要素のソート機能のイベント発火を防止
  if (e.key === 'Enter') {
    handleSave();
  } else if (e.key === 'Escape') {
    handleCancel();
  }
};
```

- 子要素だった各種ボタン要素を兄弟要素の関係に変更（＝ソートのドラッグ操作機能の管轄対象外にする）
```diff
<div className="flex items-center justify-between">
+ <button
+        onClick={() => onToggleDone(item.id)}
+        className={`mr-3 w-5 h-5 rounded-full border-2 flex items-center justify-center
+              ${item.isDone
+                ? 'bg-green-500 border-green-500 text-white'
+                : 'border-gray-300 hover:border-green-500'
+            }`}
+        title={item.isDone ? '完了済み' : '完了にする'}
+    >
+        {item.isDone && '✓'}
+ </button>
  <div className="flex items-center flex-1" {...listeners}>
-    <button
-        onClick={() => onToggleDone(item.id)}
-        className={`mr-3 w-5 h-5 rounded-full border-2 flex items-center justify-center
-              ${item.isDone
-                ? 'bg-green-500 border-green-500 text-white'
-                : 'border-gray-300 hover:border-green-500'
-            }`}
-        title={item.isDone ? '完了済み' : '完了にする'}
-    >
-        {item.isDone && '✓'}
-    </button>
    ...
    ..
    .
```

または以下のようにソート機能を担う特定の記述を移動させ（て兄弟要素の関係にす）る

```diff
return (
    <div
        ref={setNodeRef}
        style={style}
        {...attributes}
-       {...listeners}
        className="bg-white border border-gray-200 rounded-md p-4 cursor-grab flex items-center justify-between"
    >
        {/* Item content */}
        <span 
          className="mr-2" 
+         {...listeners} 
        >{props.content}</span>
        ...
        ..
        .
```

##### インポートエラー
以下のようなライブラリ関連を筆頭にインポートエラーも良く見られた現象です。
```diff
import {
  DndContext,
  closestCenter,
  KeyboardSensor,
  PointerSensor,
  useSensor,
  useSensors,
+ type DragEndEvent,
- DragEndEvent,
} from '@dnd-kit/core';
```

他にも、`Tailwind CSS`は既にインストール及び設定済みで作業依頼しているにもかかわらず、`Tailwind CSS`を改めてインポートしようとして、その旨を伝えたもののインストールした結果インストールエラーやパスエラーなどを引き起こしたりして自爆していました。

「だから言わんこっちゃない」って感じで、ちょっと可愛かったです。

##### スタイルに関するもの
ソート完了（実施）後に、ソート時（`active`時）のスタイルが継続してあたっている現象がいくつかの成果物で確認されました。
ライブラリ特有の記述で解消したものもあれば、こちらでスタイルを追記して対応したものもありました。

具体的には多くの成果物では、ソート完了時をステート管理していて三項演算子を用いたスタイル指定を行っていました。

```diff
- isDraging ? opacity-75 : '' or 'undefined' or null　// false の場合は空か undefined か null を指定
+ isDraging ? opacity-75 : opacity-100 　　　　　　　　// 明示的にスタイル指定
```

そこで上記のようにスタイルを明示的に指定することで対応しました。

### 使い勝手
使い勝手なんて完全に人によりますし、筆者の主観なのでサラっといきます。

使い勝手は`GitHub Copilot`が個人的に一番良かったですが、かなり僅差で次点が`Cursor`という印象でした。

---

と、ここまで述べてきた内容を加味して、総合的に自分に合っていると感じたのは以下の順序でした。

`GitHub Copilot` > `Cursor` > `Cline`

## 筆者の壁打ちに対するAIの返答
どのAIも似たような返答だったので、代表として`GitHub Copilot`の返答を載せておきます。

![スクリーンショット 2025-05-05 16.25.26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3368730/c5b65273-1c73-4b91-b3d4-6e1210cdc5d3.png)

しっかりとこちらの壁打ちに対応してくれており、
今回の依頼内容である機能実装に関するアクションを段階別に提示してくれています。

心強い先輩や同僚が側にいる安心感といいますか、
このあたりで「AIとの協業」というものを強く実感しました。

個人的に興味深かったのがAIの提案が **（論理的な説明を経て）Yes or Noで答えられるようなものとなっている点**です。

こういった丁寧な提案の仕方やスタンスは、例えば上司への相談や報告などにも活かせるでしょうし、学ぶところがあるなぁと素朴に感じました。

## まとめ
同じ条件や制約のもと色々な組み合わせで Vibe Coding を試してみました。

事前情報通りな感触もあれば、触ってみて初めて実感するような学びもあって、やはり手を動かす大切さを再認識した次第です。

途中で書いた内容の再掲となりますが箇条書きすると、
今回筆者は以下のような内容を再認識したり、学んだりしました。

- 事前にある程度、環境を用意（構築）しておいた方が効率的
- プロンプトは否定形ではなく肯定形で依頼
- 機能要件（ユーザー管理機能やデータ処理、外部連携の有無など）を細かく伝えることで、AIがより正確な設計を提案してくれる。**作業依頼（タスク）とは異なり、設計部分は詳しければ詳しいほど良い**
- 依頼する**タスクは極力小さく、細かく区切った方が効果的**（かつ互いに楽）
- すべてをAIにお任せは、現状ではまだ厳しそう
- Vibe Coding や AI を用いたコーディング・プログラミングには前提知識が求められる
    - 例えば、スタイルの修正依頼ひとつ取っても`ドロップシャドウ`や`ブラー`、`ホバー`などの用語を知っていないと適切かつ端的な修正指示ができない
    - 作業依頼に関する補足情報または実装イメージがしっかりしないとうまく指示を出せない
    例えば、`CRUD`機能やデータベースの種類、データベースを用いない簡易なデータ管理方法（`localStorage`）など、**要件定義や技術選定に関わってくるような「何がしたいのか」を具体的に伝達できる知識が必要**だと感じた
- 副次的に論理的思考力を磨くトレーニングにもなる
- **Vibe Coding は知らない記述・記法や未知のライブラリの勉強になるし、その場で聞けるのでキャッチアップ効率も高まる**

::: note info
- Vibe Coding や AI を用いたコーディング・プログラミングには前提知識が求められる

上記について補足しておきます。

課題解決の実行部分（例：コーディングやプログラミングなど）は今後AIが担っていくことを前提とした話です。

筆者は、未知への挑戦や課題発見、アイデアの実現といった**上流工程において「課題把握力」と「課題想起力」が大切**だと個人的に考えています。
そして、それらを活用して導き出した **「課題解決の方針やアプローチを実施」させる（例：Vibe Coding）上で必要となるのは「適切な指示（プロンプト）」で、それを用意（指示草案）するには前提知識が求められる**と思うのです。
:::

あと、冒頭にも書きましたが、現状では **Vibe Coding できる（しても良い）案件と、できない（するのは危険な）案件とを明確に分けて活用したほうが良い印象**です。

AIは課題解決を最優先に、特定ファイルに留まらずAI自身の自律的な判断の上で色々なファイルを凄まじい速度で修正・更新していきます。

指示された内容の解決を最優先とするためそうなっているのかもしれませんが、保守や運用、可読性、拡張性といったものをそこまで考慮せずに修正範囲を広げられると管理しづらい（というか管理不能では）と筆者は感じました。

---

ここまで読んでいただき、ありがとうございました。