如何解决存储库可以在 Clean Architecture 中调用 UseCase 吗?
这是一个非常棘手的问题,因为当我们检查规则时,并没有明确指出存储库不能调用用例。然而,这似乎不合逻辑。 是否有任何定义/良好做法以及为什么不应该这样做?
谢谢!
解决方法
简短的回答是“不”——不应该,无论上下文如何(在大多数情况下)。至于为什么 - 定义、原则和良好做法 - 考虑在整个 Clean Architecture 实施中明确分离关注点可能会有所帮助。
将此图作为思考如何组织清洁架构主要部分之间的交互(和依赖关系)的背景。
说明的主要原则是——
-
通过执行,用例具有不同的“数据需求”(A 和 B)。它没有实现实现它们本身的逻辑(因为它们需要一些特定的技术)。因此,在此示例中,用例将它们声明为两个
Gateway
接口(“端口”)。然后在其逻辑中调用它们。 -
这两个接口都声明了一些应该从“外部”提供(实现)的不同操作集。用例,在其逻辑中,需要并调用所有这些 A 和 B 操作。它们被分为 A 和 B,因为它们不同种类的职责 - 并且可能由系统的不同部分实现(但不一定)。假设用例需要加载持久域对象(作为 A 操作的一部分),但它也需要检索配置(作为一些键值对),它们是 B 操作。这些接口是隔离的,因为这两组操作为用例服务不同的目的。无论如何,在设计方面很重要,它们都明确地“服务”用例需求——也就是说,它们不是通用的以实体为中心的 DAO/Repository 接口;它们仅具有用例实际需要和调用的操作,其形状和形式(参数、返回值)正是用例特别需要的。它们是要“插入”的“端口”,作为整个用例的一部分。
-
这些职责的“外部”提供者是这些需求的适配器(实施者)。为了实现它们,它们通常使用一些特定的技术或框架——数据库、对某个服务器的网络调用、消息生产者、文件操作、Spring 的配置属性等。
-
用例仅由架构的驱动程序方(即发起方)调用(调用)。实际上,用例本身是其进一步协作部分(例如,适配器)的“发起者”之一。
-
另一方面,用例由架构的适配器方“技术支持”(其需求的声明部分“实现”)。
-
实际上,谁调用了什么——这意味着,在运行时,调用堆栈以明确的方向控制流在整个架构中进行。
-
控制流总是从驱动程序到适配器(通过用例),而不是相反。
这些是我在我的职业生涯中在不同项目中学到、研究、实施和纠正的原则。换句话说,根据我的经验,就实际和有用的方面而言,它们是由现实世界塑造的 - 在关注点分离和责任明确划分方面。您的自然可能会有所不同,并且没有通用的适用性 - CA 不是一个配方,它是一种软件设计的思维方式,可以通过(更好或更坏)多种方式实现。
简单地想,在您的情况下,Repository
是您的用例(数据)Gateway
的“数据存储网关”实现。 UC 需要来自“某处”的数据——而不关心它来自哪里或如何存储。这非常重要 - 整个核心领域以及用例需要与框架和 I/O 无关。
您的 Repository
满足了该需求 - 提供持久域对象。但是用例不能直接调用它,而是声明一个网关(在六角形例如端口和适配器架构中,命名为 Port
) - 带有您的存储库需要的所需操作来实施。通过使用某些特定(数据库/持久性)技术,您的 Repository
实现了它 - 它实现了用例的“端口”之一,作为适配器。
如上所述 - 在极少数情况下,某些 Gateway
实现可能需要例外。他们可能需要多次来回交互,甚至跨越您的架构。它们是罕见且确实复杂的情况 - 可能不是 Repository
实现所必需的。
但是,如果这确实是不可避免的情况 - 那么最好是用例在调用网关时提供回调 接口作为调用的参数。因此,在其处理过程中,网关的实现者可以使用该接口中的操作进行回调——有效地实现来回的必要性。但是,在大多数情况下,这意味着适配器级别的逻辑和复杂性过多,应该避免这种情况 - 并且强烈暗示应该重新设计当前的解决方案。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。