SHOEISHA iD

※旧SEメンバーシップ会員の方は、同じ登録情報(メールアドレス&パスワード)でログインいただけます

DeveloperZine(デベロッパージン)- エンジニアの意思決定を支える技術情報メディア ProductZine

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

IDDD本から理解するドメイン駆動設計

実践DDD本 第5章「エンティティ」 ~一意な識別子で同一性を識別~

IDDD本から理解するドメイン駆動設計 第5回


[3]エンティティを識別する属性と振る舞いを検討

 続いて、エンティティに注目してモデリングを行います。エンティティ設計の初期段階では「エンティティを一意に特定する属性と振る舞い」にだけ注目します。

モデルの一意な識別子の検討と用語集の作成
モデルの一意な識別子の検討と用語集の作成

 同時に用語集を作成し、ユビキタス言語について認識を合わせます。ドメインエキスパートとして業務が正しく表現できているか、開発者としてそのまま実装できるかを確認していきます。

[4]「一意な識別子」の設計

 そして、エンティティを識別する「一意な識別子」を検討します。SaaSOvationでは、テナントは「テナントID」と「テナント名」、ユーザーは「テナントID」と「ユーザー名」を一意な識別子としています。テナントの場合、システム的には「テナントID(UUID)」にて一意性を保証します。利用者の視点では「テナント名」を使って問い合わせを行い識別します。

 なお、テナントIDは別の境界づけられたコンテキストを含む他のオブジェクトから参照されるため、独立した「値オブジェクト」として設計しています。

一意な識別子の生成パターン

 一意な識別子を決定したら、一意な識別子の生成方法について検討します。IDDD本では一意な識別子の生成方式として以下の4パターンを提示しています。一意な識別子というと難しく感じるかもしれませんが、IDや主キー値の生成方法といえば、イメージしやすいと思います。

「一意な識別子」の4つの生成パターン
No 概要 値の例 メリット デメリット
1 ユーザーが「入力」 USR123 識別子を生成する仕組みが不要 重複せず適切な識別子を利用者に登録してもらうワークフローやチェックの仕組みが必要
2 アプリケーションが「生成」

"912649a0-0ed2-4071-8af6-1a350d4adbd0" (UUIDのみ)や
"2017-12-31-USER-1a350d4adbd0" (意味ある値とUUIDの組み合わせ)

UUID(GUID)の生成アルゴリズムを用いて一意な値を軽量に生成 人間には理解しがたい文字列(そのため、通常は利用者には非表示)
3 永続化メカニズム(DB)が「生成」 10001 Oracleのシーケンス等の仕組みを用いて連番を簡単に生成 DB依存が高く性能面の課題がある(早期生成時におけるキャッシュの仕組みの検討が必要)
4 他の境界づけられたコンテキストから「割り当て」 USR123やUUID等 識別子生成の仕組みを他のコンテキストに託せる 他のコンテキストに対して識別子を取得するための検索/マッチング/割り当ての仕組みが必要

 エンティティに適した生成方法を選択します。SaaSOvationの「ユーザーエンティティ」では、テナントIDは「アプリケーションでの生成(UUID生成)」を行い、ユーザー名は「ユーザーが入力」という形をとっています。下図はそのコード例です。

TenantIdの一意な識別子の生成例(Java)
TenantIdの一意な識別子の生成例(Java)

一意な識別子の生成タイミング(早期、遅延)

 次に、一意な識別子の生成タイミングについて紹介します。生成タイミングについては、「早期生成」と「遅延生成」の2パターンが存在します。上図のコードの通り、TenantIDでは、リポジトリ(12章)を用いて「早期生成」を行っています。

一意な識別子の生成タイミング
No 概要 メリット デメリット
A 早期生成(オブジェクト作成時に生成) オブジェクト作成と同時に識別子を使用可能 DBから識別子を生成する場合は、オブジェクト生成時にリポジトリ経由でDBから識別子を取得する必要がある
B 遅延生成(オブジェクト保存時に生成) 昔ながらの生成方法で、馴染みやすい オブジェクト生成時にドメインイベントを発行させる場合に、一意な識別子が存在しない。またオブジェクト生成時に識別子が未設定(nullや0)のためオブジェクト間の比較に失敗する

一意な識別子で、エンティティの同一性を判定(equals/hashCodeメソッド)

 エンティティが同じかという「同一性」を判定する場合、一意な識別子を使ってオブジェクト同士を比較します。IDDDでは下図のコードのように、equalsメソッドとhashCodeメソッドをオーバーライドして、一意な識別子の値の組み合わせが同じであれば、同じエンティティであるとみなしています。

同一性判断メソッドにおける一意な識別子の役割
同一性判断メソッドにおける一意な識別子の役割

 従来のシステム開発ではDB保存時にIDを生成する「遅延生成」が多かったと思います。しかし遅延生成の場合、一意な識別子にデフォルト値(nullや0)が設定されているため、異なるオブジェクトが同一と判定されてしまう問題があります。この問題に対応するには、遅延生成をやめるか、早期生成でも問題ないようにequalsメソッドとhashCodeメソッドをオーバライドして、識別子以外で同一性を判断できるようにする必要があります。

一意な識別子を変更しない「不変性」

 注意点として、一意な識別子を設定した後は、その識別子の値を変更しないようにします。もし、識別子が設定済みにもかかわらず、変更処理が呼び出された場合はエラーとなるようにしなければいけません。通常は、一意な識別子のアクセサメソッド(セッター)にアサーションを記載します。

O/Mマッパー用のID項目「代理識別子」

 なお、最近の実装ではDBにアクセスするライブラリとして、HibernateやEntity FrameworkといったO/Rマッパーを使用することも多いと思います。「代理識別子」とは、O/Rマッパーが使用するシステム的な識別子のことです。

「レイヤスーパータイプ」で共通処理を実装

 代理識別子(システム上のキー)は一意な識別子(ビジネス上のキー)ではないため、外部から見えないようにしておくことが望ましいです。代理識別子を外部から見えなくする方法として、レイヤ共通の処理を記述する「レイヤスーパータイプ」を導入することができます。下図のコードでは、エンティティの親クラス(レイヤスーパータイプ)で、idという代理識別子を提供し、可視範囲をProtectedで絞り込み、外部から見えないようにしています。

レイヤスーパータイプで代理識別子を管理(Java)
レイヤスーパータイプで代理識別子を管理(Java)

 このように共通処理を適切に管理できる場合は、レイヤスーパータイプを導入するとよいでしょう。下図は、同一性を判断するメソッドをレイヤスーパータイプで共通化する例です。

レイヤスーパータイプで同一性に関する処理を共通化(C#)

レイヤスーパータイプで同一性に関する処理を共通化(C#)

 

次のページ
[5]エンティティの振る舞い(メソッド)を検討

この記事は参考になりましたか?

IDDD本から理解するドメイン駆動設計連載記事一覧

もっと読む

この記事の著者

WINGSプロジェクト 青木 淳夫(アオキ アツオ)

WINGSプロジェクトについて>有限会社 WINGSプロジェクトが運営する、テクニカル執筆コミュニティ(代表 山田祥寛)。主にWeb開発分野の書籍/記事執筆、翻訳、講演等を幅広く手がける。 2026年時点での登録メンバは約50名で、現在も執筆メンバを募集中。興味のある方は、どしどし応募頂きたい。著書記事多数。 RSS X: @WingsPro_info(公式)、@WingsPro_info/wings(メンバーリスト) Facebook

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

山田 祥寛(ヤマダ ヨシヒロ)

静岡県榛原町生まれ。一橋大学経済学部卒業後、NECにてシステム企画業務に携わるが、2003年4月に念願かなってフリーライターに転身。Microsoft MVP for Visual Studio and Development Technologies。執筆コミュニティ「WINGSプロジェクト」代表。主な著書に「独習シリーズ(Java・C#・Python・PHP・Ruby・JSP&サーブレットなど)」「速習シリーズ(ASP.NET Core・Vue.js・React・TypeScript・ECMAScript、Laravelなど)」「改訂3版JavaScript本格入門」「これからはじめるLaravel実践入門」「はじめてのAndroidアプリ開発 Kotlin編 」他、著書多数

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

この記事は参考になりましたか?

この記事をシェア

CodeZine(コードジン)
https://codezine.jp/article/detail/10038 2018/11/13 12:50

イベント

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー