TL;DR
- 例外を使うか、エラーを値で返すかは、使う言語やフレームワークの慣習に合わせる。
- その選択の前に、誰がエラーを拾うか、リカバリーが必要か、ユーザにどんなメッセージを出すかをトップダウンで設計する。
内容
プログラミングにおけるより良い選択とは の 2 つ目のテーマ。
慣習に合わせる
渋川さんによると、例外とその他のエラーハンドリングのどちらを選ぶかは、使う言語やフレームワークに合わせる。慣習に合っていない独善的なコードは書かない。松岡さんもこれに同意した。
ただし、松岡さんによると議論の余地はある。e.g. TypeScript では例外の型推論が効かないので、エラーを値で返すほうがよい。Kotlin や Scala のように、オブジェクト指向と関数型プログラミングを併せ持つ言語では、この議論になりやすい。松岡さんは Kotlin でエラーを値で扱うライブラリ kotlin-result を紹介した。
先にトップダウンで設計する
渋川さんは、例外か他の方法かを選ぶ前に、トップダウンで設計すべきことが多いと話した。
- 誰がその例外やエラーを拾うのか
- リカバリーが必要か
- ユーザにどんなメッセージを出したいか
松岡さんによると、ポリシーが定まれば、その中でメリットとデメリットを比べて手段を選べばよい。設計標準を定め、意思決定の内容と判断の過程を記しておくのもおすすめだという。ただし、設計標準はあくまで参考にするためのものという位置づけである。
例外を使うメリット
渋川さんによると、深いところで起きた例外でも、処理する場所を 1 か所に集約できる。C++ ではデストラクタを呼んでくれる。
松岡さんは、Go の error と panic のような使い分けが大切だと話した。Go では、呼び出し元で対処できるかどうかで使い分ける。
意図が分からないまま残っているコード
実装した当時の考えが分からない例外処理でも、エラーを握りつぶすのかリトライするのかといった結果が気に入らなければ、必要に応じて直すべきである。この点は両者とも同じ意見だった。
キーワード
自分の理解
Go はエラーを戻り値で返す言語なので、慣習に合わせるという話はしっくりくる。
kotlin-result は、プロジェクトやメンバによっては採用していたが、思っていたよりメジャーであることに驚いた。
レイヤごとに独自のエラーを定義するかも設計で決めることの 1 つだと思う。普通は定義するとは思うけど。