LoginSignup
15
1

More than 3 years have passed since last update.

Streamの中からIOExceptionを外に投げたい?それなら

Last updated at Posted at 2019-12-12

1
VavrのTryかEitherを使おう。

こういうことありませんか?

image.png

Streamで値を処理していて、途中のラムダ式内で検査例外を処理しないといけないようなケース

注:BookReaderは外部にあるなどで、変えるのが大変だと思ってください

よくあるであろう対処

image.png

実行時エラーRuntimeErrorに変えてしまうケース。
メソッド内やprivateな範囲できちんとエラーをハンドリングしているならまだしも、publicな世界に例外をぶっ飛ばしていたりしたらもう大変ですね。
また、今はそんなことをしていなくても、カジュアルにそういうことができてしまう作りになっている点が不安です。

無理にStreamつかわなきゃいいじゃん

image.png

ごもっとも。RuntimeError投げるよりかはよっぽどマシだとは思います。
ローカル変数をが0個から2個に増えたり、2倍以上のコーディング量になったり、ネストが2レベル深くなってますが、チーム全員がこれで満足しているなら別に良いんではないでしょうか。

本題

たとえばGolangではタプル(複数のインスタンスの組)を使って異常系の結果を呼び出し元へ伝搬させますが、Javaではタプルを言語仕様レベルではサポートしていません。
クラスを作れば代替できますが、関数型プログラミングに関してはScalaやHaskellを参考にすると、よりよいアイデアがあります。

Vavrは、Javaで関数型プログラミングをやりやすくするためのライブラリです。

Either

RightLeftいずれかの値をとるクラスです。正常系はRight、異常系はLeftにするのが通例です。(ダジャレ)

Optionalの強化版なイメージを持ってもらえればいいかと思います。
Optionalではnullか否かという情報しかStreamの下流へ流せませんが、Eitherは例外などの値を流すことができます。

Try

名前そのまま、try-catchを関数型に書くためのクラスです。
検査例外を投げうるラムダ式を受け取り、例外が発生したときの処理をラムダの形で表現できます。

こちらもEither同様に正常値・異常値のいずれかを内包しているOptional強化版と思ってください。

雰囲気だけ見るとTry一択に感じますが、Tryでは異常系処理の入力がThrowableになってしまいダウンキャストが発生しがちなので、Eitherで書いたほうがもやもやしないケースもあります。

書いてみる

例えばこんな感じになるかと思います。

Either:
image.png

Try:
image.png

Tryはthrows Throwableな点に注意。正しくハンドリングするならダウンキャストが必要になってくる。

ちなみに

Vavrはがっつり使いはじめると、もはやJavaに見えなくなって保守しにくくなり、なぜScalaやHaskellを使わないのだろうと自問し始めてしまうので、つまみ食い程度に使うことをおすすめします。

ほかの解決案

無理にJavaを使いつづけなくてもいいのでは?とボスに進言してもいいかもしれません。

雑感

これ、OSSの話かなぁ…

15
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
15
1