37

在阅读了几篇文章之后,我开始了解 DAO 和 Repositories 之间的区别,但我发现自己在尝试理解 Repositories 和 Services 之间的区别时遇到了麻烦。

简而言之,在 OO 范式中:

  • DAO:包含CRUD operations一个实体类的基础的类。它有必要的代码来获取或检索底层持久存储系统的东西。一般来说,方法接收对象实体作为参数,除了在retrieve使用标识符类型有效的方法中。

  • 存储库:在更高级别的抽象中..通常我读过的是一种放置处理聚合对象(具有子对象的对象)的操作的代码的地方。它使用DAOs 从数据库中检索对象,最后以领域“业务”语言公开一个接口。(但同样,我认为使用 id 的数据类型是非常有效的)。示例:一个非常简单的addSomethingwheresomething是父对象的子对象,其实例顺便说一句,由存储库作为一个整体进行管理。

  • 服务:同样,它处于更高的抽象级别。在我看来,它们是连接两个不共享父子关系的类的好地方,但(在抽象方面)与存储库一样远。例:transferCash两者之间的方法bank accounts

所以,这就是我的阅读,但我在这里问上述想法是否正确。或者我应该怎么想。或者让我真正理解所有这些概念的区别的东西。

一些来源:

4

3 回答 3

32

存储库 - 就像你说的 - 一个抽象。它们源自 Martin Fowler 的对象查询模式。存储库和 DTO 都可以通过将持久数据映射到实体对象的等效集合来简化数据库持久性。但是,存储库比 DAO 更粗粒度,因为它提供对整个聚合根 (AG)的控制,通常对客户端隐藏很多内部状态。另一方面,DAO 可以像专用于单个实体对象一样细粒度。对于存储库和 DAO,通常使用Hibernate或其他对象/关系映射 (ORM) 框架,而不是编写自己的实现。

通常,服务可以驻留在服务层中,并且可以充当功能外观、反腐败层和缓存和事务的协调器。它们通常是进行日志记录的好地方。粗粒度和面向用例的服务,例如Service.updateCustomerAdress()Service.sendOrder(). 存储库可能过于细化,以至于客户端无法使用,Customer.add(…)例如Order.modify(…).

存储库和 DAO 具有相同的目的 - 永久保存数据。另一方面,服务应该对持久性一无所知,并且不了解您的数据库。它们通常与域服务、存储库、域核心紧密协作。

于 2013-11-12T22:57:35.777 回答
16

存储库是用于存储和检索聚合根 (AR)的接口,而不是单个实体。您的域模型的每个 AR 都有一个存储库。

根据 Fowler 的存储库模式,存储库的行为类似于内存中的对象集合,这是将它们与 DAO 进行比较的主要区别之一。

存储库接口是域模型的客户端(因此是域模型的一部分)开始使用域模型的一种方式。客户端的目的是从存储库中获取 AR 实例,在其上调用一些方法,这些方法通常会修改其内部状态,然后将其存储回存储库。

于 2013-11-15T08:51:57.560 回答
4

I'm not sure what "DAO" even is. Repositories are an abstraction for loading entities. You should be able to Get an entity and Save one, that is it. No querying. If you want to query some data, write a query (maybe even within an MVC action method, or with the simplest of simple abstractions allowing some SQL to be executed and some DTOs returned that can be rendered straight into the HTML).

Services on the other hand are tricky. For a start the term is overloaded. "Application Services" as defined by the DDD book by Eric Evans exist because objects in the Domain Model are not allowed to access infrastructure concerns like databases, messaging, caching etc. They need all of that stuff done for them and handed to them on a plate, and Application Services do just that. Application Services, for their part do not contain any logic. I would not expect to see ICustomerService.ChangeAddress() do anything other than:

  1. Load the Customer entity.
  2. Call Customer.ChangeAddress(newAddress) <- this encapsulates the domain logic
  3. Save the customer.
  4. Perhaps publish some events.

If you have a service that is loading a customer, setting it's Address property and saving it, then that service is actually a Transaction Script and the Customer is a DTO. Meaning you definitely have a leaky abstraction and likely have an anaemic domain model. Domain model objects should not have public setters, and when DDD is combined with CQRS, your domain model may not even have any public state at all beyond the main entity ID values.

于 2013-11-14T00:15:58.907 回答