1hakusai1
@1hakusai1

Are you sure you want to delete the question?

If your question is resolved, you may close it.

Leaving a resolved question undeleted may help others!

We hope you find it useful!

[DDD]ValueObjectが投げたRuntimeExceptionをどう扱うべきか

ドメイン駆動設計に関わらず、使用する値を値オブジェクトとして設計している例が多数見られます。これらで示されている(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;
    }
}

GitHubDDDを謳っている実装例を探してみたりもしましたが、すべからくチェック例外ではなく実行時例外を投げているように見えます。

質問

  • この時、生成時に投げられたRuntimeExceptioncatchすべきなのでしょうか、すべきでないのでしょうか?
  • catchすべきなのであれば、どこでcatchすべきなのでしょうか?

ユーザーの入力を受け付けるアプリケーションであれば、不正な値を入力される可能性は常に存在すると思います。

catchしない

そもそもチェック例外ではなく実行時例外を投げているということ自体が、catchすべきでないということを体現しているとも言えます。その場合、Webアプリケーションであれば、初期化に失敗した時点でエラー応答が返されることが確定します。

このエラー応答は、javaであればTomcatJettyのエラーページなどになるでしょうか。APIサーバーとして機能しているのであれば、Status: 500の空の応答を返すでしょうか。どちらの場合も、ユーザーフレンドリーとは言い難いです。入力した値が不正なのであれば、内容をユーザーに表示するなどのアクションが欲しくなるところです。

catchする

不正な値が入力された場合になにがしかの対処を行いたい場合、投げられた例外をcatchする必要があります。catchすべきなのであれば、RuntimeExceptionではなくチェック例外を投げるべきなのではないでしょうか。RuntimeExceptionを投げる実装では、catchしなくてもコンパイルが通りますし、このクラスを使う側は(コードの中身を読まない限り)例外を投げられる可能性すら知りえません。

そもそも例外が投げられないようにする

そもそも例外が投げられるような不正な値が入力されることが問題と考えて、インスタンス生成前に入力値の検証を行うというのはどうでしょうか。この場合、値オブジェクト自身と生成するクラスに二重に検証のロジックが書かれることになります。これでは仕様変更に弱い実装になってしまいます。

私自身としては、不正な値をコンストラクタで弾く可能性があるのであれば、それを明示するためにチェック例外を投げるべきなのではないかと考えているのですが、皆さんはどのように考えていらっしゃいますか?

0

tainted value(汚染された値)を扱う場合、入力検証が必須なので、Validatorでエラーが無かった場合に生成させる方法をよくとります。

なので、"そもそも例外が投げられないようにする"に1票かな

0Like

@ktz_alias さん

ありがとうございます。
その場合、値オブジェクト自身とValidatorに同じロジックが書かれて、保守性が低くなったりしませんでしょうか?

それとも値オブジェクトに検証のロジックを書かず、Validatorに全て検証を任せる感じでしょうか?

0Like

@1ha1ru0ki1 さん
Validatorに全て委ねる派ですね。

ValidatorValueObjectの組み合わせでもって一つのコンポーネントと位置付けているので、OOPプロ市民から「ドメインモデル貧血症だ有罪だ!」と謗られてもキニシナイ姿勢でいます。

またこれはValueObjectに限らず、Entityにおいても同様に扱っています。

0Like

@ktz_alias

Validator+ValueObjectの組み合わせでもって一つのコンポーネントと位置付けている

なるほど。大変参考になります。ありがとうございます。

0Like

Your answer might help someone💌