今回はDDD+オニオンアーキテクチャで普段開発している傍らMENTAでDDD+オニオンアーキテクチャやクリーンアキテクチャを教えていて、
集約の決め方がわからないといった声が多かったので、今回0からどのように考えていくのかを解説していきたいと思います。
記事執筆者:オザック
Web開発を生業にしていて9年以上のrevenue-hackです!
某有名R社で働き、副業も含めて個人事業主で関わってきたプロジェクトは20以上。
DDDやクリーンアーキテクチャを得意とするバックエンドエンジニアで、現在はフリーランスとして従事。
目次
この記事の対象: DDDのドメイン設計のやり方を知りたい人
この記事の対象者としては
- DDDを少しでも学びたい人
- 設計に興味のある人
- DDDを学んでいるけどつまずいている人
などの初心者を対象にしています。
少しでもDDDやクリーンアキテクチャを学びたいという方は、こちらから気軽にメッセージください!
MENTAでDDDやクリーンアーキテクチャについて実践的に教えるプランはこちら
DDDの集約の決め方の流れ(モデリングの流れ)
簡単な流れ
- ユースケースを洗い出す
- ユースケースからエンティティ、値オブジェクトを洗い出す
- ユースケースごとの集約をまとめていく
- 集約ごとの重複をチェックしてまとめて、ID参照に変更する
この順で集約の設計を行って行きます。
今回考慮しないこと
- 集約に関して調べてくるユーザなら知っていそうなことは説明を省く
- 実際のユースケースでこのユースケースは不自然じゃない?的なことは無視してください
- 実際の実装方法については今回はやらない
DDD集約を考えるに当たりサンプルとなる題材について
今回はMENTAのプランを教えるときに実際に使っているMENTAを元に考えたユースケースを使います。
以下がサンプルユースケースになります。
具体的には以下になります。
- ユーザ新規作成
- 必須項目
- 名前: 255文字以内
- メールアドレス: 255文字以内
- パスワード: 12文字以上,英数字それぞれ最低1文字以上
- スキル
- タグ名(選択式)
- 評価: 1~5
- 年数: 0以上のint型(5年まで)
- 1つ以上
- 任意項目
- 自己紹介: 2000字以内
- 経歴
- 複数
- 詳細: 1000字以内
- 西暦from: 1970年以上のint型
- 西暦to: 1970年以上のint型、西暦fromよりも大きい数字
- 必須項目
- ユーザ更新
- 上記同様
- メンター募集作成
- 必須項目
- タイトル: 255文字以内
- カテゴリ(1つ)
- プログラミング
- マーケティング
- デザイン
- ライティング
- 動画・映像
- ビジネス
- 語学
- ライフスタイル
- 相談形式
- 単発
- 継続
- 相談方式
- チャット
- ビデオ通話
- ディスクリプション(2000文字)
- 予算(from円~to円)
- 1000円以上の数値
- 応募期間
- 1日単位
- 最大14日後まで可能
- ステータス(公開or中止)
- 公開・受付中止にすることができる
- 任意項目
- タグ(複数OK)
- 必須項目
- メンター募集に提案する
- 提案内容: 2000文字以内
- 提案できるのはスキルを5個以上持つユーザのみ
- プラン作成
- 以下必須項目
- タイトル: 255文字以内
- カテゴリ(1つ)
- 上記のカテゴリ参照
- タグ(5個まで)
- 選択式
- 内容
- 2000文字以内
- ステータス
- 公開or中止
- 料金体系
- 月額or単発
- 金額
- 任意項目
- 相談方式
- チャットorビデオ電話
- 相談方式
- 以下必須項目
- プラン契約リクエストを送る
- メッセージ(最大500文字)
- プランへの契約を承認する
- メッセージ(最大500文字)
最終的に完成したDDDの集約(モデリング図)
結果のモデリング図は以下のような形になります!
DDDの完成したモデリング図
(何故か集約がAggregateとなっている部分がありますが、特に集約と違いはなく、同じものとして作っています)
サンプル例を使ったDDDのモデリング(集約)の決め方
では実際に集約を決める手順について解説していきます。
ちなみにMENTAでDDDやクリーンアーキテクチャについて、教えているのはこちらのプランになります!
MENTAでDDDやクリーンアーキテクチャについて実践的に教えるプラン
ユースケースを出す
まず決め方としてユースケースで永続化するケースを抽出します。
ユースケースは先程上記に記載したので割愛します。
ユースケースからエンティティと集約を洗い出す
1つ1つのユースケースからエンティティと集約を出していきます。
集約とは?
DDDの集約とは、エンティティの集合体で整合性を保ちながらデータを更新する単位となります。
エンティティとは?
DDDのエンティティとは、一意なものを表現するオブジェクトです。
例えばMENTAサービスでいうとメンターは同じ「佐々木」という名字の方が複数人いても、それぞれ別々の人物のため一意のオブジェクトと考えることが出来、エンティティと呼ぶことが出来ます。
メンターエンティティはIDで識別することで名字が同じでも別の人物と把握します。逆に識別する必要のないものは値オブジェクトといいます。
まずは1つ1つのユースケースで永続化するデータを1つの集約として考えていきましょう!
今回はユーザ作成のユースケースで考えていきます。
エンティティ,値オブジェクトを洗い出す
エンティティ、値オブジェクトを出していきます。
エンティティ、値オブジェクトの出し方はRDBのテーブルを出すような感じでまずは出してみましょう。
※ただしDDDの手順としてはRDBのテーブルを考える前にモデリングを行います。あくまで考え方を伝えるためにテーブルを考える容量でやるという話です
テーブルで考えると
のようになるので、
エンティティ、値オブジェクトは
- ユーザ
- スキル
- 経歴
- タグ
となります。
※今回は集約の決め方の例になるので、エンティティか値オブジェクトかは考慮しないです
これをモデリング図に表すと
こんな感じになります。
それぞれのユースケースごとに集約をまとめると、、、
一旦上記の方法で全てのユースケースで集約を作ってみると、、、
メンター募集集約
プラン作成集約
メンター提案集約
契約集約
このようになります!
集約の重複チェック
作成した集約を見ると色々なところでユーザやタグのオブジェクトが重複していることがわかります。
オブジェクトが重複しているのはおかしいので直していきます。
ポイント
対処法としては「集約間ではIDを参照すること」で避けるようにしましょう!
結果どうなるかと言うと、、、
基本的にはオブジェクトが重複している部分を集約のIDを参照するようにします。
ただ一点だけ複数の集約から参照されている「タグ」に関しては、別のオブジェクトとしてタグ集約を作りID参照するようにしています。
DDDにおけるモデリング(集約)の決め方サンプル例のまとめ
今回はDDDで集約における決め方をサンプルを使ってまとめていきました。
DDDの集約の決め方は基本的にはこれで良いと思いますが、色々と集約をまたがないと行けなかったり、実装してみたらうまくいかないことが出てきたりと不都合も多々あるので、そのあたりはまた今後話していければと思います。
少しでもDDDやクリーンアキテクチャを学びたいという方は、こちらから気軽にメッセージください!
MENTAでDDDやクリーンアーキテクチャについて実践的に教えるプランはこちら
また普段設計や技術的な内容をツイートしてるので良かったらフォローしてください!