実践ドメイン駆動設計 第7章メモ

実践ドメイン駆動設計 (Object Oriented Selection)

実践ドメイン駆動設計 (Object Oriented Selection)

実践ドメイン駆動設計

実践ドメイン駆動設計

実践ドメイン駆動設計 第7章

  • ドメインにおけるサービス
    • そのドメインに特化したタスクをこなす
    • ステートレスな操作
  • 集約や値オブジェクトのメソッドにするのは場違いと感じたときにつくる
  • 集約ルート上にstaticメソッドを作りたくなったとき => サービスのつくりどき
  • SaaSOvationの例

7.1 ドメインサービスとはなにか(…の前に、ドメインサービスとは何でないのか?)

  • サービスで思い浮かべるもの
  • ドメインサービス
    • エヴァンスの定義
    • ドメインにおける重要なプロセスや変換処理が、エンティティや値オブジェクトの自然な責務ではない場合、その操作は、サービスとして宣言される独立したインタフェースとしてもでるに追加すること
    • モデルの言語を用いてインタフェースを定義し、操作名がユビキタス言語の一部になるようにすること
    • サービスには状態を持たせないこと
  • ドメインサービスもドメインモデルと同様
    • 粒度の細かい振る舞いを扱う
    • 目の前にある仕事の特定の側面に注目
    • 単一のアトミックな操作で複数ドメインオブジェクトを扱うこともある
  • エンティティや値オブジェクトに属するものではないとみなすためには?
  • サービスはステートレスにする
  • ユビキタス言語に沿ったインタフェースを持つ

7.2 本当にサービスが必要なのかを確かめる

  • なんでもかんでもサービスとしてモデリングしてはいけない
    • 複数のエンティティや値オブジェクトをまたがるドメインロジックが全てサービスにはいってしまう
    • ドメインモデル貧血症
  • 認証の例
    • システムのユーザーは、認証済みである必要がある。ただし、テナントがアクティブなときしか認証できない
    • 本の例での問題点
      • クライアントが認証済みとはどういうことか知っておく必要がある
      • ユビキタス言語が明確にモデリングされていない
        • モデルに対して「認証してください authenticate」と聞いているわけでない
      • ユーザの認証に関するチームの発見を適切にモデリングできていない
        • テナントがアクティブかどうかのチェックを行っていない
    • 次の例の問題点
      • テナントがアクティブかはチェックしているが、認証の仕組みをクライアント側が知っておくべきこと以上の知識を要求している
      • Tenantがパスワードの扱いを知らなければならなくなった
        • パスワードは暗号化して格納する必要がある => テナントで暗号化する必要がある?
    • 考えられる4つの手法
      • Tenant内で暗号化 => SRP違反
      • Userが暗号化について知っている必要があるので(暗号化済みかチェックする必要がある)、Userに認証メソッドを用意する
      • TenantがUserに平文のパスワードを問い合わせ、暗号化した上でUserが保持するものと比較
        • 余計な手順が増える
      • クライアントがパスワードを暗号化、Tenantに渡す
        • クライアントの責務を無駄に増やす
    • クライアント側にドメイン固有の知識を漏らしてはいけない
      • クライアントの唯一の責務は、単一ドメイン固有の操作を実行すること
      • authenticatonServiceのステートレスなインスタンスへの参照を取得して、authenticateメソッドを問い合わせるだけ
      • 認証に関する詳細をドメインサービスにまとめる
        • クライアントのアプリケーションサービスからは全て追い出す
      • ユビキタス言語にも沿っている
      • 戻り値として値オブジェクトのUserDescriptorを返す
        • User全体を返すのではなく、Userを参照するのに欠かせない属性のみ含めた
        • ユーザごとのwebセッションを格納するのに適している

7.3 ドメインにおけるサービスのモデリング

  • ドメインサービスのモデリングは非常にシンプル
    • サービスにセパレートインタフェースを持たせるべきかどうかを判断
    • 上記OKならインタフェースをもたせる
      • 認証に係る集約と同じモジュールで行う => 認証に関する概念であるから
    • 実装はドメインモデルの外部に置く
      • ここではインフラストラクチャレイヤのモジュールに配置する
    • 実装上の注意点 nullのガード

セパレートインタフェースは必須なのか

  • 必ずしも必須ではない
  • テナントによっては特殊なセキュリティ標準を求めるところがあるかもしれない
    • そういう場合はセパレートインタフェースで、分離するのが必要な場合もある
    • 実装クラスに分離
      • 複数の固有実装が必要になったときは、それぞれの特徴にあわせた名前(型)を決める必要がある
      • 注意深く名前をつける事自体が、ドメインにおいてその特徴があることを照明している
        • Implをつけるほうが大規模なパッケージの中見つけやすいというのもあるが、大規模なパッケージになってる時点でモジュールの狙いに反している
    • ドメイン固有のサービス(例:計算処理)は、その正確性を保証するためにテストが必須
  • セパレートインタフェースが有用なのは、分離したいというゴールがある場合
    • DIやサービスファクトリを使っている場合は、分離しなくてもクライアントは実装を気にせずにすむ
  • コンストラクタを使ったり、メソッドのパラメータとして依存関係を設定する人もいる
  • 本書はDomainRegistry(ファクトリ)を使っているが必ずしも推奨するものではない

計算プロセス

  • アジャイルプロジェクト管理コンテキスト
    • 特定の型の集約から取得した値を任意の数だけ使って、結果を計算する
  • staticメソッドからドメインサービスへ
    • 計算の結果を値オブジェクトBusinessPriorityTotalsのインスタンスとして返す
    • 計算だけでなく、指定したScrumのプロダクトの中から未処理のバックログアイテムを探して、それぞれのBusinessPriorityの値を合計する
  • ドメイン内のサービスは必要に応じてリポジトリをつかえる

変換サービス

  • より技術的なドメインサービスの実装で、明らかにインフラストラクチャに属するものは、統合の際に使われる
    • 13章境界づけられた婚的との統合参照

ドメインサービスのミニレイヤの仕様

  • ドメインモデルのエンティティや値オブジェクトの上に、ドメインサービスの「ミニレイヤ」をかぶせたくなるときがある
  • トランザクションやセキュリティはアプリケーションの関心ごととして、アプリケーションサービスで対応するものであり、ドメインサービスで対応するものでない

7.3 サービスのテスト

  • ここまで作ったモデルがユーザの視点でつかえるものになってるか?
  • ドメインに注目したテストでそのモデルがどのように使われるかのかを反映させる
    • ユーザがわかるテスト
  • 正常系
    • アプリケーションサービスのクライアントからどのように使われるかをテストで示す
    • リポジトリは完全な実装でもモックでもいい
      • ここはおまかせ
  • 異常系
    • ここでは間違ったTenantID、ユーザ名、パスワードをそれぞれ渡す
    • 認証失敗したケースではUserDescriptorがnullになる
      • これはクライアントが知るべき詳細
      • 例外でなくnullを返すので、認証に失敗することはドメインの通常の動作のひとつにすぎないということを表している
  • これだけではテストは不十分
    • テナントがアクティブでない場合などがある

7.5 まとめ

  • ドメインサービスは使いすぎてはいけない
    • 用法用量は適切に
  • テストはサービスの使い方を、うまく示せるようなテストを提供する

メモ

昨日の関西DDD.javaスタートアップの話を聞いてから、この第7章読むと、他の章よりあまり長くない理由がわかった気がする。そのドメインモデルに係るビジネスロジックを集めるべきで、サービスはそこから外れるけどアプリケーションサービスに漏れてはいけないビジネスロジックをうまくドメイン層に閉じ込めるためのツールだ。ということを念頭に置くと、今のプロジェクトでServiceと名付けて使ってるものはちょっと違うなぁ。これはリファクタリング対象だな。

raydive.hatenablog.jp

エリック・エヴァンスのドメイン駆動設計 (IT Architects’Archive ソフトウェア開発の実践)

エリック・エヴァンスのドメイン駆動設計 (IT Architects’Archive ソフトウェア開発の実践)

エリック・エヴァンスのドメイン駆動設計

エリック・エヴァンスのドメイン駆動設計