- - PR -
例外処理について
1
投稿者 | 投稿内容 | ||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
投稿日時: 2006-07-11 16:48
例外処理で過去記事を検索し読んできました。
なんだか自分の例外処理が間違っているのでは!?と不安になったので質問させてください。 現在のシステムは発注元様が色々なクラスを作っております。 私はその1端を開発しております。 たとえばデータベースアクセスクラスなるものがあったとします。 SELECT文を一つ投げるのでも 結果がDataSetでほしければGetDataSetメソッド 結果がDataTabeleでほしければGetDataTableメソッド 結果がDataRowでほしければGetDataRowメソッド 結果が1行1フィールドの場合GetDataObjectメソッド などなどほかにもたくさんあります。 呼び出し元から各メソッドのVyRef引数にDataSet、DataTable、DataRow、Objectなどを渡してやると そこにデータを入れてくれるんです。 各メソッドの戻り値はBooleanで異常時True、正常時Falseを返します。 たとえばGetDataRowメソッドでDataSet.DataTable(0).Rows(0)をVyRef引数にセットしてくれるんですが Rows(0) が NothingだったらTrueが返るんです。「True」です。「False」ではありません。 内部で例外が発生すると例外をログに書き込み且つエラーメッセージを表示し例外はThrowしてくれません。 戻り値「True」が返ります。 SELECT文を投げるときはデータベースアクセスクラスの各メソッドを使用しなくてはなりません。お約束です。 データベースアクセスクラスを修正することもナシです。 ここからが本題です。 各メソッドを使うかぎり、自由にコードを書いていいのですが例外処理についても同様に自由です。 データベースアクセスクラスが何をして、戻り値が何で、どんな例外をThrowするのか ソースを読めばわかりますがメンドクサイので すべての例外をExceptionでCatchし最上位のコードまで例外を再Throwさせて最上位で処理するようにしています。 これはゴールキーパー以外はハンドで反則になるのでしょうか? private sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click Try Call SubTest1 Catch ex As ApplicationException messagebox.show(ex.Message) Catch ex As Exception WriteLog(ex.ToString) messagebox.show(ex.ToStrin) End Try End Sub Private Sub SubTest1 Dim datarow as DataRow Dim sql as new System.Text.StringBuilder(String.Empty) Try '予想しうる例外 If ("").Equals(Me.TextBox1.Text.Trim) Then Me.TextBox1.Focus() Throw New ApplicationException("テキストボックス1が未入力です。") End If 'SELECT文を投げDataRow取得 sql.Append(" SELECT COUNT(*) FROM table1") sql.Append(" WHERE field1 = '" & Me.TextBox1.Text.Trim & "'") call データベースアクセスクラス.GetDataTable(datarow,sql.tostring) ’予想しない例外 if datarow is Nothing Then Throw new Exception("DataRowオブジェクトが取れないよ。") End If Catch ex As ApplicationException throw(ex.message) Catch ex As Exception throw(ex.ToString) End Try End Sub | ||||||||||||||||||||||||||||||||
|
投稿日時: 2006-07-11 18:37
なぜか、私の直前の書き込みから本文がぬけてたので、再度。
なります。 この辺は、通称「赤間本」に詳しく出ています。 「.NETエンタープライズWebアプリケーション開発技術大全シリーズ」 「発注元様」のクラスにも問題があるように思います。 .NETではどのようなコードで書くべきか、については、MSから出ている多くの サンプルから掴み取るのがよいと思います。 Enterprise Library for .NET Framework 2.0は、多くのコードが公開されて いる、膨大なサンプル郡です。 この辺を少し読むだけでも、設計によい変化があらわれると思います。 http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnpag2/html/EntLib2.asp _________________ たつごろー codeseek こみゅぷらす | ||||||||||||||||||||||||||||||||
|
投稿日時: 2006-07-11 18:48
途中の説明が理解できているか微妙なので、本題だけ...
然るべき処理が必要だからこそ、例外処理が書いてあるという前提で考えれば、 Catch した例外を 「Throw」 とだけ書いて、上位に伝えるのは問題ありません。 「予見」 できないもの全部 Catch しているとなると、'ペナルティ エリア外' になってしまうと思います。 _________________ C# と VB.NET の入門サイト じゃんぬねっと日誌 | ||||||||||||||||||||||||||||||||
|
投稿日時: 2006-07-11 22:58
ゴールキーパーでもキャッチすると反則、、、ですね(^-^; # 昔、「じゃ、相手のペナルティエリアでは?」と聞いたやつがいた。。。 | ||||||||||||||||||||||||||||||||
|
投稿日時: 2006-07-11 23:14
Get の場合、たいてい、戻り値で返ってくるようにしませんか?これだと、Put とか SetInto とか???
それは、実装のひとつとしてアリだと思います。ただ、本当に処理を継続しなければならないのか、というところを考え直すと、ナシになるかもしれません。
お約束なんて、何かの前提の上にあるんだから、前提が崩れたらお約束も崩れちゃうんだよね。
ここ、わかりません。 普通、コーディング規約によって、同じようにコード化すると思います。あるところは「例外はすべて握りつぶして、True/False を返す」で、あるところは「例外で通知」だと、一貫性がないと思います。
ん???おかしくないですか?string を throw できましたっけ? それはともかく、再投するなら、Throw だけです。これを Throw ex 等とすると、ここが例外の発生場所になってしまいます。 また、この例であれば、try - catch の中で投げている例外を再投しているのですから、無意味です。
と、一致していません。 また、どんな例外を投げるかわからないからといって、すべての例外をキャッチする必要もありません。上に届かせたくない例外だけ、キャッチすればいいのではないですか? 使う側は、例外が投げられることだけを知ればいいと思います。例外が投げられて、処理が中断してしまうとき、リソースの解放等が的確に行われるようにコーディングしてさえいれば、良いのではないでしょうか。 | ||||||||||||||||||||||||||||||||
|
投稿日時: 2006-07-12 10:39
!?
例外処理について根本的な考えが間違ってました。 下位で発生した例外を上位に伝えるためには Throw new ○○Exception("")しないといけないと思ってました。 オハズカシイ...アナガアッタラハイリタイ... って事は下位で上位に伝えたい例外が発生したら Catchして再Throwするか(このときはThrowと書くだけ) Ctachせず何もしなければ上位に伝わるのですネ。 知らぬは一生の恥になるところでした。 private sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click Try Call SubTest1 Catch ex As ApplicationException messagebox.show(ex.Message) Catch ex As Exception WriteLog(ex.ToString) messagebox.show(ex.ToStrin) End Try End Sub Private Sub SubTest1 Dim datarow as DataRow Dim sql as new System.Text.StringBuilder(String.Empty) ’★Try〜Catchはいらない★ 'Try '予想しうる例外 If ("").Equals(Me.TextBox1.Text.Trim) Then Me.TextBox1.Focus() Throw New ApplicationException("テキストボックス1が未入力です。") End If 'SELECT文を投げDataRow取得 sql.Append(" SELECT COUNT(*) FROM table1") sql.Append(" WHERE field1 = '" & Me.TextBox1.Text.Trim & "'") call データベースアクセスクラス.GetDataTable(datarow,sql.tostring) ’予想しない例外 if datarow is Nothing Then Throw new Exception("DataRowオブジェクトが取れないよ。") End If ’★Try〜Catchはいらない★ 'Catch ex As ApplicationException ' throw New ApplicationException(ex.message) 'Catch ex As Exception ' throw New Exception(ex.ToString) 'End Try End Sub | ||||||||||||||||||||||||||||||||
|
投稿日時: 2006-07-12 11:20
このやり方を完全に否定するつもりはないですが、高コストな例外を使わなくとも、
でいいんではないかと思います。 こういう書き方の様な、「条件に合わないとき、Returnしちゃうこと」を、ガードといいます。
これはオブジェクトが取れない、でただしいのですか? このメッセージが、原因の追究の邪魔になるかもしれませんよ。
とあるので、この設計者は、
と書いて欲しいのではないかと思います。 この書き方は、私はお勧めできないのですが、他のプログラム担当者はそうやっているのでは ないかと想像しますよ。 この辺はチームで意識あわせをする必要を感じます。 ここで書いたコードは、意図的に質問者さんのコードを使う形にしています。 _________________ たつごろー http://www.codeseek.net [ メッセージ編集済み 編集者: たつごろー 編集日時 2006-07-12 11:22 ] |
1