はじめに
・さっきまで値が入っていた
・途中で突然 null になる
・どこで消えたのか分からない
👉 こんな経験ありませんか?
例えば、
var user = GetUser();
var name = user.Name;
実行すると、
NullReferenceException
になる。
でも、
👉 「user はさっき見た時、値入ってたよね?」
となる。
実務では、
👉 「どこで null になったのか分からない」
で止まることがかなり多いです。
この記事の位置づけ(シリーズ)
これまでのシリーズでは、
・処理が追えない
・意味が分からない
・どこに書けばいいか分からない
など、
👉 「コード理解」
について整理してきました。
今回はその中でも、
👉 「値の追い方」
にフォーカスします。
なぜ null が追えなくなるのか
理由はシンプルです。
👉 “値が変わるポイント”を見れていないから
多くの人は、
👉 「今の値」
だけを見ています。
でも重要なのは、
👉 「どこで変わったか」
です。
よくある勘違い
nullになると、
👉 「この行がおかしい?」
と思いやすい。
例えば、
var name = user.Name;
ここで例外が出ると、
👉 「Name取得がおかしい?」
と思う。
でも実際には、
👉 user が null
なだけ。
本当に見るべき場所
重要なのは、
👉 「最後に正常だった場所」
です。
つまり、
「どこで壊れた?」
ではなく、
「最後に正常だったのはどこ?」
を追う。
null調査で重要な考え方
null調査は、
👉 「逆向き」に追います
例えば、
var user = repository.Get(id);
var name = user.Name;
ここで null なら、
まず確認するのは👇
repository.Get(id)
の戻り値。
さらに遡る
もし、
return cache.Get(id);
なら、
👉 cache の中を見る。
つまり、
結果
↑
戻り値
↑
取得元
↑
入力値
と、
👉 逆向きに辿る
よくある null 発生パターン
パターン① 初期化漏れ
かなり多いです。
User user;
だけで、
👉 new していない
症状
user.Name
で落ちる。
パターン② 条件分岐で代入されていない
User user = null;
if (isLogin)
{
user = GetUser();
}
isLogin == false
だと、
👉 user は null のまま
パターン③ 非同期で値が変わる
これ実務でかなり多い。
await LoadAsync();
user.Name
一見問題なさそう。
でも実際には、
👉 await 中に状態が変わる
ことがある。
パターン④ 別処理で上書きされる
例えば、
currentUser = null;
が別イベントで動いている。
すると、
👉 「さっきまで値あったのに」
になる。
null調査でありがちなミス
❌ 例外行だけ見る
かなり多い。
例えば、
user.Name
で落ちても、
👉 本当の原因はもっと前
❌ 今の値だけ見る
これも多い。
重要なのは、
👉 「どう変化したか」
です。
❌ 全部追おうとする
これも迷子になる。
正解は、
👉 「最後に正常だった場所」
から追うこと。
実際の調査イメージ
例えば、
① null が発生
↓
② 直前の値確認
↓
③ どこから来たか確認
↓
④ その戻り値確認
↓
⑤ さらに遡る
👉 これを繰り返す
ブレークポイントで見る場所
重要なのはこれです。
✔ 代入直後
user = GetUser();
👉 ここで値を見る
✔ 戻り値直前
return user;
👉 ここで null になってないか確認
✔ 条件分岐
if (user != null)
👉 分岐条件を見る
「nullになった場所」と「原因の場所」は違う
ここかなり重要。
例えば、
user.Name
で落ちても、
原因は👇
・初期化漏れ
・条件分岐
・非同期
・別イベント
かもしれない。
つまり、
👉 「落ちた場所」
ではなく、
👉 「値が変わった場所」
を見る必要があります。
まとめ
null が追えなくなる原因の多くは、
👉 “値の変化”を追えていないこと
です。
重要なのは、
・今の値
ではなく、
👉 「どこで変わったか」
を見ること。
そして、
👉 「最後に正常だった場所」
から逆向きに追うことです。
✔ 1つだけ意識するなら
👉 「最後に値が正常だった場所はどこ?」
これを意識するだけで、
👉 null調査はかなりやりやすくなります
実務では、
👉 「nullになった」
より、
👉 「なぜ null になった?」
を調査することの方が重要です。
最初は難しく感じますが、
👉 値の流れを逆向きに追う
ことを意識すると、
少しずつ原因が見えるようになります。
もし、
「この null の追い方で困った」
「このケースでハマった」
などあれば、ぜひ教えてください。
今後の記事で取り上げていきます。