关于存储库的域驱动设计问题

时间:2012-04-21 21:21:20

标签: zend-framework dependency-injection singleton domain-driven-design

我正在尝试实现DDD,所以我创建了以下类 - 用户[域名模型]
- UserRepository [管理对象的中央工厂]
- UserMapper + UserDbTable [用于映射应用程序功能并提供CRUD实现的Mapper]

我的第一个问题是,当模型需要与持久层进行通信时,它是否应该与存储库或映射器联系?就我个人而言,我认为它应该询问将与映射器联系并提供所需功能的存储库。

现在我的第二个问题是,同一个类的所有对象应该只有一个存储库,这意味着我将创建一个单例。但如果我的应用程序有很多域模型(比方说20),那么将有20个单身人士。它感觉不对。另一种选择是使用DI(依赖注入),但我使用的框架(Zend Framework 1.11)不支持DIC。

我的第三个

2 个答案:

答案 0 :(得分:6)

  
      
  • UserRepository [管理对象的中央工厂]
  •   

在DDD Repository中不是Factory。存储库负责域对象的中间和寿命结束。工厂负责开始。从概念上讲,持久化和恢复在其中间生活中发生在域对象中。

  
      
  • UserMapper + UserDbTable [映射应用程序功能并提供CRUD实现的Mapper]
  •   

这些类不属于域层,这是数据访问。它们都将被存储库实现封装(或者如果使用ORM则根本不存在)。

  

我的第一个问题是当一个模型需要与之沟通时   持久层应该联系Repository还是映射器?   我个人认为它应该询问存储库哪个会   联系映射器并提供所需的功能。

模型不需要与持久层通信。实际上,您应该尝试使模型尽可能与持久性无关。从您的域模型的角度来看,Repository只是一个接口。该接口的实现属于不同的层 - 数据访问。稍后将在Application层的某个位置注入实现。应用层知道持久性和事务。您可以在此处实现Unit Of Work模式(也不属于域层)。

  

现在我的第二个问题是,同一个类的所有对象应该只有一个存储库,这意味着我将创建一个单例。但如果我的应用程序有很多域模型(比方说20),那么将有20个单身人士。

首先,您可以拥有给定域对象的more than one存储库。这是大多数时候发生的事情,因为你想避免Repository接口上的'方法爆炸'。其次,单例存储库是一个坏主意,因为它会将所有消费者耦合到单个实现,其中包括使单元测试变得困难。第三,拥有20个或更多存储库没有任何问题,实际上你拥有的聚焦类越多越好,请参阅SRP

更新:

我认为您正在混淆常规工厂模式和DDD工厂。在DDD术语中,当从数据库恢复对象时,它已经在概念上存在(即使它是内存中的新对象)。因此,存储库有责任持久化并恢复它。当复杂域对象开始生命时,DDD工厂开始发挥作用 - 无论它是否是长期存在的对象(保存在db中)。

答案 1 :(得分:1)

回答你的第二个问题。 ZF1的方法是为每个对象类创建一个单例。你可以有一个工厂/注册表为你创建这些,并在你要求已经创建的工厂/注册表时返回它。或者,如果您使用的是PHP 5.3,请使用DI容器,例如PimpleZend\Di