実践ドメイン駆動設計 (Object Oriented Selection)
- 作者: ヴァーン・ヴァーノン,高木正弘
- 出版社/メーカー: 翔泳社
- 発売日: 2015/03/17
- メディア: 大型本
- この商品を含むブログ (2件) を見る
- 作者: ヴァーン・ヴァーノン
- 出版社/メーカー: 翔泳社
- 発売日: 2015/03/19
- メディア: Kindle版
- この商品を含むブログを見る
5.1 なぜエンティティを使うのか
- ドメインの概念をエンティティとして設計するのは、その同一性を気にかけるとき
- システム内の他のオブジェクトとの区別が必須の制約となっているとき
- エンティティは一意なものであり、長期にわたって変わり続けることができる
- 一意な識別子があって変化する => 値オブジェクトと異なる点
- エンティティが適切でない場合もある
- DDDが投資に見合うか、考える必要がある
- あるオブジェクトが同一性によって識別されるのであれば、モデルでこのオブジェクトを定義する際にはその同一性を第一とすること
- エンティティを適切に重視する方法
- エンティティの設計に関する様々なテクニック
5.2 一意な識別子
- エンティティの設計の初期段階では、そのエンティティを一意に特定するためにポイントとなる属性や振る舞いだけに注目する
- エンティティの問い合わせのときにも使える
- 主たる属性や振る舞いが定まるまでは、その他の属性や振る舞いについては意図的に無視する
- エンティティオブジェクトの定義を最も本質的な特徴まで削ぎ落とすこと
- 本質的な特徴 => 識別するものや検索し突き合わせるのに通常しようするもの
- 識別子の実装に関して、様々な選択肢を持っておくこと、長期にわたって一意性を保証できることが重要
- エンティティの一意な識別子 == 検索やマッチングのキー ではない => 使いづらいこともある
- キーとして使えるかどうかに大きく関わってくるのが人間にとっての可読性
- 一意な識別子の例
- 一意でない => Personエンティティの名前 => 同姓同名
- 一意 => 納税者IDをキーにして企業を検索 => Companyエンティティの一意な識別子
- 値オブジェクトは一意な識別子の受け皿として使える
- 不変なので、識別子が変わらないことを保証できる
- 識別子に固有な振る舞いも一元管理できる
- 一般的な作成方針
- ユーザが入力 => アプリケーション側で一意性を保証する
- シンプルしかし込み入ったことにもなりえる
- よくできた識別子がユーザ次第になる => 一意だけど間違った識別子を作るかも
- 識別子は変更不能なので、ユーザで変更できてはいけない
- 修正できるようにしておくメリットもある => 一意な識別子としてタイトルを採用した場合、タイトルを間違えたら?
- ユーザに一意な識別子を設定させるときの、うっかりミスを防ぐ方法を見当する必要がある
- 作成と承認に人手間かけた識別子がビジネス全体に長年に渡って使われるようであれば、多少手間はかけていい
- マッチングには使うけど、一意な識別子には使用しないという判断もある
- アプリケーション内部で生成 => 一意性を保証できるアルゴリズムを使う
- 信頼性の高い方法はいろいろある
- 分散環境上は注意が必要
- UUID, GUID
- メモリのオーバーヘッド => DBが生成する8バイトの識別子を使えばまし
- UUIDそのままはユーザに嬉しくない => 他の情報と合わせてUUIDの一部を表示する
- 文字列そのままで扱うのは好ましくない => 値オブジェクトで扱うといい
- クライアント側で識別子を知っておく必要はない => 集約ルートで識別子に仕込んだ情報をとれるようにしておく
- 永続化ストアにも生成できるものがある => Riak, MongoDB
- リポジトリに識別子のファクトリを任せることが多い
- アプリケーションがデータベースなどの永続化ストアに任せる
- ドメインモデルの知識がデータベースに流出してしまう
- DBのシーケンスなどを使えば一意であることが保証
- 弱点としてパフォーマンス => 問い合わせは時間がかかる、キャッシュなどが必要(リポジトリでやる)
- サーバノードの再起動で未使用の値を失うことが考えられる
- シーケンス値に空きが許容できない場合などキャッシュが現実的でないこともある
- 識別子の生成を後回しにすると、これらの問題は起きない => 生成のタイミングは考える必要がある
- 識別子の早期生成 => エンティティを永続化する前に生成と割り当てを行う
- 識別子の遅延征性 => エンティティを永続化するときに生成と割り当てを行う
- Oracleのシーケンス、MySQLの自動インクリメントによるシーケンスの模倣
- Hibernateのシーケンス => 遅延生成のみ
- 別の境界づけられたコンテキストが、すでに一意な識別子を定めており、ユーザがその識別子を入力する
- 別の境界づけられたコンテキストに識別子を割り当てさせるには、識別子の検索とマッチング、そして割り当てといった機能をそこに組み込む必要がある
- 性格なマッチングが最重要、口座番号やユーザ名、メールアドレスなどの情報を指定子て望む結果を特定する必要がある
- あいまいな入力にもとづいた複数の結果を提示して、その中からユーザに選択してもらうということも多い
- 例として、ユーザ名のあいまい検索から外部の境界づけられたコンテキストAPIにアクセスする
- 参照している外部のオブジェクトでローカルのエンティティに関わる変更があれば、イベント駆動アーキテクチャとドメインイベントを組み合わせれば対応できる
- ドメインイベントを購読させ、関連するイベント通知を受け取ったらローカルシステム側でもエンティティを更新、外部の変更を反映
- 逆にローカルの変更を外部にプッシュする必要もあるかもしれない
- この手法はどうしても必要な場合にだけ使うようにしよう
- 識別子生成のタイミング
- 代理識別子
- 識別子の普遍性
- ユーザが入力 => アプリケーション側で一意性を保証する