域模型关联延迟加载

时间:2013-12-27 12:01:22

标签: php model domain-driven-design domain-data-modelling

我目前正面临处理聚合中实体之间关联的问题。

请考虑以下示例:

现在,我们有一个用户“实体,这也是我的聚合根。他可以只有一个,产品”与他相关,还有很多,别名“。我现在需要的是能力在域模型中按需检索相关的,“产品”和“别名”。用户由UserFactory创建,可以单独使用,也可以在持久性数据中创建实体时在UserRepository中使用。

<?php
class User {
   private $id;

   private $aliases;
   private $product;

   public function isEligibleForCompanyPromotion() {
      //I need a good way to populate this without a performance bottleneck. 
      $product = $this->product;
      [.. code comparing things between User and Product begins ..]
   }     

}

之所以这样,是因为我们的业务逻辑(正如你在例子中看到的)很大程度上依赖于对象之间的关联,我想这个与对象之间的关联相关的逻辑应该在域模型中完成(或者这应该是搬出去了?)

我考虑过以下解决方案:

1)只需在构建用户时加载所有内容(关联的产品和别名)。

优点:

  • 作品?

缺点:

  • 大的性能问题(不幸的是我正在使用实时高负载系统,因此无法通过)

2)将关系存储库注入域模型    

  private $productRepository;
  private $aliasesRepository;
  [...]

}

优点:

  • 作品..

缺点:

  • 击败(imo)DDD的目的,要求用户在内部拥有存储库(因此域模型与持久性相关联。)

3)将与关联相关的逻辑委托给域模型(可能是域服务和策略?)

优点:

  • 也有效

缺点:

  • 实际上我觉得这会导致Anemic Domain Models,因为我们的大部分业务逻辑都是基于对象的关系,所以很多代码都会被移出域对象,这是没有意义的。

4)创建一个专门的Relationship对象来处理关系:

<?php
class UserFactory { 

private $relationshipFactory;

public function createUser($persistenceData) {
    $user = new User();
    [.. creating of User, populating data etc .. ]
    $user->product = $this->relationshipFactory->createUserProductRelationship($user);
}

}


class UserProductRelationship {

    private $user;
    private $product;
    private $productRepository;

    [.. productRepository is being injected within relationshipFactory, and user is  provided ..]

    public function loadProduct() { 
      [.. load the product based on the relationship criterias ..]
    }

    [.. calls to this object are proxied to lazy-loaded product via __call, __get etc. )
}

优点:

  • 也有效

缺点:

  • 循环依赖(用户需要在其中具有UserProductRelationship并依赖于它。需要为User实体提供UserProductRelationship。将这两个类组合将导致场景#2)。

也许我不理解某事。如果有人有任何建议,我会很高兴听到它。

谢谢!

1 个答案:

答案 0 :(得分:1)

如果某些责任不属于任何对象,或者域对象需要太多不相关的数据来解决问题,请引入规范对象。

您需要的是EligibleForCompanyPromotionSpecification,如:

class EligibleForCompanyPromotion {
    private $productRepository;
    private $aliasesRepository;

    public function isSatisfiedBy(User user) {
       //I need a good way to populate this without a performance bottleneck. 
       $product = $productRepository.find(user.productId);
       [.. code comparing things between User and Product begins ..]
}   

class User {
   private $id;

   private $aliasesId;//only identifiers needed
   private $productId;//only identifiers needed 

在这种情况下,域逻辑不会泄漏到应用程序层,我们不必将存储库注入用户。