値オブジェクトとは
ドメインのオブジェクトをエンティティだけで構成した場合、あらゆるオブジェクトがidをもち、オブジェクト同士の区別をする必要があることになる。
しかし、ユーザークラスの属性である名前や所属といったような、単なる説明にすぎないオブジェクトにもidをあたえて区別する必要はなく、これらは値オブジェクトとして生成するのがいい。
値オブジェクトのポイント
値オブジェクトのポイントは区別する必要がないということ。
ユーザークラスの名前オブジェクトを Name クラスとして作成する場合、たとえ同姓同名のユーザーが存在しても、それらを区別する必要はない。
区別する必要がないことでうまれる特徴
値オブジェクトは、特定のそれと指し示す必要がないので、その属性は不変となる。
これがユーザーの場合であれば、特定のその人と指し示す必要があるので、「id 〇〇の名前を××に変える」という処理が発生するけれども、ユーザーの名前オブジェクト(値オブジェクト)を差し替えるときには、その名前オブジェクト自体を新たに生成して差し替えるだけとなる。
「変更」という処理自体、コレとソレを区別する必要があるからこそ発生する操作であって、区別する必要のない、ものを説明したり形容したりするだけの概念は、作ったり捨てたりすることはあっても、変更することはない。
なぜエンティティとしてはいけないか
値オブジェクトをエンティティとしてはいけない、というわけではなく、値オブジェクトのメリットを享受するために利用するものとおもわれる。
値オブジェクトのメリットは、不変である(publicなsetterをもたない)ために、このインスタンスをまるごとメソッドに渡しても、その中身が意図せず変わってしまうことが防げるとあらかじめわかることにあるとおもう。
より制約の強い値オブジェクトを積極的に利用することで、バグの発生する可能性を減らし、無用な心配の種を最初から摘み取ることができることが大きなメリットになる。
エンティティ or 値オブジェクト
不必要にエンティティをつくらず、できるだけ値オブジェクトで構成することを検討したほうがいいとおもう。
特に、「本来エンティティにするべきところ値オブジェクトにしてしまった」、という問題は後で気づいて修正しやすいが、「本来値オブジェクトにするべきところエンティティにしてしまった」という問題は、間口がひろくなっただけで問題として認識されにくいようにおもわれる。