# はじめに
どうも、私です。
最近、というかここ数年、タイムラインを眺めていると、「プログラミングを始めました!」「LLMでアプリを作りました!」みたいな投稿を頻繁に目にするようになりました。それ自体はとても素晴らしいことだと思いますし、新しく何かを始めようとしている人を否定するつもりは毛頭ありません。
ただ、その後の様子を眺めていると、どうにも釈然としない気持ちになることが多くあります。
「動きません」「エラーが出ます」「分かりません」「何もしていないのに壊れました」、そういう質問が、携わるコミュニティで、Twitterで、Discordで、GitHubで、毎日のように流れてきます。それ自体は別に良いんです。分からないことを聞くのも大事だと思いますから。
問題は、その質問に何の情報も含まれていないことや、そもそも自分の手元で起きていることを、自分で確認すらしていないことです。
タイトルは少しばかり煽情的かもしれませんが、自分自身も普段から書いては消し、書いては消しを繰り返している身として、向いてないと切り捨ててしまう前に、もう少し言いたいことがあります。そんな話を、つらつらと書き散らしていきたいなと。
# エラーメッセージは目の前にあるのに何故か読まれません
世の中には、エラーが出た瞬間に、画面の前で固まる方々が一定数いらっしゃいます。
固まったまま、5分、10分、酷い時には30分。エラーメッセージは画面の真ん中にずっと表示されているのですが、その本文を読んでいる気配がありません。読んでいたら、その後の口から「分かりません」という言葉が出てくるはずがないからです。
Connection refused, Permission denied, Module not found, Unexpected token.
これらは何かの呪文ではなく、コンピュータがあなたに対して、丁寧に問題を教えてくれている、とてもありがたい案内です。
エラーメッセージを読むというのは、別に難しいことではありません。Connection refused 127.0.0.1:5432と書いてあれば、「ローカルの5432ポート宛接続が拒否された」と読めばいいだけですし、5432はPostgreSQLのデフォルトポートなのでPostgreSQLが起動していないか、接続情報が間違っているか、そのあたりに当たりがつきます。1分もあれば原因に辿り着ける問題に何を無駄な時間を費やしているのでしょう。
「英語が読めません」と言う方もいらっしゃいますが、refusedをリフューズドと読み下せれば、それだけで意味は推測できますし、どうしても分からなければ翻訳ツールに通せば済む話です。あなたが普段スマホで観ている海外動画の字幕、あれだって機械翻訳でしょ?同じです。
そして、信じられないかもしれませんが、エラーメッセージを読まない方々は、何度プログラムを実行しても出続けるエラーに対して、毎回最初から驚きます。「またこのエラーが出ました」と言うのですが、そら当然です。書かれていることに対処しない限り、何回実行しても同じエラーが出ますし、コンピュータは、あなたの祈りとかには反応しません。中身を変えず同一の試行を繰り返した挙句、違う結果を望むのはとても愚かなことです。小学生ですらやりません。
エラーが出るというのは本来ありがたいことです。間違っている箇所を教えてくれるものですから、感謝しながら読んで直せば済みます。逆に、エラーも出ずに動いている、けれど結果が間違っている、という状況の方が、遥かに恐ろしく感じます。エラーは敵ではありません。
# 「こう動くはずなんですけど」って、それあなたの感想ですよね
これも本当によく見かけるパターンで、本当に心底嫌いです。
曰く、「私は、ここはこういう風に動くはずだと思ってるんですけど、動かないんですよ」と。
そうですか。それで、あなたの思いと実際の挙動、どちらが正しいと思います?
答えは決まっています。動いていないのなら、あなたの思い10割10分が間違っています。
ところが、自分の認識を譲らない方が一定数居るようで、「いや、ここはこう動くはずなんですよ」だとか、「でも、こういう風に書いたんですから、こう動くはずじゃないですか」みたいなことを平然と言ってのけます。すごい自信家ですよね、感心します。でも実は違うんです。あなたの認識と、コンピュータの実際の挙動がズレているんです。修正すべきは、コードでも、ライブラリでも、コンピュータでもなく、傲慢なあなた自身です。
思いをベースに議論しても、コンピュータは1nmも動きませんし、コードを動かすのは、そこに書かれている事実です。実際に出力された値、実際に走った行、実際に発生したエラー等々。それらだけが、原因の手がかりであって、あなたの思いは、原因の特定に役立ちません。
デバッグの第一歩は、自分の思いを一旦脇に置くことでしょう。「ここは絶対こう動いているはず」と思い込んでいる箇所こそ、printでも console.log でも dbg! でも構わないので、実際の値を出力して確認してください。殆どの場合、あなたの思い込みは外れています。本当に、本当に、外れています。騙されたと思って私を信じてください。
ちなみに、デバッガを使ったことがない方も、かなりいらっしゃるようですが、VSCodeでもJetBrains系IDEでもブラウザのDevToolsでも、ブレークポイントを置いて、ステップ実行して、変数の中身を覗く、ということができます。これを覚えるだけで、デバッグの効率が劇的に変わります。printデバッグも悪くはないのですが、ちゃんとしたデバッガを使えるようになっておくと、人生の何割かを取り戻せます。暇なら覚えておきましょう。
# 詰まったら考えるより先に手を動かそう
エラーメッセージを読みました。それでも原因が分かりません。さて、どうしましょうか。
ここで多くの方が、画面の前で固まる作業に戻ります。けれど、それでは何も解決しません。考え込んでも、コンピュータは何も教えてくれません。
ここでやるべき事は、手を動かして状況を観測することだけです。
怪しい箇所の値を出力する。リクエストの中身をダンプする。条件分岐の手前で実行を止めて状態を覗く。データベースに直接クエリを投げて状態を確認する、みたいな。動いているはずと思っている部分が、本当に思った通りに動いているか、ひとつずつ確かめていく必要があります。
考えてから手を動かすのではなく、手を動かしながら考えるべきです。これは、おそらくベテランの方も全く同じことをしています。違うのは、観測の精度と、観測する場所を絞り込む速度だけです。経験を積むと最初に怪しいと睨んだ箇所が当たる確率が上がっていく、というだけの話に思えます。
さて、「闇雲に試して動いたら、それで本当に直ったと言えるんですか?」と言われてそうです。良い指摘です。実際、闇雲に値を変えていたら偶然動いた、というケースは、本質的な問題の解決には至っていません。
しかし、観測した結果から「ここの値が想定と違っていた」と特定できれば、それは立派な原因究明です。観測のないトライアンドエラーは博打ですが、観測のあるそれは、ちゃんとしたデバッグであると考えます。
考え込まないでください。手を動かしてください。コードは、あなたの思考の中ではなく、メモリ上で実際に動いています。
# 「LLMに聞いたら違うことを言ってきました」
そんな事を言うくらいなら、はなから私なんかに聞かずとも、永遠に一人寂しくLLMとイチャついてればいいと思うのですが、最近特に増えたのがこのパターンです。
「LLMに聞いたらこう書けばいいって言われたんですけど、動きません」
そうですか?うんうん、すごいでちゅね〜!それで、あなたはその実装を読みました?
LLMが生成したコードは、それなりに動きます。それなりに、です。ライブラリに破壊的な変更があれば動きませんし、APIが廃止されていれば動きません。そもそもLLMの学習データに無かったマイナーなライブラリだと、平気でハルシネーションを起こします。実在しない関数を、自信満々で提案してきたりしやがります。
それを確認もせずにコピペして、挙句、動かなかったら「LLMが嘘をついたんだ!!!!」と憤慨するのは、些か筋違いです。
LLMは便利なツールですが、便利なツールを使うために必要な能力は、依然として人間側に求められています。これは、Stack Overflowが流行った時も、Qiitaが流行った時も、ChatGPTが流行った時も、Clineに全部賭けたときも、Cursorが流行った時も、ずっと変わっていません。
LLMに頼ること自体は何も悪くありませんし、私も普段からLLMにかなりの出力を強要しています。GeminiにもOpusにも毎日お世話になっています。ただ、LLMが出力したコードは必ず自分で読みます。読んで理解して、おかしいところがあれば修正します。これをやらない人間がLLMを使うと、ただのコピペ職人が爆誕します。それも、自分が何をコピペしているかすら分からない、史上最悪のコピペ職人が、です。
ちなみに、LLMに「このコード動きません」と投げて、LLMが返してきた修正をまたコピペして、それでも動かない、というループに陥っている方も散見されます。それを何時間も繰り返した挙句、LLMはダメだと結論付ける。残念ながら、ダメなのはLLMではなく、あなたの頭です。
LLMはあなたの状況を完全には理解していません。あなたが理解した上で、適切に指示を出す必要があります。
以前にも別の記事で書きましたが、LLMがどれだけ優秀になっても、使う人間の側に何もなければ、出力される成果物も同様のものでしょう。
# 自分が何をしたいのか整理して
これも本当によく言われます。やめてくださいね。
「○○がしたいんですけど、どうすればいいです?」
その○○が、抽象的すぎてなんと言うかものすごくふわっとしている。
「Webサイトを作りたいんだけど〜」
どんなサイトを?静的サイトですか、動的サイトですか?認証認可は必要ですか?どんなコンテンツを載せたいですか?利用者は何人を想定していますか?運用のコスト感は?収益化したいですか、趣味ですか?
これらはあなたが答えるべき質問です。私が答える質問ではありません。
目的を整理するというのは、プログラミング以前のごく当たり前の力です。これができないと、コードを書く以前に何を書けばいいかすら定まりません。そんなんじゃお話になりません。
これはエンジニアリングの問題ではなく、もっと手前の自分の思考を整理して言語化する国語の問題です。プログラミングは思考を厳密にコンピュータが理解できる形に翻訳する作業ですから、思考が曖昧なままではそもそもコードに翻訳することすらままならないことは自明でしょう。
紙でもメモアプリでもLLMでも構わないので、自分が何をしたいのかを書き出してください。やりたいこと、やるべきではないこと、分かっていること、分からないこと等々。整理されていない要望をぶつけられても、こちらは何も答えようがありません。
そして、もうひとつ。課題文を読めない方も本当に多いです。
例えば、業務でちょっとしたツールを依頼する場面で、「Slackに来たメッセージのうち、特定のキーワードを含むものをスプレッドシートに記録してください」と伝えたとします。これは、「Slackからメッセージを受け取る」、「キーワードでフィルタする」、「スプレッドシートに書き込む」の3つの工程に分解できる、ごく単純な依頼です。
ところが、これが分解できない方は、依頼文を一塊のまま受け取って、最初の一歩で固まります。「何から手を付ければいいんでしょうか」と相談されるのですが、お渡しした依頼文には既に手を付ける順番が書いてあります。一文として読むのではなく、要素ごとに区切って読んでください。それだけで、何をすればいいかが見えてきます。
これはもうプログラミング以前の、国語の問題です。
それすらできないようであれば、小学生のお勉強からやり直すことを推奨します。
# 大きい問題に挑む前に小さい問題に分割して
「○○を作ってください」という課題が出たとします。例えば、社内向けのちょっとしたダッシュボード、みたいな。
ここで、できない方は、いきなり全部を一気に書こうとして、数時間悩んだ末に画面の前で固まる作業に戻ります。「データ取得をどう書いて、それをどう加工して、どうUIに表示して、認証はどうして、エラー処理はどうして…」と、全てを同時に考えようとして、結局1行も書けないのです。
私ならこう書きます。
