🚨

[Dart] Exceptionはcatchしていいが、Errorはコードのバグなので極力catchしてはいけない

2023/06/18に公開

DartにおけるError型とException型の使い分け

  • Error

    • プログラムの問題
      • コードの修正が必要であり、プログラムは強制終了した方が良い。
      • try ~ catchで補足しない方が良い。
      • ArgumentError
      • AssertionError
      • AsyncError
      • NoSuchMethodError
      • OutOfMemoryError
      • StackOverflowError
      • StateError
      • TypeError
  • Exception

    • 実行時の問題
      • コード側であらかじめ予期することが難しい。
      • try ~ catchで制御した方が良い。
      • catchしないとisolateが保留となり、そのisolateは終了する
    • abstract + interface型として実装されている
      • 独自のExceptionクラスを定義する場合は、implementする
      • FormatException
      • IOException
      • TimeoutException
      • DeferredLoadException
      • IsolateSpawnException
      • NullRejectionException
      • OSError
  • 参考資料

Error class

https://github.com/dart-lang/sdk/blob/main/sdk/lib/core/errors.dart#L71-L124

Exception class

https://github.com/dart-lang/sdk/blob/main/sdk/lib/core/exceptions.dart#L22-L38

ExceptionのHandlingの実装例

Error handling(dart.dev)

try {
  breedMoreLlamas();
} on OutOfLlamasException {
  // 特定の種類のExceptionをcatch
  buyMoreLlamas();
} on Exception catch (exception) {
  // 全てに種類のExceptionをcatch
  print('Unknown exception: $exception');
} catch (e, stackTrace) {
  // errorも含めて全てcatch
  // eはObject型
  print('Something really unknown: $e');
  print('Stack trace:\n $stackTrace');
} finally {
  print('finally');
}

ExceptionのHandlingのプラクティス

Error handling(Effective Dart)

AVOID catches without on clauses.

ExceptionやErrorをcatchするときはon句を使って種類を制限する。
全てcatchするとErrorを握りつぶしてしまうため。

DON’T discard errors from catches without on clauses.

on句無しでのcatchを利用した場合、errorを必ず出力する。
errorは握り潰さない。

DO throw objects that implement Error only for programmatic errors.

Errorはコードにバグがあることを表すクラスなので、コードの修正が必要な場合のみErrorオブジェクトをthrowする。
普通にアプリケーション開発しているときにError throwすることはなさそう。
パッケージの開発する時とか。

DON’T explicitly catch Error or types that implement it.

今までと同じこと言ってる。
Errorはcatchしない、なぜならバグだから。
プログラムが終了するのが適切。

DO use rethrow to rethrow a caught exception.

catchした後に、再度Exceptionを発生させる場合はrethrowを使おう

try {
  somethingRisky();
} catch (e) {
  if (!canHandle(e)) rethrow;
  handle(e);
}

Exceptionは伝播する

画像引用:https://www.cresc.co.jp/tech/java/Google_Dart2/language/exceptions/exceptions.html

Discussion