AI コード生成のベストプラクティス
AIアシスタントで実証済みのベストプラクティスに従い、より良いコードをより速く書きましょう。
指示だけでなくコンテキストを提供する
最もよくある失敗パターンは、すでに持っているコードを見せずにコードを求めることです。あなたのスタック、規約、既存パターンが見えないモデルは、あなたのアーキテクチャと衝突する汎用的なコードを生成します。
同じタスクに対する2つのプロンプトの違いを考えてみましょう。改善前:返金を処理する関数を書いて。これでは、もっともらしいが汎用的なコードが返ってきて、エラー処理や型は勝手にでっち上げられます。改善後:私たちのExpress APIで、PaymentGatewayラッパーを通じて返金を処理するTypeScript関数を書いて。下記のrefundService.tsの構造に従い、失敗はAppErrorクラスで送出し、貼り付けたZodスキーマで入力を検証して。参照ファイルを実際に添えた2つ目のプロンプトなら、最小限の手直しでコードベースに収まるコードが得られます。
これを低コストで習慣化するコツ:
- 新しいモジュールを頼むときは、代表的な既存ファイルを1つ貼り付けて、モデルに命名と構造を真似させる。 - フレームワーク、データベース、ランタイムなど、スタックとバージョンを明示する。デフォルトはバージョンごとに異なります。 - エラー処理とログの規約は、毎回レビューで直すのではなく、セッションごとに一度伝えておく。 - 関数シグネチャだけでなくビジネスルールを説明する。エッジケースはビジネスルールの中に潜んでいます。
ジュニア開発者のコードのようにレビューする
AIが生成したコードは、実際に正しい頻度よりはるかに高い頻度で、コンパイルが通り、慣用的に見えます。有能だが監督されていないジュニア開発者からのプルリクエストとまったく同じように扱ってください。すべての行を読み、すべての前提を疑い、信頼する前に実行することです。意識的にチェックすべき、繰り返し現れるバグの類型:
- ループ、スライス、ページネーション境界でのoff-by-oneエラー。 - nullとundefinedの処理、特にAPIレスポンスのオプショナルフィールド周り。 - 非同期コードの競合状態:awaitされていないPromise、共有される可変状態、欠落したロック。 - 微妙に間違ったAPIの使い方——実在するメソッドを誤った引数順で呼ぶ、非推奨のオーバーロードを使う、バージョン間で変わったデフォルト値に依存する。 - 設定から取得すべき値のハードコーディング。
有効な規律の1つは、マージする前に、生成された各関数が何をするのかを一文で説明してみることです。説明できないなら、まだレビューしていないということです。
ハルシネーションされたAPIと存在しないパッケージ
モデルはメソッド、オプション、さらにはパッケージそのものを日常的にでっち上げます。ハルシネーションされた名前が危険なのは、まさにもっともらしいからです。実在する2つのライブラリの混合だったり、別のフレームワークには存在するメソッドだったりすることがよくあります。見慣れないAPIの上にコードを組み立てる前に、公式ドキュメントで確認し、周辺コードを書く前にインポート単体を試してください。
ここには本物のセキュリティ上の問題もあります。攻撃者は、AIモデルがよくハルシネーションする名前で悪意あるパッケージを公開してきました。タイポスクワッティングの変種で、スロップスクワッティングと呼ばれることもあります。アシスタントが提案したという理由だけでパッケージをインストールしてはいけません。まずレジストリのページ、ダウンロード数、メンテナーの履歴、できればソースリポジトリを確認してください。広く共有されているAIコーディングセッションの分析では、でっち上げられたパッケージ名は、このチェックを時々ではなく固定の習慣にすべきなほど頻繁に登場します。
セキュリティレビューは任意ではない
生成されたコードは、地味なセキュリティ作業をしばしば省略します。AIの支援を受けたすべての変更で、以下を明示的にチェックしてください:
- インジェクション:データベースクエリは文字列連結ではなく必ずパラメータ化する。シェルコマンドにも同じことが当てはまります。 - シークレット:モデルはプロンプト内のAPIキーや接続文字列を平気でソースファイルにハードコードします。シークレットは環境変数かシークレットマネージャーに保管し、本物の認証情報を決してプロンプトに貼り付けないこと。 - 入力検証:HTTPハンドラー、キューコンシューマー、ファイルパーサーなど、あらゆる境界が悪意ある入力を受け取ると想定し、生成コードがそれを検証しているか確認する。 - 認可:生成されたエンドポイントは認証はチェックしても、リソース単位の認可を省略しがちです。
モデル自身に自分の出力の脆弱性をレビューさせるのは価値ある二次チェックで、実際の問題を定期的に見つけますが、人間のレビューと静的解析ツールを補完するものであって、置き換えるものではありません。
再生成ではなく反復的に磨く
出力がおおむね正しいなら、全体を生成し直したい衝動を抑えてください。再生成は、すでに正しかったものをすべて捨て去り、レビューされていない新たなばらつきを持ち込みます。代わりに、具体的な欠陥を名指ししましょう:この関数はそのままで、items配列が空のときに空のsummaryオブジェクトを返すガードだけ追加して。機能はデータモデル、次にエンドポイント、次に配線という段階で構築し、各段階をレビューすることで、後の工程が未検証の出力ではなく検証済みのコードの上に立つようにします。
テストを先に書く
テスト駆動開発はAIと際立って相性が良いのです。テストは自分で書くか、生成させたなら厳しくレビューして、実際の要件をコード化した上で、モデルにそれを通過するコードを実装させます。これにより信頼の問題が逆転します。不透明なロジックを一行ずつ監査する代わりに、自分が管理する仕様に照らして振る舞いを検証できるのです。
同じセッションで同じモデルがコードの後に生成したテストには注意してください。そうしたテストは、コードがすべきことではなく、コードがしていることを検証しがちで、あなたが捕まえたかったまさにそのバグを平然とアサートしてしまいます。最低限、生成されたテストに欠けているエッジケース——空の入力、境界値、エラーパス、並行アクセス——をレビューしてください。
AIコード生成を使うべきでないとき
- 学習元となる公開コードがほとんどない新規アルゴリズムやニッチな領域——出力品質が急落し、ハルシネーション率が上がります。 - 暗号や認証フローのようなセキュリティ上の重要プリミティブ:生成された実装ではなく、検証・監査済みのライブラリを使うこと。 - 自分が評価する資格を持たないコード。出力の正誤を判断できないならレビューはできず、レビューされていないAIコードは負債です。 - すべての行の出所とライセンスが問われうる、コンプライアンス上センシティブなコード。
アーキテクチャの責任は人間が持つ
モデルはもっともらしい局所解に最適化されているだけで、システムの長期的な形に責任を負いません。サービス境界、データフロー、依存関係の選択、障害モードに関する意思決定は、その結果とともに生きていく人間が行うべきです。AIは選択肢の探索に使い、反論を求めて設計をプレッシャーテストし、自分が定めた構造の中で実装させましょう。ただし、決定そのものと、それに対する説明責任は人間の手元に残してください。
これらのプラクティスをまとめて採用すれば、AIコード生成は微妙な欠陥の発生源から本物の生産性の増幅器に変わります。ドラフト作成とボイラープレートでは実質的なスピード向上を得ながら、正しさは依然として、コードをマージする人間が保証するのです。