Vibe Codingに関する私の考え
最近、React.js AI Chatbot built with ChatGPT, Gemini and DeepSeek という React 開発コースを受講しました。
正直なところ、私はモダンなフロントエンド開発を体系的に学んだことがなく、私のフロントエンドスキルは2014年のJSP、JavaScript、HTML、CSS、jQuery、AJAXの時代で止まっています。そのため、「モダンフロントエンド」を始めるために純粋なReactプロジェクトを選びました。
バイブコーディングが実現可能になったと断言できます。
2022年にLLMが普及する前から、「コーディングはソフトウェアエンジニアリングの比較的小さな部分である」という言葉の意味を理解していました。想像してみてください、ソフトウェア/システムを開発する際にどのような知識が必要でしょうか?私のキャリアでは、2014年だけが純粋な開発者でした。2015年から現在(2025年)までのITキャリアにおいて、私の仕事は常にインフラとシステムプラットフォームを中心に展開してきたため、「ソフトウェアエンジニアリングを深く理解している」と言う資格はないかもしれません。それでもなお、私は「テクニカルリーダーシップ」に関して独自の考えを持っていると信じており、プログラミングに一貫して焦点を当て、学習してきました。私の簡潔な答えは、「すべてのテクノロジーは、最終的には蓄積されたボイラープレートを適用することによって、実践的な形で存在する」というものです。
Andrew Ngはかつて次のような声明を出しました:
私は、2022年以前の古い働き方に固執しているベテラン開発者よりも、AIを真に理解している新卒者をフルスタックエンジニアリングの役割によく選んできました。しかし、私が知っている最高の開発者は新卒者(新卒の方には失礼のないように!)ではなく、AIの変化に常に追いついている経験豊富なエンジニアであることを強調したいです。今日の最も生産性の高いプログラマーは、コンピューターを深く理解し、ソフトウェアのアーキテクチャを構築する方法、複雑なトレードオフを評価する方法を知っているだけでなく、最先端のAIツールにも精通している人々です。
元のリンク:DeepLearning.AI The Batch Weekly Issues - Issue 317
私の考えは以下の通りです:
- ITプロフェッショナルとして、生涯学習は避けられません。そのため、何を学ぶべきかが最も重要な問いとなるはずです。
- 次に重要な問いは、どのように学ぶか?です。
LLMが非常に普及し、私自身がバイブコーディングを試して完全に実行可能な解決策であると分かった後、私は先ほど述べた「コーディングはソフトウェアエンジニアリングの比較的小さな部分である」という言葉にさらに自信を持ちました。
コーディングとは、ロジックと指示をコンピューターが理解できる言語に翻訳するプロセスです。これは間違いなくソフトウェア開発の中核スキルであり、ソフトウェア構築の基礎です。しかし、成功し、堅牢で、保守可能なソフトウェア製品に関わる作業は、コーディングだけにとどまりません。
ソフトウェアエンジニアリングは、以下の要素を含むソフトウェアライフサイクル全体をカバーする、体系的で規律ある測定可能なプロセスです:
- 要件分析: ユーザー、クライアント、市場の真のニーズは何であるかを理解すること?これには、広範なコミュニケーション、調査、抽象的思考スキルが必要です。
- システム設計: 要件を実現可能な技術的ソリューションにどのように変換するか?これには、アーキテクチャ設計、データベース設計、インターフェース設計、モジュール分割などが含まれます。システムのパフォーマンス、スケーラビリティ、セキュリティ、コストなど、多くの要素を考慮する必要があります。
- プロジェクト管理: 時間を計画し、リソースを割り当て、リスクを管理し、プロジェクトが期限内に品質を保って提供されることをどのように保証するか?これには、アジャイル開発、スクラム、カンバンなどの手法が含まれます。
- テストと品質保証: ソフトウェアの品質をどのように保証するか?これには、単体テスト、統合テスト、システムテスト、パフォーマンステストなど一連の活動が含まれ、テストケースの作成と自動テストフレームワークのセットアップが必要です。
- デプロイと運用 - DevOps: ソフトウェアを本番環境に確実にデプロイし、安定した運用を保証する方法は?これには、CI/CD(継続的インテグレーション/継続的デプロイメント)、監視、ログ分析、トラブルシューティングが含まれます。
- 保守とイテレーション: ソフトウェアのリリースは始まりに過ぎません。その後の機能更新、バグ修正、システムリファクタリングがソフトウェアのライフサイクルの大部分を占めます。
一般的な類推として: ソフトウェア開発が大きな建物を建てることに例えられるなら、コーディングはレンガを積み、コンクリートを流し込む具体的な建設作業のようなものです。一方、ソフトウェアエンジニアリングは、都市計画、建築設計、構造力学計算、材料選定、建設管理、ユーティリティシステム設置、そしてその後の不動産保守といったあらゆる側面を含みます。レンガを積むことは不可欠ですが、プロジェクト全体のごく一部に過ぎないことは明らかです。
特定のプログラミング言語(例:Python、Java、Go)やフレームワーク(例:React、Spring、Django)に加えて、少なくとも以下の知識も必要です:
-
CS(コンピュータサイエンス)の基礎:
- データ構造とアルゴリズム: 問題解決のための核心的な内部スキルであり、コードの効率と品質を決定します。
- コンピュータネットワーク: TCP/IPプロトコル、HTTP/HTTPS、DNSなどを理解すること。この知識がなければ、ネットワークアプリケーションを構築することはできません。
- オペレーティングシステム: プロセス、スレッド、メモリ管理、ファイルシステムなどを理解すること。これは、高性能かつ高並行性のプログラムを作成するために不可欠です。
- データベースの原理: SQLであろうとNoSQLであろうと、データの保存方法、インデックス作成、クエリ、整合性の確保方法を理解する必要があります。
-
ソフトウェアアーキテクチャとデザインパターン:
- マクロアーキテクチャ: マイクロサービス、モノリシックアプリケーション、イベント駆動型アーキテクチャなど。適切なアーキテクチャパターンをどのように選択するか?
- ミクロ設計: SOLID原則、GoFデザインパターンなどを学び、適用して、保守しやすく拡張可能なコードを書くこと。
-
ツールとエコシステム:
- バージョン管理: Gitは今日の事実上の標準です。
- ビルドツール: Maven、Gradle, Webpackなど。
- CI/CDツール: Jenkins, GitLab CI, GitHub Actionsなど。
- コンテナ化とオーケストレーション: Docker, Kubernetes (K8s)は、現代のアプリケーションデプロイメントの標準となっています。
- クラウドサービス: 少なくとも1つの主要なクラウドプラットフォーム(AWS, Azure, GCP)が提供するコンピューティング、ストレージ、データベース、ネットワーク、その他のサービスを理解すること。
-
ソフトスキル:
- コミュニケーションとコラボレーションスキル: プロダクトマネージャー、デザイナー、テストエンジニア、さらには顧客と効果的にコミュニケーションをとること。
- 問題解決能力: 問題を定義し、根本原因を分析し、解決策を提案・評価する方法。
- 学習能力: テクノロジーは常に進化しています。継続的な学習はこの業界の生き残りルールです。
- 抽象化とモデリング能力: 複雑な現実世界の問題を簡潔なソフトウェアモデルに抽象化すること。
「すべてのテクノロジーは、最終的には蓄積されたボイラープレートを適用することによって、実践的な形で存在する」という私の理解
ここで「ボイラープレート」は、**「ボイラープレートコード」、「定型ルーチン」、「解決パターン」、または「ベストプラクティス」**と理解できます。
この言葉の核心は、経験豊富な開発者は新しい問題に直面したときに、ゼロから考え始めることはめったにないということです。彼らの心の中には、すでに大きな「パターンライブラリ」が蓄積されています。
-
パターン認識: 要件や問題を目にしたとき、彼らは無意識のうちにそれを自身の知識ベースにある既知のパターンと照合します。「ああ、これは典型的なプロデューサー・コンシューマー問題だ」、「ここではデカップリングのためにストラテジーパターンが使える」、「この並行処理のシナリオでは、データの一貫性を確保するために分散ロックが必要だ」といった具合に。
-
ボイラープレートの適用: パターンが認識されると、彼らは対応する「ボイラープレート」コードやソリューションを迅速に適用できます。この「ボイラープレート」は、単なるコピー&ペーストではなく、彼らが理解し、内面化し、さらには改善してきた、成熟した信頼性の高い実装アイデアとコードスケルトンのセットです。
-
蓄積と反復: この「ボイラープレート」は、以下から蓄積されます:
- 過去の成功経験: 類似のプロジェクトに携わり、どの方法が効果的かを知っていること。
- 落とし穴から学んだ教訓: どのプラクティスがパフォーマンス問題、セキュリティ脆弱性、保守の困難さにつながるかを知っていること。
- 優れたコードを読むこと: オープンソースプロジェクトや会社のコアコードリポジトリからベストプラクティスを学ぶこと。
- 継続的な学習: 書籍、記事、技術共有を通じて自身の知識ベースを常に更新すること。
したがって、この言葉はテクノロジーが固定的で創造性を必要としないという意味ではありません。 むしろ、創造性は深い蓄積の上に築かれることを強調しています。シニアエンジニアの価値は、他には書けないような絶妙なコードを書くことだけでなく、もっと重要なのは、複雑なシステムの骨格を迅速かつ確実に構築し、初心者が陥りがちな落とし穴を避ける能力にあります。なぜなら、彼らの心の中にある「ボイラープレート」には、すでにこれらの貴重な経験が含まれているからです。
簡単な例を挙げると、十分に開発されたひな形プロジェクトがある場合、要件を受け取った後にゼロから新しいプロジェクトを開始するのではなく、このひな形プロジェクトに基づいて開発を進めるでしょう。その前提条件は、このひな形プロジェクトを「理解している」ことです。そして、この理解は、単なるコード実装よりも、デザインパターンやソフトウェアエンジニアリングの側面に傾倒しています。もちろん、高性能なソフトウェアは依然として優れたコード実装に基づいています。しかし、現在のLLMの発展により、LLMの機能をパターン化して利用することで、コードの最適化とリファクタリングという実現可能な目標を大いに達成できると私は信じています。
Reactチャットボットに戻る
簡単に言えば、私は現在、バイブコーディングのアプローチを使ってReactベースのWebアプリを構築できると信じています。その前提条件は、TypeScriptやZustandなどの業界標準の、本番環境レベルの技術スタックを使用しないことです。
以下のGIFは、UdemyコースのReact.js AI Chatbot built with ChatGPT, Gemini and DeepSeekから学び、GitHub Copilotを使いながら私が「書き写した」Reactチャットボットアプリです。
Reactの基礎を体系的に学ばずに直接プロジェクト開発に飛び込んだ者として、私の感想は以下の通りです(これらに限定されません):
- Reactはフロントエンドの要素を関数にカプセル化し、コンポーネントとして整理しています。
- また、Reactの重要な側面は、様々なフックのユースケースに慣れることのようです。
-
reduce
は一般的にuseMemo
フックと組み合わせて使用されると感じました。 - LLMに
useState
とuseEffect
の典型的なシナリオについて尋ね、回答を得た後も、真に「理解する」ためには意図的な実践的なケーススタディが必要だと感じました。つまり、練習なしでは、面接でこの質問に例を挙げて答えることはできないでしょう。 - Reactコンポーネントで
useState
とuseEffect
の両方が同時に使用される場合、「Maximum update depth exceeded(更新深度が最大を超えました)」という典型的な問題に注意する必要があります。 - 親コンポーネントは
props
を介して子コンポーネントにデータやオブジェクトを渡し、子コンポーネントは親コンポーネントが提供するコールバックを通じて親コンポーネントの状態を変更します。
この「バイブコーディング」の全過程を通じて、私はシンプルなチャットボットに徐々に新機能を追加し、バグに遭遇した際もGitHub Copilotの助けを借りて修正しました。全体として、私は問題の発生源を概ね理解していました。なぜなら、少なくともコードをトレースする方法、どのファイルのどのコンポーネントがWebアプリのどの要素に対応しているか、そしてこれらのコンポーネントが使用するJavaScript関数がどこにあるかを知っていたからです。JavaScriptのシンタックスシュガーには詳しくありませんが、GitHub Copilotにコードのリファクタリングが可能か意識的に尋ねた後、それが作成したFactoryクラス、Baseクラス、特定のAssistantクラスなどの意味を少なくとも直感的に理解することができました。要するに、LLMが何をしているかを理解しており、問題が発生したときには修正の方向性を示すことができました。
理解していない技術スタックに基づいた仕様駆動開発を意図的に試す
数日前、私はSpec KitというGitHubリポジトリを見つけました。
簡単に言えば、その原理はプロンプトエンジニアリングに関連する概念を含んでおり、具体的には「仕様駆動開発(Spec-Driven Development)」の概念を用いてバイブコーディングを行うためのプロンプトエンジニアリング製品です。以下の説明は、そのリポジトリのREADMEからの引用です:
仕様駆動開発は、従来のソフトウェア開発の常識を覆します。何十年もの間、コードが王様であり、仕様は「実際のコーディング作業」が始まると構築され破棄される足場に過ぎませんでした。
仕様駆動開発はこれを変えます。仕様が実行可能になり、単に実装をガイドするだけでなく、直接動作する実装を生成します。
私はすぐに一つのアイデアを思いつきました。不慣れな技術スタックを使ってアプリをバイブコーディングすることは実現可能だろうか?いや、むしろ結論から言えば、それは確実に実現不可能でしょう。なぜなら、問題が発生したとしても、LLMを修正へと導くことや、コードのリファクタリングを正しく指示すること、あるいは問題の存在に気づくことすら自信がないからです。
しかし、私はこれまで、サンプルコードを一切提供せず、理解していない技術スタックを使ってアプリを完全にバイブコーディングするという試みをしたことがありません。
したがって、そのような試みは、私が現在所有しているLLMの能力と、それらを使用する私の能力をテストするための良い経験となるでしょう。
「完全なバイブコード」を達成するために、私の意図は、以前学んだReactプロジェクトの複製として、React、TypeScript、Zustand、Tailwind CSSを使用してチャットボットを構築することでした。
私はTypeScript、Zustand、Tailwind CSSを学んだことがないので、それらに「不慣れ」であると言っても差し支えありません。
以下は、最終的に完全にバイブコーディングされたチャットボットのバージョンです:
明確にしておくべきは、このプロトタイプがLLM APIを正常に呼び出して応答を得ることは期待できないということです。なぜなら、元の純粋なReactバージョンと同じレベルの完成度を達成するためにAPIキーをさらに提供するのが面倒だったからです。
結果から言えば、アプリを「実行可能な」状態まで開発することは可能であり、バグが発生した場合でもGithub Copilotを使って調査し解決できると言えます。
私が自信を持てないのは、開発プロセスにTDDやPlaywrightによるスクリプトテストのようなプラクティスが導入されたことです。これらにも不慣れであるため、Spec Kitによって生成されたタスクが十分であるかどうかはわかりません。
LLMによって生成された計画が過剰設計であるかどうかを知ることは重要です。
Spec KitでチャットボットRayアプリを生成する過程で使用した重要なプロンプトはここにあります:📁Spec_Kit_Chatbot/specs/used_prompts
簡単に言えば、これらのプロンプトはSpec KitのREADMEにあるこのセクション - 📋 Detailed processを参照して書かれました。
そして、Spec Kitによって生成された特定の仕様、計画、タスクはここにあります:📁Spec_Kit_Chatbot/specs/001-develop-chatbot-ray。
まとめ
具体的なコーディングの重要性はますます低下しているようです。私のようにプログラミングに熟練していない者にとって、要件分析、システム設計、ビジネスモデリングといった理論的知識を体系的に学ぶことは、実践的に大きな意味を持つようになりました。
プログラミングに熟練していないプログラマーでも、フルスタックアプリ開発者になることが実現可能になりました。例えば、DDDとOpenAPIの核となる原則を把握し、「包括的な」APIサービスシステムをボイラープレートプロジェクトとして学ぶことで、LLMの利用と組み合わせれば、コーディングに熟練していない人でも信頼性の高いソフトウェアシステムを構築できると私は個人的に信じています。
ツールの使用における「創造性」は、いくらか重要性を増しています。より決定的なのは、LLMを「知識工学」構築に利用することで、ツールや知識の学習を加速させ、ツール自体を使用するエンジニアリング能力を向上させることに関わっています。
もちろん、上記は完全に私の個人的な意見です。