良い設計ができるようになりたくてDDDを勉強している。DDDに出てくるワードに関して現状の理解をまとめる。
これがDDDの全てというわけではない。
コンテクスト
アプリケーションを構築するときに、コンテクストを意識して境界をつくる。
すべてごちゃまぜの巨大なアプリケーションを構築しないようにする。
基準の例としては「コンテクストが変わると言葉の意味が変わる」というのがある。
例えば、ECサイトを例に出すと「ユーザー」という言葉が表すものが、購入ページでは購入者であり、出品ページでは販売者になる。
これはその間にコンテクストの境界がある指針になる。
値オブジェクト
値以上の意味を持たないものをオブジェクトとして定義したもの。
例えば年齢は値である。
age1 = new Age(20) age2 = new Age(20)
この場合
age1 == age2
はtrueとなる。
わざわざ定義しなくてもint型を年齢として使えばいいけど、値オブジェクトとして定義することで、ありえない値が入らないようにチェックしたりとか、機能をもたせることができる。
エンティティ
そのコンテクストで意味のあるデータ単位。
永続化されたりする。
例えばUserみたいなやつ。
user1 = new User("太郎") user2 = new User("太郎")
この場合
user1 == user2
はfalseとなる。
値オブジェクトの場合と異なり、コレは太郎という同じ名前を持った別人だからfalseになる。
エンティティはidのようなユニークな識別子を持つ。
エンティティは値オブジェクトや、他エンティティの識別子などで構成される。
リポジトリ
エンティティを永続化させるのに使うオブジェクト。
user = user_repository.find_by_id(1) user.name = new Name("次郎") user_repository.save(user)
みたいな感じでつかう。
永続化処理がまとまっていることで、保存先をDBにしたりメモリにしたりを柔軟に切り替えることができる。
集約(いまいちよく解ってないかもしれない)
トランザクションの観点で関連の強いエンティティを集めて構成したもの。
例えば学年のクラスを扱うとする。クラスには生徒がいる。
クラスごとに生徒一覧とか生徒連絡先一覧とかを表示する機能が必要。
このとき、クラスオブジェクトをエンティティとして作っていると、生徒のidしか持っていないから毎回生徒リポジトリから生徒エンティティを読み出して来る必要がある。不便。
だから、クラスオブジェクトに生徒エンティティを直接もたせておいたほうが扱いやすい。
これが集約なんかなと。
集約に対応してリポジトリも存在してて、
class = class_repository.find_by_id(1) class.students[0].name # 山田
みたいな感じか?
ファクトリ
集約みたいに複数要素で構成されるオブジェクトを使うには「組み立て」作業が発生する。
組み立て方法にルールがあったりするとそれをどこかにまとめて記述しておきたい。
そういう情報をファクトリに記載しておく。
集約の場合、DBとかから取得したデータ配列をまるっと渡してやると集約オブジェクトを得られるようにしておくと便利なのかも。
ドメインサービス
ロジックを書く際に、エンティティにも集約にもかけない時にはドメインサービスを用意してそこに書く。
エンティティや集約だけで特に困らない場合はドメインサービスが必要ないという場合もありえる。
アプリケーションサービス
ドメインAPIのインターフェースになる部分。
ドメイン単位でのコントローラー的な感じ?
ドメインイベント
ここでも書いた。
【DDD】ドメインイベントについて学んだので自分的理解をまとめる - やる気がストロングZERO
異なるドメイン(コンテクスト)と複合的な処理をする場合、全てを1トランザクションでアトミックに処理する場合もあれば、メッセージキューなどで結果整合性で処理する場合もある。
この辺りの仕組みづくりにドメインイベントがあると便利。