C#:もっと気楽に例外処理を使っていけ!

C#

今回はサクッと行きましょう。
C#で例外処理をうまく使おうというテーマで書いていきます。
こちらも使いこなせるようになると、脱初心者です!頑張って中級を目指しましょう。

そのころ感じていた例外処理というのは、
プログラムを読んでくれるマシンが
『あ、これ処理できんわ。エラー投げとこ』と勝手に投げてくれるものであり、
自分で例外処理を書くメリットがいまいち分かりませんでした。

しかしながら、実はこの例外処理は
開発者側(プログラムを組む人)が能動的に設定することで、色んな使い方ができます。

という訳で早速、例外処理の使い訳について説明します。
私は例外処理をする時はこんなケースです。

  • バグを見つけやすくするため
  • そのメソッドの役割ではないとき
  • 仕様上、その処理をはじくとき
  • タイムアウトの後に再試行する

ちなみに、例外処理というのは、
人によっては『エラー』といったり、『Exception』と言ったりしますね。
実際に、


try{
   // エラーが起きそうな処理
    UpdateData(param);

   }catch(Exception ex){
    // 
    throw new Exception("エラーだよ");
}

という感じでTry-Catchの中で使いますが、以下のように単体で使っても構いません。


if(parm == null){
    throw new ArgumentException("nullやで")
}

また、使うExceptionも色々ありますが、
よく使うものとしては、

  • 引数が良くないよ:ArgumentException()
  • そもそも仕様上だめだよ:ApplicationException()
  • 実装してないよ:NotImplementedException()

という感じで使い分けます。
NotImplementedExceptionは、開発途中において、
『メソッドの枠だけ作るけど中身は実装中だよ』という時に使います。
今回は取り上げていません。

では、それぞれ見ていきましょう。

スポンサードサーチ

バグを見つけやすくするため

ひとつはバグを見つけやすくするためです。
Exceptionを投げるときに一緒にメッセージも投げれますから、
何かエラーが起きたときに、
『システムが勝手に投げたエラーなのか、こちらで自発的に設定したエラーなのか』分かるようになります。

設定したエラーの内容を見たときに
『ユーザー情報がnullです』とだけ書かれているだけでも、
あらかた見当がつけれます。
『Null Reference Exception』とだけ出るのでは、かなり違います。

もちろん、どの付近でエラーが起こったかも探せば分かりますが、
なじみのある日本語で書いてあった方が明らかに分かりやすいです。
この恩恵は、処理が複雑になればなるほど効いてきます。

そのメソッドの役割ではないとき

これは、
『メソッドは、ある役割だけを遂行するためのもの』という考えに基づいています。

例えば、
『ユーザー検索に関するデータ取得のメソッド』を作るときを考えてみます。

『ユーザー検索に関するデータ取得のメソッド』は戻り値として
『ユーザーのリスト』を返すとします。

このメソッドを以下のように分けてみましょう。

 

『ユーザー検索に関するデータ取得部分のメソッド』 :ユーザーのリストを返す   >① 検索パラメータのチェック     :bool   >② 検索パラメータからDBのクエリ(string myQuery)を作る     : string     >③ 作成したクエリ(myQuery)DBに投げ、 ユーザーリストを取得する     : ユーザーのリストを返す

このように、③のメソッドによって、
大枠である『ユーザー検索に関するデータ取得部分のメソッド』はユーザーリストを返すことができます。

そしてこの③のメソッドに注目してみると、
引数としてmyQueryを使っています。
では、もしそのmyQueryがnullや空文字だった場合どうでしょうか。

チェックをするメソッドを入れたくなりますが、
チェックをするメソッドは①で既にやっています。
そのため、③で再度チェックするのはナンセンスになります。

ですので、


if(string.IsNullOrEmpty(myQuery)){
    // ArgumentExceptionは、引数がよくないよという例外です。
    // メッセージを入れるのは人の好みですが、私でしたら入れちゃいます。
    throw new ArgumentException("クエリがありません");
}

という感じで投げちゃいます。

なぜなら、③のメソッドの仕事は、『DBにクエリを投げ、取得する』だけだからです。
私はこんな時、躊躇なくExceptionを投げます。

無理矢理こんなケースを作る必要はないですが、なんか行き詰った、どうしようもないという時はおススメします。

スポンサードサーチ

仕様上、その処理をはじくとき

これは
『ユーザーがある特定の操作をしたとき、処理しない』という様に、
仕様として決まっているときです。

その操作が分かった瞬間にエラーを投げ、
UI付近でキャッチし『その操作では表示できません』と出します。
システムチックな本当のエラーというより、
ユーザー操作によるエラーという感じです。

たとえば、アカウント情報を保持しているWebシステムを想定してみましょう。
そのときに、自分のプロフィール画面のURLが以下の形式だったとします。

  • https://hoge/user/1000

今自分のプロフィール情報が1000番ですから、例えばそれを1001に変更したとします。
1001で誰かユーザーが保存されているとすると、
特に制限していなければ誰でも見れてしまいます。

このような場合には、
『自分以外見れない』という処理をどこかに入れる必要があります。
そして、その結果として『その情報は閲覧できません』などとUI側で出力するようにします。

タイムアウト後に再試行する

ケースとしては、メール送信などです。
よくあるのが、メール送ったときに意外と時間がかかってしまい、システムがタイムアウトとしてエラーを投げてしまいます。
このようなときにいちいちエラーとして落としてしまうと、他のシステムもダウンしかねません。

そのため、よく取る手段として、
try-catchの中にメールを投げる処理をいれておいて、タイムアウトしたら例外をキャッチするようにしておきます。
そして、再度メール送信を行います。
数回してダメだったら、ログか何かを貯めるようにしておいて処理を終わるようにします。

数回行うのは、たまたまメールの処理に時間がかかっていた場合がよくあるためです。
ここではシステムを落とさないようにすることが大事です。
仕様をよく相談するようにしましょう。

スポンサードサーチ

まとめ

今回は例外処理の使いどころについてまとめました。

  • バグを見つけやすくするため
  • そのメソッドの役割ではないとき
  • 仕様上、その処理をはじくとき
  • タイムアウトの後に再試行する

になります。

ただ、開発段階においては、
もっと気軽にExceptionを書いて投げて、システムを落とせばいいのかなと思います。
ぜひ参考にしてみてください。