小さなオブジェクト階層をトラバースして値を取得し、TextViewオブジェクトに表示するコードを実装する必要がありました(これはAndroid/Javaです)。これを行う必要がありました6回でオブジェクト階層のさまざまな値に6 TextViewsを入力します。
私の実装は実装Bでした。しかし、レビューの結果、私の同僚は反対し、実装Aが適切であると確信しました。私のバージョンはよりクリーンであるだけでなく、開発者として何かを簡単に見逃す可能性があるため、エラーが発生しにくいと私は信じています。
これらの実装の両方の長所と短所について、ご意見をお聞かせください。
if (house != null && house.getLounge() != null && house.getLounge().getLetter() != null)
{
String myValue = house.getLounge().getLetter();
textView.setText(myValue);
}
else
{
// Do nothing, or maybe make textView hidden.
}
try
{
String myValue = house.getLounge().getLetter();
textView.setText(myValue);
}
catch (NullPointerException e)
{
// Do nothing, or maybe make textView hidden.
}
あなたが与えたシナリオを考えると、私は実装Aに行きます。
どちらの実装でも、house
がnull
またはhouse.getLounge()
またはhouse.getLounge().getLetter()
return null
である場合が処理されます。
実装Bの1つの問題は、呼び出されたメソッドのいずれかでcouldが発生するNullPointerException
を、abnormalの発生である正常なものとして処理することです。コメンターが指摘したように、それは例外を「飲み込む」。 todayの時点で、呼び出されたメソッドがNullPointerException
を発生させないことが証明できれば、それは問題ではありません。コードの変更、エラーの導入、私たちがそうであると私たちが思ったのは、実際にはそうではない、など.
実装Bもロジックを覆い隠しています。実装Aを見ると、開発者がhouse
がnull
になるのを防いだことなどは明らかです。「何もしない」ブランチが発生する条件のセットは取りました。実装Bでは、NullPointerException
になる条件のセットは何ですか? getLounge
は時々NullPointerException
をレイズしますか?私は他の場所を見なければ分からない。
A
:の利点
あなたは何をしたいかcondition
の下で明確にします:
_house != null && house.getLounge() != null && house.getLounge().getLetter() != null
_
それが条件です。そして、ある値をget
、もう1つの値をset
したいとします。
_String myValue = house.getLounge().getLetter();
textView.setText(myValue);
_
intent
の通信に関しては、これはclearです。ところで2番目の条件は必要ありません。文字列がnullの場合、何も表示されません。
B
が間違っている理由:
_try-catch
_を使用して通信します。"xを実行したいのですが、これはなんとなく危険です"-それは実際にはそうではありません。あなたの意図はA
の下ほど明確ではありません。そして-私の目には悪い-あなたはエラーの可能性を不明瞭にします:
_String myValue = house.getLounge().getLetter();
textView.setText(myValue);
_
NullPointerException
がスローされるのは、a)getLounge()
がnull
を返した場合、b)textView
がnullの場合です。あなたはoneNPEをキャッチしているので、どれがどれかわかりません。もちろん、このような単純なケースでは、debugにするのは簡単ですが、これは一般に間違った方法です。
私は3番目の方法に賛成です:
_String myValue = (house.getLounge()!=null)?house.getLounge().getLetter:"";
_
もちろん、_ternary Operator
_(一部の言語は概念を放棄しました)の使用についてDiskussionがありますが、この場合は最適です:デフォルト。
別のオプション
import Java.util.Optional;
Optional.fromNullable(house)
.map(House::getLounge)
.map(Lounge::getLetter)
.ifPresent(letter -> textView.setText(letter));
これにより、フロー制御の例外の使用が回避されますが、可能な各nullの詳細な処理も回避されます。代わりに、そのロジックはオプションのマップロジックの一部です。
バージョンAは自己記述型です。それはまさにそれが言うことをすることを目指しています。コンテキストから外されたバージョンBを見ると、防御がnull
であるかtextField
がnull
であることに反対するものであるかどうかはわかりません(おそらく、一部のレイアウトでは使用できず、他の一部のレイアウトでは使用できません-Androidリソース)を扱う場合、これは奇妙なことではありません。
レイアウトファイルにいくつかのタイプミスが導入されたため、ある日textField
がnull
である場合(長期的にはかなり可能性があります-findViewById
return null
if itは見つかりません)-バージョンAはエラーを明確にし、役立つ例外をスローします。そして、バージョンBはエラーを隠し、簡単な間違いを本当にあいまいでよく隠されたバグにします。
バージョン "b"について唯一言えることは、53文字短いということです。これはwayにして、適切な選択にするためのものです。