という記事があって面白かったので。
一番はやはり
Nullチェックを一々コードに埋め込むのは冗長だということに尽きる。
例1
Null云々とは少し違うが、例えば Door クラスを作ったとして、以下の2つのプロパティを書いたとする。
class Door
private bool isShut
private bool isLocked
ここで、
!isShut && isLocked
という状態は有り得ないので、Doorクラスを扱う際は『常に』気を使う必要がある。
例えば、isShutのsetter内に、falseにセットするときに次のように書いたり。。
if(newval==true){
this.isShut = true
}
else{
this.isShut = false
if(this.isLocked){
this.isLocked = false
}
}
例2
あるいは、次のようなPersonクラスに、名前の総文字数を計算するメソッドを用意することを考える:
class Person
private string FirstName
private string MiddleName
private string LastName
当然ながら、string型は Null にもなるし、空文字にもなる。
ので、次のメソッドは不十分で:
let TotalNumCharsInPersonsName(p:Person) =
p.FirstName.Length + p.MiddleName.Length + p.LastName.Length
こんな風に書かなきゃいけない:
let TotalNumCharsInPersonsName(p:Person) =
(if p.FirstName=null then 0 else p.FirstName.Length)
+ (if p.MiddleName=null then 0 else p.MiddleName.Length)
+ (if p.LastName=null then 0 else p.LastName.Length)
解
これだけ見ても、どんだけアホなんだと言いたくなる。
(でもプログラムを長く書いていると、もう慣れてしまってそのアホさに鈍感になってくる。)
じゃあどうやって解決するのか。それは、
新しい型をつくることだ。
例1なら、こうする。
type DoorState =
| Open | ShutAndUnlocked | ShutAndLocked
# then I could define
class Door
private DoorState state
例2なら、こうする。
(ここにstringはnon-nullであり、Option<T>
は(T型の値 or null)である)
class Person
private string FirstName
private Option<string> MiddleName
private string LastName
let TotalNumCharsInPersonsName(p:Person) =
let middleLen = match p.MiddleName with
| None -> 0
| Some(s) -> s.Length
p.FirstName.Length + middleLen + p.LastName.Length
もうここにアホさは残っていない。本質的に必要な処理だけをコーディングしている。
結論
Nullはコードを不要に複雑にする。複雑さは全てのソフトウェアにおいて『敵』であり、我々は常にこれを排除するよう努めなきゃいかん。
元記事