正しくnullを使用する
を使用するさまざまな方法がありますnull
。最も一般的で意味的に正しい方法は、単一の値を持つ場合と持たない場合に使用することです。この場合、値null
はデータベースのレコードなどと同じか、意味のあるものになります。
これらの状況では、次のように(擬似コードで)ほとんど使用します。
if (value is null) {
doSomethingAboutIt();
return;
}
doSomethingUseful(value);
問題
そして、それは非常に大きな問題を抱えています。問題は、呼び出した時点でdoSomethingUseful
値がチェックされていない可能性があることですnull
!そうでない場合は、プログラムがクラッシュする可能性があります。また、ユーザーには「エラーが発生しましたが、値が必要ですがnullになりました!」などのエラーメッセージが表示されることさえありません。(更新後:Segmentation fault. Core dumped.
などのさらに有益なエラーが発生する可能性がありますが、さらに悪い場合もありますが、エラーが発生せず、nullでの不正な操作が発生する場合があります)
状況のチェックを書くのを忘れてnull
対処するnull
ことは非常に一般的なバグです。これが、発明したTony Hoare null
が2009年のQCon Londonと呼ばれるソフトウェア会議で、1965年に10億ドルの間違いを犯したと言った理由です。https:
//www.infoq.com/presentations/Null-References-The-Billion-Dollar-ミストニーホア
問題を回避する
一部のテクノロジーと言語null
では、さまざまな方法で忘れることをチェックできないようにして、バグの量を減らしています。
たとえば、Haskell Maybe
にはヌルではなくモナドがあります。これDatabaseRecord
がユーザー定義型であるとします。Haskellでは、typeの値はMaybe DatabaseRecord
等しいJust <somevalue>
か、等しい場合がありますNothing
。その後、さまざまな方法で使用できますが、どのように使用してNothing
も、知らないうちに何らかの操作を適用することはできません。
たとえば、呼び出されたこの関数zeroAsDefault
はx
for Just x
および0
forを返しますNothing
。
zeroAsDefault :: Maybe Int -> Int
zeroAsDefault mx = case mx of
Nothing -> 0
Just x -> x
Christian Hacklは、C ++ 17とScalaには独自の方法があると言います。したがって、あなたの言語がそのようなものを持っているかどうかを調べて、それを使用したいと思うかもしれません。
ヌルはまだ広く使用されています
あなたがより良いものを持っていない場合null
は、使用しても問題ありません。気をつけてください。とにかく、関数での型宣言は多少役立ちます。
また、それはあまり進歩的ではないように聞こえるかもしれませんが、同僚が使用したいかどうかを確認する必要がありますnull
。彼らは保守的かもしれず、何らかの理由で新しいデータ構造を使いたくないかもしれません。たとえば、古いバージョンの言語をサポートします。このようなことは、プロジェクトのコーディング標準で宣言され、チームと適切に議論される必要があります。
あなたの提案について
別のブールフィールドを使用することをお勧めします。しかし、とにかくチェックする必要があり、それでもチェックを忘れることがあります。だからここで勝ったものは何もない。毎回両方の値を更新するなど、何か他のものを忘れることさえできれば、それはさらに悪いことです。確認するのを忘れるという問題がnull
解決されない場合、意味がありません。回避することnull
は難しく、それを悪化させるような方法で行うべきではありません。
nullを使用しない方法
最後に、null
誤った使い方の一般的な方法があります。そのような方法の1つは、配列や文字列などの空のデータ構造の代わりに使用することです。空の配列は、他の配列と同様に適切な配列です!ほとんどの場合、複数の値を収めることができ、空にできる、つまり長さが0のデータ構造にとって重要で便利です。
代数の観点からすると、文字列の空の文字列は、数値、つまり恒等式の0に非常に似ています。
a+0=a
concat(str, '')=str
空の文字列はモノイドになるため、一般的に文字列を可能にします:
https://en.wikipedia.org/wiki/Monoid
あなたはそれを取得しない場合、それはあなたのためにそれは重要ではありません。
この例でプログラミングがなぜ重要なのかを見てみましょう。
for (element in array) {
doSomething(element);
}
ここで空の配列を渡すと、コードは正常に機能します。何もしません。ただし、null
ここに渡すと、「nullをループできません、ごめん」などのエラーでクラッシュする可能性があります。それを包むこともできif
ますが、それはあまりきれいではありません、あなたはそれをチェックするのを忘れるかもしれません
nullの処理方法
何をdoSomethingAboutIt()
すべきか、特に例外をスローすべきかどうかは別の複雑な問題です。要するに、それはnull
与えられたタスクの受け入れ可能な入力値であったかどうか、そして応答で期待されるものに依存します。例外は、予期されていなかったイベントです。そのトピックについては詳しく説明しません。この答えはすでに非常に長いです。
std::optional
またはを使用しますOption
。他の言語では、適切なメカニズムを自分で構築する必要がある場合があります。または、null
より慣用的であるため、実際に頼るか、またはそれに似た何かをする場合があります。