ドメイン駆動設計(DDD)ってなに?第4回:ファクトリってなに?認証工場で考えてみた

前回、「集約と集約ルート」について調べてみました。
つまり、「この情報たちはセットで扱うよ!」というひとかたまり(=集約)と、
「このまとまりの出入り口はここだよ!」という受付窓口(=集約ルート)の話でした。
目次
で、次の疑問:「じゃあ、その窓口ってどう作るの?」
集約ルートを通してしか中をさわっちゃダメ、っていうのはわかったけど…
そもそもその「受付窓口」って、どうやって作るの?
勝手に new
しちゃダメなの?
という疑問がわいてきたので、今度はファクトリ(Factory)について調べてみました。
ファクトリとは「正規ルートで作る場所」
ざっくり言えば、「ちゃんとルールにしたがって集約を生成する専門部署」です。
いわば認証付きの工場みたいなもの。
たとえば、社員証がないと入れないセキュリティの厳しい工場。
その中でだけ、新しい注文やユーザーやアイテムを作っていいことになっている。
つまり、ドメインの外から直接 new しちゃうとルール違反になる、ってことなんですね。
なぜ勝手に new しちゃダメなの?
たとえば、注文(Order)を作るときって、
- 最低1つの商品が必要
- 合計金額が0円未満になっちゃダメ
- ユーザーがブラックリストに入ってたらNG
みたいな業務ルールがあるはず。
でも、これを new Order(...)
で自由に作れるようにしてしまうと、
ルールをすっ飛ばした“壊れた注文”が大量に発生する危険があるんです。
そこで Factory の出番!
ファクトリの役割は、こうした複雑な生成ルールを1箇所に閉じ込めておくこと。
$order = OrderFactory::create(
$user,
$cartItems,
$deliveryAddress
);
みたいに使って、ルールをチェックしながら、安全にインスタンスを作る。
じゃあ全部Factory経由にすればいいの?
調べてみると、そこまではしないことも多いらしいです。
たとえば:
- ただの値オブジェクト(例:住所、金額)なら new でOKな場合も多い
- 集約ルートの初期化がシンプルなら、static メソッドで済ませることもある
でも「生成ルールが多い」「生成ロジックが複雑」「テストで毎回同じ初期化を書くのがしんどい」みたいなときには、Factoryクラスに切り出すとスッキリするという感じでした。
まとめ
なるほど…ファクトリっていうのは、「勝手に new するのを防ぐセキュリティ付きの工場」みたいな役割だったんですね。
ちゃんとした入り口からしかオブジェクトを作れないようにすることで、
- ビジネスルールを守れる
- 意図しない状態を防げる
- テストもしやすくなる
などのメリットがあるようです。
次回は、この作った集約を**外にどう渡すか?という話。
つまり、✉️DTO(封筒で渡すデータ)**について調べてみます!
→ 続き:「DTOってなに?封筒で渡すデータという考え方」に続きます!