【问题标题】:Hexagonal architecture with repository带有存储库的六边形架构
【发布时间】:2016-09-29 09:00:40
【问题描述】:

我试图通过Repository 的例子来理解六边形架构。 在这个设置中,我有以下几层:框架(基础设施)-> 应用程序-> 域。

我在域部分有User,假设我想通过DuplicateUsernameValidator 验证User,如果没有任何重复。为了获得这些信息,我需要从某个地方获得这些信息。我在领域层又增加了一个接口UserRepository,这样就可以在上面的层解决了。

这对我来说是棘手的部分。我想实现UserRepository的逻辑,但对我来说在应用层实现这个没有意义,因为持久化上下文在基础设施层(例如JdbcUserRepositoryJpaUserRepository)。 但是如果我正确理解了六边形结构,我就不能直接在我的基础设施层中实现UserRepository 接口,因为基础设施层不应该知道域层。

我错过了什么?

【问题讨论】:

    标签: hexagonal-architecture


    【解决方案1】:

    我想知道完全相同的问题,这是我的结论:您正在谈论的实现是由适配器处理的。

    您已将业务层开发为六边形。好!这意味着,您的实现取决于暴露给外部的合约(= API 接口)。同样,您的实现使用其他接口与外部通信(= 您称为 UserRepository 的 SPI 接口)。由于这些接口,您的六边形与外部隔离。 当您的六边形将被实例化时,您的 SPI 的实际实现应该作为参数传递(控制反转)。

    现在,在您的基础设施层中,您将通过实现适配器(适配器模式)来实现您的 Jpa 逻辑。

    您的适配器(例如,可以是 Spring 服务)将实现您的接口 UserRepository 并包装您的 JpaUserRepository。然后,您的 UserRepository 中的每个方法都将被重定向到您的 JpaUserRepository 的相应方法(有或没有一点调整)。

    【讨论】:

      【解决方案2】:

      我认为您面临的困惑来自于您试图从六边形架构的角度来处理已经存在的三层应用程序。
      让我们变得简单。
      让我们暂时忘记什么是“应用层”。
      你有你的六边形,如果我理解正确的话,它包含你的应用程序的域(用户对象)。
      正确地,您在六边形内定义了一个 port,允许您从其他地方检索用户。 (我说的是UserRepository接口)
      您的端口(@98​​7654322@ 或 JpaUserRepository)的所有实现都将代表您的端口的适配器,并且应该驻留在您的六边形之外,以免将适配器的低级别细节与您的六边形的高级策略耦合。
      就是这样。
      可能最困难的部分是从具有三层架构(或某种......)的应用程序开始,了解六边形内部必须包含哪些内容,哪些不可以。
      将与您的域完全相关且与基础设施无关的内容保留在六边形内。
      移出一切都与外界有关,但不包含任何业务逻辑。
      将具有上述两种上下文的所有内容分开并相应地移动。

      【讨论】:

      • 我不明白的一点是,将JpaUserRepository 之类的实现放在基础设施层有什么意义。例如,User findByName(String userName) 方法将基本上实现为qry = em.createQuery("select u from User u where u.name = ?1"); qry.setParameter(1, userName); return qry.getSingleResult();。它只使用领域语言和抽象基础设施 API(JPA API 和 JP-QL DSL)。将它放在领域层有什么问题,在传统的分层架构中会出现这种情况吗?六边形不是大材小用吗?
      • 当您考虑到许多现实世界的查询不可避免地在其中嵌入业务逻辑时,就更难理解了。示例:select e from SomeEntity e where e.status = :Requested and not exists (...)。其中一些查询很长,并且嵌入了许多单独的业务规则。在域层之外编写它们似乎不对......
      • 我认为这并不过分。避免将基础设施细节放在核心域中的原因有很多。主要的一个是:耦合。将数据库代码放在自己的适配器中的优点是什么?许多: - 职责分离:如果我必须更改从我的数据库中检索数据的方式,我不必修改与我的业务逻辑相关的类/模块; - 个人“可开发性”:例如开发人员可以改进查询性能,而另一个开发人员可以解决业务逻辑上的错误,而不会出现大问题
      • - 单独的可部署性:您可以交付单个模块,而无需一次交付整个应用程序
      • 基于以上所有原因,我认为将业务逻辑放在查询中并不好。此外,如果我需要更改数据库,我不会重写我所有的业务逻辑代码。显然,这始终是一个权衡问题。有时,为了获得更好的性能,业务逻辑的一小部分会在查询中爬行。根据我的经验,我学会了尽可能干净地开始,将我的代码的所有职责分离到它们的私有上下文(六边形和适配器)中。后来我只有在有充分理由的时候才会做出妥协。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-06-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-06-14
      • 1970-01-01
      相关资源
      最近更新 更多