[DDD]ValueObjectが投げたRuntimeExceptionをどう扱うべきか
Discussion
ドメイン駆動設計に関わらず、使用する値を値オブジェクトとして設計している例が多数見られます。これらで示されている(java
の)実装例においてほとんどの場合、値の初期化時に不正な値が渡された時にはRuntimeException
を投げるようになっていると思います。
public class UserID {
private String id;
public UserID(String id) {
if (id == null) {
throw new NullPointerException();
}
if (id.length() < 8) {
throw new IllegalArgumentException();
}
this.id = id;
}
}
GitHub
でDDD
を謳っている実装例を探してみたりもしましたが、すべからくチェック例外ではなく実行時例外を投げているように見えます。
質問
- この時、生成時に投げられた
RuntimeException
はcatch
すべきなのでしょうか、すべきでないのでしょうか? -
catch
すべきなのであれば、どこでcatch
すべきなのでしょうか?
ユーザーの入力を受け付けるアプリケーションであれば、不正な値を入力される可能性は常に存在すると思います。
catch
しない
そもそもチェック例外ではなく実行時例外を投げているということ自体が、catch
すべきでないということを体現しているとも言えます。その場合、Web
アプリケーションであれば、初期化に失敗した時点でエラー応答が返されることが確定します。
このエラー応答は、java
であればTomcat
やJetty
のエラーページなどになるでしょうか。API
サーバーとして機能しているのであれば、Status: 500
の空の応答を返すでしょうか。どちらの場合も、ユーザーフレンドリーとは言い難いです。入力した値が不正なのであれば、内容をユーザーに表示するなどのアクションが欲しくなるところです。
catch
する
不正な値が入力された場合になにがしかの対処を行いたい場合、投げられた例外をcatch
する必要があります。catch
すべきなのであれば、RuntimeException
ではなくチェック例外を投げるべきなのではないでしょうか。RuntimeException
を投げる実装では、catch
しなくてもコンパイルが通りますし、このクラスを使う側は(コードの中身を読まない限り)例外を投げられる可能性すら知りえません。
そもそも例外が投げられないようにする
そもそも例外が投げられるような不正な値が入力されることが問題と考えて、インスタンス生成前に入力値の検証を行うというのはどうでしょうか。この場合、値オブジェクト自身と生成するクラスに二重に検証のロジックが書かれることになります。これでは仕様変更に弱い実装になってしまいます。
私自身としては、不正な値をコンストラクタで弾く可能性があるのであれば、それを明示するためにチェック例外を投げるべきなのではないかと考えているのですが、皆さんはどのように考えていらっしゃいますか?