あなたが「バイブコーディング」をしているのを見抜ける
(alexkondov.com)- 最近、チーム内でLLMが生成したコードだとすぐ見分けられる
- こうしたコードはプロジェクト固有の規約を守らないままでも明快で、テストもよく書けている
- 様々な既存のパターンやライブラリを無視して、独自に新しく実装してしまう
- ソフトウェア開発で速度だけを追い求める傾向が強まることへの懸念が高まっている
- 結局、重要なのは品質と一貫性、そして保守可能性である
バイブコーディングの痕跡
- 最近、チームメンバーが書いたコードの一部が明確で機能的に完璧に見える一方、プロジェクト固有の規約を守っていないためLLMが生成したとすぐに分かる
- たとえば、すでにプロジェクトにデータフェッチライブラリがあるにもかかわらず、すべての例外ケースを扱うHTTPリクエスト実装を直接書いている
- 既存のモジュールのユーティリティ関数を繰り返して新たに作り直したり、モジュール単位の設定変更メカニズムがあるのに、グローバル設定を変更してしまう
- 関数型でコードを記述する文化が根付きつつあるにもかかわらず、クラスベースのコードを新しく書いている
- このようなコードは何年も前には人間が決して書かなかったであろうスタイルだ
保守性とソフトウェア原則の重要性
- ソフトウェア開発では、長期間保守可能なパターンと標準を確立するためにこれまで努力してきた
- 実際に動くだけのコードは誰でも作れるが、長期的な運用と修正が容易なコードこそ真の挑戦だ
- 重要なのは機能実装そのものではなく、時間が経っても保守できるコードベースが鍵である
- 「バイブコーディング」はこのような哲学と基準を崩す可能性がある
速度だけを最優先にすることは?
- 喫茶店で新しいバリスタが慌ててコーヒーをこぼす様子にたとえ、速度への執着が正しい結果をもたらさないことを強調している
- 今日の開発チームも同様に、あまりに急いで新しいソフトウェアを作ろうとして品質低下が起こる
- 人々が本来求めるのは、少し時間をかけてもちゃんとした成果物だ
- 本来、速度だけを追い求めるのは非開発職の問題だと考えていたが、同僚の開発者たちも原則を捨てて速度だけを追う現実に失望を覚える
本当に望むもの
- コードをIDEにどう取り込んだかは重要ではない
- 重要なのは開発者が品質に意識を向ける態度である
- LLMがすばらしい技術的イノベーションであることは認めるが、なお実際のソフトウェアを作る責任は開発者にあることを強調している
- 「より良いプロンプト作成」「適切なライブラリ指定」「例の提示」「小さなファイル単位での作業」など、具体的な既存の原則を理解して活用することを勧める
- コード品質と保守性をモデルの「重み」にだけ任せないよう注意を促している
2件のコメント
Hacker Newsの意見
既にプロジェクト内にあるデータフェッチ用ライブラリがあらゆる例外ケースをカバーしているなら HTTP フェッチ実装を新しく作り直したり、既存のユーティリティ関数モジュールがあるのにわざわざ再実装したり、グローバル設定を個別モジュール側で変えられるのに変更しなかったり、普段は関数型のやり方を使っているのに新しくクラスを作ったりしない、そんなチームで働いてみたい、でも実際には多くの開発者がこういうことを頻繁に繰り返している
正直に言うと、大規模プロジェクトで文書化が不十分だと上のようなことは本当に簡単に起こる。私が関わっている学術研究プロジェクトのコード文書は、コード自体がセルフドキュメントになっているという前提で、CMake の設定やビルド、ベンチマーク方法が少し触れられている程度だ。内部ルールや慣習のようなものは実際に触れながら把握するしかない。新しい人が入ると、既に実装済みの機能をまた作ったり、グローバル設定を変えてしまったりすることが多い。結局、コードベースをインデックスして LLM に直接聞くのが最善になる(主要メンバーはもう去っていたり、返事が来るのがかなり後だったりする)
著者の要点を外していると思う。もし速度が最高の徳目なら、そういうことはこれからも繰り返される。速度が絶対的な価値なら、生産量が幾何級数的に増えない限り技術的負債は相殺できない。速度以外の要素も重要なら、負債は賢く管理して返していかなければならない。だが最近は、ただ大きな負債を抱えたまま何とかなるだろうという空気を感じる。そして多くの人は実際、負債管理があまり得意ではない
機会さえあれば毎回車輪の再発明をして、期待される慣習を無視したり、パターンを混在させたりすることはよくある。著者はこれを "vibe coding" と呼ぶのだろうが、実際には LLM だけの問題ではなく、誰にでも、急いで結果だけを出そうとしたり経験が浅かったりすると起こる現象だ。"チームの誰もそんなふうには書かないコード" という表現を見ると、誰か特定の人物に向けた不満の可能性もある。この見方を他の場面に適用するのは慎重であるべきだ
ORM ライブラリをさらに追加する開発者も見たことがある。最初の ORM で十分なのに、「最近ホットだから」という理由で2つ目を入れるケースだ。開発者であれ LLM であれ、それぞれにバイアスがある。プロジェクト内のルールやパターンを把握し、その枠の中で作業するのは非常に重要だ。文脈を考えずに自分の流儀で作るのはとても危険だ。人間の場合はコードレビュー文化やコードを読む習慣を促すことで対処できるが、LLM の場合はあらゆるパターンとルールを明確にガイドしなければならない。そうしないとプロジェクトと噛み合わないコードを作る危険が高い。重要なのは、価値観と明確な基準を明示的に設定することだ
私はそういう良いチームで働いた経験がある。2〜4人規模で動く、重要度の高いプロジェクトが多かった。そういう環境では、品質と速度のバランスを取る開発文化や合意を作りやすい。そういうチームでは、人間であれ LLM であれ、上のようなコードの PR が承認されることは絶対にない
個人的には、LLM はとてもジュニアな開発者だと思っている。仕事はうまくやろうとするし指示にも従うが、コードベースやパターンへの理解が足りない。全工程を直接案内し、潜在的な誤りまで説明してやる必要があり、具体的で小さな単位の作業を与えて、コードを細かくレビューしなければならない。私はまず頭の中でデータモデルを描いてからコードに入るので、具体的な説明が重要だ。1つの不文律として、常にファイル先頭にブロックコメントを入れてそのファイルの内容を説明させている。これはセッション再開時の2つ目のプロンプトのように機能する。このやり方は「魔法みたいだ」という感じはないが、うまく回る。ただ途中で30%くらいはコード整理、リネーム、リファクタリングをしないと見栄えのよい水準にはならない。それでも LLM があるおかげで、完全に手で書くよりはずっと速く仕事ができる
"ジュニア開発者" や "コパイロット" という表現では、LLM の長所と短所の両方をうまく捉えきれないことがある。普通の人間と違って簡単に忘れたり、非常に初歩的なミスをしたりする一方で、私よりうまい部分(たとえば配列まわりの off-by-one のような問題)もある。そしてインターネット上のほとんどすべてを百科事典のように知っている。実際に使ってみた感想として、LLM は猟犬に似ていると思う。主人が狩りを主導し、最後は自分で仕留めなければならない
LLM とジュニア開発者の違いは学習能力にある。ジュニアは徐々に学び、成長できるが、LLM はそうではない。プロンプトに指示を多く入れるほど、より多くを忘れて一般的な返答に戻ってしまう確率が高くなる。プロンプトを新しく始めるたびに、最初から案内し直さなければならない
LLM はインターネットでコードを検索してコピペするのと大差ないように感じる。結局のところ、開発者がコードを自分で点検して正しく動くか確認しなければならない。最近は目の健康のために20分単位で作業して休む必要があり、効率がいっそう重要になった。LLM は人間よりコード生成が圧倒的に速いので、基本的な領域だけ任せても大きな利点がある。今は Unity C# と LINQ で SIMD 用の構造体を生成しているが、単に LLM に欲しい条件を伝えるだけで、自分でコピペするよりずっと速く望むコードや文字列を得られる。AI を HUD のように使うという感覚が実感としてある。プログラム全体を作る AI より、小さな単位で強力な開発補助ツールが必要だ
私にとって LLM は StackOverflow よりはるかに良い代替だ。気になることをすぐ質問すれば正確に答えてくれる。その答えを参考にして自分のコード向けに書き直したり、関数だけ作らせたりすることもある。コピーする前には必ずコードを完全に理解しようとする。ときどき、40万行の PR をよく知らない言語でオープンソースプロジェクトに投げるほうが、正直で品質重視の仕事をするよりキャリアに有利なのではないかと考えたこともある。実際にはスキルより年次(Years of Experience)のほうが重視される現実があるからだ
LLM にうまく作業させるには、思考ではなく実際のコーディング段階だけに限定するのがよかった。タスクを細分化し、具体的な仕様、修正するファイル、参考例の場所などまでできるだけ詳しく伝えるほど適用率が上がる。そこまで細かすぎる必要はないが、手がかりが多いほど成功確率は高い。できあがったコードも
git add -pで塊ごとに自分で確認する。準備とレビューには時間がかかるが、1人で全部書いたり雑なコードをそのままにしたりするより、確実に時間とエネルギーを節約できるVibe coding の最大の危険は、実力のある開発者は少し速くなる程度で済むのに対し、実力不足の開発者ははるかに速い速度で大量の悪いコードを生み出してしまうことだ。問題は、そうした開発者が vibe coding を通じて実力を伸ばせるのか、それともそのまま停滞するだけなのかという点だ
経験上、mediocore(平凡な)開発者でも非常に速く悪い開発者になり得る。理由は、誤った自信とコード生産量の急増だ。AI が作ったコードには、全体アーキテクチャや情報の流れ、単一責任原則への配慮がほとんどない。安全なコードにするため、例外を投げる代わりに placeholder を返すような構成になりがちだ。その結果、呼び出し側コードは戻り値が placeholder かどうかを毎回確認しなければならない。そもそも入力パラメータがよくないと、AI が勝手に直そうとして
gather_parameters → call → process_resultsの構造を無視する。そしてテストの段階まで行くと、問題はさらに大きくなるこれから多くの開発者が、net-negative programmer(存在自体がプロジェクト品質を下げる開発者)という概念を再発見することになるだろう
私が見るに、ここで最も不足している資源は caring、つまり気にかける姿勢だ。vibe coding 自体が無関心の原因なのではなく、AI はただの道具にすぎない。著者が挙げたすべての問題は人間のジュニア開発者にも同じように当てはまり、もう少し丁寧にガイドしたりコミュニケーションしたりすれば改善できる。AI のせいで品質への関心が下がるとは思わない(もともと関心のない人は昔からそうだった)。よくある反論として「ジュニアを育てる機会を失う」というものがあるが、余力がなくて AI を当座のしのぎとして使う場合も多い(採用がうまくいっていない私のスタートアップもそうだ)。AI ツールによってソフトウェア品質の基準が変わる可能性はあり、この点は今後さらに変化の余地が大きいと思う
LLM は現在の状態だけでなく、過去のコミット履歴まで文脈として活用できるべきだ。多くのコードベースはパターン A から B へ段階的に移行中で、さまざまなパターンが共存している。移行は一度に完了できないため、古いものと新しいものが長く混在し続ける。HTTP の例のように、LLM がパターンを認識しても、どちらに従うべきかは運次第になってしまう
20年以上にわたり合併、改名、買収などを経験してきた大規模コードベースで働いたことがある。非常に古い API 呼び出しの例が残っていて、実際にはもっと新しいコードが別に存在するが、特定顧客向けに残してあるものも多い。文書がまったくない類似 API も多く、欲しいデータを得るにはどれを使えばよいのか一つひとつ探さなければならない
CLAUDE.mdのようなファイルで「このパターンには従え、あれは避けろ」と明確に案内するのも1つの方法だそれより、各部分ごとの作業方法や例を非常に具体的に伝えるほうが効果的だ
問題は、こうした文脈認識力そのものが vibe coding をしている人にはかなり不足していることだ。多くの人は LLM 以前の段階でコーディング経験が足りない
こうしたことが可能なのは、コミットメッセージがきちんと書かれている場合に限る。実際には「このファイルを修正」「バグ修正」みたいなメッセージが大半だ
LLM を活用する際、リンター、フォーマッター、厳格な型チェックのような自動化ツールは非常に大きな助けになる。特にコードスタイルや暗黙ルールを知らない人(あるいは LLM エージェント)からコード貢献が入るとき、自動化された方法でコードを検査し、可能なものはその場で直せる。テストも同様だ。自動化された検証体系は、人間であれエージェントであれ、品質維持に非常に有用だ
ただ、そうしたツールが実際には記事で言及されている vibe coding の事例の大半を防げるとは思わない
こうしたツールは、問題を覆い隠したまま表面だけをきれいにしてしまうこともある
主要な AI assistant はどれも、こうした問題を緩和する方法を既に標準で備えている。Claude Code の
/init、Cursor の/Generate Cursor Rulesなどで、単純な context engineering よりも自動化された形で組織全体に適用できる。結局、こうしたツールが開発コミュニティをどう分断していくのかも興味深い論点だ実際には、
CLAUDE.mdにどれだけ明確に書いても CC(Claude Code)が無視することは多い。会話が続くほど同じ問題を繰り返している感じがあり、まだ完全に満足できる解決策は見つかっていない。だからこのアーティクルを単なる AI 反対論として片付けるのは正しくないと思うCursor を再評価しているところだ。期待したほど速度が出ない理由は、些細な誤り(LM が
:を,に変えるようなこと)だけではなく、コードベースが大きすぎて古く、品質のばらつきも大きいからだ。LLM は結局、最もよく使われている(= 良くない)パターンをより頻繁に取り込む。明確に「この部分を参考にしろ」と指示しても、コードベース全体の影響を受けてしまう。ルールとして指定しても、プロンプトに直接埋め込むのと大差ないように思える。解決策があるのか知りたい問題の核心はツールではなく、vibe を重視する「コーダー」のほうだ。気にもかけず、コードの書き方も甘い
私の経験では、ほとんどすべての問題は限られたコンテキストウィンドウと、最適とは言えない "context engineering" の結果だ。LLM はグローバル関数など重要な文脈が適切に渡されれば比較的うまく活用する。問題は、どの文脈を途切れなく維持しながら提供するかだ。今後は sub-agent のような形で、この点には大きな進展があると期待している
この話は全体として正しいと思う。LLM を使う最良の方法は、コンパイラがアセンブリより一段高いレベルを提供するのと同じように、要求と入出力を明確に説明して、論理的な翻訳としてコードを作らせることだ。だから入力の混乱(エントロピー)を最小限に抑える必要がある。LLM は本質的に translation engine だ。「生成」ではなく「翻訳」に使うほうが効率的だ。それでも、より賢く直感的に進化したモデルは定期的に現れており、そのぶん気を遣わなくても結果は良くなっている。結局いつかは、どんなタスクでも LLM が人間開発者より良い結果を出す時代が来るだろうし、人間の他の役割についても同じことが起こるだろう
誤った比喩だ。LLM は自然言語を高水準コードへ「コンパイル」するエンジンではない。プログラミング言語と機械語は明確で一貫した意味体系を必要とするが、自然言語はそもそも抽象化の階層が違う。同じ LLM でも、新しいシード値やバージョンでは異なる結果が出ることがある。一方でコンパイラは、同じ入力なら常に必ず同じ出力を返さなければならない
LLM がコンパイラのような抽象レイヤーだという考えには同意できない。実際のところ LLM は、ただの任意トークン生成器にすぎない。LLM を使って作られた成果物で、本当に使い物になるものを見たことがない。シンギュラリティやデータ無限確保のようなテクノ楽観主義には現実的根拠が乏しい。結局、高品質データの確保には莫大なコストがかかる。現時点では希望的予測に意味はない
「多くの人は良いコーヒーより、速くて安いコーヒーを求める」ということを、著者よりも遅れて理解した。現実には大半の人が品質より速度と価格を重視する
本文よりHNの投稿のほうがずっと甘い