- - PR -
文字列をequalsで判定する時
投稿者 | 投稿内容 | ||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
投稿日時: 2008-02-14 02:19
具体的な考察は先の返答に書いたので参照してください。 私は挙げられたケース(HTTPヘッダとの比較)では実際に定数との比較をするとは考えにくい。 HTTPヘッダとの比較で具体的に用いたという例があれば参考のために挙げて欲しい。 私も見落としているかもしれない。
なるほど、可能性としては確かにありえますね。 かつ、else句ではstrが利用されない、あるいは代入のみという限定的な条件がつきますが。 単に、可能性があるからやめましょう、というのであれば思考停止だと思うのです。 このような事例があるとして、それはどのぐらい起こりうるだろうか、 そのリスクの度合いを考慮して、デメリットの大きさを測る必要があると考えている。 現時点では、定数を前に置いた時の例外隠しのリスク評価としては、 上記の場合に限られるわけですよ。 そして、このリスクの程度と、テスト漏れでのNullPointerExceptionの発生とを 秤にかけることになるのかな? | ||||||||||||
|
投稿日時: 2008-02-14 02:49
そうですね。私も「可能性があるからやめましょう」とは思ってない。というか自分でも "hoge".equals(str) と書くので。 どのぐらい起こりうるかというのは測るのが難しいけれど、常に "hoge".equals(str) と書いているなら、事故が起こる確率も上がりますね。
そうなるの…かな? ちょっと読み返すのが面倒で、読み返してないのだけど nagise さんは、str が null でも大抵の場合、比較不一致ということで問題ないから "hoge".equals(str) のほうが安全側に倒したコードだと言っていましたよね。たしか。 でも、予期せぬコード実行がおこなわれてしまう可能性という視点でみると、たとえテストが漏れていたとしても、実行時に NullPointerException が発生してくれる str.equals("hoge") のほうが安全側に倒したコードであるとも考えられる。プログラムは止まってしまうけど、止まったほうが安全という考え方。 で、ここは私は nagise さんと考えが違うところなんだけども。私は、null 考慮不足に対して"hoge".equals(str) が安全側に倒れているとは考えられない。常に "hoge".equals(str) と書くのなら、null 考慮不足はとても危険だと思う。 だから、私は "hoge".equals(str) と str.equals("hoge") を使い分けている。もし、記述を統一しなければならないという枷があるとしたら、(ここで unibon さんと同じ意見になるのだけど) NullPointerException の発生してくれる str.equals("hoge") のほうが安全で良いコードだと考えます。 個人的には、書き分けるのが一番良いと思っていますけどね。 | ||||||||||||
|
投稿日時: 2008-02-14 04:20
strと"hoge"を、colorと"red"に置き換えたらどうなるだろう。
color.equals("red") "red".equals(color) 天気だったら? weather.equals("clouded") "clouded".equals(weather) 私は前者の方が圧倒的に読みやすいと感じるのだが、これは単なる主観なんだろうか。 | ||||||||||||
|
投稿日時: 2008-02-14 09:37
colorとequalsするってことは、colorが"red"と等しいか判断するイメージでしょうが、"red"とequalsするってことは、"red"と等しいものを探すようなイメージになるのでしょうか。 私は主語 - 目的語という考え方はしていないですが、 どちらを基準にどちらを考えるかってことなのでしょう? プログラム的には"red"の場合だけifの中を通したいのだから、 "red"と等しいものを探して通すって考え方ならむしろ自然なのでは? 「自分はこっちが読みやすい」だと主観の話にしかなりませんが、 「自分が読みやすく感じるのはこのような考え方をしているのではないか?」 という話だと面白いのかもしれませんね。 | ||||||||||||
|
投稿日時: 2008-02-14 09:43
個人的には、"hoge".equals(str)は単にコードを短くするためのものだと思うんですけどね。冗長な記述は書くのもいやだし、読むときも思考の妨げになる。
単に有効な文字列がセットされているかどうかチェックするのに、
とか書きたくないし、
とか見ると、ただでさえCode Readingにはパワーを使うのに、本質的ではない部分でそれが浪費されるような気がする。 null考慮漏れがどうとか考えたことないし、今でもこの問題をそれとの関連で考えるべきものなのかどうかがよく分からないです。 | ||||||||||||
|
投稿日時: 2008-02-14 10:01
もちろん、状況に応じて書き分けるのですけども、デフォルトとして、 つまるところ常時の習慣としてどちらで書くべきだろうか、と。 そういう話なんですよね? (そういえば、ここの認識がはっきりしていないのか…) 書き分けるのは前提として、まずどちらの書き方から思考をスタートさせるか。 手が勝手にstr.equals("hoge")と打ち込んでから、 あぁ、ここは"hoge".equals(str)で記述したほうがよいな、と考えるのか。 それとも手が勝手に"hoge".equals(str)と打ち込んでから あぁ、ここはstr.equals("hoge")で記述したほうがよいな、と考えるのか。 習慣としてどちらで書くか、というのはどちらをデフォルトとしているのか ということなのですよね? 習慣としてstr.equals("hoge")と書く人は、nullチェックをうっかり忘れると ただちにNullPointerExceptionを作り込むことになる。 しかし、それはテストさえ行っていれば検出が容易だ、と。 習慣として"hoge".equals(str)と書く人は、大抵の場合で問題とはならないけども、 ごく稀に検出しにくいバグを作り込むのではないか。 ここまでの議論ではそういう話になっているわけですよね。 そして、私が検討しているのが 「ごく稀に検出しにくいバグを作り込むのではないか」 というのは本当だろうか、あるとしたらどういうケースなのか、ということ。 個人的な経験則で"hoge".equals(str)を習慣としていて、そのような事故に 遭遇したことがないわけですから、3つの可能性が考えられる。 A.事故にあう確率はとても低い B.事故にあう確率は低くはないが、たまたま遭遇したことがないだけ C.事故になりそうで実は事故は発生しない そして、「どういうケースで事故となるのだろう?」「その具体例は?」と 問うているのは、Cの可能性を考察しているから。 AとかBの可能性を論じることは非常にやりにくいですから、 Cの可能性を考えてみましょうよ、と。 「そんなわけはない」という結論ならAかBということなのでしょう。 「実は例外隠しとなる条件が満たされることは 現実的なコードで起きえないのではないか?」 というのが今の仮説なわけです。 危険性の考察はよくされているけども、具体的に痛い思いをしたという 話が挙がってこないことを鑑みれば、実は定数を左に置くことで 例外隠しが起こるってのは都市伝説じゃないの、と疑っている。 科学は疑うことから始まるようなものですから、 立場云々は関係ないことであることを再度表明しておきます。 例外隠しの実例が出てきたら、それは貴重な体験談となるのではないでしょうか。 | ||||||||||||
|
投稿日時: 2008-02-14 10:11
これだけ長いと読んでいなくても仕方ないですが、 その話はもう終わってます。 「if (str.equals("Hoge")) 」 「if ("Hoge".equals(str)) 」 の比較で十分です。 コードの長さは同じですね。 思考の妨げになるのは、順序のほうですね。 「どちらが自然と感じるか」とか、 「どちらが保守しやすいか」など。。。 僕の場合は、 設計書に「strが"Hoge"の場合…」と書かれているなら、 「if (str.equals("Hoge")) 」 が自然だと思っているのです。 もし、「"Hoge"がstrの場合…」と書かれているなら、 「if ("Hoge".equals(str)) 」 でも、まったく構いません。 # むしろ、強くこちらを推奨します! これも前出ですが、アサーションやエラー処理は別途考慮されている という前提です。 細かいテクニックの話が出るので、一応、応戦していますが、 上記、以外に主張はありません。 # 細かいテクニックにこだわる人でも上記が前提であれば、 # 「へー、そんなこともできるんだ」というふうに感心して捉えています ↑これが他のA派の人の考えと一致するかどうかは知りません。 | ||||||||||||
|
投稿日時: 2008-02-14 10:18
nagiseさん、
それは、あるかないかどちらにしても、 (すぐ書くかどうかは別にして最終的には)別途、チェックするという前提なら、 関係ないのではないでしょうか。 そういうケースは自然に考えてもいくつかあるかも知れませんし、 無理やり作り上げれば、いくらでもありそうですから。。。 今まで検証してきたことは無駄ではないと思いますが、 ずっと、それでひっぱる理由はもうなくなっていると思いますよ。 |