エラー処理の方針とString#equalsの書き方

String#equalsを使った文字列リテラルとの比較の書き方として、str.equals("リテラル")と書くのがいいか、"リテラル".equlas(str)と書くのがいいかという論争がありました。
そこで、この問題について、エラー処理の方針と絡めて考えてみようと思います。


エラー処理の方針として、エラーパッシングとエラーリカバリーという考え方があります。


エラーパッシングは、エラーがあってもそれを無視して処理を行うという考え方です。例えば音楽データの再生時に、データの一部が欠けていたとしてもそこを適当に補完を行って再生を続けるような考え方です。
人間相手の処理では、エラーによって処理が止まるよりも、それなりの対処を行って処理を続けることのほうが求められるので、ユーザーインタフェースやコンテンツのプログラムではエラーパッシングで考えることが多いと思います。


エラーリカバリーは、エラーが起こったときにエラーが起こらなくなるように処理をする考え方です。エラーが起こったらもう一度実行したり、そこで処理を止めてプログラムを修正して再実行するというような考え方です。
信頼性の求められる処理を行う場合、フェイルファストという考え方が重要になります。エラーをなるべく早く検知するという考え方です。このとき、エラーが起こっていたときには変な処理をせず、そこで処理を終わらせるということが大切です。フェイルファストでは、処理が正常終了するかエラーを発生したらなにもせずに終わるかどちらかであるということになります。
フェイルファストを求める場合は、エラー処理の方針としてはエラーリカバリーになります。業務データ処理はフェイルファストである必要があるので、エラーリカバリーで考えることが多いと思います。


それでは、この考え方をString#equalsの書き方にあてはめてみます。
strがnullであってはいけないとき、strがnullになっていたらそれはエラーです。"リテラル".equals(str)の書き方はそのエラーがあってもそれを無視して処理を行うので、エラーパッシングということになります。str.equlas("リテラル")の書き方では、strがnullであるときに例外が発生して処理が止まるので、これはエラーリカバリーということになります。
strがnullであってはいけない場合、フェイルファストを考えるとstr.equlas("リテラル")と書くほうが適しています。これがstr.equals("リテラル")がよいという場合の説明であったと思います。
フェイルファストを求めてエラーリカバリーの考え方をとるか、利便性を求めてエラーパッシングの考え方をとるかというのは、作るものの性質や開発でのポリシーによります。つまり、strがnullであってはいけない場合には、str.equals("リテラル")でも"リテラル".equals(str)でも、どちらでも状況にあったほうで書けばいいということになります。


では、strがnullであってもいいときはどうでしょうか?
"リテラル".equals(str)の書き方はstrがnullのときfalseを返し、これは正常動作になります。一方で、str.equlas("リテラル")はstrがnullのとき例外を出し、これはこの処理自体がバグになっています。

書き方 nullを拒否 nullを許容
str.equals("リテラル") エラーリカバリ バグ
"リテラル".equlas(str) エラーパッシング 正常

このことから、str.equals("リテラル")という書き方は、strがnullであってはいけないときのみ許される書き方ということになります。strがnullであってもいいときには、str.equals("リテラル")という書き方は、この式自体がバグになってしまいます。


プログラムを書くときには、エラーがあったときの方針をどうするかということよりも、そもそもエラーを出さないことが重要だと考えます。そのため、ぼくは、エラーの発生源となりうるstr.equlas("リテラル")という書き方よりは、エラーの発生源にはならない"リテラル".equlas(str)という書き方を勧めます。
もちろん、nullチェックを必ず行うという条件をつけてstr.equals("リテラル")がよいとする考え方もあるでしょうが、ぼくはコーディング規則は無条件であることが望ましいと考えます。


エラーリカバリーがいいかエラーパッシングがいいかという視点での議論には意味がありません。「エラーが早くみつかるのがいい」とか「エラーがあってもそれなりに動くのがいい」というのは、それぞれの状況によって決めることです。
String#equalsの書き方について議論するときは、nullを許容する場合にstr.equals("リテラル")がバグになる可能性がどれだけあるか、バグを作りこむ可能性の排除と他でのバグを発見することのどちらを優先するか、条件付コーディング規則を認めるかという観点で意見をだす必要があると思います。