「null」をフラグとして使うのは、やめた方がいい

null をフラグとして使うのは、やめた方がいいと思います。


null は、ただ変数が初期化されていないことを表しているだけです。
この意味以外で、null を使わない方がいいと思います。

null をフラグとして使う

「null をフラグとして使う」というのは、「null なら xxxx」というように、null が何らかの意味を持って使われていることを指します。
例えば、下記のコードでは「null はゲストユーザを指すフラグ」として使われています。

/**
 * ユーザ用のヘッダを作る処理
 */
public String createHeader(User user){
    (…中略…)
    String name;
    if(user != null){
        name = user.getName();
    }else{
        name = "Guest";    // null ならゲストユーザ
    }

問題点

これの問題点は、null が何を意味しているのか、すぐに分からないという点です。

例えば、以下のコードを見たときにnull の意味をすぐに理解できるでしょうか*1

    String header = createHeader(null);


null をフラグとして使うときの問題点はここです。
それぞれの処理において好き勝手に意味を定義して null を使用すると、コードを読むときにそれぞれの処理で null が何を意味しているかを理解する必要がでてきてしまいます。


また、上記のコードに続きがあったらどうでしょうか。

    String header = createHeader(null);
    String body = createBody(content, null);

null が2回出てきていますが、「createHeader の引数の null 」と、「createBody の引数の null 」は意味が同じであるとは限りません。
しかし、このコードだけではそれを理解できません*2
また、仮に理解していたとしても、読むたびに「最初の null はこういう意味で、次の null はこういう意味で…」と思い返さなければいけません。



このように、null をフラグとして使用すると、コードが途端に難しくなってしまいます。

解決策1

例えば、最初の処理であれば「ゲストユーザ」というオブジェクトを用意すれば、null をなくせます。

    /**
     * ゲストユーザ
     */
    private static final User GUEST = new User() {
        @Override
        public String getName() {
            return "Guest";
        }
    };

    /**
     * ゲストユーザを取得します。
     * 
     * @return ゲストユーザ
     */
    public static User getGuest() {
        return GUEST;
    }


これを使うと、先ほどの処理は以下のようになります。

    String header = createHeader(User.getGuest());

これなら、「ゲストユーザ用のヘッダーを作っている」というのが理解しやすいと思います。


また、createHeader メソッドの処理もすっきりさせることができます。

public String createHeader(User user) {
    (…中略…)
    String name = user.getName();

解決策2

メソッドをオーバロードして、null を局所的な範囲にとどめるという手もあります。

    public String createBody(Content content){
        createBody(content, null)
    }

    public String createBody(Content content1, Content content2){
        (…中略…)
    }


これなら、先ほどのコードは以下のように書き直せます。

    String header = createHeader(User.getGuest());
    String body = createBody(content);    // null を書かなくて済む!

まとめ

null をフラグとして使うべきではないと思います。
そのように null を使ってしまうと、コードをとても難しくしてしまうからです。


それを避ける方法は状況に応じて様々で、一概には解決できないやっかいな問題です*3
それでも null をフラグとして使っているのを見かけたら、どうすればそれを避けることができるのか、考えてみる必要があるのではないかと思います。

*1:createHeader(user) と書かれていたなら「ユーザ用のヘッダーを作っている」と理解できそうですが、null だとそうはいきません。

*2:null という単語から想像できることは、冒頭に挙げた「変数が初期化されていないことを表している」だけです。

*3:今回挙げた解決策だけでは、おそらくすべてのパターンを解消することはできないと思います。