• 2019年5月1日水曜日
アリスト戦記
アリスト戦記 https://blog.aristo-solutions.net/2019/05/javatemplatebatchexception.html

オリジナルのExceptionを有効活用せよ

Javaの保守性を向上させるコツの一つに、例外処理がある。

オリジナルのExceptionを作る事例を紹介してみよう。

オリジナルの例外を作る事例

Javaで自分のオリジナルの例外を作るのに適しているタイミング、それは自分のロジック上、論理的におかしいと言うタイミングが明らかな時に作り込むと良い。

例えば、ここにWebAPIがあるとしよう。

ログインユーザのユーザIDをキーとしてWebAPIにリクエストを投げれば、確実にデータが取れることは規約上、約束されている。
もし取得できなかったら、それはデータ不整合だ。

こういう時はオリジナルの出番である。

NullPointerExceptionを継承した「WebApiDataNotFoundException」とでも命名した例外クラスを自分で作成し、値が取れるはずなのに取れないという結合的問題が起きた場合はこれを投げるという実装にする。

こうすると、ログに「WebApiDataNotFoundException」と出ているから原因がすぐ分かる。

これがオリジナルの例外クラスの使い道だ。

ダメな事例

上記のロジックでダメな事例は、こんな感じ。

  • WebAPIを実行する。
  • 正常に値が取れた場合は、それをreturnする。
  • 値が取れない場合は、nullをreturnする。
  • 例外が起きた場合はtry-catchした上でnullをreturnする。

これがよくある。

何故か、無意味に例外を握り潰しnullを返す!!

何でこんなソースがあっちこっちにあるのか?

たぶん、プログラマーが「例外」という部分まで実装の思想を広げることが出来なくて、

  • 正常の場合は普通に値を返す。
  • 取れなかったら、nullってことで。呼び出し元は値がnullだったら異常と思って下さい。

なんて考え方。

これをやられると、呼び出し元からはnullの原因が「ネットワークエラー」なのか「本当に値が無い」のか、原因が何一つ分からなくなる。

基本的に例外処理は握りつぶしてはイカン。

そして「nullなんてありえないんだ」ということを表現したい場合は、自前の例外を作ること。
「呼び出し元でnullは不正と判断してください」とか、そんな申し送りで実装を組むなんておかしいんだ。

入力チェックサンプル

オリジナルの例外は色々な使い道がある。

この記事はJavaのバッチテンプレートを作るものだから、バッチを実行した時の引数が不正であった場合に例外を投げる、ということを表現したサンプルを作成した。

/**
 * コマンドラインからの入力引数をチェックするサンプルクラスです。
 *
 * @author アリストマスター
 *
 */
public class InputCheckSampleExecuter extends AbstractExecuter {

   /** logger */
   private static final Logger log = LoggerFactory.getLogger(InputCheckSampleExecuter.class);

   /**
    * 処理実行
    *
    * @param args 入力引数
    * @throws InputParameterCheckException
    */
   public static void main(String[] args) throws InputParameterCheckException {

      InputCheckSampleExecuter exe = new InputCheckSampleExecuter();
      exe.start(args);

   }

   /**
    * 入力引数のバリデーションチェック
    *
    * @param args 入力引数
    * @throws InputParameterCheckException
    */
   @Override
   protected void inputParameterCheck(String[] args) throws InputParameterCheckException {

      log.debug("inputParameterCheck:{}", "start");

      if (args == null || args.length == 0) {

         throw new InputParameterCheckException("入力引数がありません。");

      }

      log.debug("inputParameterCheck:{}", "end");

   };

   /* (非 Javadoc)
    * @see net.aristo.template.batch.exe.AbstractExecuter#doStart(java.lang.String[])
    */
   @Override
   public void doStart(String[] args) {

      log.warn("本体の処理です。");

   }

}

ほら、こうすると、バリデーションチェック部分のソースが本体から独立して綺麗でしょ?
ログにもちゃんと「InputParameterCheckException」と出てくれるし。

exit 0 とか、exit 1 とか、そんなのいらないんだ。

例外を上手く使うと非常にソースを綺麗に書けるようになるわけだ。

0 件のコメント:

コメントを投稿