
AIはコードを模倣するだけです。プログラミングの核心は、深く考え、複雑な問題を解決することです。これはまさに AI の欠点であり、本物のプログラマーの価値を置き換えることはできません。
私たちが書くコードは、プログラムが実際にどのように実行されるかを完全に表現したものからは程遠いものです。次の単純なイベント リスナーを例に挙げます。
const thing = document.querySelector("#thing");
thing.addEventListener("click", () => {
console.log("this is: ", this);
});
この短いスクリプトを本当に理解するには、次の数行に直接反映されていることを考える必要はほとんどありません。
このコードはどのように動作するのでしょうか?全く分かりません。基本的なプログラミングの直感からすると、それを実行するにはインタープリターが必要であることがわかりますが、ブラウザ環境では、プロセス全体が想像以上に複雑になります。
getElementById、addEventListener、console.log などの関数はこのスクリプトでは定義されていません。外部環境によって提供されるコンテキストがなければ、彼らが実際に何をするのかを知るすべはありません。
このスクリプトは特定の環境とバージョンの組み合わせ向けに設計されている可能性が高いため、特定の状況でのみ正常に動作する可能性があります。予想されるすべての環境でスムーズに動作しますか?この結論は、単にコードを見ただけでは導き出せません。人間の経験、判断、推論が必要です。
このイベント ハンドラーは、「クリック」イベントが発生したときにのみトリガーされ、制御パターンの反転です。つまり、コードの実行フローは単純に上から下への連続的なものではないということです。
ハンドラー内では、 this キーワードはウィンドウ オブジェクトを参照しますが、これも非常にわかりにくいものです。 Window もグローバル オブジェクトであり、暗黙的に参照される可能性があります。そのため、誤ってグローバル変数を定義し、誤って他の場所で参照してしまう可能性があります。
さらに、このハンドラーは渡された引数を黙って無視します。
また、このコードはバンドラーによって処理される可能性が高くなります。ソースコード マッピングを追加で構成しないと、実行時にエラーが発生すると、表示されるスタック トレース情報が乱雑になり、問題の特定が困難になる可能性があります。
コード内の #thing は DOM 要素を参照しますが、ここでは完全に文脈外です。この構文自体は、まったく異なる言語システムの概念である CSS セレクターを指します。
最後に、対応する DOM 要素が読み込まれる前にスクリプトが実行されると、スクリプトは正しく動作しません。
これはほとんど何もしない 4 行のコードです。ご想像のとおり、実際のアプリケーションはこの例よりもはるかに複雑になります。
「JavaScript 自体には多くの問題がありますが、だからといってすべてのプログラミング言語がそうだというわけではありません」と主張する人もいるかもしれません。 「コード テキストでは実行時の状況を完全に反映できない」という点では JavaScript の方が極端であるため、私は JavaScript を選択しました。しかし、限られた信頼性の低いシステム リソース、並行処理の複雑さ、大きく異なるオペレーティング環境、システム統合、メモリ割り当て、サービスの展開、および特定の機能要件について考えると、記述されたコードは実行時のプログラムの全体像を真に反映することはできないという私の見解が依然として正しいことがわかります。
もちろん、経験豊富な人間のエンジニアである私たちは、プログラムが最終的にどのように実行されるかを完全に理解し、推論することができます。しかし、このプロセスは、コード自体に直接反映されていないすべての要素について検討することがいかに重要かつ複雑であるかを示しています。
動作しているように見える悪いコードを書くのは簡単です。本当に堅牢で適切に動作する優れたコードを書くには、はるかに多くの時間と労力がかかります。したがって、ソフトウェア エンジニアリングのワークフローは、単にコードを入力するのではなく、思考と議論を中心に展開する必要があります。参照用にテスト済みのソフトウェア パッケージやコード サンプルが大量に存在し、ほとんどのソフトウェア アプリケーション (パッケージ、プログラム、Web アプリケーションなど) が互いに多くの類似点を持っていることを考慮すると、ソフトウェア エンジニアリングの真の核心は、私たちが構築および構想しているアプリケーションを深く理解し、真にユニークな約 10% に対してソリューションを補完することにあります。
これは AI プログラミング ツールの問題を指摘しています。誰かが興奮気味にこう発表するかもしれません。「見て! かなりリアルに見えるコードスニペットを吐き出すロボットを作ったよ!」しかし、AIは考えているわけではなく、言語のパターンを予測しているだけなのです。言い換えれば、「動作しているように見える」種類の悪いコードを生成します。 AI 生成コードを使用しようとすると、次のようなことがよく起こります。
AIが実際に書いた内容を、戻って再確認し、検証する必要がありました。
少し複雑なタスクの場合、AI によって生成されたコードは、エンジニアのような判断力や設計能力がないため、ほぼ常にエラーだらけになります。
AI が生成したコードの一部を保持することになったとしても、それを検証するプロセスは、自分たちで書いたコードを検証するよりもはるかに困難になります。その理由は次のとおりです。
AIはなぜそのようなことを書いたのかを実際に説明することはできません。
多くの場合、それは厳密な方法でまとめられたコードスニペットの単なる集合であり、内部ロジックや一貫性が欠如しています。
AI は、明確で再利用可能な抽象化を構築する代わりに、さまざまな慣用句を直接インライン化する傾向があり、その結果、長くて読みにくいコードが生成されます。
その結果、理解と品質(本当に難しくて価値のある部分)を、多くの質の悪いコード(簡単に生成できるが、後で多くの問題を引き起こす部分)と交換することになります。全体的に見て、これはかなり悪い取引だ。
それに比べると、既存のツールやリソースの多くははるかに優れています。たとえば、適切に設計されたモジュールは、明確なインターフェース、詳細なドキュメント、よく考えられた抽象化を提供するため、車輪の再発明をすることなくコードを簡単に再利用できます。プロジェクト ドキュメント内のサンプル コードと Stack Overflow の Q&A は、コード スニペットがどのように機能するかについての貴重なコンテキストを提供します。オープンソース プロジェクトでは、少なくとも関連する背景情報とプロジェクト ドキュメントを提供できます。これらはすべて、AI が生成したコードよりも優れた選択肢であり、エンジニアが知恵と判断力を必要とする非常に難しいタスクに集中し、それをうまく実行するのに役立ちます。
これは、Linux カーネルのデバッグについて語ったときに Linus Torvalds が言ったことを思い出させます。
これは単に「ソースコード vs バイナリ」の問題ではなく、もっと深いところまで掘り下げた話です。重要なのは、ソースコードを見る必要があるということではありません(もちろん見なければなりませんし、優れたデバッガがあれば簡単にできます)。重要なのは、ソースコードの先にある「意味」を理解する必要があるということです。デバッガがなければ、基本的にもう一歩先、つまり個々のコード行だけでなく、プログラムが実際に何をしているのかを理解する必要があります。率直に言って、本当に難しい問題(つまらないバグではありません)のほとんどでは、デバッガはあまり役に立ちません。そして、私が本当に気にしているのは、そういう難しい問題です。残りの問題は、遅かれ早かれ修正されるであろう些細な問題に過ぎません。
コードを書く事自体は難しくないかもしれませんが、良いプログラムを書く事は非常に難しいです。これは考える人のためのゲームです。