MENU

『ドメイン駆動設計』第5章 エヴァンス本 まとめ&感想

前回のふりかえり

  • 第4章の主旨
    • MDDを実現するには、モデル要素であるドメインオブジェクトを、他の機能から分離させる必要がある。
    • その手法として、レイヤードアーキテクチャを利用できる。
    • ドメイン層として凝集度を高め、他の層から独立させる。

第5章 ソフトウェアで実現されたモデル

  • この章では、モデルを構成する個々の要素に注目する。
    • モデルを表現するのには、3パターンの要素があるといえる。
      • エンティティ
        • 連続性と一意性を持っている
      • 値オブジェクト
        • 何かの状態を記述する属性
      • サービス
        • アクションや操作をする責務を持つ

関連

  • 現実世界では、多対多の関連がたくさんあって複雑。関係を制限することで設計をシンプルにできる。
    • 設計がより実用的になり、ドメインに対する分析が実装に反映される。

関連を扱いやすくするには...

  1. 関連を辿る方向を 一方向だけにする(×双方向)
  2. 多対多から一対多の構造になる
  3. 限定子をつけて多重度を減らす。(条件で絞って対象となるものを減らす)
  4. 本質的ではない関連を除去する。(例えば、国と大統領の関連に銀行口座の情報は本質的に必要ない

エンティティ

  • オブジェクトの中には、属性ではなく同一性によって定義されるものがある。
    • それがエンティティ
  • エンティティにはライフサイクルからなる同一性がある。(ex. 人)
    • エンティティのが何を以て同一と見なせるか判断するには、モデルから同一性を定義する必要がある。
    • エンティティが一意であると保証するには下記の方法を取りうる
      • 属性や・属性の組み合わせで一意か否かを判断
      • システムによって自動生成されたIDから判断
  • 同一性の担保には様々な技術的問題があるが、下記の概念的な問題を見失わないこと
    • 2つのオブジェクトが同じものである、とはどういう意味なのだろうか?という問い

値オブジェクト

  • 値オブジェクト:同一性を持たず、「何」であるかだけが重要なもの

ex) 人...誰であるかが問題 ボールペン...字が書ければ、たくさんあるボールペンが同一かどうかは問題ではない

  • 値オブジェクトは、下記の使い方ができる。
    • 値オブジェクトは、他のオブジェクトが組み合わされてできていることもある
      • ex. 住所オブジェクト(都道府県・市町村等を内包)
    • エンティティを参照することもできる。
      • ex. 経路オブジェクト(xx駅というエンティティを参照)
    • エンティティの属性として使用できる。
      • ex. ユーザーの 名前住所 など

値オブジェクトを設計する

  • 値オブジェクトは下記の二つの方法で渡すことができる
    • コピーする(基本的にはこちらを利用)
    • 共有する

※ ただし、安全にコピー・共有するのであれば 不変 にした方が良い

  • なぜ不変にするのか?
    • 不必要な制約(値の変更を追うための制約?)をなくすことで、本質的な制約をはっきりさせる。
    • 改修したら別の箇所に影響が出た!なんてことが無くなるので、開発者は安心して、自由に設計の調整ができる。

値オブジェクトの関連

  • 値オブジェクト同士の双方向の関連は絶対やらない。
    • もし双方向の関連が必要だという話になったら、それはそもそも値オブジェクトではなくエンティティ

サービス

  • サービスとは、モノというよりも操作や活動を表すもの。
  • 優れたサービスとは...
    • 操作がドメインの概念に関係していて、エンティティや値オブジェクトの一部としては不自然になるもの
    • ドメインモデルの他の要素とは独立してインターフェースを持てる
    • 操作に状態が無い(個々のインスタンスの履歴を気にしなくていい)

サービスの種類

  • サービスのほとんどは純粋に技術的で、インフラ層に属するもの。
    • ただし、そのサービスの責務にビジネスルールを含んでいれば、それはドメイン層のサービスになる
    • 責務に応じてアプリケーションサービスやドメインサービスがある

サービスの粒度

  • サービスの粒度が細かすぎると、ドメイン層からアプリケーション層へ知識が流出することがある
    • アプリケーション層は、ドメインオブジェクトのふるまいが組み合わされる場所
    • 中粒度のドメインサービスが、アプリケーション層とドメイン層の境界を維持してくれる

モジュール

  • モジュール間は低結合、モジュール内は高凝集が理想
    • 結合度を下げることで、結合しているモジュールの関係を気にするコストが抑えられる。
    • 凝集度を高めることで、モデリングと設計は1つのモジュールに集中できる。
  • モジュールは意思表示。
    • 複数のクラスを1つのモジュールにするというのは「そのクラスたちはひとまとめに考える」ということ。
    • そのモジュールの名前は、ユビキタス言語に組み込まれたものをつける。そして言語とモデルの変更に合わせてリファクタリングしていく。
  • パッケージングの方法は色々あるが、レイヤ化アーキテクチャが一般的
    • 技術基準で同じ概念のオブジェクトを様々なパッケージに分けるのはモデルの進化を阻害する。
    • ドメイン層を他のコードから分離するためにパッケージングを使用する。

なぜオブジェクト指向設計なのか?

思ったこと・気になったこと

サービスの粒度が細かすぎると、ドメイン層からアプリケーション層へ知識が流出することがある

これ、すごいはっとしました。

ちょっと前にDDDやってみた時、エンティティと値オブジェクトに業務ロジックを詰め込んだつもりだったのに、気が付いたらアプリケーション層にロジック書き始めてたんだよね。

それはドメインサービスが無かったから?それとも、エンティティの粒度が細かすぎた? 当時のコード後で読み返してみよう。

参考