先月、あるAIアシスタントが本番プロジェクト用のPythonスクリプトを生成しました。出力されたコードはエラーなく動作し、データも問題ないように見えました。しかし、手動レビューを行ったところ、データベース呼び出しの中にN+1クエリパターンが潜んでいることが判明しました。小規模なデータセットであれば、そのコードは問題なく動作します。しかし、それを数千件のレコードにスケールアップさせると、アプリケーションは親オブジェクトに対して1つのクエリを発行した後、関連データに対して数千件もの追跡クエリを発行することになります。その結果、ユニットテストでは決して検知できない、致命的なパフォーマンスの急落を招くことになります。
これが現代のソフトウェア開発の現実です。AIツールは今や、人間には到底及ばないスピードでコーディング、デバッグ、アーキテクチャの提案を行っています。その速度は本物です。しかし、それはあなたの仕事のあり方を根本的に変えてしまいます。あなたはもはや、主に構文を入力するために給料を払われているのではありません。監査を行い、設計を行い、まさにこうした目に見えない罠を見つけ出すために報酬を得ているのです。
「論理的には正しいが、誤っている」という静かな危険
AIが生成したコードは、コンパイルが通り、実行でき、期待通りの値を返すため、一見正しく見えることがよくあります。表面上のロジックは整合性が取れています。しかし、その裏側では、静かに壊れている可能性があるのです。
正規表現を例に挙げてみましょう。AIは、英語においてはメールアドレスや識別子に完璧に一致するパターンを提示するかもしれません。しかし、その同じ式をドイツ語のウムラウト、アラビア文字、あるいはUnicode正規化のエッジケースに対して実行すると、サイレントに失敗します。コードが例外を投げるような「間違い」をしているわけではありません。単に、現実世界の有効なデータを除外してしまっているだけなのです。
データベースクエリも同様のリスクを孕んでいます。AIは、テスト中には正しい行を返すPostgreSQLクエリを書くことができますが、それでもテーブルをデッドタプルで肥大化させたり、インデックスの活用をスキップさせたり、本番環境のワークロードを麻痺させるシーケンシャルスキャンを強制したりすることがあります。デモ用のデータセットで機能することと、実際の負荷の下で機能することは、全く別物です。機械はレイテンシを感じません。クラウドの請求書を支払うわけでもありません。
「書く」から「検証する」へ
本質的な転換は、「これをどう書くか?」から「これをどう検証するか?」へと移ることです。AIが初稿を作成する場合、あなたの認知負荷はより下流の工程へと移るべきです。あなたは、疲れ果てた著者が自分の書いたものを読み飛ばすようにではなく、セキュリティ監査人がコードを読むように読まなければなりません。
これには異なる種類の規律が求められます。「オートメーション・バイアス(自動化バイアス)」は実在します。ツールが流暢で構文的に完璧な出力を生成すると、人間の脳は弛緩します。プレゼンテーションが洗練されているため、正当であると思い込んでしまうのです。その衝動に抗うことこそが、現在の核心的なスキルです。すべての提案は、それが証明されるまでは一つの「仮説」であると想定しなければなりません。
機械と共に働く
AIコーディングアシスタントから有用な出力を引き出すことは、タイピングを速くすることではありません。機械の学習データと、あなたの具体的な現実との距離を縮めることなのです。いくつかの具体的なプラクティスによって、その距離を縮めることができます。
プロンプトは正確に。 ここでの曖昧さは詩を生むのではなく、バグを生みます。「この関数を最適化して」といったプロンプトは、一般的なアドバイスを招くだけです。代わりに、「逐次的な保存ではなく、単一のバルクデータベース更新を使用するように、このPythonループをリファクタリングして」と書いてください。具体性を高めることで、可能性の範囲を絞り込むことができます。
実際のコンテキストを提供する。 あなたがKubernetesクラスター内で、厳格な30秒のリクエストタイムアウトを設定したPostgreSQL 15上のDjango 4.2を動かしていることは、あなたが言わない限りAIには分かりません。依存関係のバージョン、内部ライブラリ、そして譲れない制約条件を伝えてください。コンテキストは飾りではなく、ガードレールです。
自身のドキュメントに基づいて回答させる。 検索拡張生成(RAG)は、単なるチャットボットの流行語ではありません。アシスタントに、実際のAPI仕様書、アーキテクチャ決定記録(ADR)、およびコードベースの規約を指し示してください。モデルが学習データから推測するのではなく、あなたのドキュメントから事実を取得するようになれば、一般的なアドバイスと実用的なコードとのギャップは劇的に縮まります。
複雑な作業を個別のタスクに分解する。 エージェント・パターンは、各ステップのスコープが狭い場合に最も効果を発揮します。一度にマイクロサービス全体のフルリファクタリングを求めないでください。まずデータスキーマを求め、それを検証します。次にマイグレーションスクリプトを求め、それを検証します。それからサービスレイヤーへと進むのです。
