エリックエヴァンスのドメイン駆動設計を読んでいる(第2部 第5章)

関連

関連を扱いやすくする方法は以下の3つの通り * 関連をたどる方向を強制する * 限定子を付与して多重度を減らす * 本質的ではない関連を除去する

関係の方向性が双方向にあるということは、それぞれのオブジェクトが存在するときにのみその挙動が把握できるということを意味する。これを単方向に変えることができれば、プログラムを把握することが容易になる。

参照の方向性を絞ることによって単純化し、限定子を使って絞ることでより単純化する。

証券取引口座の例がとてもわかりやすいですね。モデルとコードがそれぞれ示されて、知識を取り入れることでモデルとコードが変わる様子が見えるのは実践のイメージがつかめるのでいい感じです。

エンティティ

ライフサイクルを通じた連続性を持ち、アプリケーションのユーザーにとって重要な同一性の区別が属性から独立して行われる場合はそのモデルはエンティティである。

人は住所や年齢は変わるし、名前も変わるかもしれない。そんな人の同一性を区別することがアプリケーションのユーザーにとって重要なことであれば、それを区別するためのIDが必要になる。この場合はエンティティである。

モデル化する上では、エンティティオブジェクトの定義を極限まで削ぎ落とすことが大切になる。

本質的に必要なものと操作に絞り込み、そこから外れたものは別のモデルとして切り出す必要があるだろう。

あくまでそのモデルを使うユーザー側がIDによって一意に区別する必要があるかどうかで変わるものみたいです。

バリューオブジェクト

IDで区別される必要がないオブジェクトにはIDを振るべきではない。設計ではすべて必要最小限な状態を保つべきなんでしょう。

バリューオブジェクトはインスタンス化される際に何であるか?は重要だが、誰であるか?とかどれであるか?は関係がない。

例えば色は赤であるとか青であるとかは大切だが、どの赤であるか?とかどの青であるか?ということを考える人はいない。

このように設計においてあるモデル要素がその属性しか関心の対象とならない場合、その要素はバリューオブジェクトとして分類すること。バリューオブジェクはイミュータブルなオブジェクトとして扱うこと。

バリューオブジェクトを設計する上で、関連性はエンティティと同様に簡素な形にするべきである。

一点異なるのはバリューオブジェクトは双方向の参照を持たないようにするべきであるという点で、バリューオブジェクトは双方向性を持つべきではない。双方向性が解決できないような事態になったらそもそもそれはバリューオブジェクトにするべきではない。まだ隠れている同一性があるはずだ。 筆者の経験からそんなことが述べられていた。

サービス

エンティティやバリューオブジェクトにしっくりと当てはめることができないような操作がドメインに含まれることがある。

無理やり当てはめようとするとせっかくモデルがシンプルで正しく簡潔に現実を反映していたのによくわからなくなってしまうかもしれない。そんな時は無理をせず、新たなサービスという概念を取り入れよう。

ただし、安易にサービスに逃げるようなことがあってはダメ。エンティティやバリューオブジェクトにおいて存在するべき操作は確実にそれらに持たせること。

責務に従うことが何より大事。

サービスはエンティティなどとは異なり純粋にクライアントに対して何ができるのか?という視点で設計される。

サービスは下記の3つの点を意識して設計する

  • 操作がドメインの概念に関係しており、かつエンティティやバリューオブジェクトの自然な一部ではない
  • ドメインモデルの他の要素の観点からインタフェースが定義されている
  • 操作に状態がない

モジュール

パッケージの切り方についても同様に責務を意識して低結合、高凝縮な区切り方をしていきましょうという内容。

まあうちの現場的にはとりあえずレイヤーごとに区切りつつその中はサービスごとに区切るというルールがあるので一周目はスルーしておこうと思います。