微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

存储库可以在 Clean Architecture 中调用 UseCase 吗?

如何解决存储库可以在 Clean Architecture 中调用 UseCase 吗?

这是一个非常棘手的问题,因为当我们检查规则时,并没有明确指出存储库不能调用用例。然而,这似乎不合逻辑。 是否有任何定义/良好做法以及为什么不应该这样做?

谢谢!

解决方法

简短的回答是“不”——不应该,无论上下文如何(在大多数情况下)。至于为什么 - 定义、原则和良好做法 - 考虑在整个 Clean Architecture 实施中明确分离关注点可能会有所帮助。

将此图作为思考如何组织清洁架构主要部分之间的交互(和依赖关系)的背景。

enter image description here

说明的主要原则是——

  • 通过执行,用例具有不同的“数据需求”(AB)。它没有实现实现它们本身的逻辑(因为它们需要一些特定的技术)。因此,在此示例中,用例将它们声明为两个 Gateway 接口(“端口”)。然后在其逻辑中调用它们。

  • 这两个接口都声明了一些应该从“外部”提供(实现)的不同操作集。用例,在其逻辑中,需要并调用所有这些 A 和 B 操作。它们被分为 A 和 B,因为它们不同种类的职责 - 并且可能由系统的不同部分实现(但不一定)。假设用例需要加载持久域对象(作为 A 操作的一部分),但它也需要检索配置(作为一些键值对),它们是 B 操作。这些接口是隔离的,因为这两组操作为用例服务不同的目的。无论如何,在设计方面很重要,它们都明确地“服务”用例需求——也就是说,它们不是通用的以实体为中心的 DAO/Repository 接口;它们仅具有用例实际需要和调用的操作,其形状和形式(参数、返回值)正是用例特别需要的。它们是要“插入”的“端口”,作为整个用例的一部分。

  • 这些职责的“外部”提供者是这些需求的适配器(实施者)。为了实现它们,它们通常使用一些特定的技术或框架——数据库、对某个服务器的网络调用、消息生产者、文件操作、Spring 的配置属性等。

  • 用例仅由架构的驱动程序方(即发起方)调用(调用)。实际上,用例本身是其进一步协作部分(例如,适配器)的“发起者”之一。

  • 另一方面,用例由架构的适配器方“技术支持”(其需求的声明部分“实现”)。

  • 实际上,谁调用了什么——这意味着,在运行时,调用堆栈以明确的方向控制流在整个架构中进行。

  • 控制流总是从驱动程序到适配器(通过用例),而不是相反。

这些是我在我的职业生涯中在不同项目中学到、研究、实施和纠正的原则。换句话说,根据我的经验,就实际和有用的方面而言,它们是由现实世界塑造的 - 在关注点分离和责任明确划分方面。您的自然可能会有所不同,并且没有通用的适用性 - CA 不是一个配方,它是一种软件设计的思维方式,可以通过(更好或更坏)多种方式实现。

简单地想,在您的情况下,Repository 是您的用例(数据)Gateway 的“数据存储网关”实现。 UC 需要来自“某处”的数据——而不关心它来自哪里或如何存储。这非常重要 - 整个核心领域以及用例需要与框架和 I/O 无关

您的 Repository 满足了该需求 - 提供持久域对象。但是用例不能直接调用它,而是声明一个网关(在六角形例如端口和适配器架构中,命名为 Port) - 带有您的存储库需要的所需操作来实施。通过使用某些特定(数据库/持久性)技术,您的 Repository 实现了它 - 它实现了用例的“端口”之一,作为适配器

如上所述 - 在极少数情况下,某些 Gateway 实现可能需要例外。他们可能需要多次来回交互,甚至跨越您的架构。它们是罕见且确实复杂的情况 - 可能不是 Repository 实现所必需的。

但是,如果这确实是不可避免的情况 - 那么最好是用例在调用网关时提供回调 接口作为调用的参数。因此,在其处理过程中,网关的实现者可以使用该接口中的操作进行回调——有效地实现来回的必要性。但是,在大多数情况下,这意味着适配器级别的逻辑和复杂性过多,应该避免这种情况 - 并且强烈暗示应该重新设计当前的解决方案。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?