- PR -

例外処理の体系について

1
投稿者投稿内容
taka
会議室デビュー日: 2007/10/27
投稿数: 4
投稿日時: 2007-10-27 14:13
【はじめに】
初めて投稿させていただきます。
私は、VB.NET2003(FrameWork1.1)で業務アプリケーションの開発を行っています。
アプリケーションは、MVCモデルにのっとって作成しています。
Vが画面で、Cが制御部分、Mが各種機能部分です。

【聞きたいこと】
下記で説明することを達成できる例外処理・エラー処理の体系が知りたいです。
また、私が考えた二つの方法についても、意見をお願いします。

【やりたいこと】
・例外やエラーに独自に番号を振り、対応するメッセージを作成しておく。
・エラーや例外が発生した場合、上記メッセージを表示する。
・メッセージはすべて、コントローラ部分で表示する。
・発生した例外の処理は、その場で行い、エラー番号だけをコントローラに伝える。

【前提条件】
・テストを簡単するため、ModelとController間ではオブジェクトのやり取りを極力行いたくない。
・メソッドの返値で、エラー番号を返すことはしたくない。

【考えた方法1】
Model部分で、例外をCatchで捕まえ、Throwする。
Throw new System.Exception("独自のエラー番号orコード")

この方法だとModelとController間では極力オブジェクトをやり取りしたくないという前提に反してしまいます。

【考えた方法2】
Model部分には、例外発生を表すプロパティを用意する。
Model部分で、例外をCatchで捕まえ、プロパティにエラー番号を書き込む。
Controller部分で、Modelを使い終わった後で、プロパティを参照して、
エラーが起きていないか確認する。

この方法だと、前提条件には反していないのですが、何か微妙な感じがします。


[ メッセージ編集済み 編集者: taka 編集日時 2007-10-27 14:14 ]
unibon
ぬし
会議室デビュー日: 2002/08/22
投稿数: 1532
お住まい・勤務地: 美人谷        良回答(20pt)
投稿日時: 2007-10-27 16:21
引用:

takaさんの書き込み (2007-10-27 14:13) より:
アプリケーションは、MVCモデルにのっとって作成しています。
Vが画面で、Cが制御部分、Mが各種機能部分です。


背景として MVC があるということは分かりましたが、例外をどうするかは、MVC がどうかには直接依存せず、あくまでもモジュール間の受け渡しの問題でしかないと思います。

引用:

takaさんの書き込み (2007-10-27 14:13) より:
【考えた方法1】
Model部分で、例外をCatchで捕まえ、Throwする。
Throw new System.Exception("独自のエラー番号orコード")

この方法だとModelとController間では極力オブジェクトをやり取りしたくないという前提に反してしまいます。


これは、リスロー(rethrow)に近いやりかただと思います。「方法2」との違いは、例外を使うか使わないかだけですよね。例外は極力使わないほうが良いと思います。もし使うのならば、Model は例外を catch せずそのまま外部にスルーしてしまうほうがまだマシだと思います。

引用:

takaさんの書き込み (2007-10-27 14:13) より:
【考えた方法2】
Model部分には、例外発生を表すプロパティを用意する。
Model部分で、例外をCatchで捕まえ、プロパティにエラー番号を書き込む。
Controller部分で、Modelを使い終わった後で、プロパティを参照して、
エラーが起きていないか確認する。

この方法だと、前提条件には反していないのですが、何か微妙な感じがします。


Model が、その内部で起きた例外を捕らえて、内部の状態に変換するのは良いことだと思います。しかし、例外をプロパティーにそのまま素通しに1対1に変換するというのは、Model の内部構造をそのまま外部に公開していることになり、隠蔽をしていないことになります。

引用:

takaさんの書き込み (2007-10-27 14:13) より:
【前提条件】
・テストを簡単するため、ModelとController間ではオブジェクトのやり取りを極力行いたくない。
・メソッドの返値で、エラー番号を返すことはしたくない。


そもそも、Model 内部で発生する例外はどんな種類のものかにもよると思います。
また、モジュール間の(広い意味での)メッセージのやりとりが必要ならば、そのやりとりは仕方のないものでありやらなければならないでしょう。例外を使ったりプロパティーを使ったりすることと、メソッドの返り値を使う(あるいはエラー用に値オブジェクトを使うなどすること)ことに、本質的な情報量に違いはないのではないでしょうか。

メッセージの種類として、例外ありき、で作ると、あたりまえですが、例外だらけのコードになってしまいます。外部リソースのエラーが原因で起こる例外以外は、例外というものはなるべく使わないほうが良いと思います。

--
unibon {B73D0144-CD2A-11DA-8E06-0050DA15BC86}
一郎
ぬし
会議室デビュー日: 2002/10/11
投稿数: 1081
投稿日時: 2007-10-28 12:11
例外の種類で発生したエラーの種類を伝えようが、例外のMessageにエラー番号を設定しようが、メソッドの返り値でエラー番号を返そうが、呼び出し元にエラーを伝えるという点では同じです。
同じですが、目的を達成できずにそれ以降処理を続行しても無駄なため、プログラマに何らかの判断を迫るために例外という仕組みがあります。
(その他、例外時のコードをまとめるとか色々効能はありますけど。)

たとえば、
Dim i as Integer = Integer.Parse("12a")
こうすると、Parseに失敗しiは何の意味もない値ですので、iを使ってそれ以降の作業をしても仕方がないですよね。
ファイルのオープンに失敗したら、それ以降ファイルを扱う処理を続行しても意味がないですよね。
例外が発生したとき、プログラマはどう対処するかということを決めなければならなくなります。
無視するのであれば、積極的に空のcatch文を書いた「無視するコード」を書かなければならなくなります。

例外にはそういった効果がありますので、
>メソッドの返値で、エラー番号を返すことはしたくない。
時と場合によりきりですが、これはあんまりしない方がいいと思います。
メソッドの返り値のチェックを忘れて処理を続行してしまうようなコードを書いてしまう可能性があるからです。
コードを書いている今はいいですが、半年後に別の人が手直しをするようなことになった場合に「この時はこうしなければいけない」というルールを、takaさんの作ったドキュメントをいちいち見て確認しながらコードを書いてくれる保証はないからです。
ですので、takaさんの【考えた方法2】の
>Model部分には、例外発生を表すプロパティを用意する。
も同様に良くないです。というより「メソッドの返り値にエラー番号」よりもっと悪いです。
takaさんが微妙な感じを感じているのはこのせいですかね。

通常の正しい運用をしていても発生するものであれば、それをControllerに通知するのに例外を使うべきではありません。
(例えばユーザーが入力したIDとパスワードが正しいかチェックして違っている場合など)
正しい環境正しい運用であれば起きないはずの例外的なものであれば、例外を発生されるべきです。
【考えた方法1】だと例外の情報が失われますし、Messageにエラー番号ってのもおかしいので、たとえばこんなのはどうでしょう。
コード:

Public Class ModelException
Inherits Exception

Private Const message As String = "モデル内で例外が発生しました。"
Public Readonly Reason As ModexExceptionReason

Public Sub New(reason As ModexExceptionReason)
MyBase.New(message)

Reason = reason
End Sub
Public Sub New(reason As ModexExceptionReason, innerException As Exception)
MyBase.New(message, innerException)

Reason = reason
End Sub

EndClass

Public Enum ModexExceptionReason
Other
DBConnectionFailure
ConfigFileNotExist
・・・
End Enum


Modelから外に投げる例外はすべてこれにして、その内容を列挙型で表すというのは。
(ソースコードは掲示板に手打ちですので、コンパイルが通らないかも)

[ メッセージ編集済み 編集者: 一郎 編集日時 2007-10-28 12:14 ]
Jitta
ぬし
会議室デビュー日: 2002/07/05
投稿数: 6267
お住まい・勤務地: 兵庫県・海手
投稿日時: 2007-10-28 17:26
ユーザーが関与することで生成される不都合と、
システムとしてあるべきではない、または開発中に潰しておかなければならない不都合に分類します。


私なら、前者はビューで表示させます
後者は、開発中ならその場で表示、リリース後はエラーログとして記録できるようにするかなぁ?

また、後者はさらに、業務処理を継続できる不都合と、継続できない不都合に分類したいなぁ
taka
会議室デビュー日: 2007/10/27
投稿数: 4
投稿日時: 2007-10-29 02:31
皆様貴重なご意見ありがとうございます!
これを参考に、もう一度考えて見ます。
まとまり次第、再び書き込みたいと思います。
では取り急ぎ、お礼のみで失礼します。
1

スキルアップ/キャリアアップ(JOB@IT)