はじめに
簡易的なリストの並び替え機能(いわゆるToDoリスト)の実装を通じて Vibe Coding を試してみました。
月並みな感想ですがプロンプト入力後に「バァーっとコードが勝手に書かれていく」のは未来感がありました。
Vibe Coding(雰囲気コーディング)とは、「AIがコードを自動生成し、開発者は自然言語でAIに指示を出すだけでアプリケーションを開発できる、新しいプログラミング手法」を指します。
今回試してみた内容は以下になります。
-
GitHub Copilot
×Claude 3.5 Sonnet
(エージェントモード) -
Cline
(VSCode拡張機能)×gemini-2.0-flash-001
- 余談ですが
Gemini
は現在無料でAPIキーを発行できるのでお試しチャンスです
上記リンク先で[APIキーを作成]を押下で生成できます。
- 余談ですが
-
Cursor
×Auto
初期設定のままで使ったのでモデルはAuto
になります。
ちなみにAuto
に関しては以下の説明。
Cursor helps you select the best premium model, based on performance and speed(訳:Cursor は、パフォーマンスと速度に基づいて最適なプレミアムモデルの選択をサポートします)
どのモデルを使っているか名言していないので、Cursor
が良しなに適宜選んでくれてるのでしょうかね?🙄
これらを比較した上での筆者の所感を述べていきたいと思います。
- 比較検証なので、各AIには後述する同じプロンプトや参考画像などを渡した同じ条件を元に作業してもらっています
- 筆者は個人PCで
Windows 11
、会社PCでMac M1 12.7.6
を使用しており、各機でも同じ作業を実施して比較検証しました
今回は比較対象するにあたって以下を制約としました。
- 事前に環境をこちらで用意(構築)しておく
vite
×React
で環境を用意(npm create vite@latest
)しておく。
Tailwind CSS
も公式サイトを参照に事前インポート及び設定しておく - プロンプトはマークダウン形式で記述
ただし、一度やり取りが始まれば基本的にはプレーンテキストで行い、適宜必要に応じてマークダウンを用いる
上記に関して事前に環境を構築しておくのは、作業効率的に重要だと感じました。
後述しますが、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への依頼では否定形を避けて肯定形で行うほうが良いという情報もあったので、「壁打ちなので参考にしないでください」というよりも「無視して行ってください」という肯定形を意識しました。
あと、今回のプロンプトでは筆者の壁打ちチェックの部分もあって純粋なコード生成依頼の観点でいうとノイズが入っていると思います。
参考キャプチャ画像
筆者の所感
結論を先に書いておきます。
これらを使ってみて、総合的に自分に合っていると感じたのは以下の順序でした。
GitHub Copilot
> Cursor
> Cline
あと、今回の検証を通じて得た所感は以下になります。
- 事前にある程度、環境を用意(構築)しておいた方が効率的
- プロンプトは否定形ではなく肯定形で依頼
- 依頼するタスクは極力小さく、細かく区切った方が効果的(かつ互いに楽)
- すべてをAIにお任せは、現状ではまだ厳しそう
- Vibe Coding や AI を用いたコーディング・プログラミングには前提知識が求められる
- 例えば、スタイルの修正依頼ひとつ取っても
ドロップシャドウ
やブラー
、ホバー
などの用語を知っていないと適切かつ端的な修正指示ができない - 作業依頼に関する補足情報または実装イメージがしっかりしないとうまく指示を出せない
例えば、CRUD
機能やデータベースの種類、データベースを用いない簡易なデータ管理方法(localStorage
)など、要件定義や技術選定に関わってくるような「何がしたいのか」を具体的に伝達できる知識が必要だと感じた
- 例えば、スタイルの修正依頼ひとつ取っても
- 副次的に論理的思考力を磨くトレーニングにもなる
- Vibe Coding は知らない記述・記法や未知のライブラリの勉強になるし、その場で聞けるのでキャッチアップ効率も高まる
機能面
Cline
以外、どのAIも機能実装面では、ほぼ一発で期待通りの成果物を提供してくれました。
ほぼ一発という理由は、生成開始までに設定や環境構築で何度かやり取りしたものの「コード書き初めの段階で言うと一発目で期待通りの成果物を提供」してくれたためです。
先ほど載せた筆者のプロンプトには生成に関係のないノイズ(筆者の壁打ちチェック部分)が入っていたのでそれが邪魔をしたのかもしれません。
筆者が情報収集する中ではタスクは極力小さい粒度・単位で依頼する方が良いという情報があったので、その点に鑑みると筆者のプロンプトは色々と盛り込んでしまっている印象です。
-
Cline
に関して
個人PC(Win11
)では他のAIと同様にほぼ一発で期待通りの成果物を生成してくれたのですが、会社PC(Mac M1
)ではずっとpackage.json
の設定エラー対応を行っていて実装まで進みませんでした。
個人PC(Win11
)と会社PC(Mac M1
)での違いは、作業開始前の言語設定で「日本語」にしているか否かという違いでした。
作業開始前に、ユーザー
とワークスペース
ともに日本語設定していた会社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を生成してくれました。
プロンプトや参考画像が全く同じという条件でも成果物のUIは結構違いますよね。
GitHub Copilot
Cursor
と違って、GitHub Copilot
は成果物のUIが結構似ていますね。
Cline
先ほど説明したようにMac M1
では生成まで進めなかったのでWin11
のみになります。
上部がパツパツですが、本当にこの通りでpadding-top
やmargin-top
もあたっていないスタイルでした。
今回の比較対象の中では一番質素なUIでした。
あと、言語設定が英語なので入力欄のプレースホルダーや各種ボタンも英語表記になっていますね。
追加修正・改善依頼に対するパフォーマンス面
どのAIも全てを任せきりとはいかず、こちらで手を加える必要がありました。
例えば、どの成果物も全てソート機能は働いているものの、他の削除機能や更新機能はうまく働いていないという状態だったのです。
事前情報通り「0 -> 1」の生成はどのAIもスムーズに行ってくれたのですが、生成した成果物の調整・微修正などには詰まった印象です。
自身のエラー対応を何度も繰り返し続けて抜け出せなくなっているのを見て「これが『pit of death』か」とか思っていました。
CursorやClineでAIにコーディングさせていると、いずれpit of death(エラーから抜け出せない、同じ失敗を繰り返す、etc・・・)が訪れます。これを復帰させるには、人間の開発者の手による修正が必要です。
AIがハマっていた具体例
リストの編集や削除機能
どのAIも全てハマってました。
原因としては、どのAIもUI/UX向上の観点からドラッグ系のライブラリを導入してくれていたのですが、そのライブラリのドラッグ系のイベントと、編集や削除を実施するボタンクリックや編集入力に関するイベントが競合してしまっていたのです。
そこで対応としては対象関数にstopPropagation
を記述したり、
ラベル要素(ソートのドラッグ操作機能を担う特定の記述{...listeners}
が付与された要素)の子要素だった各種ボタン要素を兄弟要素の関係にしたりして解消しました。
-
stopPropagation
を記述
// キーボードイベントの処理
const handleKeyDown = (e: React.KeyboardEvent) => {
+ e.stopPropagation(); // 親要素のソート機能のイベント発火を防止
if (e.key === 'Enter') {
handleSave();
} else if (e.key === 'Escape') {
handleCancel();
}
};
- 子要素だった各種ボタン要素を兄弟要素の関係に変更(=ソートのドラッグ操作機能の管轄対象外にする)
<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>
...
..
.
または以下のようにソート機能を担う特定の記述を移動させ(て兄弟要素の関係にす)る
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>
...
..
.
インポートエラー
以下のようなライブラリ関連を筆頭にインポートエラーも良く見られた現象です。
import {
DndContext,
closestCenter,
KeyboardSensor,
PointerSensor,
useSensor,
useSensors,
+ type DragEndEvent,
- DragEndEvent,
} from '@dnd-kit/core';
他にも、Tailwind CSS
は既にインストール及び設定済みで作業依頼しているにもかかわらず、Tailwind CSS
を改めてインポートしようとして、その旨を伝えたもののインストールした結果インストールエラーやパスエラーなどを引き起こしたりして自爆していました。
「だから言わんこっちゃない」って感じで、ちょっと可愛かったです。
スタイルに関するもの
ソート完了(実施)後に、ソート時(active
時)のスタイルが継続してあたっている現象がいくつかの成果物で確認されました。
ライブラリ特有の記述で解消したものもあれば、こちらでスタイルを追記して対応したものもありました。
具体的には多くの成果物では、ソート完了時をステート管理していて三項演算子を用いたスタイル指定を行っていました。
- 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
の返答を載せておきます。
しっかりとこちらの壁打ちに対応してくれており、
今回の依頼内容である機能実装に関するアクションを段階別に提示してくれています。
心強い先輩や同僚が側にいる安心感といいますか、
このあたりで「AIとの協業」というものを強く実感しました。
個人的に興味深かったのがAIの提案が (論理的な説明を経て)Yes or Noで答えられるようなものとなっている点です。
こういった丁寧な提案の仕方やスタンスは、例えば上司への相談や報告などにも活かせるでしょうし、学ぶところがあるなぁと素朴に感じました。
まとめ
同じ条件や制約のもと色々な組み合わせで Vibe Coding を試してみました。
事前情報通りな感触もあれば、触ってみて初めて実感するような学びもあって、やはり手を動かす大切さを再認識した次第です。
箇条書きすると、今回筆者は以下のような内容を再認識したり、学んだりしました。
- 事前にある程度、環境を用意(構築)しておいた方が効率的
- プロンプトは否定形ではなく肯定形で依頼
- 依頼するタスクは極力小さく、細かく区切った方が効果的(かつ互いに楽)
- すべてをAIにお任せは、現状ではまだ厳しそう
- Vibe Coding や AI を用いたコーディング・プログラミングには前提知識が求められる
- 例えば、スタイルの修正依頼ひとつ取っても
ドロップシャドウ
やブラー
、ホバー
などの用語を知っていないと適切かつ端的な修正指示ができない - 作業依頼に関する補足情報または実装イメージがしっかりしないとうまく指示を出せない
例えば、CRUD
機能やデータベースの種類、データベースを用いない簡易なデータ管理方法(localStorage
)など、要件定義や技術選定に関わってくるような「何がしたいのか」を具体的に伝達できる知識が必要だと感じた
- 例えば、スタイルの修正依頼ひとつ取っても
- 副次的に論理的思考力を磨くトレーニングにもなる
- Vibe Coding は知らない記述・記法や未知のライブラリの勉強になるし、その場で聞けるのでキャッチアップ効率も高まる
ここまで読んでいただき、ありがとうございました。