- PR -

文字列をequalsで判定する時

投稿者投稿内容
あぶぽん
大ベテラン
会議室デビュー日: 2005/10/20
投稿数: 205
投稿日時: 2008-02-14 10:57
nagiseさん、

追記です。

引用:

その場合、設計書もそれなりの考えに基づいた文章になっていないといけませんが、



君子豹変かも知れませんが、

こなれた文章を提示されたら寝返るかも知れないですよ。

そもそも、設計書の書き方がOO的でないのかも知れないですから。

僕もちょっと考えてみましたが、簡単な例では表しきれないですね。

「"Hoge"と同じものを探し…」とかだと、まだ詰めが甘いですね。
A派に突っ込まれます。。。
未記入
大ベテラン
会議室デビュー日: 2008/02/07
投稿数: 115
投稿日時: 2008-02-14 10:58
引用:

書き分けるのは前提として、まずどちらの書き方から思考をスタートさせるか。



うーん。どうだったかな。普段、自然に漢字を書いているけど書き順は意識したことがない。どういう書き順で書いてる?と問われても書き順を思い出せないような感じ。無意識に、なんとなく書いてるから。

それでも、がんばって、自分のコーディング順序を思い出してみよう。

まず、事前条件を最初に書くということはしないですね。ロジックが組み上がってから、事前条件を付加する。

だから、最初に書くのは if(str.equals("hoge") ...

ここで考える。えっと str が null の場合は…。

(分岐1) str が null だとまずいなあ。よし事前条件を追加しよう。

if(str == null) {
  // return or throw Exception
}
if(str.equals("hoge")) {
  //メソッドの目的コード
}

とするか、もしくは、事前条件の短縮記述として…

if(str != null) {
  if(str.equals("hoge")) {
    //メソッドの目的コード
  }
}
//return or throws Exception

さらに短くして、

if(str != null && str.equals("hoge")) {
  //メソッドの目的コード
}
// return or throws Exception

と書くことも多い。

(分岐2) str が null でも問題ないよな。

if("hoge".equals(str)) {
  //メソッドの目的コード
}

こうしたほうが楽チンだ。

……こんな流れで私はコード書いてると思う。まず、str.equals("hoge") と書いて、str が null を許容するか許容しないかによって、事前条件を追加するか、"hoge".equals(str) に書き換えるかのどちらかをしている。

分かりやすく書くと以上のような流れだと思うけど、実際は慣れちゃっているから、str.equals("hoge") を書き始める前に手がとまって null について考えてると思う。そして、

事前条件 + str.equals("hoge")



"hoge".equals(str)

のどちらかで一気に書いてる。

引用:

手が勝手にstr.equals("hoge")と打ち込んでから、
あぁ、ここは"hoge".equals(str)で記述したほうがよいな、と考えるのか。
それとも手が勝手に"hoge".equals(str)と打ち込んでから
あぁ、ここはstr.equals("hoge")で記述したほうがよいな、と考えるのか。


なので、どちらかといえば、str.equals("hoge") と打ち込んでからということになると思う。あくまでも、どちらかといえばだけどね。慣れちゃえば、書き始める前に null について考えるようになるから、あとから書き換えるというのは減ってくると思う。

引用:

習慣としてstr.equals("hoge")と書く人は、nullチェックをうっかり忘れるとただちにNullPointerExceptionを作り込むことになる。しかし、それはテストさえ行っていれば検出が容易だ、と。

習慣として"hoge".equals(str)と書く人は、大抵の場合で問題とはならないけども、ごく稀に検出しにくいバグを作り込むのではないか。

ここまでの議論ではそういう話になっているわけですよね。


そういう話だったのですか…。それじゃあ、私と意見が合わないわけだ。私は、null チェックを忘れるべきじゃないと思ってる。null チェックを忘れる可能性があるのなら、絶対に str.equals("hoge") がいい。null でも問題ないという確認をしたうえでしか、"hoge".equals(str) とは書かないので。

引用:

危険性の考察はよくされているけども、具体的に痛い思いをしたという話が挙がってこないことを鑑みれば、実は定数を左に置くことで例外隠しが起こるってのは都市伝説じゃないの、と疑っている。

科学は疑うことから始まるようなものですから、
立場云々は関係ないことであることを再度表明しておきます。

例外隠しの実例が出てきたら、それは貴重な体験談となるのではないでしょうか。


ごめんなさい。私は、nagise さんの主張をはじめから読み違えていたようです。当初の nagise さんの意見に同意です、というのは撤回します。null について考慮せずとも、"hoge".equals(str) が安全だなんて私は認められない。
rain
ぬし
会議室デビュー日: 2006/10/19
投稿数: 549
投稿日時: 2008-02-14 11:03
引用:

カーニーさんの書き込み (2008-02-14 10:44) より:

そうか! nullを無害化すればいいのか!

コード:
if (str == null) {
  str = "";
}

if (str.equals("")) {
  ...
}



#ジョークです・・・



ジョークにつっこむのも無粋ですが、これって無害じゃなくて有害のような。
# そこまで含めてジョークだったらすみません
あぶぽん
大ベテラン
会議室デビュー日: 2005/10/20
投稿数: 205
投稿日時: 2008-02-14 11:18
引用:

# そこまで含めてジョークだったらすみません



もちろん、含めてでしょう(笑)

さらに無粋な解説をつけると、
『無害化』というのは、4ページで、かつのりさんが
おっしゃった言葉です。

その後、僕はその意見に『無害化』の定義も確かめず、
同意してます。。。

「いつから『無害化」が、アサーションとエラー処理になったんだ?」

って突っ込まれたら、痛いです(>_<)
よねKEN
ぬし
会議室デビュー日: 2003/08/23
投稿数: 472
投稿日時: 2008-02-14 11:43
「終わっている」と考えられた場所を教えていただいてありがとうございます。

引用:

あぶぽんさんの書き込み (2008-02-14 11:18) より:
引用:

# そこまで含めてジョークだったらすみません



もちろん、含めてでしょう(笑)

さらに無粋な解説をつけると、
『無害化』というのは、4ページで、かつのりさんが
おっしゃった言葉です。

その後、僕はその意見に『無害化』の定義も確かめず、
同意してます。。。

「いつから『無害化」が、アサーションとエラー処理になったんだ?」

って突っ込まれたら、痛いです(>_<)



既にご自身で気づかれているように、nullを許容する前提ではお話されていないということでよろしいですね。
nullを許容する前提での無害化は、カーニーさんのジョークにある通りになると思います。(以降、この無害化をジョーク無害化と呼びます。かつのりさんのおっしゃるところの無害化とイコールかどうかわかりませんので)

つまり、nullを許容する場合の記述は、

引用:

よねKENさんの書き込み (2008-02-14 10:32) より:

strがnullを許可する場合、

(1) str != null && str.equals("")
(2) "Hoge".equals(str)
(3) str.equals("Hoge")

(1)(2)の二つは等価ですが、(3)は違いますよね。

strにnullを許可しないことを前提とした場合の議論は進んでいますが、
strがnullを許可する前提ではどうか?という話については、
それぞれにどんなメリットがあるか?という話はなかったと思います。

少なくともあぶぽんさんはA派と宣言されていますが、(1)と(2)の比較については
言及されていなかったと思うのですが、違いましたか?



先のこの投稿に書いたように(1)と(2)が選択肢となります。
この場合もあぶぽんさんは(1)のような書き方がよいとお考えである、
という認識でよいですか?

(1)の書き方が駄目とは言わないまでも、私は可読性の観点から(2)がよいと考えています。
(2)がよいと思う理由はカーニーさんの書かれた内容に同感です。加えるなら、ジョーク無害化を行うことは有害になる可能性があります。それは無害化処理とequalsでの比較処理の距離が離れた場合です。

equalsでの比較処理だけを見たら、strがnullだと例外が発生しそうに見えるのに、実際には例外は発生しない。nullに対してどのように扱いたいのかが一目ではわからなくなります。このジョーク無害化と(3)の組合せを使うくらいなら、明らかに(2)の方がましでしょう。

後は、(1)と(2)の可読性をどう捉えるかの問題なので、そこはこれ以上は主張しません。
人の主観によりさまざまでしょうから。

引用:

あぶぽんさんの書き込み (2008-02-14 10:41) より:
何度も横道にそれていますが、
アサーションとエラー処理は別途考慮するということに

反論されていた方っていましたか?



いえ、特にないと思います。
ただし、nullを許可する場合には、アサーションもエラー処理もないですよね。
なので、nullを許可する前提とnullを許可しない前提は区別して考える必要があると思います。
あぶぽん
大ベテラン
会議室デビュー日: 2005/10/20
投稿数: 205
投稿日時: 2008-02-14 12:42
よ、よねKENさん。。。A派だったんじゃ。。。他人のこと言えないですけど(*^_^*)
(あ、B派って書かれてますね。。。なんとなく論調がA派だったので。。。失礼m(__)m)

引用:

既にご自身で気づかれているように、
nullを許容する前提ではお話されていないということでよろしいですね。




既に話しているつもりでしたが。。。

6ページです。
引用:

あぶぽんさんの書き込み (2008-02-12 17:31) より:
X. valueがnullであることがプログラム・ミスの場合
Y. valueがnullであるときにエラー処理を行なう場合
Z. valueがnullであっても良い場合

Xの場合は、アサーションではじきます。
Yの場合は、エラー値を返すなり、例外をスローするなりのエラー処理を行ないます。
Zの場合は、nullのときの動作を決めて、その動作をするようにします。

Aは、Yにあたります。
Bは、Zの一種で、
「valueはnullであっても良くて、その場合はfalseとして扱う」ということです。
Cは、考慮が漏れているので、XYZのどれかを決めること。



11ページです。
引用:

 NULLを許容しない:NULLであるときはバグである(もしくはエラー処理する)
 NULLを許容する:NULLであるときは偽(または真)とする




でも、よねKENさんのおっしゃりたいことは分かります。

 NULLを許容する:NULLであるときは偽(または真)とする

場合の処理を書くときに、

 (偽)の場合の例:
 「if (str != null && str.equals("Hoge"))」

と書く必要がありますが、

それについては、短所ではなく長所であると言いました。

それなのに、

 カーニーさんがおっしゃった、
 「"hoge".equals(str)は単にコードを短くするため」

というのを否定しているということですよね?

それは、今、言いますが、

1.許容しない場合は、A派もB派もアサーションもしくはエラー処理をしますね。

  だから、コードは同じ長さです。

2.許容する場合は、A派もB派もアサーションもしくはエラー処理をしないですね。

  B派のほうがコードが短いというのは認めます。
  しかし、それは短所ではなく長所です

というのが主張です。

だから、コードの長さの話はもう終わっているということです。

付け加えるなら、

11ページ:未記入さん
コード:
"test".equals(str) が null を許容するという思い込みは危険だなあって。
それだけ。今後は、気が向いたら "test".equals(str) の横に //nullでもいいよ。とコメント書いておきます。 



この「//nullでもいいよ」というコメントは、
2の場合で(nullは偽)だから必要なのではないですか?

2の場合で(nullは真)なら、言うまでもなく。。。ですね。
よねKEN
ぬし
会議室デビュー日: 2003/08/23
投稿数: 472
投稿日時: 2008-02-14 13:05
引用:

あぶぽんさんの書き込み (2008-02-14 12:42) より:
1.許容しない場合は、A派もB派もアサーションもしくはエラー処理をしますね。

  だから、コードは同じ長さです。

2.許容する場合は、A派もB派もアサーションもしくはエラー処理をしないですね。

  B派のほうがコードが短いというのは認めます。
  しかし、それは短所ではなく長所です

というのが主張です。



2の場合は、(ご自身がそうするかどうかは別にして)B派のスタイルも"あり"という考えということですね。
全面的にA派スタイルしかありえないよっていうスタンスかと思っていたので誤解していたようです。

引用:

あぶぽんさんの書き込み (2008-02-14 12:42) より:
11ページ:未記入さん
コード:
"test".equals(str) が null を許容するという思い込みは危険だなあって。
それだけ。今後は、気が向いたら "test".equals(str) の横に //nullでもいいよ。とコメント書いておきます。 



この「//nullでもいいよ」というコメントは、
2の場合で(nullは偽)だから必要なのではないですか?

2の場合で(nullは真)なら、言うまでもなく。。。ですね。



私は「//nullでもいいよ」というようなコメントは不要だと思います。

ただし、あぶぽんさんの事例にようにコーディング規約でB派スタイルが義務付けられている場合は、実装者が自分の書いたコードの意味を理解していない可能性があるので、その限りではないかもしれませんが。
かつのり
ぬし
会議室デビュー日: 2004/03/18
投稿数: 2015
お住まい・勤務地: 札幌
投稿日時: 2008-02-14 13:15
名前が出ていたので。

無害化とは空文字列の代入を意味しています。
単純に比較のみの目的であれば不要とかと思いますが、
開発の現場では前後に別の処理もあったりしますので、
空文字列を代入しています。

俗に言うNull Objectパターンに近いと思います。

例えばWEBシステムを作っていたとします。
よくある大半のWEBの画面の項目との入出力では、
空文字列とnullを明示的に区別しなければいけないケースって、
そんなに多くないのではと思います。
そんな場合、予め無害化を行っておくと処理が簡潔になります。

スキルアップ/キャリアアップ(JOB@IT)