- PR -

Exceptionについて

投稿者投稿内容
なび
ぬし
会議室デビュー日: 2007/08/27
投稿数: 273
投稿日時: 2007-09-25 15:10
こんにちは。

本日、もう1点だけお聞きします。
VB2005での開発です。

Try
処理
Catch ex As Exception
MessageBox.Show("エラーが発生しました" + vbCrLf + ex.Message, Me.Text, MessageBoxButtons.OK, MessageBoxIcon.Error)
End Try

とコーディングしましたが、
この場合、例えばSQLServerからデータを取得する時、デーブルが見つからないエラーは
「エラーが発生しました。オブジェクト名 'WDB.DBO.WTBL'は無効です'」と表示されます。

また列名が見つからない時は
「エラーが発生しました。列名 'KMK1'は無効です'」と表示されます。

これだと、使用者にデータベース名や、テーブル名、列名等が解られてしまいます。

上記の場合エラーは共にSQLExceptionです。

エラーを
「エラーが発生しました。テーブルが見つかりません」とか
「エラーが発生しました。列名が見つかりません」と表示はできますか?

また、みなさんは使用者に解られてよいエラーの表示、解られてはまずいエラーの表示を
何かコントロールしていますか(どのようにコーディングしていますか)?
さかもと
ぬし
会議室デビュー日: 2004/05/14
投稿数: 586
投稿日時: 2007-09-25 15:18
さかもとと申します。

まず、「テーブルが見つからない」とか「列名が・・・」というのは、リリースする段階で、通常はあってはならないエラーかと思います。(ちゃんとテストしましたか?という意味で)

私は何かしらエラーが起こったらログファイルなどに書き込み、メッセージとしては
「エラーが発生しました。」程度にとどめて、余り詳細なエラーは見せないようにしています。

その後、ログファイルを送って原因を突き止めたり、深く反省したりします。



_________________
------------------------------------------
拝啓、さかもとと申します♪
まるく
大ベテラン
会議室デビュー日: 2004/01/09
投稿数: 181
投稿日時: 2007-09-25 15:27
発生を想定している Exception のみ Catch し、他は Catch しません。
こぼれた Exception は親元で Catch するようにしておきます。

親元での処理:
WindowsForm なら
Application.ThreadException を AddHandler
Web なら
Page_Error, Application_Error
よっし〜。
ベテラン
会議室デビュー日: 2007/04/17
投稿数: 89
お住まい・勤務地: 北のほうの国
投稿日時: 2007-09-25 16:27
コード:
Try
  '処理
Catch sqlex As SqlException
  'SQLのエラー
  MessageBox.Show("SQLエラーが発生しました" + vbCrLf + sqlex.Message, Me.Text, MessageBoxButtons.OK, MessageBoxIcon.Error)
Catch ex As Exception
  'それ以外
  MessageBox.Show("エラーが発生しました" + vbCrLf + ex.Message, Me.Text, MessageBoxButtons.OK, MessageBoxIcon.Error)
 End Try



Catch する例外が確定しているならこんな感じに記述することもできます。
詳細なエラーメッセージを出力したくなければ、sqlex.Message を削ります。
さらにSqlExceptionによって場合分けしたければ、エラーナンバーから把握する
という手もありますが、全てのパターンを網羅するのは不可能に近いのでは。
kiyokura
ベテラン
会議室デビュー日: 2007/08/08
投稿数: 69
お住まい・勤務地: 岡山
投稿日時: 2007-09-25 16:45
『例外に対してどのようなメッセージをどのような粒度でユーザに対して表示するのが良いのか』という話題ですと、やはりケース バイ ケースと言いたくはなるのですが、「そのエラーが発生したときにユーザに何ができるか、また、ユーザに何をしてほしいか」を基準に考えるのがよいのでは、と思います。

例外発生時に、ユーザ側で正常に動かすための対応ができないエラーであれば、詳しいことを出しても無駄ばかりか、不要な混乱を招く可能性もあります。
逆にユーザの操作ミスにより発生した例外で、ユーザが正しい方法でやり直すことで回復するのであれば、その手助けになる文言を表示するべきと思います。。
(たとえば、ダイアログで選択したファイルが存在しないような場合は、ユーザの操作によって起こった例外ですから、ユーザにその内容などを通知することで回避できます。しかし、ご質問の内容のように、DBのテーブル名やカラム名が違うようなら、多くの場合は利用者にはどうしようもないのではないでしょうか。)

ですので私は、ユーザが何もできないような例外に対しては、画面上には

  • エラーで処理が継続できないこと

のみを表示する、もしくは運用の形態などによっては、

  • 誰に(どこに)、どう連絡すればよいか
  • サーバサイドの処理の場合は、ログ中のどのプロセスやスレッドが対応しているのかを示す識別番号

等、最小限の情報のみを表示しておくだけにしておき、

  • スタックトレースやその他追跡に必要な情報は全てログ出力する

という手法を、私はとるようにしています。


また、コード上での例外の捕捉の仕方については、特別に処理する必要がある例外のみを捕捉、それ以外は呼び出し元などでまとめて捕捉してやるほうが良いと思います。
なび
ぬし
会議室デビュー日: 2007/08/27
投稿数: 273
投稿日時: 2007-09-25 16:51
みなさん貴重なご意見ありがとうございます。

さかもとさん
 
  私は何かしらエラーが起こったらログファイルなどに書き込み、
 メッセージとしては
 「エラーが発生しました。」程度にとどめて、
 余り詳細なエラーは見せないようにしています

 そうですね。ログファイルに書き込むという方法がありますね。


まるくさん

 発生を想定している Exception のみ Catch し、他は Catch しません

 大変参考になりました。

よっし〜さん

 全てのパターンを網羅するのは不可能に近いのでは

 確かにそうですね。

 
ありがとうございました。
ちなみに、どのような感じで
エラー表示して、ログファイルに書き込みして
いるのか教えて頂けないでしょうか?

宜しくお願いします。
kiyokura
ベテラン
会議室デビュー日: 2007/08/08
投稿数: 69
お住まい・勤務地: 岡山
投稿日時: 2007-09-25 17:02
蛇足かもしれませんが、ご質問のコードのケースで、もしカラム名やテーブル名をユーザが指定するようなアプリケーションで、ユーザがテーブル名を間違っているので訂正してほしいような場合であれば……。


要求されているようなメッセージを出すには、例外をもう少し小さなくくりでcatchするようにして、Exception.Numberの値で切り分けて、出力すべきメッセージを自分で設定するようにする必要があると思います。
また、ここで特に処理しないエラーについては、呼び出し元等、もっと上位に投げてしまえばよいかと思います。


コード:
''-- 適当なところで、細かく制御したExceptionのNumberをあらかじめ定義
const SQL_ERR_TEBLE_NOT_FOUND  As Integer = xxxxxxx   '' SqlExceptionで、テーブルがないときに帰ってくる番号を設定
const SQL_ERR_COLMUN_NOT_FOUND  As Integer = yyyyyyy  '' SqlExceptionで、カラムがないときに帰ってくる番号を設定

Try
  ''処理
Catch exSql As SQLException
  Dim ErrMessage As String
  '' 細かく処理を切り分ける必要があるもののみ、処理
  Select Case exSql.Number
    Case SQL_ERR_TEBLE_NOT_FOUND
      ErrMessage = "テーブルが見つかりません"
    Case SQL_ERR_COLMUN_NOT_FOUND
      ErrMessage = "項目が見つかりません"
    Case Else
      ErrMessage = ""
  End Select

  If ErrMessage.Length <> 0 Then
    MessageBox.Show("エラーが発生しました:" + vbCrLf +ErrMessage, Me.Text, MessageBoxButtons.OK, MessageBoxIcon.Error) 
  Else
    '' 想定外の例外はそのまま上になげる
    throw exSql
  End IF
End Try

なび
ぬし
会議室デビュー日: 2007/08/27
投稿数: 273
投稿日時: 2007-09-25 17:27
kiyokuraさん、大変丁寧な回答ありがとうございます。

最初の回答で書かれていました通り

「DBのテーブル名やカラム名が違うようなら、多くの場合は利用者にはどうしようもな いのではないでしょうか。」

その通りなのです。

SQLServerを使ったVBの入力アプリの場合
どのようなエラーは表示させて、どのようなエラーは詳細に表示させないのを
聞きたかったのです。(セキュリティの関係などで)

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