前回の記事
【ミライトデザイン社内勉強会#13】「IDDD本から理解するドメイン駆動設計」輪読会~第4章「アーキテクチャ」~ - Qiita
実践DDD本 第5章「エンティティ」 ~一意な識別子で同一性を識別~ (1/4):CodeZine(コードジン)
一意な識別子の生成パターン
でNo2.アプリケーションでUUIDを生成する
ときにリポジトリで生成しているのは何か理由があるの?サービスクラスで生成するのは何か問題あるの?
- サービスクラスで生成するのは違和感がある。
- リポジトリは集約を生成したりするので、生成した集約の採番をするのはリポジトリクラスが行っている方が、役割として違和感がない。
- DBで採番する方法もあるので、その場合はリポジトリで生成される。この場合はリポジトリで違和感ないはず。
- ファクトリで生成する方法もある。決まりはないけどサービスにあるのは、微妙。
「一意な識別子」の4つの生成パターン
でアプリケーションで生成する方法が一番無難な気がするけど、他の3つのパターンで生成することもあるの?
-
システムによってはユニークなキーは人が決めたいってこともある
- 人が決めたユニークなキーとは別でシステムが生成したユニークなキーを一意な識別子として使用する場合もあるけど
- 例えば、TwitterとかはIDはユーザーが決めるけど、変更ができるのでおそらくユーザーエンティティの識別としては使用されていない
- 人が決めたユニークなキーとは別でシステムが生成したユニークなキーを一意な識別子として使用する場合もあるけど
-
システムの個性による
- URLに一意な識別を入れてユーザーにリンクを踏んでもらうようなシステムの場合、人間が理解しずらい長い識別子をURLに使っているとユーザーから問い合わせやクレームがきたりする場合もある。
-
一番楽なのはDBにまかせちゃうこと
- DBの auto increment をキーにするのが一番実装コストは低い気がする
一意な識別子の生成タイミング
に早期と遅延があるが、遅延で生成するメリットがあんまりない気がするけど、あえて遅延で識別子を生成した時とかがあるの?
-
基本的には早期生成したいけど、既存のシステムを引き継いだ場合だとDBで生成していたりして遅延生成になっている場合もある
- DBで生成している場合も早期に生成することはできなくもないけど、技術的なコストはかかる
PHP UUID version4 を生成する
Laravel Eloquent の主キー(ID)を UUID に変更する
Entityは値オブジェクトの塊という意味であってる?
-
値オブジェクトを使わなくても、プリミティブな型の場合もある
値オブジェクトを使ってモデリングをした時のイメージがわかない
- 値オブジェクトは不変的なものなので、可能な限り値オブジェクトで定義する
- 値オブジェクトとして定義できるものは極力値オブジェクトとして定義した方がいい
- 値オブジェクトの方が小さい単位なので、小さい単位で洗い出す
- 値オブジェクトを決めていくと、集約が見えてくる
- 概念モデルを設計するときに、値オブジェクトを洗い出す
- 概念モデルから集約や設計の洗い出しに使う
実践ドメイン駆動設計 (Object Oriented SELECTION) | ヴォーン・ヴァーノン, 髙木 正弘 |本 | 通販 | Amazon
可能な限り、エンティティよりは値オブジェクトを使ってモデリングすべきだと聞いたら、驚くかもしれない。ドメインの概念をエンティティとしてモデリングしなければいけないとしても、そのエンティティの設計は、子エンティティのコンテナではなく値のコンテナとして組み立てるよう心がけるべきだ。このアドバイスは、単なる気まぐれによるものではない。値型は何かを設計したり定量化したり説明するときに使うもので、作成やテストがしやすいし、使うのも最適化するのも保守するのも楽だ。
データと処理を一緒に取り扱うってどういうこと?Modelにメソッドを書いている状態のこと?
ドメインモデル貧血症とは、オブジェクト指向設計の基本である「データと処理を一緒に取り扱う」ことを行わない、単なる手続き型設計のことです。
- yes, noならyes
- オブジェクト指向の基本はデータと処理を一緒に取り扱うこと
- オブジェクト指向では、データと処理は同じクラスに書いてあった方がいい
図ではEntityにメソッドが書いてあるけど、実際は別のClassに実装する場合もあるの?
- 実装はクラス図に書いてあるように実装する
- そのためにクラス図を書いてる
- モデリングは実装に反映される
- データと処理は同じクラスに書いてあった方がいい
DB保存時にidが生成されることが多い気がするけど、遅延生成はなるべく避けた方が良いの?
p.2
従来のシステム開発ではDB保存時にIDを生成する「遅延生成」が多かったと思います。しかし遅延生成の場合、一意な識別子にデフォルト値(nullや0)が設定されているため、異なるオブジェクトが同一と判定されてしまう問題があります。
- 問題になるシチュエーションがイメージできていない
- UserEntityはuserIdを持っていることをエンティティのオブジェクトを生成するときに保障したいが、遅延生成の場合はuserIdが生成した直後はnullになるため、userIdがnullであることを許容しないといけなくなる
- UserEntitiyを使用する他のクラスでもuserIdがnullの場合を考慮して実装する必要が出てくる
- 例えば、ショッピングサイトだと未登録なユーザーでもカートに入れたり、クレカ情報を入力させたりしたいけど、遅延登録の場合一度ユーザーを登録してからクレカ情報とかを登録させる必要が出てくる
- 早期生成の場合は、ユーザーを登録する前でもすでに一意のユーザーとして扱うことができるため、クレカ情報などを紐付けることができる
属性単位やオブジェクト単位でバリデーションすることってある?FWのバリデーションを使うことが多そう?
p.4
- EntityのバリデーションはEntitiyを生成するときに、整合性をチェックするためのチェック
- フレームワークのバリデーションは使わない
- 画面入力(postデータ)のバリデーションとは役割が別
- Entityのバリデーションをpostデータのバリデーションに使ってしまおうっていう考えもある
- Entityのバリデーションとpostデータのバリデーションは分ける派
- 例えば、最初はユーザーが入力できるユーザー名が50文字以内というルールがあり、途中で20文字以内に変更になった場合、postデータのバリデーションは20文字以内に変更できるが、過去に入力されているユーザー名は50文字のままになるため、エンティティのユーザー名のルールを20文字以内に変更してしまうと過去のデータと整合性が取れなくなってしまう。みたいなパターンも考えられるので
次回
【ミライトデザイン社内勉強会#15】「IDDD本から理解するドメイン駆動設計」輪読会~第6章「値オブジェクト」~ - Qiita