チームでドメイン駆動設計(以下DDD)に取り組んでおり、開発や勉強会を通して知見を高めています。DDDでは様々な概念が登場する為、理解に苦労することも多いです。この記事ではDDDの基本概念である値オブジェクトとエンティティについて、他の方に分かりやすく説明できるようにまとめてみたいと思います。
記事を書くにあたり参考にした文献がこちら。大変分かりやすく書いてあるので、DDDに興味がある方はぜひ一読されることをおすすめします。
ドメイン駆動設計入門
値オブジェクト
システム上に登場する概念を値オブジェクトとして定義したもの。概念というのは例えばユーザー情報を登録する処理で例えばユーザーの住所などが挙げられますが、この住所が1つの概念になります。値オブジェクトにするメリットは以下の2つが挙げられます。
・ロジック(ビジネスルール)の散在を防ぐ(結果として、コードの変更がしやすくなる)
・値オブジェクト自身が仕様書になる(コードの理解がしやすい)
住所は郵便番号・都道府県といった要素から構成されますが、そのビジネスルールをロジックとして記載する必要があります。値オブジェクトを切るとそういったビジネスルールを散在させることなく、値オブジェクト自身にまとめることができます。またそうすることで、値オブジェクトを見るだけでその概念の仕様書にもなるので、コードを見た時に理解がしやすいのも特徴として挙げられます。
では値オブジェクトに切り出す基準は何なのかと考えた時、下記2点を軸に切り出すか検討すると良さそうです。
・ルールが存在しているか(住所は郵便番号・都道府県などから構成される)
・単体で取り扱いたいか(郵便番号や都道府県で別々のルールが存在する場合)
住所は郵便番号・都道府県などから構成されるというルールがあります。また単体で取り扱いたいかについては、郵便番号や都道府県で別々のルールが存在するかを考えると良さそうです。例えば郵便番号では、3桁の数字(都道府県を表す市外局番)と4桁の数字(町域や番地を表す局番)から構成されるというルールがある為、別の値オブジェクトとして切り出すのも有りかもしれません。
エンティティ
値オブジェクトの性質の反対の性質を持つのがエンティティと呼ばれるものです。値オブジェクトは属性によって識別されるのに対し、エンティティでは同一性によって識別されます。例えば上記で解説した値オブジェクトである住所は郵便番号・都道府県といった属性から構成されます。これらの属性の中身を変えた場合、異なる住所として認識されます。エンティティの例として代表格と言われるのが、ユーザー自身でしょう。ユーザーを表すにあたり住所もそうですし、年齢・体重・身長など様々な属性から構成されますが、これらの属性の中身が変わったからといって、そのユーザーが別のユーザーとして認識されることは普通に考えてあり得ません。この点が値オブジェクトとエンティティの大きな違いでしょう。値オブジェクトの時と同様、エンティティに切り出す基準は何なのかと考えた時、下記を軸に切り出すか検討すると良さそうです。
・ ライフサイクルが存在し、そこに連続性が存在するか
ユーザーはシステムを使用するにあたり、利用者によって作成されます。そしてシステムを利用していく内に、利用者にとってこのシステムはもう不要だなと感じ、退会(削除)することもあるかと思います。こうした作成されて、月日が経ち削除されるという流れこそがライフサイクルが存在し、連続性のある概念だと言えます。こうして見ると、値オブジェクトとエンティティは異なる性質を持つことが明白になったかと思いますが、どちらも切り出すことで得たいメリットに本質的に変わりはありません。
終わりに
DDDの基本概念である値オブジェクトとエンティティについて紹介しましたが、これ以外にもService・Repository・Factoryなど様々な概念が存在します。機会があればそれらの概念も紹介する記事を書きたいなと思っています。