Categories
ドメイン駆動設計

値オブジェクト

概要

 値オブジェクト(Value Object)は、ソフトウェア開発において使用されるデザインパターンの一つです。値オブジェクトは、不変(Immutable)であり、単純なデータを表現するために使用されるオブジェクトです。エンティティとは対照的な概念となり、属性は持つが、同一性を持たないオブジェクトのことを指します。

値オブジェクトは、特定のコンテキストで意味を持つ値を表現します。通常、プリミティブなデータ型(整数、文字列、日付など)ではなく、より複雑な概念やコンセプトを表すために使用されます。例えば、座標、日付範囲、金額、住所などが値オブジェクトの例です。

値オブジェクトは以下の特徴を持ちます:

  1. 不変性(Immutable): 値オブジェクトは作成後に変更されることがなく、不変性を持ちます。つまり、値を変更するためには新しいオブジェクトを作成する必要があります。これにより、予測可能で信頼性の高い振る舞いを提供し、バグの原因となる副作用を防ぐことができます。
  2. 等価性による比較: 値オブジェクトは、その内部の値に基づいて等価性を判断します。つまり、同じ値を持つ値オブジェクト同士は等価であり、値が異なる場合は異なる値オブジェクトとみなされます。これにより、値オブジェクトをコレクション内で利用する際に便利です。
  3. 振る舞いの少なさ: 値オブジェクトは主にデータを表現するために使用されるため、複雑な振る舞いや操作を持つことは少ないです。一般的には値の取得や比較など、基本的な操作が提供されます。

値オブジェクトはドメイン駆動設計(Domain-Driven Design)などのアーキテクチャスタイルや、不変性と正確性が求められる領域で特に有用です。値オブジェクトは不変であるため、副作用の心配がなく、スレッドセーフな操作が可能です。また、ドメインモデルの表現やドメインロジックの実装において、より意味的な表現と保護を提供します。

コード例

#include <iostream>
#include <string>

class Address {
private:
    std::string street;
    std::string city;
    std::string zipCode;

public:
    Address(const std::string& street, const std::string& city, const std::string& zipCode)
        : street(street), city(city), zipCode(zipCode) {}

    std::string getStreet() const {
        return street;
    }

    std::string getCity() const {
        return city;
    }

    std::string getZipCode() const {
        return zipCode;
    }

    // 等価性の比較演算子のオーバーロード
    bool operator==(const Address& other) const {
        return street == other.street && city == other.city && zipCode == other.zipCode;
    }
};

int main() {
    Address address1("123 Main St", "City", "12345");
    Address address2("456 Elm St", "City", "67890");

    if (address1 == address2) {
        std::cout << "The addresses are the same." << std::endl;
    } else {
        std::cout << "The addresses are different." << std::endl;
    }

    return 0;
}

この例では、Addressクラスが値オブジェクトとして定義されています。Addressクラスはstreet(住所)、city(市町村)、zipCode(郵便番号)の3つのプライベートメンバ変数を持ちます。

コンストラクタによって値が設定された後は、これらの値は変更不可です。また、getStreet()getCity()getZipCode()メソッドを通じて値を取得することができます。

operator==演算子をオーバーロードして、値オブジェクト同士の等価性比較が行えるようになっています。

main関数では、2つのAddressオブジェクトを作成し、それらの等価性を比較して結果を表示しています。

このような値オブジェクトを使用することで、データのカプセル化と不変性を確保し、安全な操作とコードの保守性を実現できます。