ドメインモデルをコードへ落とす 〜あなたのクラスは、どこから?〜


annotation:
現在コメントいただいている通り、一部誤りを含んでいる様です。
追って確認・修正いたしますが、現行ではコメントも合わせてお読み頂ければと思います。

こんにちは、風邪はだいたい喉から来るぷーたんです。

「DDDの構成要素はこれだー」というのはたくさんあったのですが、
「このドメインオブジェクトはどの要素だー」と逆引きするものがなかったので調べてフローチャートにしてみました。
例えばドメインモデル図とコードがうまく合致しない時の見直しなどに使えるのではと考えています。

ではご覧ください♪

検討フローチャート


図1.フローチャート

1) 複数のドメインオブジェクトを扱い、整合性を担保するか

まず複数のドメインオブジェクトを扱うかを考えます。
ドメインモデル図では集約線が引かれていたり、複数の関係線が引かれていたりします。


図2.ドメインモデル図の例

上記のような場合であれば、「本棚」と「購入」はYes、「書籍」「在庫」「所持金」はNoです。

また、扱う複数のドメインオブジェクトに対して整合性を担保するかも考えます。
不要な場合、ドメインオブジェクトとして扱うほどでもない概念かもしれません。(6に飛ぶ)

2) 状態を持つか

状態を保つ必要があるかどうかを考えます。
図2の例では「本棚」は書籍をどのような順番で保持しているかという状態を考慮する必要がありそうなのでYes、「購入」はそうでもなさそうなのでNoとなりそうです。

図2の例は簡素な図なのでなんとなくでいけましたが、実際にはもう少し考えます。
扱う複数のドメインオブジェクトの整合性を「しっかりとした整合性(完全一貫性)」とするか
「多少遅延してもいい整合性(結果整合性)」とするかを考えます。
前者であれば扱うドメインオブジェクトを状態としてそれらを保持することで外部との関係を疎にします。
後者で良ければ状態として保持する必要はないでしょう。

3) あるクラスのメソッドとして実装しても複雑にならなそうか

そうであればドメインオブジェクトとして切出さず、そのクラスのドメインオブジェクトの一部としたほうが良さそうです。
これを見直さない場合、ドメインサービスが膨らむ一方でドメインオブジェクト(=クラス)がやせ細り、
世に言う「ドメインモデル貧血症」を起こしてしまうかもしれません。
そうではない複雑な処理であればそのドメインオブジェクトはドメインサービスとして実装するのが良さそうです。
ドメインサービスについて

4) エンティティを4種以上扱っているか

IDDD本では事例として

彼らチームは、すべての集約の約7割を、ルートエンティティに値型のプロパティを数個持たせるだけにできた。残りの3割も、たかだか二つか三つ程度のエンティティしかなかった。

と挙げられており、大きい集約はパフォーマンスやスケーラビリティが低くなるとされています。
4というのは飽くまで目安ですが、Yesの場合はそのドメインを細かく分割できないか検討すると良さそうです。

検討の結果、十分小さく分けられていればそのドメインオブジェクトは集約(ルートエンティティ)として実装するのが良さそうです。
また、「デメテルの法則」や「Tell-Don't-Askの方針」を守れているかを確認することで、内部を密に、外部と疎にでき、より扱いやすい集約とすることができます。
集約について

5) IDを必要とする(同一性を担保する)か

同一性とは値が変わったとしても同じものとして認識できるか、というものです。
例えば「人」モデルが「私」を表現しており「年齢:34」という状!状態を持っていたとすると、
「年齢:35」となっても同一人物として見る必要があります。
この様な場合はYesとなり、エンティティとして、
そうでなければNoとなり、値オブジェクトとして実装するのが良さそうです。

エンティティは上記のように属性が変化し続けるので、その連続性や同一性を考慮した複雑な設計を要します。
一方で値オブジェクトは属性が変わればもう別物なので、エンティティのような複雑さを回避できます。
この違いを見極めることで無駄な考慮コストを抑えることができるでしょう。
エンティティについて
値オブジェクトについて

6) 途中で当てはまらなくなった

若干のずるいですが例外をキャッチする部分をつくりました。(フローチャートとは。。)
チャートがうまくできていたとすれば、当てはまらない場合はドメインオブジェクトには当てはまらない概念かもしれません。
候補として次のものを考えました。

  • アプリケーションサービス
  • リポジトリ
  • 他のドメインの一部に含まれる概念

アーキテクチャにもよりますが、上2点は別のレイヤーの概念です。
レイヤーをまたいでしまわないように、もう一度整理しましょう。

3点目は書き出してはみたけどあまり知識持ってないなーというやから。
他のドメインオブジェクトに含めて凝集度が上がるならその方が良いでしょう。

まとめ

  • DDD構成要素逆引きチャートを作ってみた
  • 実装とドメインモデル図が合わない時にズレの確認に使える(使えたらいいな)

参考資料