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

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

ただいまの
回答率

91.03%

  • C#

    5749questions

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

例外・ログメッセージ管理のプラクティス

解決済

回答 4

投稿

  • 評価
  • クリップ 2
  • VIEW 521

ikasoumen

score 92

アプリケーションで想定するエラーやログのメッセージ管理はどのようなプラクティスがありますか?

例えば、データベースが切断された場合や、入力値が不正である場合など、
エラーの種類により、Exceptionクラスを定義するのか、
それとも、アプリケーション独自のExceptionクラスは1つで、
MessageIDなどで紐づけたCSVファイルのようなデータからメッセージを取り出すなど、
どのようなアプローチが一般的でしょうか。

エラーのカテゴリによって、エラーメッセージの粒度が違っていたり、
うまく体系化するのが難しいと感じています。

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

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 4

checkベストアンサー

+3

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/15 09:23

    ご回答ありがとうございます。参考にいたします。
    破損状態例外というのは、初めて聞きました。

    しかし、恐れながら、例外の処置方法は本質問の趣旨でなく、
    例外・業務エラーをどこで体系化・管理するかというのが質問の趣旨となります。

    キャンセル

  • 2017/11/15 09:25

    フレームワークはASP.NET MVC5を利用しています。

    キャンセル

  • 2017/11/15 10:18

    > 例外・業務エラーをどこで体系化・管理するか

    すみませんが意味が理解できません。

    何のためにどのような目的で「体系化・管理」するのか、MVC5 アプリの話に限って、やりたいことの全体のシナリオ・ストーリーを具体的に書いていただくと自分も理解できそうですが・・・

    キャンセル

  • 2017/11/15 10:27

    あと、もう一つ、

    > 例外の処置方法は本質問の趣旨でなく、

    とのことですが、それ(例外の処置方法)が決まってから、発生する例外・業務エラーをどう管理するかという話になると思います。なので、順番が違うような気がします。その点誤解があれば書いてください。

    キャンセル

  • 2017/11/18 13:22

    すいません。質問を再度整理しました。

    メッセージ一覧で管理する項目はどのようにするべきか。
    メッセージは、例外・業務エラーなどのカテゴリでどう体系化するべきか。

    メッセージを外出しする意図としては、以下のようなことが上げられます。

     ・コードの実装とメッセージのメンテナンス作業を分離したい。
     ・一覧化し、資料として活用したい。
     ・国際化対応など、表示メッセージの切り替え処理に対応したい。
     ・どんな機能・どんな状況で発生するメッセージか把握したい。

    キャンセル

  • 2017/11/18 23:27

    上記に対するレスは回答欄に書きます。

    キャンセル

  • 2017/11/22 22:53

    ご丁寧にご回答ありがとうございました。

    「業務エラー」と「例外」については理解いたしました。
    ビジネスロジックは、ASP.NETでサポートしている検証機能はフルに活用すべきだと思っております。

    メッセージの管理については、リソースファイルがよさそうですね。
    ただ、列を追加するなどカスタマイズはできなそうですね。

    ともかく今度試してみようと思います。

    キャンセル

+1

アプリケーション独自のExceptionクラスは1つで、
MessageIDなどで紐づけたCSVファイルのようなデータからメッセージを取り出す

個人的にはこちらを採用することが多いです。
特定のエラーについて情報を増やすためにサブクラスを作成することはあります。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/11/15 09:08

    複数のエラーが発生する処理などでは、
    列挙機構を持つエラークラスに、それぞれの詳細なエラーをまとめておくなど必要そうですね。

    キャンセル

  • 2017/11/15 09:15 編集

    複数のエラーが発生し得る場合も、一度に発生するエラーは1つではないかと思います。
    "入力値が不正である場合"等も質問に記載されているので、バリデーション等を意図されているのでしょうか。

    キャンセル

  • 2017/11/15 09:34

    バリデーションも意図しています。
    バリデーションに関しては、ASP.NET MVC5でサポートされている、
    モデルのプロパティに属性を付与することで実現しています。

    キャンセル

+1

例外の方だけ。
msdnの例外の推奨事項Eric Lippert氏のVexing exceptionsのページ

例外に以下のラベル付けを行っています。
・Fatal
・Boneheaded
・vexing and exogenous

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

0

例外処理はオブジェクト指向の仕組みです。
C言語になくて、C++やC#やJavaにあるというだけでなく、
じっさい、例外時に例外オブジェクトを生成するでしょう。

エラーの種類により、Exceptionクラスを定義するのか
それとも、アプリケーション独自のExceptionクラスは1つ

だから、オブジェクト指向らしい例外処理ということでは、
例外の種類によって、例外クラスを分けていきます。
基本的には、普通のクラスを分けていくことと同じです。

ただ、小規模ならひとつで済む場合もあるかと思います。
というより、例外処理に手を掛けられないという方が実態かも。


エラーのカテゴリによって、エラーメッセージの粒度が違っていたり、
うまく体系化するのが難しいと感じています。

たしかに、例外処理は難しいです。本に載ってないことが多いし、
そもそもエラーは個別的だから体系化が難しい。

じっさい、言語処理系のエラーメッセージですら、
分かりにくいことが多いですよね。

じゃあ、具体的にどうすればいいのかというと、
本体の処理ができた後でエラー処理をくっつけていくのではなく、
最初からエラー処理や例外設計がしやすい設計にします。

たとえば、レイヤーアーキテクチャで階層を分けるのは、
理由は色々あるでしょうが、エラー処理のしやすさも、そのひとつでしょう。

というのも、UIやDBは独自のエラーをモリモリ出してくるから、
それらをドメインモデルと混ぜてしまうと、
エラー処理でドメインが埋まってしまう。だから分けると。


データベースが切断された場合や、入力値が不正である場合

何を例外にするかは、私の見方では大別すると、
エラー処理には、「例外なく例外を使う」考え方(統一派)と、
DBは例外で、入力値の不正は例外にしない、
という「例外は例外的状況にのみ使う」という考え方(純粋派)があります。

統一派は入力値の不正も例外にしますが、
純粋派はそれは「準正常系」だといって、例外にしません。
どうするかというと、IF文で分けたり、戻り値でエラーを表現したりします。

例外処理における統一派と純粋派は、それぞれ一長一短だと思います。
言語仕様を見ると、Javaは統一派で、C#は純粋派に近い立場でしょう。

統一派は、IF文のエラー処理で本体の処理が埋もれる、
リターン値のエラーコードは見過ごされる、と主張します。

純粋派は、とくに大規模では例外処理が複雑になり過ぎる、
だから実態としては例外でできることが少ない、と主張します。

「すべてがオブジェクト」みたいに「すべてのエラーが例外」と、
例外に統一化した方がOOの理想郷ではあるが(私も考え方としては好きです)、
現実には純粋主義的な例外の方が使いやすい場面もあるのかなと思います。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/11/15 09:07

    私もクラスで書きたいですが、
    そうするとトラブルシューティングとかのネタにするメッセージの一覧がなくて困ったり、
    肥大化するとどんなエラーを選べばよいか、分類できないから新たに定義するべきかなど考え事が増えてきそうですよね。
    エラークラスからメッセージ集めて自動出力とかできればいいのですが。

    処理の失敗を戻り値で伝えるか、例外で伝えるか、
    私の経験上、戻り値で伝えようとした場合、どうしても情報が足りなくて例外が必要になる場合があり、
    初めから例外に統一した方がいいかなと思っています。

    レイヤーの設計では、検証(ビジネスロジック)・登録・更新(DB層)で分け、
    登録・更新を行う場合は、渡された値は検証済みのため正しいという前提を元に処理するようにしています。

    UIから渡された値を検証するには、上記でいいですが、テーブル間の整合性のチェックなどは、
    処理の中でゴリゴリチェックを書きがちになってしまいますね。

    キャンセル

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

  • ただいまの回答率 91.03%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

  • 解決済

    (JUnit)同じ例外でエラー内容が異なるテストケースを判別する方法

    JUnit4のテストコードの書き方について解らないため質問させてください。 ある例外が発生することを期待値にしたいのですが、その例外が発生するパターンが2通りあり、スローされる例外

  • 解決済

    IOExceptionの発生原因と例外処理

    androidのアプリ開発において、ファイルの作成や読み込みの処理を記述(ストリームを閉じるoos.close()など)する際に、 IOExceptionなどの例外に対する処理を記

  • 解決済

    exception こういった使い方はNG?

    お世話になります。 Exceptionの使い方としてこういった使い方は間違っているのでしょうか。 以下のつかいかたは、 条件がFになったときにMsgExceptionをスローしま

  • 解決済

    エラーメッセージどこに書いていますか?

    業務アプリケーションではエラーメッセージを、何処に書くのがベストだと思いますか? ① javaのソースに直接書き込んでしまう ② 画面毎にメッセージファイルを作る ③ システム共

  • 解決済

    Python Exceptionについて

    PythonのExceptionについての質問です。 みんなのPython第3版に以下のような記述がありました。 「except文でExceptionクラスを指定すると

  • 解決済

    IOSでFirebaseを使ってチャットアプリを作りましたが、エラーが出て起動しません。

    IOSでFirebaseを使って、簡易的なチャットアプリを作りました。しかし、起動時にエラーがでてしまいます。 ViewController.siwft import

  • 解決済

    例外クラスとstd::exception

    C/C++でやっています。 C/C++で例外処理ってありますよね。 今までは int型で投げていたのですが、std::exception を継承すればより簡単にできるような

  • 受付中

    phpデータの受け渡しがうまくいかない

    データベースの情報を修正するフォームを作っていて、その時の画面がうまく動作しないのですがどこが間違っていて動作しないのかよくわかりません。どなたか教えていただけないでしょうか?

同じタグがついた質問を見る

  • C#

    5749questions

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