アプリケーションで想定するエラーやログのメッセージ管理はどのようなプラクティスがありますか?
例えば、データベースが切断された場合や、入力値が不正である場合など、
エラーの種類により、Exceptionクラスを定義するのか、
それとも、アプリケーション独自のExceptionクラスは1つで、
MessageIDなどで紐づけたCSVファイルのようなデータからメッセージを取り出すなど、
どのようなアプローチが一般的でしょうか。
エラーのカテゴリによって、エラーメッセージの粒度が違っていたり、
うまく体系化するのが難しいと感じています。
気になる質問をクリップする
クリップした質問は、後からいつでもMYページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
回答4件
0
ベストアンサー
C# のタグが付いていますので .NET アプリの話と理解してレスします。(そういうことは、質問の一番最初に書いておいてほしいです)
.NET の例外処置について、自分的にベストプラクティスと思っていることを書きます。
詳しくは後の方に紹介した記事を読んでいただきたいのですが、要約すると以下の通りです。
(1) 予測可能で正しい業務フローに戻すことができる「業務エラー」(例:ユーザーの入力間違い)と、予測できないもしくは予測はできても何の対応もできない「例外」(例:DB サーバーダウン)を区別して対処。
質問者さんが挙げた、
例えば、データベースが切断された場合や、入力値が不正である場合など、
のようなケースでは、前者を「例外」、後者を「業務エラー」として扱うということです。紹介した記事にも書いてありますが、いずれも SqlException としてしか検出できない場合でも、その中身を調べて処理を分けることは可能です。
(2) 「例外」はランタイムに拾わせてアプリケーションを停止させる。
(3) よほどのことがない限り try-catch は書かない。
(4) キャッチせざるを得ない場合でも Exception はキャッチしない。
(5) 間違って補足してしまった例外は throw する。(注:catch ブロックでキャッチした例外を throw するとスタックトレースが途切れるので単に throw と書く)
(6) ユーザーへの通知が必要なら、集約的例外処置を利用する。
詳しくは以下の記事を見てください。
NETの例外処理 Part.1
https://blogs.msdn.microsoft.com/nakama/2008/12/29/net-part-1/
.NETの例外処理 Part.2
https://blogs.msdn.microsoft.com/nakama/2009/01/02/net-part-2/
あと、.NET 4 からは破損状態例外は catch できなくなっているそうですが、「それでも Catch (Exception e) を使用するのはよくない」ということについては以下の記事を見てください。
破損状態例外を処理する
https://msdn.microsoft.com/ja-jp/magazine/dd419661.aspx
【追伸】
下記は 2017/11/18 23:27 のコメント欄で「上記に対するレスは回答欄に書きます」と書いた件です。
上に書いた「業務エラー」と「例外」を区別して対処というところは納得していただけたでしょうか?
そうでないとするとこの先話を続けてもなかなか理解が得られないと思いますが、そこは自分の考えでレスします。
まず、「例外」ですが、それは開発者にのみ提供すればいい情報ですので、.NET Framework が提供する例外情報(例外の種類、メッセージ、スタックトレースなど)がログなどで取得できればよく、管理とか体系化とか余計な個とは考えなくてもいいと思います。
「業務エラー」の方は、ユーザーにユーザー入力の訂正などを促して正しい業務フローに戻すということになるでしょうから、ユーザーに適切に情報を提供する必要があります。そのためには何らかの管理は必要になるのは分かります。
ASP.NET MVC アプリの場合は、ユーザー入力の検証結果をどのようにユーザーに伝えるかがメインとなり、そのための機能にデータアノテーション属性による検証とエラーメッセージの表示があると思います。(それだけではないとは思いますが、範囲を広げると話が発散するので)
そのためには、以下のような配慮をするということだと思います。(質問者さんの言う「管理」とは違うかもしれませんが)
(1) DataType 属性による検証やデフォルトのエラーメッセージに頼らず、Range, RegularExpression, Required, StringLength 属性などを組み合わせて使い、エラーメッセージは自分で各データアノテーション属性の ErrorMessage プロパティに設定する。そのあたりについての詳細は以下の記事を見てください。
DataType 属性による検証
http://surferonwww.info/BlogEngine/post/2016/03/08/validation-by-datatypeattribute-and-default-error-message.aspx
(2) コードにエラーメッセージをハードコーディングしたくないならリソースファイルを使用する。リソースファイルを使用すればもちろん国際化はできます。詳しくは以下の記事を見てください。
データアノテーション検証の多言語対応
http://surferonwww.info/BlogEngine/post/2014/09/11/multi-languages-message-for-data-annotation.aspx
(3) オマケ情報ですが、ADO.NET Entity Data Model を使って作成したモデルの場合は以下のようにデータアノテーション属性を付与できます。
EDM にデータアノテーション属性を付与
http://surferonwww.info/BlogEngine/post/2017/05/21/how-to-add-dataannotation-attributes-to-edm-generated-by-visual-studio.aspx
投稿2017/11/14 23:56
編集2017/11/18 14:33退会済みユーザー
総合スコア0
0
例外の方だけ。
msdnの例外の推奨事項とEric Lippert氏のVexing exceptionsのページ
例外に以下のラベル付けを行っています。
・Fatal
・Boneheaded
・vexing and exogenous
投稿2017/11/14 21:47
編集2017/11/15 00:30総合スコア5846
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
0
アプリケーション独自のExceptionクラスは1つで、
MessageIDなどで紐づけたCSVファイルのようなデータからメッセージを取り出す
個人的にはこちらを採用することが多いです。
特定のエラーについて情報を増やすためにサブクラスを作成することはあります。
投稿2017/11/14 20:49
退会済みユーザー
総合スコア0
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
退会済みユーザー
2017/11/15 00:15 編集
2017/11/15 00:34
0
例外処理はオブジェクト指向の仕組みです。
C言語になくて、C++やC#やJavaにあるというだけでなく、
じっさい、例外時に例外オブジェクトを生成するでしょう。
エラーの種類により、Exceptionクラスを定義するのか
それとも、アプリケーション独自のExceptionクラスは1つ
だから、オブジェクト指向らしい例外処理ということでは、
例外の種類によって、例外クラスを分けていきます。
基本的には、普通のクラスを分けていくことと同じです。
ただ、小規模ならひとつで済む場合もあるかと思います。
というより、例外処理に手を掛けられないという方が実態かも。
エラーのカテゴリによって、エラーメッセージの粒度が違っていたり、
うまく体系化するのが難しいと感じています。
たしかに、例外処理は難しいです。本に載ってないことが多いし、
そもそもエラーは個別的だから体系化が難しい。
じっさい、言語処理系のエラーメッセージですら、
分かりにくいことが多いですよね。
じゃあ、具体的にどうすればいいのかというと、
本体の処理ができた後でエラー処理をくっつけていくのではなく、
最初からエラー処理や例外設計がしやすい設計にします。
たとえば、レイヤーアーキテクチャで階層を分けるのは、
理由は色々あるでしょうが、エラー処理のしやすさも、そのひとつでしょう。
というのも、UIやDBは独自のエラーをモリモリ出してくるから、
それらをドメインモデルと混ぜてしまうと、
エラー処理でドメインが埋まってしまう。だから分けると。
データベースが切断された場合や、入力値が不正である場合
何を例外にするかは、私の見方では大別すると、
エラー処理には、「例外なく例外を使う」考え方(統一派)と、
DBは例外で、入力値の不正は例外にしない、
という「例外は例外的状況にのみ使う」という考え方(純粋派)があります。
統一派は入力値の不正も例外にしますが、
純粋派はそれは「準正常系」だといって、例外にしません。
どうするかというと、IF文で分けたり、戻り値でエラーを表現したりします。
例外処理における統一派と純粋派は、それぞれ一長一短だと思います。
言語仕様を見ると、Javaは統一派で、C#は純粋派に近い立場でしょう。
統一派は、IF文のエラー処理で本体の処理が埋もれる、
リターン値のエラーコードは見過ごされる、と主張します。
純粋派は、とくに大規模では例外処理が複雑になり過ぎる、
だから実態としては例外でできることが少ない、と主張します。
「すべてがオブジェクト」みたいに「すべてのエラーが例外」と、
例外に統一化した方がOOの理想郷ではあるが(私も考え方としては好きです)、
現実には純粋主義的な例外の方が使いやすい場面もあるのかなと思います。
投稿2017/11/14 21:46
総合スコア5592
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2017/11/15 00:07
あなたの回答
tips
太字
斜体
打ち消し線
見出し
引用テキストの挿入
コードの挿入
リンクの挿入
リストの挿入
番号リストの挿入
表の挿入
水平線の挿入
プレビュー
質問の解決につながる回答をしましょう。 サンプルコードなど、より具体的な説明があると質問者の理解の助けになります。 また、読む側のことを考えた、分かりやすい文章を心がけましょう。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2017/11/15 00:23
2017/11/15 00:25
退会済みユーザー
2017/11/15 01:18
退会済みユーザー
2017/11/15 01:27
2017/11/18 04:22
退会済みユーザー
2017/11/18 14:27
2017/11/22 13:53