技術とか戦略とか

IT技術者が技術や戦略について書くブログです。

コーディング中のバグ対応の一般的な手順

コーディングにおいては、実行時に見つかる些細なバグの対応がつきものです。
バグの対応を素早く行うことができれば、コーディングも早く行うことができるようになります。
 
今回の記事では、バグ対応の一般的な手順を説明しようと思います。
手順を大まかに書くと、以下のような手順になります。
1.バグの発生箇所を特定する
2.バグの原因を確認して取り除く
 
例として、「0~9の範囲の値を実行する度にランダムに表示する」というプログラム(モジュール)をJavaでコーディングしながら説明していきます。
 
----
 
まず、コーディングを一通り済ませてみました。
このソースコードにはバグがあり、実行すると「NullPointerException」という例外が出力され、処理が途中で止まってしまいます。
以降で、バグの原因を特定して、バグを取り除いてみます。
 
【サンプルコード1】
・NullPoTest.java
import java.util.Random;

public class NullPoTest {

    public static void main(String args) {

        // Randomクラスのオブジェクトを生成する
        Random random = null;

        // ランダムな値を生成する(0~9)
        int outputValue = random.nextInt(10);

        // 生成した値を表示する
        System.out.println(outputValue);

    }

}
 
【実行結果】
Exception in thread "main" java.lang.NullPointerException
    at NullPoTest.main(NullPoTest.java:11)
 
----
 
まずは、「1.バグの発生箇所を特定する」の手順を実施していきます。
 
実装や環境を問わずに実施できる方法としては、「デバッグ表示の行を入れ込み、どこまで通っているのかを確認する」という方法です。
今回の例では、この方法で「Random random = null;」まで処理が通っており、「int outputValue = random.nextInt(10);」が通っていないことを確認することができます。
また、今回の例では実施していませんが、デバッグ表示の行の中で変数の値を出力し、変数がどのような値を取っているのかを確認するのも良い方法です。
 
なお、実装や環境は問いますが、以下のような方法も有効です。
スタックトレースに表示される行数を手掛かりにする(実は、今回の例では、エラーメッセージ中に「NullPoTest.java:11」と出ているので、それを手掛かりにすることもできます)
IDEEclipse等)のデバッグ機能を用いる
ソースコード中でエラーメッセージの文言を作っている場合は、その文言でソースコード中を検索する
 
【サンプルコード2】
・NullPoTest.java
import java.util.Random;

public class NullPoTest {

    public static void main(String args) {

        System.out.println("チェックポイント1");

        // Randomクラスのオブジェクトを生成する
        Random random = null;
        System.out.println("チェックポイント2");

        // ランダムな値を生成する(0~9)
        int outputValue = random.nextInt(10);
        System.out.println("チェックポイント3");

        // 生成した値を表示する
        System.out.println(outputValue);

    }

}
 
【実行結果】
チェックポイント1
チェックポイント2
Exception in thread "main" java.lang.NullPointerException
    at NullPoTest.main(NullPoTest.java:14)
 
----
 
バグの発生箇所を特定できたので、次は「2.バグの原因を確認して取り除く」を実施していきます。
 
NullPointerException」をWebで調べてみると「参照先が無い(nullを示している)参照型変数を参照した場合に発生する」という類のことが出てくると思います。
オブジェクト指向言語に慣れていないと説明だけ読んでもわからないかもしれませんが、Webの記事の中にサンプルコードが併記されていることも多く、それを読むと理解の助けになると思います。
今回のソースコードでは、「Random random = null;」という箇所で参照型変数「random」にnullを代入しているのが原因のため、ここを修正し、新たなオブジェクトを割り当ててそれを代入することで、バグを解消することができます。
 
これはJavaの言語がエラーメッセージを出している場合の調査方法ですが、他のバグの場合は調べ方が変わってきます。
例えば、出力される値が期待する値と異なる場合は、計算がどこで間違っているのかをソースコードを追ったり変数の値をデバッグ表示でこまめに出力したりしながら確認していくことになります。
また、ソースコード中でエラーメッセージの文言を作っていてそれが出力された場合は、そのエラーメッセージが何を示しているのかを仕様書等を参考に確認していくことになります。
 
知識や経験が少ないと、調べても原因の特定に至らない場合があります。
類似処理を別のソースコードで行っている場合は、その類似処理と見比べることで原因を特定できる場合もあるので、それを試してみましょう。
それでもわからない場合は、無理をせずに他の人に聞いてみると良いでしょう。既に、発生箇所を特定し、原因調査も途中までは済ませているため、あまり時間を取らせずにスムーズに回答を得ることができます。
 
【サンプルコード3】
・NullPoTest.java
import java.util.Random;

public class NullPoTest {

    public static void main(String[] args) {

        // Randomクラスのオブジェクトを生成する
        Random random = new Random();

        // ランダムな値を生成する(0~9)
        int outputValue = random.nextInt(10);

        // 生成した値を表示する
        System.out.println(outputValue);

    }

}
 
【実行結果】
5