こういうことありませんか?
Streamで値を処理していて、途中のラムダ式内で検査例外を処理しないといけないようなケース
注:BookReader
は外部にあるなどで、変えるのが大変だと思ってください
よくあるであろう対処
実行時エラーRuntimeErrorに変えてしまうケース。
メソッド内やprivateな範囲できちんとエラーをハンドリングしているならまだしも、publicな世界に例外をぶっ飛ばしていたりしたらもう大変ですね。
また、今はそんなことをしていなくても、カジュアルにそういうことができてしまう作りになっている点が不安です。
無理にStreamつかわなきゃいいじゃん
ごもっとも。RuntimeError投げるよりかはよっぽどマシだとは思います。
ローカル変数をが0個から2個に増えたり、2倍以上のコーディング量になったり、ネストが2レベル深くなってますが、チーム全員がこれで満足しているなら別に良いんではないでしょうか。
本題
たとえばGolangではタプル(複数のインスタンスの組)を使って異常系の結果を呼び出し元へ伝搬させますが、Javaではタプルを言語仕様レベルではサポートしていません。
クラスを作れば代替できますが、関数型プログラミングに関してはScalaやHaskellを参考にすると、よりよいアイデアがあります。
Vavrは、Javaで関数型プログラミングをやりやすくするためのライブラリです。
Either
Right
かLeft
いずれかの値をとるクラスです。正常系はRight
、異常系はLeft
にするのが通例です。(ダジャレ)
Optional
の強化版なイメージを持ってもらえればいいかと思います。
Optional
ではnull
か否かという情報しかStreamの下流へ流せませんが、Either
は例外などの値を流すことができます。
Try
名前そのまま、try-catchを関数型に書くためのクラスです。
検査例外を投げうるラムダ式を受け取り、例外が発生したときの処理をラムダの形で表現できます。
こちらもEither
同様に正常値・異常値のいずれかを内包しているOptional
強化版と思ってください。
雰囲気だけ見るとTry一択に感じますが、Tryでは異常系処理の入力がThrowable
になってしまいダウンキャストが発生しがちなので、Either
で書いたほうがもやもやしないケースもあります。
書いてみる
例えばこんな感じになるかと思います。
Tryはthrows Throwable
な点に注意。正しくハンドリングするならダウンキャストが必要になってくる。
ちなみに
Vavrはがっつり使いはじめると、もはやJavaに見えなくなって保守しにくくなり、なぜScalaやHaskellを使わないのだろうと自問し始めてしまうので、つまみ食い程度に使うことをおすすめします。
ほかの解決案
無理にJavaを使いつづけなくてもいいのでは?とボスに進言してもいいかもしれません。
雑感
これ、OSSの話かなぁ…