えー今現在、設計の仕事をしていますが、今までいい加減だったエラーの処理を見直すいいきっかけになってます。
半年前にも同じような記事書いてますねー。苦手意識は変わらないようです・・(汗)
ポイントとなる考え方について。
Contents
例外使用時
あくまでも「例外」なのでできれば使わないのが望ましいです(本来であれば・・・)
例えばRuntimeException系のもの(nullポインタ、配列の数が合わない、数字できないものを数字にしようとしている)に関しては通常の条件分岐で対応できるため例外で対処しない方が望ましいです。
ただプログラムの中で制御できないエラー(DBの接続、カラムがない、ファイルがない、・・・)も存在するため、その場合はtrycatchをする必要があります。(いわゆる必須の例外。javaだと強制になります。)
具体的なケースとしては以下のような時に使います。
- DBに接続できない
- SQLでこける(一番頻度高い)
- API接続できない
- ファイルがおかしい、ない
実際の使用時にはDBがらみの処理がもっとも高頻度かと思います。
try catch
DBエラーなどは常に発生する可能性があるため、DBが絡むときは必ずtry{}catchで囲む。上部(Serviceから見たControllerなど)に送る場合はthrowを忘れない。
Service層のレスポンスに関して
ServiceからControllerに値を返すときでも基本的にデータと一緒にレスポンスコード(正常な時とタイプによるエラーわけ)と処理結果(true/false)をセットで。最後のview以外に渡すときでもこの癖をつける。
データの型は以下のようになる感じでしょうか。
1 2 3 4 5 6 |
[ "responseCode" => 数字、 "result" => true/false "data" => 渡すべき値 "errorMessage" => falseの場合はここにエラーメッセージ ] |
当たり前かもしれませんが、errorMessageにはExceptionの内容などを入れる。
Service層の中は以下のような作りがいいかも・・・
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
//必須データのチェックなどでfalse //エラー時のレスポンス return { } //処理その1 try { //モデルのメソッドを呼び出すのが一般的 }catch (Exception $e){ //エラー時のレスポンス return { } } //処理その2 try { //モデルのメソッドを呼び出すのが一般的 }catch(Exception $e) { //エラー時のレスポンス return { } } //正常時のレスポンス return [ ] |
今まではかなりtry{}catchのスコープを長く取っていたんですが、短く取るようにした方が良さげかも・・
Serviceの中でtrycathがある場合はControllerでは不要ですが、上(Controller)にthrow eしている場合はControllerでキャッチを行います。
Modelの役割
通常のデータを渡す役割(プロパティのセットとSQLの発行)のみなのでデータを渡すような処理でOKでしょう。
Exceptionを握り潰していいとき or 処理がfalseであっても後続処理を継続する時
一般にExceptionを握りつぶすことはアンチパターンとされていますが、
こけても上部のシステムに影響がないと判断される時(ログ的なDBへの書き込みなどでロールバックまでは考えない時)
には握りつぶす(後続の処理でのロールバックをしない、ログに出して終わりなど)こともあるようです。
似たケースとして、処理結果がfalseにも関わらず、後続の処理を継続するパターンなどもあります。
例としては
メールやプッシュなど処理の成功、不成功を完璧には判断できないケース(処理が成功しても、相手に届くとは考えられない)
などです。
例外やエラー処理も勉強することがまだまだ多いですねー