2

私は DDD を学習しており、Google Datastore を使用してリポジトリを実装しようとしています。

データストアから DDD エンティティを再作成するのは非常に難しいと思います。DDD エンティティをデータストア エンティティにマップするためのフレームワークがあることを読みましたが、最初に低レベル API を学びたいと考えています。

リポジトリはセッターを使用してエンティティの状態を設定できますが、これは多くの場合、DDD ではアンチパターンと見なされます。

代わりに、ビルダー インスタンスがエンティティのコンストラクターに渡されるビルダー パターンを使用することもできます。ただし、これにより、エンティティの責任外の機能 (エンティティの状態を復元する) がエンティティに導入されます。

問題を解決するための良いパターンは何ですか?

4

2 に答える 2

4

(主にOPのコメントからの回答ですが、回答を詳しく説明する方がよいと思います)

セッターは元気です。問題は、ドメインエンティティの「ユーザー」がこれらのゲッター/セッターを介してアクセスしてはならないことです。アプリケーション ロジックがこれに基づいて構築されるように、ドメイン エンティティにはビジネス上意味のあるインターフェイスが必要です。セッターは、実装オブジェクトを作成するために使用される実装レベルのものである必要があります(リポジトリなど)

例を使って説明する方が良いと思います。


これは、アンチパターンと見なされるセッターの間違った方法です

class OrderApplicationService {
  public void cancelOrder(String orderId) {
    Order order = orderRepository.getOrder(orderId);
    order.setOrderStatus(CANCELLED);
    order.setOpenQuantity(0);
    orderRepository.update(order);
  }
}

ただし、より正しい方法は次のとおりです。

// Interface for Order

interface Order {
  void cancel();

  // no setters!!!
}

class OrderImpl extends Order {
  @Override
  void cancel() {
    this.status = CANCELLED;
    this.openQuantity = 0;
  }

  void setId(String orderId) { ... }
  // some other setters
}

class OrderApplicationService {
  public void cancelOrder(String orderId) {
    Order order = orderRepository.getOrder(orderId);
    order.cancel();
    orderRepository.update(order);
  }
}

リポジトリは、ゲッター/セッターにアクセスできるように、impl を介して作成およびアクセスしています。ただし、アプリケーションロジックはインターフェイスのみに直面しており、セッター/ゲッターを使用してロジックを実装していません (これはアンチパターンです)。


上記の方法は、インターフェイスの適切な宣言によって強制されます。ただし、自己評価に頼ることができると思われる場合は、インターフェイスを省略して、ビジネス ロジック関連のメソッドと setter/getter の両方を Impl に直接配置することで、話を単純化できます。また、実装中は、ビジネス ロジックの実装中に (ゲッター/セッターではなく) エンティティのビジネス メソッドのみを使用する必要があることを知っておく必要があります。


また、セッターをアンチ DDD と見なすことは、単純な経験則ではありません。たとえば、フリー テキスト コメントをエンティティに格納する場合など、setter を business-logic-method として提供することは、必ずしも間違った決定であるとは限りません。

于 2013-01-15T01:56:19.900 に答える
2

Eric Evansの本の第6章全体が、あなたが説明している問題に専念しています。

まず第一に、DDD の Factory はスタンドアロン サービスである必要はありません -

エバンス DDD、p。139:

FACTORIES を設計するには多くの方法があります。FACTORY METHOD、ABSTRACT FACTORY、および BUILDER のいくつかの特殊な目的の作成パターンは、Gamma et. al 1995. <...> ここでのポイントは、ファクトリの設計を深く掘り下げることではなく、ファクトリの場所をドメイン設計の重要な構成要素として示すことです。

Evans FACTORY の各作成方法は、作成されたオブジェクトのすべての不変条件を強制しますが、オブジェクトの再構成は特殊なケースです

エバンス DDD、p。145:

オブジェクトを再構成する FACTORY は、不変条件の違反を別の方法で処理します。新しいオブジェクトの作成中、FACTORY は、不変条件が満たされない場合は単純にボークする必要がありますが、再構成ではより柔軟な応答が必要になる場合があります。

これは、作成と再構成のために別々の FACTORIES を作成することにつながるため、重要です。(155 ページの図では、 TradeRepositoryは、一般的な目的の TradeOrderFactory ではなく、特殊SQL TradeOrderFactory使用しています)

そのため、再構成のために別のロジックを実装する必要があり、それを行うにはいくつかの方法があります (完全な理論は Martin J Fowler Patterns Of Enterprise Application Architectureの 169 ページにあります。小見出しMapping Data to Domain Fieldsがありますが、説明されているメソッドはすべて適切に見えます (たとえば、Java でオブジェクト フィールドをパッケージ プライベートにするのは煩わしすぎるようです)。

  • 別の FACTORY を作成してドキュメント化し、開発者が永続化またはテストのみに使用できるようにすることができます。
  • たとえばHibernate が行うように、リフレクションを使用してプライベート フィールドの値を設定できます。

セッター/ゲッターを使用した貧血ドメイン モデルに関しては、近日中に出版される Vaughn Vernon の本でこのアプローチが批判されているため、あえてDDD のアンチパターンと言えます。

于 2013-01-17T22:52:32.717 に答える