教材4 AIアシストコーディング実践
4章 エラーよ、さようなら!AIデバッグ術
INDEX
目次

4章 エラーよ、さようなら!AIデバッグ術

この章の目安学習時間:60分

この章で到達できるゴール:

  • コードのエラーメッセージをAIに読み解かせ、原因と解決策を提示させることができる。
  • AIを活用して、デバッグ作業の時間を大幅に短縮できる。

【4-1】AIと協力してエラーを解決する

目安の学習時間:30分

赤いエラー表示ともお別れ!

コーディングにおいて、エラーは避けて通れないものです。
特に初学者のうちは、ブラウザの開発者コンソールに表示される赤いエラーメッセージを見て、頭が真っ白になってしまうことも少なくありません。

デバッグ(エラーを修正する作業)が難しいのは、
  • エラーメッセージが英語で、意味が分からない。
  • エラーが起きている場所と、本当の原因の場所が違うことがある。
  • 何から手をつけて良いか分からない。
といった理由が挙げられます。
しかし、AIデバッガーとしてのCopilotは、この状況を一変させます。
これからは、エラーは解決のヒントが詰まった「宝の地図」に見えるようになるでしょう。

AIにエラーの原因を特定させる方法

AIデバッグの基本は、「エラーメッセージ」と「関連するコード」をセットでAIに提供することです。
例えば、ブラウザの開発者コンソールに以下のようなエラーが表示されたとします。

Uncaught TypeError: Cannot read properties of null (reading 'addEventListener')

このエラーメッセージと、エラーが発生している箇所のJavaScriptコードをCopilot Chatに貼り付け、次のように質問します。
プロンプト例:エラー原因の特定

以下のJavaScriptコードを実行すると、コンソールにエラーが出ます。エラーの原因は何でしょうか?

エラーメッセージ:

Uncaught TypeError: Cannot read properties of null (reading 'addEventListener')

関連コード:

const button = document.getElementById('my-button');
button.addEventListener('click', function() {
  console.log('ボタンがクリックされました!');
});
AIは、エラーメッセージの意味(「nullに対してaddEventListenerを呼び出そうとしています」)とコードを照らし合わせ、「document.getElementById('my-button')nullを返している。
つまり、HTML内にIDがmy-buttonの要素が存在しないか、あるいはJavaScriptがHTML要素より先に読み込まれていることが原因です」といったように、的確に原因を特定してくれます。

修正コードをAIに提案させる神テク

エラーの原因が特定できたら、解決は目前です。続けてAIに、修正案を尋ねましょう。
プロンプト例:修正案の提示

なるほど、原因は理解できました。では、このエラーを修正するための具体的なコードを提案してください。

AIは、複数の解決策を提示してくれることがあります。

例えば、
  1. HTML側に<button id="my-button">が正しく記述されているか確認すること。
  2. JavaScriptの実行を遅らせるために、DOMContentLoadedイベントを使う方法や、scriptタグにdefer属性を付ける方法。
これらの提案の中から、自分の状況に合った最適な修正コードを選んで適用することで、エラーを迅速に解決できます。

【4-2】4章 -章末課題- [バグ探しゲーム]

目安の学習時間:30分

問題

ここに、意図的にいくつかのバグが仕込まれたHTMLとJavaScriptのファイルがあります。
このHTMLファイルをブラウザで開くと、期待通りに動作しません(例:ボタンをクリックしても何も起こらない、計算結果が正しく表示されないなど)。

ブラウザの開発者コンソールでエラーを確認し、Copilot Chatと協力してバグを全て修正し、期待通りに動作するようにしてください。
【提供されるファイル(見本)】
buggy.html
<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>バグ探しゲーム - カウンターアプリ</title>
    <style>
        body {
            font-family: Arial, sans-serif;
            display: flex;
            flex-direction: column;
            align-items: center;
            justify-content: center;
            min-height: 100vh;
            background-color: #f4f4f4;
            margin: 0;
        }
        .container {
            background-color: #fff;
            padding: 30px;
            border-radius: 8px;
            box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
            text-align: center;
        }
        #counter-display {
            font-size: 3em;
            margin-bottom: 20px;
            color: #333;
        }
        .buttons button {
            font-size: 1.5em;
            padding: 10px 20px;
            margin: 0 10px;
            border: none;
            border-radius: 5px;
            cursor: pointer;
            transition: background-color 0.3s ease;
        }
        #increase-btn {
            background-color: #4CAF50;
            color: white;
        }
        #increase-btn:hover {
            background-color: #45a049;
        }
        #decrease-btn {
            background-color: #f44336;
            color: white;
        }
        #decrease-btn:hover {
            background-color: #da190b;
        }
        #resett-btn { /* バグ1: IDのタイプミス 'reset-btn' -> 'resett-btn' */
            background-color: #008CBA;
            color: white;
            margin-top: 20px;
        }
        #resett-btn:hover { /* バグ1: IDのタイプミス */
            background-color: #007bb5;
        }
    </style>
    <script src="buggy.js"></script> 
</head>
<body>
    <div class="container">
        <h1>シンプルなカウンター</h1>
        <div id="counter-display">0</div>
        <div class="buttons">
            <button id="increase-btn">増やす (+)</button>
            <button id="decrease-btn">減らす (-)</button>
        </div>
        <button id="resett-btn">リセット</button> </div>
</body>
</html>
HTML
buggy.js
// buggy.js

// ① カウンターの初期値を格納する変数 (グローバルスコープだが問題あり)
let count = "0"; // バグ: 数値ではなく文字列として初期化

// 要素の取得 (セレクタにバグあり)
const counterEl = document.querySelect('#counter-display'); // バグ: メソッド名の間違い
const increaseBtn = document.getElementById('increase-btn');
const decreaseBtn = document.getElementById('decrease-btn');
const resetBtn = document.getElementById('resest-btn'); // バグ: IDのタイプミス (HTMLのIDとも不一致)

// ② ボタンクリックイベントのリスナー
increaseBtn.addEventListener('click', () => {
    count = count + 1; // バグ: 文字列結合になる
    counterEl.innerText = count;
});

decreaseBtn.addEventListener('click', () => {
    count -= 1; // この行は数値として処理されるが、初期値が文字列だと問題あり
    counterEl.innerText = count;
});

resetBtn.addEventListener('click', () => {
    counter = 0; // バグ: 別の変数名を使用
    counterEl.innerText = count; // バグ: 更新されていない変数を表示
});

// ③ 初期表示の更新
// counterElement.textContent = count; // バグ: 未定義の変数名を使用
JavaScript

解答手順

操作手順
  1. 提供された`buggy.html`ファイルをブラウザで開き、期待通りに動作しないことを確認します。
  2. ブラウザの開発者コンソール(Windows: `F12` or `Ctrl+Shift+I`, Mac: `Cmd+Opt+I`)を開き、表示されているエラーメッセージを読みます。
  3. 最初のエラーメッセージと、エラーが発生している`buggy.js`の関連コードをコピーし、Copilot Chatに貼り付けます。「このエラーの原因と解決策を教えてください」と質問します。
  4. AIの提案に従ってコードを修正し、ファイルを保存します。
  5. ブラウザをリロードし、エラーが解消されたか、あるいは新たなエラーメッセージが表示されていないかを確認します。
  6. 全てのエラーが解消され、Webページが期待通りに(例:ボタンを押すとカウンターが動くなど)動作するようになるまで、ステップ3〜5のプロセスを繰り返します。
  7. 修正が完了した、正常に動作する`buggy.js`ファイルを課題として提出します。
修正後
buggy.html
<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>バグ探しゲーム - カウンターアプリ</title>
    <style>
        body {
            font-family: Arial, sans-serif;
            display: flex;
            flex-direction: column;
            align-items: center;
            justify-content: center;
            min-height: 100vh;
            background-color: #f4f4f4;
            margin: 0;
        }
        .container {
            background-color: #fff;
            padding: 30px;
            border-radius: 8px;
            box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
            text-align: center;
        }
        #counter-display {
            font-size: 3em;
            margin-bottom: 20px;
            color: #333;
        }
        .buttons button {
            font-size: 1.5em;
            padding: 10px 20px;
            margin: 0 10px;
            border: none;
            border-radius: 5px;
            cursor: pointer;
            transition: background-color 0.3s ease;
        }
        #increase-btn {
            background-color: #4CAF50;
            color: white;
        }
        #increase-btn:hover {
            background-color: #45a049;
        }
        #decrease-btn {
            background-color: #f44336;
            color: white;
        }
        #decrease-btn:hover {
            background-color: #da190b;
        }
        #reset-btn { /* バグ修正: IDのタイプミス 'resett-btn' -> 'reset-btn' */
            background-color: #008CBA;
            color: white;
            margin-top: 20px;
        }
        #reset-btn:hover { /* バグ修正: IDのタイプミス */
            background-color: #007bb5;
        }
    </style>
    </head>
<body>
    <div class="container">
        <h1>シンプルなカウンター</h1>
        <div id="counter-display">0</div>
        <div class="buttons">
            <button id="increase-btn">増やす (+)</button>
            <button id="decrease-btn">減らす (-)</button>
        </div>
        <button id="reset-btn">リセット</button> </div>

    <script src="buggy.js"></script>
</body>
</html>
HTML
buggy.js
// buggy.js - 完全に修正済みバージョン

// カウンターの初期値を格納する変数
// バグ修正: 数値として初期化 (let count = 0;)
let count = 0; 

// 要素の取得
// バグ修正: querySelector メソッド名の修正 (document.querySelector)
// バグ修正: reset-btn のIDのタイプミス修正 (document.getElementById('reset-btn'))
const counterEl = document.querySelector('#counter-display');
const increaseBtn = document.getElementById('increase-btn');
const decreaseBtn = document.getElementById('decrease-btn');
const resetBtn = document.getElementById('reset-btn'); // 修正

// ボタンクリックイベントのリスナー
increaseBtn.addEventListener('click', () => {
    // バグ修正: 数値の加算 (count = count + 1; または count++;)
    count++; 
    counterEl.innerText = count;
});

decreaseBtn.addEventListener('click', () => {
    count--; 
    counterEl.innerText = count;
});

resetBtn.addEventListener('click', () => {
    // バグ修正: 正しい変数 'count' を更新 (count = 0;)
    count = 0; 
    counterEl.innerText = count; 
});

// 初期表示の更新
// バグ修正: 正しい変数 'counterEl' を使用 (counterEl.textContent = count;)
// HTML要素が読み込まれた後にスクリプトが実行されるように、DOMContentLoaded 
//イベントリスナー内に記述するのがベストプラクティスです。
// ただし、この場合は <script> タグが </body> の直前に移動されたため、直接記述しても動作します。
// より堅牢な書き方としては以下のようにラップすることもできます。
document.addEventListener('DOMContentLoaded', () => {
    counterEl.textContent = count; 
});
JavaScript

この章のまとめ

これで「4章:エラーよ、さようなら!AIデバッグ術」の解説を終わります。

かつては何時間も溶かしていたかもしれないデバッグ作業が、AIとの対話によって、数分で解決できる知的で楽しいゲームに変わる。そんな体験をしていただけたなら幸いです。

次の最終章では、この教材で学んだ全てのスキルを総括し、AIと共創するプロのWeb制作者としての心構えを固めます。
WEBCOACH | キャリアチェンジまでの全てを学ぶマンツーマンWEBスクール
© 2020 by WEBCOACH