川村渇真の「知性の泉」

エラー処理設計:対処方法をシステム全体で定める


システムのエラー処理を総合的に設計する

 どんなシステムでもエラー処理は欠かせず、たいていは大きな割合を占める。システム上のエラーはもちろん、業務上に代表される問題領域のエラーまで対応しなければならないからだ。エラー処理の基本は、エラーを検出し、その結果によって適切な処理を実行すること。しかし、システム全体でみれば、異なるタイプのエラーが数多くあるため、エラー処理が分散するし、エラーの種類ごとに対処が違う。完成度の高いシステムを目指すなら、全部のエラーを把握しながら、システムを設計する必要がある。
 一部のエラー処理は、システムの基本構造と深く関係している。エラー処理を重視すると、システムの基本構造に影響を与える。逆に、システムの基本構造がエラー処理の一部を制限することもある。仕方がないので、両者の妥協点を見付けるしかない。
 この点を考慮し、次のような手順で基本構造を設計する。最初は、エラーがないと考えて基本構造を決める。次に、代表的なエラーを洗い出し、エラーごとの大まかな対処方法を定める。対処の内容によっては、基本構造の変更が求められるだろう。この段階で、両者の矛盾する部分を解決するために妥協点を探し出す。こうした検討の結果、システム基本構造とエラー対処方法の両方を修正し、最終的な設計内容が求まるわけだ。
 以上のように、エラー処理の設計は、システム全体で検討する必要がある。そのためにも、設計の早い段階で実施すべきで、大まかな作業手順は以下のとおり。

エラー処理設計の基本手順
1. 考えられるエラーを洗い出す
2. 洗い出したエラーを分類する
3. 分類したエラーごとに重要度を評価する
4. 分類したエラーごとに対処レベルを決める
5. システム側で対処するエラーの処理方法を定める
6. 必要に応じて、エラー対処に共通のクラスや処理を設計する
7. 定めた処理方法に合わせて、個別のエラー処理を設計する

 エラーを分類して、タイプごとに対処方法を決めるので、統一された対処が可能となる。また、エラー処理に共通のクラスや処理を使えるため、無駄のないシステムになりやすい。このように、全体を意識しながら設計するためには、エラー処理でもシステム全体を考慮して検討しなければならない。
 上記の手順に沿って、順番に作業内容を解説しよう。

代表的なエラーを洗い出して分類する

 最初にすべきなのは、エラーの洗い出しである。問題領域の例外処理からハードウェアのトラブルまで、考えられるエラーを片っ端から挙げていく。
 エラーの洗い出しでは、細かなエラーを全部挙げることではなく、分類した後の種類に漏れがないことが重要だ。「とにかく何でも挙げる」やり方では、どうしても漏れが起こりやすい。それよりも、「エラーの種類を大まかに分け、種類ごとに挙げていく方法」が適している。どのように分類するかは、対象となるシステムによって違う。一般的なシステムなら、以下のような区分けが良いだろう。

エラーを洗い出す際の区分け例
・問題領域で発生するエラー(例外処理も含む)
・操作ミスや入力ミスによるエラー
・外部システムから受け取るエラー
  (ディスクや通信で受け取るファイルやデータなど)
・対象システム内のバグによるエラー
  (システム内のサブシステム間でエラー検査する場合など)
・システム側のソフトウェア環境が原因で発生するエラー
  (メモリ不足、ディスクの保存領域不足など)
・ハードウェア関連のエラー
  (ディスクの書き込みエラーなど、主なものだけに限定)

 考えられるエラーを全部挙げる必要はないが、重大なエラーはすべて挙げなければならない。重大なエラーに関しては、対処方法を個別に検討するからだ。重大かどうかは、発生したときの損害の大きさと、発生頻度の多さで判断する。
 ひととおりのエラーを洗い出したら、細かく分類してみる。洗い出しに用いた大分類をもとに、それぞれの分類内をさらに分類して、2段階の細かな分類を作る。2段階目の分類の中に多くのエラーを含む分類項目があれば、エラー処理が統一できるかどうかを検討し、統一できない場合にだけ、さらなる分類を作る。つまり、その部分だけ3段階の分類となる。
 階層的な分類により、洗い出したエラーが整理できた。改めて全体を見直し、不足するエラーがないか考える。漏れていたエラーを思い付いたら、該当する分類に追加する。漏れを調べるのには、過去に行ったエラーの洗い出しリストが役立つ。こうした検討結果は整理して保存し、後から使えるようにしておきたい。

エラーの種類ごとに損害や対処を検討する

 分類したエラーは、一番細かい分類ごとに対処方法や重要度を検討する。一番細かい分類というのは、3段階まである分類なら3段階目を、2段階までしかない分類なら2段階目のことだ。3段階目を持つ2段階目の項目は、検討の対象としない。
 個々の分類項目では、以下のような内容を明らかにする。なお、コストや大きさといった項目では、具体的な数値ではなく、5〜10段階のレベル分けで構わない。使いやすいレベル分けを自分で設定しよう。

エラーの種類ごとに明らかにすべき項目
・発生時の損害の大きさ(信用低下、業務停止や復旧時間、損害額など)
・エラーの発生頻度
・エラー処理の大まかな内容(複数の対処方法も可)
  ・エラー処理に必要な技術、ツール、人材
  ・エラー対処の難しさ(技術面や運用面など)
  ・エラー処理部分の開発コスト

 エラー処理の内容に関しては、詳しく調べるのではなく、大まかにメドを立てる程度で済ませる。発生頻度は、1年に何回や1日に何回という形で、具体的な数値として表す。損害の大きさは、代表的な複数の項目を決めて、それぞれの損害の大きさをレベル分けする。
 エラーの内容によっては、対処方法が複数考えられる。同じ目的で複数ある場合だけでなく、解決レベルの異なる対処方法も検討する。たとえば、会社の存続に関わるような重要なエラーに対し、完全に対処する方法だけでなく、損害を小さくするための対処方法もあるだろう。どちらでも選べるように、この時点で両方を挙げておく。
 以上のような検討は、細かく分類した単位で考えるため、大まかで構わない。もし、分類内の一部のエラーが全体と一致しない場合は、そのエラーだけ別に、損害の大きさや対処方法を記述する。

エラーの分類ごとに対処レベルを決める

 エラーの分類ごとに、重要度や対処方法が明らかになったので、対象システムでの対処レベルを設定する。どのような対処レベルに分けるかは、対象システムによって少し異なる。参考のために、大まかな分け方を紹介しておこう。

エラー対処レベルの例
・システム側で、エラーを自動的に解決する
・エラーの発生をユーザーに知らせる(続きは以下の3種類)
  ・ユーザーが判断して自動対処
  ・その場でユーザーが手動対処
  ・その場での対処はあきらめる
・システム側ではエラー発生の検査をしない(続きは以下の3種類)
  ・人間が発見して、システム側の対処処理を動かす
  ・人間が発見して、システム外で対処する(すべて人間が処理する)
  ・人間側も何もしない(つまり、あきらめる、または無視する)

 見て分かるように、システムがエラーを自動的に解決するものから、エラーの発生すら検査しないものまである。対処できなかったり難しいエラーは、あきらめるしかない。システムが対処しないエラーでも、検討した記録を残しておく。
 対象システムによっては、上記の特定のレベルにエラーが集中することもある。そんな場合は、そのレベルだけ細分化して、より細かいレベル分けを用意する。このように、システムの特性に合わせてアレンジすることが大切だ。
 対処レベルが決まったら、エラーの細かな分類ごとに、どれかのレベルを設定する。分類ごとに1つの対処レベルを選ぶのが基本だ。しかし、重要なエラーに関しては、エラーごとに対処レベルを設定して構わない。

対処レベルに合わせてエラー処理を定める

 対処レベルが決まると、エラー処理を大まかに設計できる。ソフトウェア側の処理だけでなく、人間の作業も含めて、エラー処理の内容を定める。
 エラー処理の内容としては、ソフトウェア側の処理ロジックだけでなく、次のような項目も検討する。

エラー処理で検討すべき項目
・エラーの発見方法(システム側または人間側)
・エラー発生をユーザーへ通知する方法
・エラーに対処する方法(システム側と人間側の片方または両方)
・エラー記録の有無と記録方法(基本的にシステム側)
・エラー発見処理、対処処理、通知処理などのシステム内での入れ場所

 上記の項目の中には、エラーの細かな分類ではなく、個々のエラーごとに定める内容もある。エラー発見方法、対処する方法などだ。ユーザーへの通知も、細かな分類で統一できない場合だけ、個々のエラーごとに規定する。
 個々のエラーごとに細かな対処方法を定めるため、対処すべきエラーを網羅しなければならない。この作業に入る前に、細かな分類ごとの具体的なエラーを洗い出す。関係者が集まり、自由に発言する形式のほうが出やすい。
 システム側のエラー対処方法は、OSとソフトのタイプが同じなら、似た処理になることが多い。メモリー不足の場合にどうするか、といった内容だ。過去の対処方法を整理して標準化し、それを参照する形で規定したほうが効率的となる。対処方法が少し異なる場合でも、参照しながら違う点だけを説明すればよい。

エラー処理の共通化を検討する

 すべての分類でエラー処理が決まったら、処理が共通化できないかを検討してみる。とくに、エラーの通知と記録は、できるだけ共通で使えるようにする。最終的には、エラー処理の共通クラスや共通プロセスとして用意する。これらを先に設計して、システムの各部を設計する際に参照できる状態にしておく。
 どんなシステムでも使いやすさの向上が求められるようになったので、エラーの通知は親切に設計しなければならない。一般的には、以下のような内容を含むことが望ましい。

エラー通知に含むべき内容の例
・エラーコード
・エラーの重要度
・エラーの発生源
・エラー内容の簡単な説明メッセージ
・エラーに関する基本的な情報
  (発生時刻、ユーザーID、レコードキー、ファイル名など)
・対処方法またはヒント

 すべてのエラーには、エラーコードを付けるべきである。エラー内容を言葉だけで伝えると、エラーの種類を特定しにくく、電話でのサポートなどが大変になる。エラーコードが表示してあれば、何のエラーなのか素早く判断できる。同様に、エラー発生源の表示も重要。多くのソフトをインストールし、バックグラウンドで動いている環境が当たり前になりつつあるため、どのソフト(または機能)が出したのか、分かるように伝えなければならない。
 このようなエラー通知を実現するためには、エラーコードを体系化する必要がある。機能別にコード領域を分け、個々の機能ごとの追加や削除をやりやすくする。そのほか、他のシステムとエラーコードが区別できる点も考慮して、コードの体系を決める。

システム全体のエラー処理を仕様書にまとめる

 以上が、エラー処理設計の全体像である。なお、システムの規模がかなり大きい場合は、共通で使える大まかな方針だけ先に決めておいて、具体的な対処方法はサブシステム単位で細かく検討する。何事も、小さな単位に分けて検討したほうが、適切に作業しやすい。
 ここで紹介したようにエラー処理を設計すると、システム全体でエラーの重要度を比較でき、特定のエラー重視に偏らず、統一した基準での対処が可能となる。また、エラー処理の共通化も実現しやすい。さらには、どんなエラー処理がどの部分に入っているのか、システム全体で把握しやすい。これは非常に重要なことだ。後からでも把握できるように、エラー処理の全体像を説明した仕様書を作成しなければならない。
 設計の途中でも、エラーの重要度や対処方法といった資料を作成する。工程ごとに設計資料を書くので、資料はかなり多い。資料や仕様書は、検討または設計しながら書くようにして、効率的に作業するのが基本だ。ほとんどの書類をシステム完成後も残しておけば、別な人がシステムを把握する際に役立つ。最終的な処理内容だけでなく、エラーの重要度なども記述してあるのだから。

 エラー処理も、システム全体できちんと設計しなければならない。そのためには、ここで示したような手順を規定し、全体を把握しながら作業を進めることが大切だ。

(1999年11月16日)


下の飾り