2011年2月23日水曜日

なぜ Null は要らない子なのか

という記事があって面白かったので。

一番はやはり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はコードを不要に複雑にする。複雑さは全てのソフトウェアにおいて『敵』であり、我々は常にこれを排除するよう努めなきゃいかん。


元記事

0 件のコメント:

コメントを投稿