アンチパターン⑪「AI特有のコード品質問題」
AIが生成するコードの特徴
OX Researchは、AI生成コードに特有のアンチパターンを10個発見しました。人間が書くコードとは異なる、AI特有の問題があります。
AI生成コードの過剰コメント問題
問題の説明:
人間のプログラマーは、複雑な箇所にコメントを追加します。しかし、AIはあらゆる場所にコメントを散りばめます。
AIが生成しがちなコード:
// ユーザー名を取得する関数
function getUserName(user) {
// ユーザーオブジェクトからnameプロパティを取得
const name = user.name;
// 名前を返す
return name;
}
問題点:
- 自明なことをコメントしている
- コードの読みやすさが低下
- メンテナンスコストが増加(コードを変更したらコメントも変更)
解決策:
function getUserName(user) {
return user.name;
}
コメントは「なぜ」を説明するときだけ使う。「何をしているか」はコード自体が説明すべき。
AI生成コードに完璧主義が欠如する理由
問題の説明:
人間のプログラマーは、コードを書いた後「もっと良くできないか」と考えます。AIにはこの「より良くしたい」という衝動がありません。
“To AI, if it works, it’s good enough.” 「AIにとっては、動けばそれで十分」
AIが生成しがちなパターン:
// 動くが、最適ではない
function processUsers(users) {
const result = [];
for (let i = 0; i < users.length; i++) {
if (users[i].active === true) {
result.push(users[i]);
}
}
return result;
}
より良いコード:
function processUsers(users) {
return users.filter(user => user.active);
}
解決策:
AIの出力を受け取ったら、「もっと良くできないか」と自問する。リファクタリングの習慣を持つ。
AI生成コードの高い循環的複雑度
問題の説明:
AIは、ネストした条件分岐を好む傾向があります。
AIが生成しがちなコード:
function processOrder(order) {
if (order) {
if (order.items) {
if (order.items.length > 0) {
if (order.payment) {
if (order.payment.status === 'completed') {
// 処理
}
}
}
}
}
}
より良いコード:
function processOrder(order) {
if (!order?.items?.length) return;
if (order.payment?.status !== 'completed') return;
// 処理
}
解決策:
- 早期リターンを使う
- ガード句でネストを減らす
- 複雑な条件は関数に分離
AI生成コードの不明確な命名規則
問題の説明:
AIは、コードベース全体での命名規則の一貫性を維持しません。
AIが生成しがちなパターン:
// ファイル1
function getUserData() { }
function fetchUserInfo() { }
// ファイル2
function retrieveUser() { }
function getCustomer() { }
問題点:
- 同じ概念に異なる名前
- コードの検索が困難
- 理解コストが増加
解決策:
- CONTEXT.mdに命名規則を定義
- AIに明示的に命名規則を伝える
- 生成後にレビューで統一
AI生成コードの重複コード氾濫問題
GitClearの調査によると、AI生成コードでは コード重複が4倍 に増加しています。
なぜ重複が発生するか:
- AIは既存コードを再利用しない
- 似た機能を依頼すると、新しく生成する
- DRY原則を意識しない
解決策:
- 既存コードを読み込ませてから依頼
- 「既存のXXX関数を使って」と明示
- 生成後に重複をチェック
AI生成コードのエラーハンドリング不備
AIは、正常系のコードは書けますが、エラーハンドリングが不十分なことが多いです。
AIが生成しがちなコード:
async function fetchUser(id) {
const response = await fetch(`/api/users/${id}`);
const data = await response.json();
return data;
}
より堅牢なコード:
async function fetchUser(id) {
if (!id) throw new Error('User ID is required');
const response = await fetch(`/api/users/${id}`);
if (!response.ok) {
throw new Error(`Failed to fetch user: ${response.status}`);
}
const data = await response.json();
if (!data) throw new Error('User not found');
return data;
}
解決策:
- プロンプトで「エラーハンドリングを含めて」と明示
- 生成後にエラーケースを確認
- エッジケースのテストを追加
AI生成コードの型安全性軽視問題
TypeScriptを使っていても、AIは型安全性を軽視することがあります。
AIが生成しがちなコード:
function processData(data: any) {
return data.items.map((item: any) => item.value);
}
より型安全なコード:
interface Item {
value: string;
}
interface Data {
items: Item[];
}
function processData(data: Data): string[] {
return data.items.map(item => item.value);
}
解決策:
- 「any型は使わないで」と明示
- 型定義を先に作成
- 生成後に型をチェック
実践的な解決策:AI出力の後処理
AI特有の問題を解決するための「後処理」チェックリストを用意しましょう。
後処理チェックリスト:
- 不要なコメントを削除
- より良い書き方がないか検討
- ネストを減らせないか
- 命名規則は統一されているか
- 重複コードはないか
- エラーハンドリングは十分か
- 型は適切か
この事例から学ぶべき教訓と実践ポイント
「AI特有のコード品質問題」から学ぶべきことは以下の通りです。
-
過剰コメント
- 自明なコメントは削除
-
完璧主義の欠如
- 「動く」で満足しない
-
高い循環的複雑度
- 早期リターンで改善
-
不明確な命名規則
- 規則を明示、統一
-
重複コードの氾濫
- 既存コードの再利用を指示
-
エラーハンドリングの不備
- 明示的に依頼
まとめ:重要ポイントの振り返り
- OX Researchが AI特有の10個のアンチパターン を発見
- 過剰コメント :自明なコメントが多すぎる
- 完璧主義の欠如 :「動けばいい」で終わる
- 高い循環的複雑度 :ネストが深い
- 重複コード4倍 :再利用しない
- 解決策:後処理チェックリスト で品質向上
- 教訓:AI出力はそのまま使うな、後処理せよ