巨大なtry-catchが許せない

他の人が書いたコードに関しては誰しも許せないと思うようなことがあるだろう。私が最もイライラするのは巨大なtry-catch構文である。

    try {
        foo();
        bar();
        ...
        ...
        spam();
        egg();
    } catch (Throwable t) {
        LOG.warn("error message", t)
    }

というようなものだ。tryブロックの中で処理が長々と書いてあって、すべてのエラー・例外をまとめてcatchする。書くのは楽だからか、こういう例を頻繁に見る。楽に書けるコードがいまいちだというこの点はJava言語の欠陥である。

これが気に食わない理由は、

  • どんな例外・エラーが起こりうるかを想定せずに書いているのが明らか
  • 失敗しても構わないような処理ならばそもそもやらなくていいと思える
  • tryブロックの中のルーチンは何かしらまとまった意味があるのだから、別のサブルーチンにすべき

という点だ。

Throwableではなく、Exceptionの場合もあるが、このような継承ツリーの根に近いものをcatchするのはありえない。NullPointerExceptionだとかOutOfMemoryErrorなどの明らかな障害もcatchするのか?それが出たら素直に落とすべきだろう?どういうエラーが出るのかを想定してそれぞれに対してハンドリングするのが異常系を考慮するということだ。想定外のエラーがあることも想定するならなお良い。catch (Throwable t)は何も考えていないのが明らかだ。

こういう書き方になるケースというのは、一連の処理を試してみて失敗したらしたで、別の動きをさせようという気持ちが現れている。そもそも失敗しても構わない処理ならやらなくてよいのではないだろうか。とりあえず試してみるみたいな言い訳じみた態度が読み取れるので、スタンスとして気に食わない。不要な処理でコードが汚されるのが許せない。

可読性・保守性の観点からも嫌いだ。tryブロックの中の処理はこれを試してみるよという何かしらの意味のある手続きだろう。ならばサブルーチンとして分けるべきだ。巨大なtry-catchは、tryブロックの中で何がしたいのか分からないことが多い。別のメソッドに分けたらならば、throws Throwableなんて異常なメソッドは作らないだろう。頭を整理する意味でも、別のメソッドに分けてほしい。

汚く正しいコードを書けるほど賢い人はいない。

The Art of Readable Code (Theory in Practice)

The Art of Readable Code (Theory in Practice)