ValueObject
ビジネスロジックにおいて用いられるさまざまな値を表現するもの.
「金額=単価*数量」であれば,「金額」「単価」「数量」がValueObjectである.
設計モデル的な話
プリミティブ型はシステムに最適な値の表現ではないため,クラスによってラップしてValueObjectとすることで利用する.
値の性質とは
不変である.
パフォーマンスの観点から不変が難しい場合は,可変にしても良い.
しかし,迷うなら不変にしておこう.
asRagi.iconC#なら構造体を利用すればアロケーションは防げそう.
交換可能である.
等価性によって比較される.
比較のためのメソッドをValueObjectが提供する必要がある.
ValueObjectはデータのコンテナではなく,振る舞いも定義される.
加算処理など.
加算された値を持つValueObjectを返す.
例外をここで早出するなど.
ValueObjectに定義されない振る舞いはValueObjectにできないことであると言える.
ValueObjectの数だけクラスが生まれる心理的ハードルがある.
導入のモチベーション
表現力が増す.
string modelNumberではなく,ModelNumber modelNumberであれば,modelNumberが何者であるかがわかる.
できる操作や概念はModelNumberに全て書かれている.
ドキュメントたりえる. -> 自己文書化
不正な値の存在を未然に防ぐ.
ValueObjectでバリデーションができる.
誤った代入を防ぐ.
string nameをUser.Idに代入する操作が正しいかどうかは仕様による.
User.IdがUserId型であれば,string nameの代入がコンパイルエラーになって嬉しい.
UserIdのValueObjectがバリデーションを実行できる.
ロジックの散在を防ぐ.
ValueObjectの新規作成と更新処理それぞれのバリデーションを一箇所にまとめられる.
どこまでをValueObjectにするべきかの問題がある.
FullNameを構成するFirstName,LastNameはそれぞれValueObjectにするべきか?
文脈によるが,どちらも間違っているとは言えない.
閉じた操作