一番はやはり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>
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 件のコメント:
コメントを投稿