捨てたい null
static String lastComponent(String url) {
if (url == null) {
return "";
} else {
final String component = android.net.Uri.parse(url).getLastPathSegment();
return component != null ? component : "";
}
}
というコードを書いてレビューに回したところ parse が null を返すこともあるので null チェックを入れてくださいと返ってきた。
そのまま指示を飲むなら、こんな感じになるのか?
static String lastComponent(String url) {
if (url == null) {
return "";
} else {
final android.net.Uri uri = android.net.Uri.parse(url);
final String component = uri != null ? uri.getLastPathSegment() : null;
return component != null ? component : "";
}
}
ああ、なんという💩(うんこ)ード……!
とりあえず以下に変更して再レビューにまわした。
static String lastComponent(String url) {
try {
final String component = android.net.Uri.parse(url).getLastPathSegment();
return component != null ? component : "";
} catch (NullPointerException e) {
return "";
}
}
けれど、やっぱりどうにも気に入らない。末尾でしている null チェック、これがどうにも美しくない。
* * *
こうすれば、まあ許容範囲 ……かな?
static String lastComponent(String url) {
try {
return android.net.Uri.parse(url).getLastPathSegment().toString();
} catch (NullPointerException e) {
return "";
}
}
でも末尾の toString() がトリッキー。もともと Uri#getLastPathSegment() は String を返す。それをわざわざ toString() するのはなぜ? という疑念をいだき削除するメンテナーが将来、でてくる気がする。(null アクセスして例外を吐かせて catch 節に合流させるためなんだけれどね……)
だったらコメント書け、あるいは、素直に null チェックしろ、なんだろう。(どちらも嫌だ)
* * *
どんな型にでもマッチする null という値の存在が、どうにもイケていないんだと、最近の僕はおもう。
* * *
計算の失敗の可能性を表現するために null を使うのは、結局その呼び手に if 分岐のペナルティを課している。パイプラインはストールして投機実行は捨てられる。
だったら計算の失敗はすべからく例外で表現する、でよいのでは?
あるいは Haskell の Either のようなパターンマッチで解決を図る。
* * *
失敗の可能性は、掛け算で分岐を増やしていく。
分岐に処理の本筋が埋もれて可読性が損なわれる。
マルチスレッド、
コールバック、
分岐。
これら処理の複雑さを、
ある時はズームアウトして概観し、
ある時はズームインして詳細に調べる。
そういうコード開発を、できないものだろうかなあ……。
この記事が気に入ったらサポートをしてみませんか?