[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しなくてもコンパイルが通りますし、このクラスを使う側は(コードの中身を読まない限り)例外を投げられる可能性すら知りえません。
そもそも例外が投げられないようにする
そもそも例外が投げられるような不正な値が入力されることが問題と考えて、インスタンス生成前に入力値の検証を行うというのはどうでしょうか。この場合、値オブジェクト自身と生成するクラスに二重に検証のロジックが書かれることになります。これでは仕様変更に弱い実装になってしまいます。
私自身としては、不正な値をコンストラクタで弾く可能性があるのであれば、それを明示するためにチェック例外を投げるべきなのではないかと考えているのですが、皆さんはどのように考えていらっしゃいますか?