Value object

出典: フリー百科事典『ウィキペディア(Wikipedia)』

コンピュータサイエンスでは、Value Object(値オブジェクト)は、同等性がアイデンティティに基づいていない単純なエンティティを表す小さなオブジェクトである。つまり、2つの値オブジェクトは、同じ持つ場合は等しく、必ずしもそれらが同一のオブジェクトである必要はない[1][2]

値オブジェクトの例としては、金額や日付範囲を表すオブジェクトなどが挙げられる。

小さいので、同じエンティティを表す同じ値オブジェクトの複数のコピーを持つことが可能である。単一のインスタンスに依存してそのオブジェクトを共有するよりも、新しいオブジェクトを作成する方が簡単な場合がよくある[2]

値オブジェクトは不変である事が好ましい[3]:これは、2つの値オブジェクトが等しく作成され、等しいままであるという暗黙の前提に必要となる。クライアントコードが値オブジェクトを無効な状態にしたり、インスタンス化の後にバグのある挙動を導入したりできないようにする点でも有用である[4]

値オブジェクトは、DDDの構成要素の1つでもある。

実装[編集]

さまざまなオブジェクト指向プログラミング言語のニュアンスにより、それぞれに値オブジェクトを実装および使用するための独自のメソッドとパターンがある。

C#[編集]

C#では、クラスは参照型であり、構造体( C言語の構造体から派生した概念)は値型である。 [5]したがって、クラス定義から派生したインスタンスはオブジェクトであり、構造体定義から派生したインスタンスはValue Objectと呼ばれる(正確には、構造体を不変にして、属性を読み取り専用として宣言する事でValue Objectを表すことができる[6] )。

次の手順を実行して、値オブジェクトの特性をC#クラスに追加できる。

  1. Object.Equalsをオーバーライドして、オブジェクトがビジネスロジックを使用して比較されることを保証する。
  2. Equalsメソッドが使用されるように、デフォルトの動作==および!=演算子オーバーロードする。
  3. Object.GetHashCode メソッドをオーバーライドして、等価性を持つオブジェクトのハッシュが同じとなるようにする。
  4. プロパティセッターを削除し、コンストラクターを介してのみメンバー値を渡すことにより、クラスを不変にする[7] [8]

あるいは、C# 9.0で追加されたレコード[9]も値オブジェクトとなる型の作成に使用できる[10]

C++[編集]

C++では、代入演算子をオーバーロードし、フィールド(コンストラクターの初期化子リストによって一度だけ評価される)とクラスのメソッドに適切なconst制約を使用することで値オブジェクトを構築できる。

ただし、フィールド自体をconstとして宣言した場合(つまり非constフィールドとgetterの組み合わせで実現する方法でなかった場合)、そのようなValue Objectは別のValue Objectで完全に上書きすることは不可能となる( object1 = object2 )。

Java[編集]

C#やC++とは異なり、Javaは言語レベルでのカスタム値型をサポートしていない。カスタム値型のサポートの拡張は検討されているが[11]、すべてのカスタム型は参照型であるため、同一性と参照のセマンティクスを持つ[12]

したがって、Javaプログラマーは、不変オブジェクトを作成することによって値オブジェクトをエミュレートする事になる[13]オブジェクトの状態が変わらない限りにおいて、参照を渡すことは、Value Objectをコピーすることと意味的に同等となるからである。

すべての属性を空白のfinal [14]として宣言し、すべての属性をArrayListまたはDateのような可変タイプのような可変タイプではなく不変タイプ(たとえば、StringInteger、またはこれらの規則に従って宣言された他のタイプ)とする。また、参照ではなく値を比較するために、equalsとhashCodeを定義するべきである。

「VALJO」(VALue Java Object)という用語は、正しく定義された不変Value Objectに必要な、より厳密なルールのセットを指すために作られた。 [15]

値オブジェクトは、Java14以降データレコードとして使用可能である[16]

[編集]

public class StreetAddress
{
    public StreetAddress(string street, string city)
    {
        Street = street;
        City = city;
    }

    public final string Street { get; }
    public final string City { get; }
}

関連項目[編集]

参考文献[編集]

  1. ^ Fowler, Martin (2003年). “Value Object”. Catalog of Patterns of Enterprise Application Architecture. Martin Fowler (martinfowler.com). 2011年7月17日閲覧。
  2. ^ a b Value Object”. Portland Pattern Repository's Wiki. Cunningham & Cunningham, Inc. (c2.com). 2012年9月6日閲覧。
  3. ^ Value Object Should be Immutable”. Portland Pattern Repository's Wiki. Cunningham & Cunningham, Inc. (c2.com). 2012年9月6日閲覧。
  4. ^ Burns. “The Value of a Value Object”. sam-burns.co.uk. 2015年4月20日閲覧。
  5. ^ Classes and Structs (C# Programming Guide)”. Microsoft Developer Network (msdn.microsoft.com) (2012年). 2012年9月5日閲覧。
  6. ^ Creating an immutable value object in C# - Part III - Using a struct”. Luca Bolognese's WebLog (2012年). 2012年9月7日閲覧。
  7. ^ Koirala. “Immutable objects in C# - CodeProject”. www.codeproject.com. 2017年12月26日閲覧。
  8. ^ koirala. “Value Object Design Pattern in C#”. www.codeproject.com. 2017年12月26日閲覧。
  9. ^ レコード - C# リファレンス”. Microsoft Docs. 2022年5月22日閲覧。
  10. ^ TillW. “DDD Value Objects as C# Records: The Missing Manual”. DEV Community. 2022年5月22日閲覧。
  11. ^ JEP 169: Value Objects”. 2015年10月7日閲覧。
  12. ^ Java Language Specification, chapter 4. Types, Values, and Variables”. 2015年10月7日閲覧。
  13. ^ Immutable objects”. Collected Java Practices (2012年). 2012年9月5日閲覧。
  14. ^ hence assignable only in the constructors
  15. ^ VALJOs - Value Java Objects”. 2014年10月19日閲覧。
  16. ^ Records Come to Java”. 2021年4月13日閲覧。