DDD / Factories


Factories

要約

  • [問題についての説明]
    • 自分の生成を責務にもつ複雑なオブジェクトは理解しにくく問題。
    • 複雑なオブジェクトの組み立てと組み立てられるオブジェトは分離するのがいい。
    • しかし、その役割をクライアントにまかせるのはもっと問題。クライアントが内部の詳細をしらないといけなくなるし、リファクタリングが難しくなる。また、クライアントがアプリケーションレイヤの一部だとすると、ドメインレイヤの責務がアプリケーションレイヤに漏れることになる(ドメインレイヤにおける抽象化の利点が台無し)。
  • 問題サマリ
    • 複雑なオブジェクトの組み立ては、組み立てられるオブジェクト自身の責務には適さない。
    • だからといって、クライアントに直接組み立てさせるのはよくない。組み立てられるオブジェクトやAGGERGATESのカプセル化を破り、結合度を高めてしまう。
  • [問題の解決方法についての説明]
    • 複雑なオブジェクトの生成はドメイレイヤの責務だが、モデル(ENTITIES、VALUE OBJECTS、SERVICES)として表されるオブジェクトのタスクではない。
    • 実装をカプセル化し、生成されるオブジェクトがどう動くかを知ることなくクライアントから利用できる仕組みが必要である。それはFACTORYと呼ばれる。
    • FACTORYは複雑なオブジェクトやAGGREGATESの生成に必要な知識をカプセル化する。
    • FACTORYはドメインモデルにおいては責務をもたないがドメイン設計の一部。
  • 解決方法サマリ
    • 複雑なオブジェクトやAGGREGATESの生成の責務は、FACTORYへ移せ。
    • 複雑な組み立てをカプセル化し具象クラスへの参照を要求しないインタフェースをクライアントに提供せよ。
    • 全体のAGGREGATESを部分ごとに生成し、不変条件を強制せよ。

Choosing FACTORIES and Their Sites

ファクトリの置き場所は3つ。

  1. AGGREGATESのルートオブジェクトにファクトリメソッドとして置く。
  2. (データを抽出しやすいとか、不変条件をチェックしやすいとかで)生成に適したオブジェクトにファクトリメソッドとして置く。
  3. スタンドアロンなファクトリクラスとして置く。

When a Constructor Is All You Nedd

常にファクトリが必要というわけではなく、直接コンストラクタを呼んだほうが適切な場合もある。

  • ポリモーフィズムが不要なとき。
  • クライアントが(ストラテジを選択するなどで)実装の詳細を必要とするとき。
  • オブジェクトのすべての属性がクライアントから利用可能なとき
  • 組み立てがシンプルなとき。
  • publicなコンストラクタが、すべての不変条件を満たすアトミックな操作であるとき。

Designing the Interface

ファクトリのインタフェース(メソッドのシグネチャ)を設計するには2つのポイントがある。

  1. 操作はアトミックにする(正常系では完全なオブジェクトを返し、異常系では例外を投げるかnullを返す)。
  2. 引数(の型)に依存することに注意する(下位のデザインレイヤに依存するのがいい。詳しくはChapter10や16で)。

Where Does Invariant Logic Go?

不変条件のチェックを行う場所はオブジェクト自身もしくはファクトリのどちらに置くべきか?

  1. AGGREGATESをファクトリクラスで作る場合はファクトリ。
  2. ファクトリメソッドで作る場合はオブジェクト自身。

ENTITY FACTORIES Versus VALUE OBJECT FACTORIES

ENTITYのファクトリとVALUE OBJECTのファクトリは異なる。

  • ENTITYは可変オブジェクトでVALUE OBJECTは不変オブジェクトであるため。
  • ENTITYのファクトリはIDを割り当てる場所として最適。

Reconstituting Stored Objects

データベースやXMLに格納されたオブジェクトを再構築するのは新規に構築するときと比べて次の2点で異なる。

  1. IDを割り当てる必要がない。
  2. 不変条件を満たしていない場合に対処する必要がある。

担当者のつぶやき

ファクトリって必要?

  • エンティティのファクトリについては新規構築の場合にだけあるといいかも(デフォルト値や関連先の設定)。再構築のときはORマッパーが担当すると考えてる。再構築のときは不変条件のチェックしなくてもいいんじゃないの。あと、わかりやすくファクトリは全部ファクトリクラスにするのがいいと思う。
  • 値オブジェクトのファクトリについては、値オブジェクトのシンプルさを考えると不要な気がする。エンティティと同じく再構築のときはORマッパーが担当すると考えるのがよさそう。

サービスがファクトリの対象になっていないような?

  • サービスがDIで取得できる場合は不要だと思う。でも動的に切り替えたい場合はファクトリを作ってDIするのがいいと思う。
    • 今のところサービスやサービスのファクトリは「アプリケーションレイヤのサービス」にDIされるものという認識。エンティティや値オブジェクトへのDIは好きじゃない(依存が双方向になるし、サービスのスコープが広がるしで見通しが悪くなるから)。

みんなの突っ込み

  • 再構築に関しては、REPOSITORYの章で「FACTORYとREPOSITORYを分けたほうが明快」という話が出てくるようですよ(p.158)。 -- 和智? 2008-10-24 (金) 22:00:52


まとめ (議事録)