世界を動かす技術を、日本語で。

数ヶ月間LLMを使ってコーディングした後、再び自分の頭を使うことにします

概要

  • AIを活用したSaaSインフラ刷新の体験談を紹介
  • GoとClickhouseへの移行で直面した課題と学びを強調
  • LLM(大規模言語モデル)を使った開発の落とし穴と限界を指摘
  • エンジニア自身のスキル活用とAIの賢い使い方を提案
  • ノンコーダーやAI推進派への警鐘と現状のAI開発環境への疑問を提示

AI時代におけるSaaSインフラ刷新の現実と気づき

新インフラ構築の背景とAI活用開始

  • 従来の PHP+MySQL構成 がSaaS要件に合わず、刷新を決断すること
  • 最新の LLM活用 に期待し、プロダクトマネージャー視点で要件整理・計画立案を行うこと
  • Go+Clickhouse の技術スタックを選定し、CursorやClaudeなどのAIツールを積極的に導入すること
  • コード品質よりも スピード重視 で開発を進め、顧客要望への迅速対応を優先すること
  • 開発の遅れが 直接的な機会損失 に繋がる状況でプレッシャーを感じること

LLM活用による開発の落とし穴

  • 開発初期は順調だが、 問題が次々と発生 し、進捗が停滞すること
  • エラー修正をAIに依存すると、 別の箇所で新たな不具合 が発生しやすい現象
  • 問題が複雑になるほど、 LLMの解決力が低下 する傾向を確認すること
  • コード全体を見直すと、 命名規則や設計の一貫性欠如、重複実装、設定ファイルの扱いのバラつき等が発覚すること
  • 十分なコンテキストを与えても、 AI生成コードの統一性確保が困難 であること

自分の技術力を再評価し、アプローチを転換

  • GoやClickhouseのベストプラクティス を自主的に学習し直すこと
  • コードレビューを徹底し、 品質の低い部分を手動でリファクタリング すること
  • LLMの利用範囲を限定 し、単純作業や言語変換など補助的な用途に絞ること
  • 計画や設計、主要な実装は 自身の頭脳と経験を活用 すること
  • AI依存による思考力低下 に気づき、ペンと紙や自力設計を重視する姿勢に回帰すること

LLM利用のバランスとノンコーダーへの懸念

  • 期待値を下げて LLMを学習・補助ツールとして活用 すること
  • コーディング未経験者がAIだけで開発することの 危険性と限界 を指摘すること
  • ノーコードツールと比較し、 AI生成コードの構造的な脆弱性 や混乱のリスクを警告すること
  • コードの意味が分からず、 エラー連鎖に陥る体験 の再現性を問題視すること

AI推進派・AIツールの現状への疑問

  • 最新モデルやワークフローを試しても、根本的な限界が残ること
  • 大規模データや複雑クエリなど、 AIが対応しきれないケース の存在を強調すること
  • 一貫性のない挙動やパフォーマンスの不安定さ が、実運用の障害となること
  • AIツールの導入・運用コストが高い場合、 本末転倒な結果 になる懸念
  • ベンチマークやインフルエンサーによる 過剰な期待煽り、LLM提供者による体験のばらつきへの疑問を呈すること

結論:AIは「魔法の杖」ではない

  • AI技術への期待と興奮 は持ちつつも、現状は「良いが完璧ではない」段階であること
  • 自己の思考力・設計力の維持 と、AIの適切な使い方のバランスを取ることの重要性
  • 「AIに頼り切る開発」は 混乱や品質低下のリスク を伴うため、 人間の主導性 を忘れないこと
  • 未来の進化に期待しつつ、現状のAI開発環境に対しては 冷静な目線で活用すること

Hackerたちの意見

それ、すごく共感できる。今でもLLMをたくさん使ってるけど、今は2つのルールを守ってる。* 深い考えを彼らに委ねないこと。例えば、難しいデザインの問題を考えるときは、自分でやる。* 彼らが生成したコードはしっかりレビューして修正する。行ごとに確認して徹底的に編集するよ。彼らが生成するものは冗長だったり、過剰に防御的だったりすることが多いからね。プロンプトでこれを修正できるかどうかは関係ない。将来のメンテナンス性を自分が責任持ちたいから。「バイブコーディング」(生成されたコードを気にしないこと)は、なんか嫌な感じがする。このアプローチはいい気分にさせてくれる。そして、繰り返しになるけど、今でもたくさん使ってて、コーディングがずっと速くなったよ。

生成されたコードを深くレビューして修正する。行ごとに確認して徹底的に編集する。これが問題なんじゃない?これをしなきゃいけないなら、時間を節約できてるの?

あらゆる深い分析をAIに委任しているけど、それは具体的な実装ステップや検証基準を持った詳細な計画をデータに基づいた再現可能なレポートで作成するためだよ(つまり、「このJSONデータを生成するスクリプトと、このデータをレンダリングするための別のスクリプトを生成して」)。計画には特定の目標があり、それがレポートに反映される(「移行した合計は100%であるべき」)。これはまだ反復的なプロセスで、生成物や計画はエッジケースを見逃すことがあるから、一般的に計画はそういうものなんだ。計画を立てるのに1時間か2時間かかるけど、私がやると一日中かかることもあるし、場合によっては数日かかるかもしれない。ADHDの脳が退屈に反発するからね。AIは、ただその場でやってしまうときには素晴らしい仕事をすることがあるし、時にはタスクを指示して一発でやってしまうこともあるけど、詳細な計画があるときに最も効果的に機能する。さらに、計画書を指さして「そうして」と言えるのは本当に満足感があるよ。

LLMに対する「オールイン」な考え方が理解できない。自分はiOS開発者で、今まで通りそれを続けてる。今の違いは、デザインに基づいて一回限りのビューを素早く生成するためにLLMを使うこと。これはアプリのコアビューでも、コア機能でも、重要なものでもない。新機能を紹介するビューとか、ウィジェットのインストール方法とか、ランダムなことだ。これまでは複雑さに応じて30〜60分かかってたのが、今は5分で済む。アプリのランディングページを作るときにも使ってる。ウェブ開発が嫌いで、LLMはそれが得意だと思う。なぜなら、ソフトウェア開発に関するトレーニングデータの90%がそれに関連してるから。だから、大きな変更を加えて手動でレビューして、他のプロジェクトと同じようにgitにコミットしてる。人々が数時間も完全に道を外れて大きな問題にぶつかり、再スタートするのは信じられない。代わりに、計画的なアプローチを使って常に前進することができるのに。

人々はブログや動画のために「オールイン」みたいな愚かなことをする。ニュアンスや合理主義は、エンゲージメントを得られない。

まさに私の考え。これに関してはオールオアナッシングな考え方が多いみたい。私にとって価値があるのは、平凡で繰り返しの作業を簡素化し、自動化する能力。自分が設計した小さな関数やインターフェースを実装することや、ドキュメントやテストを最新の状態に保つためのリンティングツールを作ることなど。これらはすべて、私の時間を無限に節約し、かなりの精神的安定をもたらしてくれた。

LLMに対する「オールイン」メンタリティが理解できないな。ちょっと辛口で皮肉っぽく言うと(この特定の投稿についてじゃなくて一般的にね)、結局コンテンツを生み出すだけなんだよね。人々に話題を提供する。自分の個性を絶対的なもので定義するけど、実際の世界は無限のグラデーションで成り立ってる。何かに「オールイン」して、その素晴らしさについて書く。1ヶ月後には「なんでこれをやめることにしたか」って、その「オールイン」したことについて書いて、どれだけホッとしたか、良くなったかを語る。ほんとに疲れ切ったギミックだよ。「なんでSQLを捨ててNoSQLにしたか、もう振り返らない」 「なんでNoSQLが俺を裏切ったか」 「FlakeyCoの私たちがこの新しいJavaScriptフレームワークにオールインしてる理由!」 「なんでその新しいJavaScriptフレームワークを捨てたか」 この同じ退屈なサイクルがここで何度も繰り返されてるけど、なぜかみんなそれに引っかかるんだよね。作成者が悪い判断をしてる可能性が高いっていう大きな指標だし、あまり信じるべきじゃない人だと思う。普通の人は、何かに「オールイン」する必要があるって感じるんじゃなくて、合理的な判断を使ってるから、日常生活でLLMを何度も活用してるよ。それでも、実際のコードにはほぼゼロパーセントしか貢献してないけど、素晴らしいリソースではあるんだ。

さまざまなツールの有用性は、その人と問題によるよ。異なる問題に取り組む2人の仮定の人を考えて、例えばCursorが役立つかどうかを見てみよう。もしあなたが: * 10年のPython開発者 * 非常に大きくて複雑なPythonコードベースでほぼ全ての作業をしている * そのコードベースに完璧に調整されたPyCharm IDEを何年も使っている * バグに対する耐性が非常に低い(安定した製品で、急いで壊す余地がない) なら:LLMはあなたを10倍にはしないよ。CursorのようなIDEは、使い方を学ぶまでの間、あなたを非常に遅くする可能性が高い。もしあなたが: * 1年のJS(React、Next.jsなど)開発者 * 新しいアイデアでほぼゼロから始める * 以前のIDEの好みがあまりない * バグに対する耐性が高く、ただ出荷して試したい なら:LLMはあなたを10倍にするよ。CursorのようなIDEは、すぐにあなたをすごく速くしてくれる。

LLMの能力を過大評価するのは、探求しているときには自然なことだよ。約2年間、スタックオーバーフローの部分的な代替や短いコードスニペットを得るために使ってきた。Claudeコードが出たときは、責任を増やしていったけど、結局混乱しちゃって、今はどこがうまくいかないか理解して、アイデアやアドバイスのためにLLMをもっと使うようになった。この流れは結構一般的だと思う。

いろんなことをやってるよ、iOSやウェブも含めて。君が言ったように、LLMの結果は二つの間でかなり違う。LLMの出力がコンパイルすらできるかどうかも信じられないし、動くかどうかなんてなおさら。昨晩も、CMVideoFormatDescriptionGetCameraIntrinsicMatrixっていうAPIを使うように言われたんだけど、そのAPIは存在しないからね。トリッキーなSwift 6の並行処理のことを扱うときに、かなり深い穴を掘るのも得意だった。一方で、最初の試みでうまく動くNext.jsアプリを丸ごと生成してくれた。結局、すべてはそのトレーニングデータ次第だね。

LLMを使ってタスクを分解することができるよ。君が言ったように、シンプルでトレーニングデータに解決策があるタスクは時間を節約できる。世の中のほとんどのコードは接着剤みたいなものだから、統合や構成に関するトレーニングデータがたくさんあるんだ。これを全体として捉えれば、ほとんどの開発作業を30-60分から5分に短縮できるかもしれない。

私の経験に似ていて、小さなタスクにはうまく機能して、検索の代わり(ほとんどの場合)や多くのボイラープレート作業をこなしてくれる。すごく複雑なプロジェクトが一つあって、これにはLLMを使えないし、使わない方がいいと感じてる。さらに、できるだけ一回のセッションでコードを生成する方が良いと思う。他のLLMやセッションを試すと、すぐに劣化してしまうから。そうなると、重複した関数や行き止まりのコードが見えてくる。

LLMに対する「オールイン」の考え方が理解できない。彼らは文字通りすべての作業を代わりにやってくれるバーチャルアシスタントとしてマーケティングされている。でも、もし本当のことをマーケティングしたら、人々はそのコストに見合わないことに気づくと思うし、ウェブを検索したり、クラウドソースで回答を得る方がずっと有益だと思う。

LLMはiOS開発に関しては、かなり当たり外れがあるなって感じてる。SwiftやSwiftUIの変化が早いのと、Appleのドキュメントがひどいのが一因かもしれない。スキャフォールディングや素早い反復のために、サクッとビューを生成するのにはすごく便利なんだけど、非同期コーディングや複雑なビジネスロジックになるとすぐにダメになっちゃう。方向性を示してくれるのは本当に役立つけど、誤解を招いたり、妄想の迷宮にハマることもあるから注意が必要だね。

これには同意する。最近はLLMを使って新しいことを学んだり、一般的なAPIのクライアントコードを生成するのに役立ててる(特に最近はboto3)。Windsurfを使ってdocker composeファイルの基本的な変更を手伝ってもらおうとしたけど、正しくできなかった時に少しやる気を失った。小さなウェブアプリの動作するプロトタイプを作ることはできると思うけど、それだけでは足りない。私にとってLLMはdevopsにとってゲームチェンジャーだけど(APIの知識は今やそれほど重要ではない)、それでもChatGPTからのコピペを続けてる、どんなに原始的に見えても。根本的に、長期的な意思決定が本当に自分よりも得意なボットに思考を委ねるのは良いアイデアではないと思う。自分が意思決定者である限り、インターフェースがどのようにあるべきか最終的な判断をしたいはず。オブジェクト指向のインターフェース(例えばAWSとのインターフェース)を慎重に定義して、LLMに実装の詳細を埋めてもらうという良い経験をしたことがあるけど、それが「バイブコーディング」とは言えないかもしれない。

著者と似たような経験をした。カーソルやコパイロットは「スマートオートコンプリート」や「(これをする小さな関数を書く)」、そして迅速なバイラルプロトタイプには素晴らしいと思った。でも、LLM主導のコードベースに1週間入った後、すべてがスパゲッティコードで、進捗が止まったことが明らかになった。この文章は最先端の状態を完璧に捉えている。将来的には改善するかもしれないけど、2025年5月の時点ではこんな感じ。

わかるし、著者と同じ問題を感じてる。いくつかのトイプロジェクトに取り組んでいて、その90%をLLMに頼ってる。結果は「手作業」でコーディングするよりも10倍速いけど、アーキテクチャは悪くてちょっと異質。まだ続けてるのは、LLM駆動のコードが未来の方向性だと確信しているから。これらのツールは本当に強力だけど、大きな混乱を生まないように使い方を学ばなければならない。現在、アーキテクチャをこうしたりああしたりと改善するように繰り返しプロンプトを出してるけど、結果はまちまち。もしかしたら、より良いプロンプトエンジニアリングが答えかも?アーキテクチャやガイドラインをもっと明確に書き出す?今のレイテンシが10分の1になり、ツールが10倍良くなったら、どんな体験になるか想像してみて。

「10倍良くなる」ポイントに到達できることを願ってる。今の問題は、人々がLLMをまるですでにそこにいるかのように宣伝していることだと思う。そしてそれは提供者だけでなく、完璧なワークフローやプロンプトを見つけたと思っているXやRedditなどの熱心な人々にも当てはまる。「もしかしたらより良いプロンプトエンジニアリングが必要」と言ってるように、私たちは「自分がうまく使えていないだけ」と思うように条件付けられている気がする。もしかしたら、ツール自体がまだそれほど良くないのかもしれない。

ここがLLMの真価を発揮するところで、グリーンフィールドプロジェクトのプロトタイピングには最適だけど、プロジェクトが本番に近づくにつれてその10倍の効果は薄れていく。アーキテクチャに対して本当に意図的である必要があるし、後からコアデザインの問題を修正すると、10倍が0.1倍になっちゃうこともあるからね。

現在のところ、複雑なコードベースに耐えられる唯一の使用パターンは、高度な音声認識としての利用だけど、音声なしでって感じかな。それに関しての主な問題は、英語で物事を表現するのがしばしば冗長すぎるから、音声なしだと手作業でやった方がずっと早いことが多いんだよね。

アーキテクチャやガイドラインをもっと明示的に書く?うん、「もし(条件)なら(アクション)をする」みたいに、もっと明示的にして…あ、待って!

できることの一つは、自分が持ちたいクラスやメソッドを定義して、LLMに実装させることだよ。難しいことについては、空のメソッドの中に実装方法についての追加メモを残しておくといい。こうすることで、全体像を考えながら、LLMには得意なコード生成をさせることができる。私は主にLLMを、すごく早くタイプする、ちょっとお調子者のジュニアエンジニアとして扱ってる。ドキュメントをすぐに読めるけど、頼まれてない機能を実装しちゃうこともあるんだよね。良いところは、生成されるコードがすごく簡単に作れるから、大きな部分を捨てて再生成することもできるってこと。LLMの助けを借りてデータセットを処理するコードを書いたんだけど、うまくいかなかったから、全部削除して、いくつかのアプローチを使って何度も書き直したら、やっと動くものができた。もし全部自分でタイプしてたら、やり直さなきゃいけないのが残念だったと思うし、たとえそれが正しいことでも、やり直すのにためらってたかもしれない。

だから「コーディングレビュー」セッションをやるんだ。そして恐怖が始まる。うん。これについては前に話したことがある。数ヶ月間Cursorを使ってたけど、得られた効率の向上はレビューで瞬時に消えた。彼が生み出した微妙なバグや明らかなバグが次々に見つかったから。バニラのVSCodeに戻って、今でもコパイロットを使ってるけど、特定のことをやるようにプロンプトを出すときだけ(テストのスキャフォールドを作るとか、これらのカラムでマイグレーションを書くとか)。Cursorのタブ補完は最初は魔法のように感じたけど、私にはその輝きが失われた。

エージェントにどんなガードレールを設定したの? SOLIDに従ったり、リンティング、100%のコードカバレッジ、テンプレート、実装前のアーキテクチャ文書、アーキテクチャルール、DRYのクリーンアップサイクル、コードレビューガイドライン(整合性に関する厳格なルールを含む)、別のLLMによるレビューなど?

カーソルのタブ補完は最初は魔法のように感じるけど、私にはその輝きが失われた。ここで好きなことは、同僚を見ていると、カーソルが彼がちょうど削除したものをタブ補完しようとする時で、時々彼は反射的にそれをやってしまうこと。

多くのLLMマキシマリストが気づいていないことは、ほとんどの人にとってのボトルネックはコード生成じゃなくて、コード理解だってこと。何かを作るスピードを倍増させたかもしれないけど、その分コードレビューやテスト、コードベースのメンタルモデルを作るのに倍の時間をかける必要がある。コードベースを維持したいなら(バグ修正やリファクタリングなど)、これをやらなきゃいけないんだ。

それは違うよ。悪いプラクティスかもしれないけど、中央値の開発者は自分が使っている依存関係の内部について全く気にしないってことを考えてみて。彼らはインターフェースや、それが機能するかどうかを気にしているだけで、実装にはあまり興味がない。LLMによって生成されたコードは、ランダムなnpmパッケージやRustクレートを取り込むのとあまり変わらない。私たちはその欠点を理解しているけど、そのプラクティスが人気な理由があるんだ。

完全に同意!コードを読むのは書くより難しいし、書くよりも読むことや理解しようとする時間の方が多い気がする。でも、最近LinkedInで会ったCEOが言ってたんだけど、「私たちはすでに生産性を向上させ、喜びを増やす可能性を持っている。それを実現するためには、ソフトウェアエンジニアリングが何であるかを見直さなければならない。それは見た目以上に難しいかもしれない、なぜならその機会は何十年も目の前に隠れていたからだ。意思決定の仕方を再考し、コードを読む必要をなくすために文脈ツールを作り、活用することから始まる。」って。文脈って、AIがSWEチームにとって全く新しい複雑さの層をもたらすってことだよね。すごく混乱してる。

LLMは自分のコードを説明してくれるのが結構得意だなって思った。

そういう洗練された自動コードエディタに対して、過剰な賛美をする人たちに対して、同じことを考えたことがよくある。

最近、いくつかの新しい小さなプロジェクトでLLMを試してみたんだけど、思った以上に成功したよ。でも、効果的に使うために使い方を調整する必要があった。まず第一に、LLMを経験の少ないプログラマーとして扱うこと。盲目的に信じず、常に変更をコードレビューすることが大事だよ。これにはいくつかの利点がある。1) コードベースと常に接触しているから、必要なときにあまり苦労せずに深く掘り下げられる。2) エラー(時には大きなもの)をすぐに見つけられて、簡単に修正できる。3) 自分の仕様に対するエラーもすぐに見つけられる。時々、細かいことを忘れていて、レビューのときに気づくことがあるし、もしかしたらLLMが実際にそれを処理していて、ドキュメントを更新するように指示できることもある。4) LLMのためのガイドラインを少しずつ調整できるから、同じ「間違い」(間違った技術的決定)を繰り返さないようにできる。時間はバイブコーディングよりもかかるけど、時間が経つにつれて減っていくし、自分でやるよりはまだマシだよ。LLMを使うことで私にとってもう一つ重要な利点がある。私はコードを書くだけじゃなくて、実際には他にもいろいろなことをやっている。電話をかけたり、ドキュメントを書いたり、要件を議論したりね。コードを書くために戻るには、メンタル状態を変えたり、プロジェクトの構造やAPIの使い方など、必要な知識を思い出さなきゃいけない。もし2時間のコーディングができればいいけど、変更が小さいと、それが私が大半の時間とメンタルエネルギーを使う部分になってしまう。あるいは、LLMに変更をお願いしてレビューすることもできる。すでにできているコードを見るのはエネルギーが少なくて済むし、思い出すのにも役立つんだ。

いくつかの場所では、文字通りソフトウェアエンジニアにLLMを使わせることを強制してる。カーソルやコパイロットには使用統計を見る機能があって、こういう会社ではその統計が最終的に解雇基準として使われるだろうね。公平に評価してみたけど、色々な理由で好きじゃない。コードの質がその一つ。強制的に使わされてから1ヶ月ほど経ったら、自分のスキルが加速的に衰えていくのを感じた。解決策を考え出す代わりに、LLMに頼って思考をオフロードするようになっちゃった。簡単なことにはまあまあ使えたけど、ループにハマるのがすごく簡単だった。生産性が上がった感じは全くしないけど、うちの会社ではそれを理由にスプリントの負荷が大幅に増えた。LLMにはほとんど宗教的な質が伴ってる。特に質の悪い開発者や、上層部の技術に疎いバカたちの間で特にそう感じる。単純な悪いコードを超えた重大なセキュリティの懸念がある。私にとっては、ハイプサイクルの最大値の指標がすべて揃ってる。確認したければLinkedInを見てみて。大手AI企業が核エネルギーを構築し始めない限り、これらのモデルを運用するのは最終的に高くつきすぎて利益が出なくなるだろう。ターボオートコンプリートとしては存在し続けるだろうけど、それ以上はない。トランスフォーマーモデルには根本的な限界があって、80年代のニューラルネットワークのように、よりニッチになって他の場所では死んでいく。WYSIWYGやノーコードのように、30年後には再びフェニックスのように立ち上がって、開発者に「失業」をもたらすだろう。水がなくなったときに誰が裸で泳いでいたのかを見るのが面白くなるね。

カーソルの使い方はオートコンプリートや小さなスニペットに限られてる。それでも、自分のスキルが衰えていくのを感じる。使わなければ失うっていうのが認知のルールだね。

1ヶ月ほど強制的に使ってたら、自分のスキルが急速に衰えてきた気がして、「コパイロットフライデー」ってルールを自分に作ったんだ。$DAYJOBでこれが起こらないようにね。

これはこの議論に関連するダイクストラの「自然言語プログラミングの愚かさについて」という古くて素晴らしい記事だ。主張は、プログラミングや数学などの形式言語が許す精度が、情報処理の進歩を可能にする鍵だったということ。つまり、LLMでのバイブコーディングは、うまくプロンプトできるシャーマンだけが知るブラックアートにコーディングを変えてしまうだろう。[1] https://www.cs.utexas.edu/~EWD/transcriptions/EWD06xx/EWD667...

LLMはコーディングにはまあまあだけど、大規模になるとごちゃごちゃしたものを作る。これって、Dreamweaverとかの時代を思い出させる。みんなはUIコンポーネントをキャンバスにドラッグ&ドロップするのがどれだけ早いかを楽しんでいて、そのツールがHTMLコードを生成してくれた。最初は素晴らしかったけど、何かが正しく動かなかったときは、そのツールが生成したスパゲッティHTMLコードを何時間も見ていた。少なくとも当時は、Dreamweaverは決定論的なロジックを使ってコードを生成していた。今は、幻覚を引き起こす能力を持ったAIがいるんだ...