質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

例外

例外(exception)とは、プログラムの処理実行中に発生する、通常の処理の続行を妨げる特殊な事象のことを呼びます。この「例外」が発生した場合に、現在の処理を中断し、変わりに別の処理を実行させる事を「例外処理」と呼びます。

VB.NET

Microsoft Visual Basic .NETのことで、Microsoft Visual Basic(VB6)の後継。 .NET環境向けのプログラムを開発することができます。 現在のVB.NETでは、.NET Frameworkを利用して開発を行うことが可能です。

Q&A

解決済

5回答

10275閲覧

例外時のログ出力、エラーダイアログ表示の制御について

yougo0411

総合スコア12

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

例外

例外(exception)とは、プログラムの処理実行中に発生する、通常の処理の続行を妨げる特殊な事象のことを呼びます。この「例外」が発生した場合に、現在の処理を中断し、変わりに別の処理を実行させる事を「例外処理」と呼びます。

VB.NET

Microsoft Visual Basic .NETのことで、Microsoft Visual Basic(VB6)の後継。 .NET環境向けのプログラムを開発することができます。 現在のVB.NETでは、.NET Frameworkを利用して開発を行うことが可能です。

0グッド

0クリップ

投稿2016/04/27 12:37

編集2016/04/27 13:14

VB.Net(C# でも)で、例外エラー時のログ出力、ダイアログ表示についてご意見をお聞かせください。

実現したい事は以下になります。
・エラーダイアログ:エラーが発生したメソッドで例外をcatchしてダイアログ表示する。
・ログ出力:各メソッドでは例外を再throw または catchしないでイベントハンドラーとなるメソッドでcatchしてログ出力する。
(エラー発生メソッドからイベントハンドラーまでの階層的なスタックトレースをログに出力する為)
・例外時にエラーダイアログの表示は1度のみとする。

ここで問題になっているのが、
・trycatchを記述していないメソッドで例外発生時に自メソッドでエラーダイアログ表示されずに、
イベントハンドラーでログ出力のみ、となってしまうことです。

各メソッでは例外に対して適切なエラー内容を表示したいので、
イベントハンドラーでpublicな「ダイアログ表示済みフラグ」などを設けて判定することは避けたいです。
(フラグの初期化漏れとかもあるので)
また、全てのメソッドにtrycatchを実装することも避けたいのです。

★画面
Sub button1_Click() Handles Button1.Click
Try
共通クラス.データ取得処理()
Dim ii AS Integer = (1/0) '←★MSG出力・ログ出力!
Catch(ex As DivideByZeroException)
MSG("0割りエラー")
ログ出力()
Catch(ex As Exception)
ログ出力()
End Try
End Sub

★共通クラス
'trycatchを実装しない(想定していない)メソッド
Sub データ取得()
~DB接続ロジック~ '←★ログ出力しかされない

マスタ取得処理()

End Sub
Sub マスタ取得処理()
Try
~SQL実行ロジック~ '←★MSG出力・ログ出力!
Catch(ex As SqlException)
MSG("SQLエラー")
Throw
End Try
End Sub

案としては、
『イベント開始時にpublicなエラー情報保持クラスを生成して、各メソッドで例外エラーが設定された場合に、
イベントハンドラー側でログ出力・ダイアログ表示させる』、が思いついたのですが、
そもそも生成した保持クラスに万人がアクセスできる為にはどこで実装すればいいのか。。(インスタンスを引数として引き回すしかないのか?)

オブジェクト指向などを考慮して実装すると上記問題は解決したりするのでしょうか。
オブジェクト指向でなくても構わないのでテクニック等あればご教授ください。

宜しくお願いしします。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答5

0

共通クラスとやらがダイアログ出しているのが気持ち悪いです。
共通クラスが本来の仕事とユーザーへの通知という2つのことを担ってしまっています。
画面に近い奴が共通クラス諸々の出した例外を受けてダイアログ出すのが自然では?

投稿2016/04/28 04:41

ozwk

総合スコア13512

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

ベストアンサー

こんにちは。

まず、ログを出力しているのですから、アプリケーションの利用者へはエラーが発生したことのみを通知すれば良いのではないでしょうかね。
詳細な情報はログへ出力すれば良いと思います。
極まれにツール的なものでアプリケーション利用者へダイレクトにエラー内容を伝えるべきケースがあるかもしれませんが、その場合は逆に例外を使用するのでなく適切なエラー判定を実装するべきかもしれません。(コード例であれば例外で補足するよりもゼロ除算をしていないかどうかのチェックを入れたほうが良いです。)

また、各処理でメッセージボックスとして表示する内容ですが、コード例のものだとあまり意味がないものになっていると思います。

以上を踏まえますとメッセージボックス表示箇所はどこかにまとめて良いと思います。
とりあえず、処理の起点となるイベントハンドラなど。
ログに出力する際は例外のMessageとStackTraceも出力したほうが良いでしょう。
e.ToString()をそのままログ出力するのが一般的だと思います。
スタックトレースからどのメソッドでどういう原因でエラーが発生したのかわかるはずです。

ログを各メソッドで出力するかルートで出力するかは設計次第ですね。

投稿2016/04/27 13:57

Tak1wa

総合スコア4791

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

yougo0411

2016/04/27 14:34

ご回答有難うございます。 確かに例外エラー通知は続行不可能であることをユーザに通知する、という観点であれば、イベントハンドラか、エントリポイントでApplication_ThreadException()を実装して同じエラー文言、でも良いのかもしれません。 アドバイス内容の線を含めて再検討したいと思います。
guest

0

こんにちは。

昔、似た問題に悩んで、結局、ダイアログ表示済フラグで逃げた記憶が有ります。

その時は、下記ケースだったように記憶しています。
①処理をユーザへ問い合わせるケースでその選択結果をログに残し、例外は投げない。
②処理を継続できないようなエラーが発生し、その旨の詳細をユーザへ通知後、例外を投げて、ログ記録。
③想定外のエラーが発生し、ログへ記録は残せるが、突然処理が中断するのでよろしくない。最低限のダイアログを出したいが、下手に出すと②とかぶる。

本来は③が発生しないようにするべきなのですが、少ない工数をやりくりしている関係上どうしても防げなかったケースでした。(頻発しなければ許されるようなアプリでした。)
意図的に投げる例外は必ず独自の例外としていたので、それにダイアログ表示済フラグを追加したような記憶があります。ここなら初期化漏れありえませんので。
知らない例外なら、無条件でダイアログ表示しても良いですし。

投稿2016/04/27 14:15

Chironian

総合スコア23272

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

ログ出力は大元で一元管理しているのに、メッセージは大元で表示したり各Catchで表示したりしているので統一性がないように感じるのかも?
どちらかに統一すればすっきりしそうです。

案①:ログは大元で出力、メッセージは必要な個所でTry~Catchして出力する
案②:ログもメッセージも大元で一括出力する

自分は案①で実装するケースが多いです。
案②を採用する場合、例えばPublicなエラー情報管理クラスを用意し、各所のCatch処理で
・エラーの発生メソッド
・エラー情報
・メッセージ内容(固有のメッセージを表示する場合)
などの情報を格納してThrowする。
その例外を大元でCatchして、エラー情報管理クラスを見ながらメッセージ表示する、といった感じでしょうか。

参考になれば幸いです。

投稿2016/04/27 13:37

jawa

総合スコア3013

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

yougo0411

2016/04/27 14:04

ご回答ありがとうございます。 案②の場合、全てのメソッドに専用の引数を用意して「エラー情報管理クラス」のインスタンスを引き回す、というイメージでよいですか?
jawa

2016/04/28 04:20

自分が案②で実装した際はモジュール内のどこからでも参照できるクラスで実装しました。 それが美しいとは思いませんでしたが...(^-^;
guest

0

・エラーダイアログを誰に見せたいのか
・それを見た人に何を期待するのか

デバッグ用にダイアログ出したいわけじゃないんですよね?
ダイアログ表示の要/不要を検討した方がいいんじゃないかなあ。

投稿2016/04/27 12:51

takasima20

総合スコア7458

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

yougo0411

2016/04/27 13:17

ご回答ありがとうございます! エラーダイアログはデバッグ用ではありません。 例えば、DB接続時のエラーは"DB接続エラー"、SQL実行のエラーは"SQL実行エラー"と出力するのですが、詳細なダイアログ(含むメッセージID)を出したい場合は、自メソッドの例外処理で書かないものですか? 遷移の大本にグローバル変数などで渡すのが一般的でしょうか?
takasima20

2016/04/27 13:35

言語や環境によって「やりやすい」形は違うと思いますが… エラーが発生したらログで調べるやり方が多かったので 一般的なやり方というと… どうでしょう? プロジェクトの方針や利用者からの要求でそういう風に して欲しいというのなら、やるんでしょうねえ。
yougo0411

2016/04/27 14:17

確かに要件による処も多いと思います。 各メソッドで独自のエラーダイアログが必要かどうかを含め、再検討を考えてみます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問