Value Object(値オブジェクト)とは
「値」のように扱えるオブジェクトです。 日本語では「値オブジェクト」と呼びます。 以下のような性質を持ちます。
- オブジェクトが不変(immutable)
- 属性のみに関心を持つ
2.を詳しく説明すると、 エンティティがIDで同一性を識別するのに対し、 値オブジェクトはオブジェクトの属性で同一性を識別します。
Value Objectに気づいたきっかけ
最初にValue Objectに気づいたきっかけが、 以下の記事を読んだときでした。
この記事はtypedefのつもりで継承を使うテクニックを、
アンチパターンとして挙げています。
Java 7からは右側が<>
と省略可能になり、
Java 10からはローカル変数の型推論があるため、過去の話になりつつありますが。
しかし、自分はこう考えました。 「別の型に割り当てられないのは型安全という意味ではむしろメリットでは?」
そう思って試しに、以下のようにStringをラップしただけのクラスを作って 使ってみました。Stringは継承できないので移譲を使って1。
public class LoginId {
private String loginId;
public LoginId(String loginId) {
this.loginId = loginId;
}
// 以下メソッドの定義
}
そうしたら予想以上に使いやすかったです。 これって他で使われてないのかなぁと思っていたところ、 Value Objectに辿り着きました。
Value Objectはオブジェクト指向と関数型の架け橋
ReduxのReducerの説明を読んだ時に気づきました。以下の図です。
要は「Old state + action」をReducerに渡すと「New state」を返すということですが、 これを見た時に、Value Objectと同じやんと思ったわけです。 具体的には、以下のように対応します。
- Old state: 元のオブジェクト
- Reducer, action: メソッドと引数
- New state: 新しいオブジェクト
Value Objectは、この「元のオブジェクト」と「新しいオブジェクト」が 別のオブジェクトであることがキモです。
検索したら、同じことを考えている人は既にいました。
HaskellのIOモナド
これ見たときに、もう一つ理解できました。 それは、HaskellのIOモナドのことです。 Haskellは10年以上前に勉強したけど分からなくて断念したのですが、 このReducerの定義を見てからHaskellのIOモナドを見ると、よく理解できました。 以下の記事にありますが、state = 現実世界ですね。
だからと言って関数型言語をやりたいという気持ちはなくて、 むしろオブジェクト指向でいいやという感じですが。。。 (どちらかと言えばKotlinとかSwiftやりたい)
-
継承自体がアンチパターンなので、今なら当然継承しませんが。 ↩︎
外部サイト
- ValueObject
- Value Object は不変にする | システム設計日記
- Value Objectパターンの本当に重要なポイントは「不変オブジェクト」ではなく「普通ならプリミティブ型を使ってしまうような場面でもあえてユーザー定義クラスを使う」という点にあるのではないか? - Qiita