将外部数据源封装在存储库模式中

时间:2015-07-12 16:09:06

标签: rest domain-driven-design repository-pattern ddd-repositories ddd-service

我正在为新服务创建高级设计。服务的复杂性保证使用DDD(我认为)。所以我做了传统的事情并创建了域服务,聚合,存储库等。我的存储库封装了数据源。因此,查询可以在缓存中查找对象,在数据库中查找失败,无法对外部服务进行REST调用以获取所需信息。这是相当标准的。现在我的同事提出的论点是以这种方式抽象数据源是危险的,因为使用存储库的开发人员不会知道执行api所需的时间,因此无法计算任何api的执行时间。写在上面。如果他知道他的电话会导致REST电话,他可能想要以不同的方式设置他的组件的行为。他们建议我将REST调用移到存储库之外,甚至可能还有缓存策略。我可以看到他们的观点,但是存储库模式背后的整个想法正是为了隐藏这种信息而不是每个组件都处理缓存策略和数据访问。我的问题是,是否存在解决这一问题的模式或模型?

3 个答案:

答案 0 :(得分:2)

  

他们建议我将REST调用移出存储库

然后你将没有存储库。存储库意味着我们不知道持久性细节,而不是我们不知道存在持久性。每当我们使用存储库时,无论其实现(从内存列表到REST调用),我们都期望“缓慢”,因为常见的知识是持久性通常是瓶颈。

将使用某个存储库实现(如基于REST)的人将知道它将处理延迟和瞬态错误。只有IRepository依赖项的服务仍然知道它处理持久性。

关于缓存策略,您可以拥有一些服务级别(更通用)缓存和存储库级别(特定于持久性)缓存。这些可能应该是实现细节。

  

现在我的同事们提出的论点是以这种方式抽象数据源是危险的,因为使用存储库的开发人员不会知道执行api所需的时间,因此无法计算执行时间他在上面写的任何apis。如果他知道他的调用会导致REST调用,他可能想要以不同的方式设置他的组件的行为。

这是浪费时间试图让你的生活复杂化。抽象的全部意义在于隐藏脏的细节。他们建议的基本上是:让用户了解一些实现细节,以便用户可以代码与耦合

关键是,开发人员应该知道他们正在使用的api。如果组件正在使用外部服务(db,Web服务),则应该知道这一点。一旦你知道要获取的数据,你就知道你必须等待它。

如果你去DDD路线那么你就有了有界的背景(BC)。制作一个依赖于另一个BC的模型是一个非常糟糕的主意。每个BC都应该发布域事件,每个感兴趣的BC都应该订阅并根据这些事件保留自己的模型。这意味着查询将是“本地”,但您仍然会遇到数据库。

答案 1 :(得分:1)

存储库模式旨在减少与持久层的耦合。在我看来,我不会冒险让存储库充满责任。

您可以针对外部服务和代理中的更改使用反腐败层来隐藏与缓存相关的问题。

然后在应用程序层中,我将编写回退策略。

答案 2 :(得分:0)

我认为这完全取决于您认为提取/回退策略所属的位置,服务层或基础架构层(后者听起来对我更合理)。

它也可能是两者的混合 - 服务通过一系列有序的存储库,以便在发生故障时一个接一个地使用。 Repos系列的构建可以放在Infrastructure层或其他地方。后备逻辑在一个地方,后备配置在另一个地方。

作为旁注,异步似乎是告诉用户某些内容可能缓慢的好方法,如果您等待它就会阻塞。比隐藏一个香草,不显眼的存储库名称更好,而不是添加一些大的威胁"这可能会很慢"您的类型的前缀,IMO。