0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

ドメイン駆動設計(DDD)における値オブジェクトと不変オブジェクト

Last updated at Posted at 2025-02-01

ソフトウェア開発において、ドメイン駆動設計(DDD)は非常に強力なアプローチです。DDDでは、ビジネスドメインを中心にシステムを設計し、複雑なビジネスロジックをシンプルで一貫性のあるコードに分解します。本記事では、DDDの設計パターンの一つである「値オブジェクト(Value Object)」と「不変オブジェクト(Immutable Object)」の使用について説明します。

全体コード構造

まずは、全体のコード構造を見てみましょう。以下のコードは、Membership クラスとそれに関連する複数の値オブジェクトを示しています。

@AllArgsConstructor(access = AccessLevel.PRIVATE)
public class Membership {
    @Getter private final String membershipId;
    @Getter private final String name;
    @Getter private final String email;
    @Getter private final String address;
    @Getter private final boolean isValid;
    @Getter private final String aggregateIdentifier;

    public static Membership generateMember(
            MembershipId membershipId, 
            MembershipName membershipName, 
            MembershipEmail membershipEmail, 
            MembershipAddress membershipAddress, 
            MembershipIsValid membershipIsValid, 
            MembershipAggregateIdentifier membershipAggregateIdentifier
    ) {
        return new Membership(
                membershipId.membershipId,
                membershipName.nameValue,
                membershipEmail.emailValue,
                membershipAddress.addressValue,
                membershipIsValid.isValidValue,
                membershipAggregateIdentifier.aggregateIdentifier
        );
    }

    @Value
    public static class MembershipId {
        String membershipId;
        public MembershipId(String value) {
            this.membershipId = value;
        }
    }

    @Value
    public static class MembershipName {
        String nameValue;
        public MembershipName(String value) {
            this.nameValue = value;
        }
    }

    @Value
    public static class MembershipEmail {
        String emailValue;
        public MembershipEmail(String value) {
            this.emailValue = value;
        }
    }

    @Value
    public static class MembershipAddress {
        String addressValue;
        public MembershipAddress(String value) {
            this.addressValue = value;
        }
    }

    @Value
    public static class MembershipIsValid {
        boolean isValidValue;
        public MembershipIsValid(boolean value) {
            this.isValidValue = value;
        }
    }

    @Value
    public static class MembershipAggregateIdentifier {
        String aggregateIdentifier;
        public MembershipAggregateIdentifier(String value) {
            this.aggregateIdentifier = value;
        }
    }
}

このコードは、顧客の「会員情報」を表す Membership クラスと、その属性を保持するいくつかの値オブジェクトを含んでいます。次に、これらの要素を一つずつ説明します。

1. 値オブジェクト(Value Object)とは

値オブジェクトは、識別子を持たず(Entityとは違う点!)、主にその属性(値)に意味があるオブジェクトです。例えば、顧客の「名前」や「メールアドレス」などが該当します。

MembershipId, MembershipName, MembershipEmail などの値オブジェクト

@Value
public static class MembershipId {
    String membershipId;
    public MembershipId(String value) {
        this.membershipId = value;
    }
}

この MembershipId クラスは顧客の「会員ID」を表す値オブジェクトです。@Value アノテーションにより、このクラスは不変オブジェクトとなり、membershipId フィールドは変更できません。

同様に、MembershipName, MembershipEmail, MembershipAddress などのクラスも値オブジェクトとして設計されています。これらのクラスは、顧客の各属性を保持するために使用されます。

2. 不変オブジェクト(Immutable Object)とは

不変オブジェクトとは、一度設定された状態を変更できないオブジェクトのことです。Javaでは、クラスのフィールドを final として宣言することで、不変オブジェクトを実現します。

Membership クラスの不変性

Membership クラスも不変オブジェクトとして設計されています。すべてのフィールドは private final であり、一度設定された後は変更されることがありません。

@AllArgsConstructor(access = AccessLevel.PRIVATE)
public class Membership {
    @Getter private final String membershipId;
    @Getter private final String name;
    @Getter private final String email;
    @Getter private final String address;
    @Getter private final boolean isValid;
    @Getter private final String aggregateIdentifier;
}

この設計により、Membership クラスのオブジェクトは一度作成されると、その状態が変更されることはありません。

3. ファクトリーメソッド(Factory Method)パターン

Membership オブジェクトは、直接インスタンス化するのではなく、generateMember というファクトリーメソッドを通じて生成されます。これにより、オブジェクト生成の一貫性が保たれ、ビジネスロジックが適切にカプセル化されます。

public static Membership generateMember(
        MembershipId membershipId, MembershipName membershipName, MembershipEmail membershipEmail, 
        MembershipAddress membershipAddress, MembershipIsValid membershipIsValid, 
        MembershipAggregateIdentifier membershipAggregateIdentifier) {
    return new Membership(
            membershipId.membershipId,
            membershipName.nameValue,
            membershipEmail.emailValue,
            membershipAddress.addressValue,
            membershipIsValid.isValidValue,
            membershipAggregateIdentifier.aggregateIdentifier
    );
}

4. アグリゲート(Aggregate)パターン

Membership クラスは、複数の値オブジェクトを含んでおり、これらの関連するオブジェクトをグループ化しています。このようなクラスは アグリゲート(Aggregate) として扱うことができます。アグリゲートは、一貫した状態を持つオブジェクト群を管理し、トランザクション単位で操作を行うための設計パターンです。

使用例

Membership.MembershipId membershipId = new Membership.MembershipId("M001");
Membership.MembershipName membershipName = new Membership.MembershipName("John Doe");
Membership.MembershipEmail membershipEmail = new Membership.MembershipEmail("john@example.com");
Membership.MembershipAddress membershipAddress = new Membership.MembershipAddress("kotoku Street, Tokyo");
Membership.MembershipIsValid membershipIsValid = new Membership.MembershipIsValid(true);
Membership.MembershipAggregateIdentifier membershipAggregateIdentifier = 
                new Membership.MembershipAggregateIdentifier("AGG-001");


Membership membership = Membership.generateMember(
                membershipId, 
                membershipName, 
                membershipEmail, 
                membershipAddress, 
                membershipIsValid, 
                membershipAggregateIdentifier
);

結論

この設計は、ドメイン駆動設計(DDD)の重要な概念である「値オブジェクト」および「不変オブジェクト」に基づいています。これにより、システムのビジネスロジックを安定的に管理し、オブジェクトの状態が常に正しいことを保証します。また、ファクトリーメソッドとアグリゲートパターンを活用することで、コードの一貫性と可読性も向上しています。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?