Effective C# 3rd 読書メモ 48 例外:強い保証を使用する

例外が投げられると、処理の流れは中断される。不適切な方法で例外を投げると、それをハンドリングすることは困難である。例外の投げ方にはベストプラクティスがある。

  1. 基本的な保証
  2. 強い保証
  3. no-throw保証

基本的な保証は、例外が投げられた後でも、そのメソッドにおいて全てのオブジェクトがリークせず、有効な状態であることを意味する。強い保証は、基本的な保証に加えて、例外が発生した場合でも、プログラムの状態が変わらないことを意味する。no-throw保証は、処理が絶対に失敗せず、例外が投げられないことをいう。

このうち、強い保証を採用することが、安全性とシンプルさの点からバランスがよい。強い保証のもとでは、メソッドの結果は、処理が完了するか、何も変わらないかのいずれかである。中間点はない。強い保証の利点は、例外をキャッチした後でも処理を継続しやすいことだ。

強い保証のためには以下のような(今までに紹介してきた)テクニックが使用できる。

  • プログラムが使用するデータはイミュータブルな値型に入れる
  • LINQクエリのような関数型プログラミングのスタイルを使用する

データの書き換えは以下の様式に沿って行うべきである。

  1. 変更されるデータのコピーを作成する
  2. コピーに対して変更を行う
  3. コピーをオリジナルと置き換える

しかし、強い保証を使用するとパフォーマンスの問題が発生することもある。たとえば、ループで大量のオブジェクトを書き換える場合には、コピーを作って差し替える方式は効率が悪い。

また、差し替え方式は、参照型では使用することができない。コピーとオリジナルと差し替えても、オリジナルを参照しているオブジェクトが残っている場合があるからだ。

実用的な対処法は、以下のように新しくデータを作り直すことである。

上の方法は絶対確実な方法とはいえない。絶対確実にするためには、以下のように、データを包含するクラス(Envelope)を作成し、そのクラスに置き換えを行わせる必要がある。

このクラスは以下のように使用する。

所感

「強い保証」の考え方はRDBMSのトランザクションっぽくて面白い。1メソッドを1トランザクションと考えて、そのメソッド内で処理が完了すればコミット、何かうまくいかないことがあればロールバック。

コメントを残す