【Java進化史 第9回】Java7 〜nullと戦ってきた世代へ〜
昔、nullと戦っていた。
NullPointerException。
あの文字を見るだけで、少し気分が重くなる。
だから、書いた。
ひたすら書いた。
if (obj == null) {
throw new IllegalArgumentException("obj is null");
}
引数の数だけ書く。
メソッドの数だけ書く。
equalsを書くときも同じだった。
(a == b) || (a != null && a.equals(b))
毎回これを書く。
コピペする。
少し修正する。
死ぬほどNullチェックを書いた。
でも、Nullぽが出るんだ。
あれだけ守ったつもりなのに。
あれだけ防御したつもりなのに。
■ それはボイラープレートだった
こういう「毎回ほぼ同じ形で書かされる定型コード」を、 ボイラープレート(boilerplate)という。
本質的な業務ロジックではない。
だが、安全のために、仕様のために、必ず書かされるコード。
nullチェックもそう。
equalsの安全比較もそう。
本当に書きたいのは業務ロジックなのに、
周辺の儀式コードがどんどん増えていく。
可読性は下がる。
コピペミスも起きる。
そして本質が埋もれる。
だから思った。
「これ、言語や標準API側で何とかならないのか?」
■ Commonsを入れる時代
多くの現場で入れた。
- Jakarta Commons Lang
- Apache Commons Lang
ObjectUtils.equals。
Validate.notNull。
HashCodeBuilder。
便利だった。
本当に助かった。
だが同時に、こうも思っていた。
「これ、最初からJDKにあってもよくないか?」
■ Java7で静かに入ったもの
Java7で java.util.Objects クラスが登場する。
Objects.equals(a, b);
Objects.requireNonNull(obj);
Objects.hash(f1, f2, f3);
たったこれだけだ。
派手ではない。
ラムダもない。
文法革命でもない。
だが、あの頃の自分には刺さった。
■ null安全な比較
Objects.equals(a, b);
もう
(a == b) || (a != null && a.equals(b))
を書かなくていい。
条件式の読み間違いも減る。
equalsの呼び出し元がnullでも落ちない。
コードが静かになる。
■ 引数チェックも一行で
this.name = Objects.requireNonNull(name);
if文を書かなくていい。
「nullなら例外」
その意図が一行で伝わる。
しかも例外は明示的。
どこで壊れたかがすぐ分かる。
■ hashCodeも簡潔に
@Override
public int hashCode() {
return Objects.hash(id, name, age);
}
昔は31を掛けた。
あるいはHashCodeBuilderを使った。
それが標準で書ける。
■ Commonsはいらなくなったのか?
全部ではない。
StringUtilsもある。
CollectionUtilsもある。
高度なユーティリティはまだ強い。
だが少なくとも、
- null安全比較
- nullチェック
- hashCode生成
このあたりは標準で足りる。
毎回Commonsを入れなくてもいい。
社内共通ライブラリを作らなくてもいい。
JDKだけで書ける。
■ これは思想の変化
Javaは昔、最小限のライブラリだった。
足りないものは外部で補う。
だがJava7は少し違った。
多くの現場で繰り返されている安全処理は、標準に取り込む。
それはつまり、
ボイラープレートを減らす方向への進化
だった。
■ あの頃の自分に言いたい
死ぬほどnullチェックを書いていた自分へ。
それでもNullぽが出て、夜にログを追いかけていた自分へ。
少しだけ、楽になる。
Java7は派手ではない。
だが、
地味だけど、確実に設計や実装の質を上げる進化をしている。
こういう進化、好きなんだよなぁ。
0 件のコメント:
コメントを投稿