DDD - 服务层和存储库之间的重复

时间:2012-09-16 17:37:12

标签: c# domain-driven-design ddd-repositories ooad

我已经研究了几个试图遵循DDD原则的应用程序,我注意到我们最终遇到了服务层和感觉像代码味道的存储库之间存在重复的情况。

对于Service层中的大多数操作,它似乎是直接映射到CRUD操作,GetAll,GetById,Create,Delete等。架构流程在以下几行内:我有一个控制器调用服务层,调用存储库,调用与后端 ORM > ..

因此,例如, GetAll 将存在于SL和存储库中。现在,如果我们有一个变更/业务要求,GetAll应该忽略某些项目,我应该怎么做,我应该忽略存储库中的这些,还是应该进入服务层的业务逻辑?如果我们只是直接调用ORM服务层,生活会不会更容易?

总结:我理解服务层可以抽象一些业务逻辑,但是 - 在大多数情况下 - 它处理简单的CRUD操作,是不是更容易摆脱存储库?但是,如果SL 包含一些具有复杂业务逻辑的方法,那么它们应该通过存储库吗?从良好的设计角度来看,我是否应该支持一致性并始终通过存储库或只是保持简单,只使用存储库,而不是简单的一对一映射到CRUD操作。

PS:我意识到看似有类似的问题,但没有找到任何令人满意的答案

4 个答案:

答案 0 :(得分:9)

  

在大多数情况下 - 它正在处理简单的CRUD操作,不是吗   更容易摆脱存储库

恕我直言,我不会说要摆脱存储库。我会说,如果你在做CRUD,你根本不需要DDD。如果您阅读Fowler的企业模式或Evans,他们都会说只有当您的域逻辑非常复杂时才使用DDD。 CRUD并不复杂,因此不需要DDD。

你描述的是代码气味。但我不认为这是DDD的气味。您只是看到过度设计的代码。

答案 1 :(得分:9)

  

我注意到我们最终遇到了重复的情况   服务层和感觉像代码的存储库之间   气味

这不是代码味道,因为他们做了不同的事情。

您应该记住,域或应用程序服务位于与存储库实现不同的层中。层是有原因的 - 不同层中的对象不具有相同的职责,也不与相同的邻居交谈。存储库实现与对象持久性的方式紧密耦合。他们可能会生成SQL语句并与关系数据库交谈,他们可能会与您的ORM交谈......重要的是他们知道对象的持久化方式,而Application Services则不然

如果您的服务层是直接调用ORM,它将真正做两件大事,打破单一责任原则。将ORM更改为另一个ORM或使用不同的持久性方法也会更加困难。

  

例如,GetAll将存在于SL和Repository中。现在,如果   我们有一个GetAll应该忽略的变更/业务要求   某些项目,我该怎么做,我应该忽略这些   存储库,或应该在服务中的业务逻辑   层

如果GetAll()忽略某些项目,我强烈建议在服务和存储库中重命名它以反映它,例如:GetAllAllowedToUser()GetAllBut...()。因此,方法的合同将是明确的,你将避免误解它应该返回什么。此外,您将能够保留原始的正版GetAll()方法,这种方法仍然有用。

答案 2 :(得分:3)

为Dtryon +1,同时:

  

现在,如果我们有变更/业务要求GetAll应该忽略某些项目

没有直接相关,我知道你只是用它作为一个例子,但我已经看到了这个确切的事情。请不要使用名为GetAll的方法,而不是全部。保持GetAll,拥有GetAll,然后拥有GetAllLive,或GetAllAvailable或类似的东西做它所说的

答案 3 :(得分:0)

也许“Finder模式”(不知道这是否是正确的术语)可以解决您的问题。根据CQS(命令 - 查询 - 分离)原则,(IMO)查询操作根本不是“业务逻辑”。我们可以在基础架构层中编写一些特定的“Finder”来执行各种查询,并让所有非查询操作(业务逻辑)保留在服务层中,然后在客户端,我们将查找器视为与服务相同。 对不起我的语言: - (。